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 (!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)); } } } } }