using System;
using Steamworks;
using UnityEngine;
namespace MegaKoop.Game.Networking
{
///
/// Low level Steam P2P messaging helper. Prepends a byte message type header for easy routing.
///
public class SteamP2PTransport : MonoBehaviour
{
public event Action MessageReceived;
[SerializeField] private EP2PSend defaultSendType = EP2PSend.k_EP2PSendReliable;
[SerializeField] private int listenChannel = 0;
private byte[] receiveBuffer = new byte[8192];
private CSteamID activeLobby = CSteamID.Nil;
private void Update()
{
#if STEAMWORKSNET
if (!MegaKoop.Steam.SteamManager.Initialized)
#else
if (!SteamBootstrap.IsInitialized)
#endif
{
return;
}
PumpIncomingPackets();
}
public void SetActiveLobby(CSteamID lobbyId)
{
activeLobby = lobbyId;
}
public void Send(CSteamID recipient, NetworkMessageType type, byte[] payload, EP2PSend sendType = EP2PSend.k_EP2PSendReliable)
{
#if STEAMWORKSNET
if (!MegaKoop.Steam.SteamManager.Initialized)
#else
if (!SteamBootstrap.IsInitialized)
#endif
{
return;
}
int payloadLength = payload != null ? payload.Length : 0;
byte[] packet = new byte[payloadLength + 1];
packet[0] = (byte)type;
if (payloadLength > 0)
{
Buffer.BlockCopy(payload, 0, packet, 1, payloadLength);
}
bool sent = SteamNetworking.SendP2PPacket(recipient, packet, (uint)packet.Length, sendType, listenChannel);
if (!sent)
{
Debug.LogWarning("[SteamP2PTransport] Failed to send packet to " + recipient);
}
}
public void Broadcast(NetworkMessageType type, byte[] payload, EP2PSend sendType = EP2PSend.k_EP2PSendReliable)
{
if (activeLobby == CSteamID.Nil)
{
return;
}
int members = SteamMatchmaking.GetNumLobbyMembers(activeLobby);
CSteamID self = SteamUser.GetSteamID();
for (int i = 0; i < members; i++)
{
CSteamID member = SteamMatchmaking.GetLobbyMemberByIndex(activeLobby, i);
if (member == self)
{
continue;
}
Send(member, type, payload, sendType);
}
}
private void PumpIncomingPackets()
{
while (SteamNetworking.IsP2PPacketAvailable(out uint packetSize, listenChannel))
{
if (packetSize == 0)
{
continue;
}
if (packetSize > receiveBuffer.Length)
{
receiveBuffer = new byte[(int)packetSize];
}
if (SteamNetworking.ReadP2PPacket(receiveBuffer, (uint)receiveBuffer.Length, out uint bytesRead, out CSteamID remote, listenChannel))
{
SteamNetworking.AcceptP2PSessionWithUser(remote);
if (bytesRead == 0)
{
continue;
}
NetworkMessageType type = (NetworkMessageType)receiveBuffer[0];
byte[] payload = new byte[Mathf.Max(0, (int)bytesRead - 1)];
if (bytesRead > 1)
{
Buffer.BlockCopy(receiveBuffer, 1, payload, 0, (int)bytesRead - 1);
}
MessageReceived?.Invoke(new NetworkMessage(type, payload, remote.m_SteamID));
}
}
}
}
}