115 lines
3.6 KiB
C#
115 lines
3.6 KiB
C#
using System;
|
|
using Steamworks;
|
|
using UnityEngine;
|
|
|
|
namespace MegaKoop.Game.Networking
|
|
{
|
|
/// <summary>
|
|
/// Low level Steam P2P messaging helper. Prepends a byte message type header for easy routing.
|
|
/// </summary>
|
|
public class SteamP2PTransport : MonoBehaviour
|
|
{
|
|
public event Action<NetworkMessage> 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 (!SteamBootstrap.IsInitialized)
|
|
{
|
|
return;
|
|
}
|
|
|
|
PumpIncomingPackets();
|
|
}
|
|
|
|
public void SetActiveLobby(CSteamID lobbyId)
|
|
{
|
|
activeLobby = lobbyId;
|
|
}
|
|
|
|
public void Send(CSteamID recipient, NetworkMessageType type, byte[] payload, EP2PSend sendType = EP2PSend.k_EP2PSendReliable)
|
|
{
|
|
if (!SteamBootstrap.IsInitialized)
|
|
{
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|