diff --git a/BoneSync/MelonLoaderMod.cs b/BoneSync/MelonLoaderMod.cs index 5365064..30933a1 100644 --- a/BoneSync/MelonLoaderMod.cs +++ b/BoneSync/MelonLoaderMod.cs @@ -25,8 +25,7 @@ namespace BoneSync SteamLobbyManager steamLobbyManager = new SteamLobbyManager(); lobby = steamLobbyManager; - transport = new SteamTransport(steamLobbyManager); - + transport = new SteamTransport(); } diff --git a/BoneSync/Networking/LobbyManager/LobbyManager.cs b/BoneSync/Networking/LobbyManager/LobbyManager.cs index a42d18a..098157c 100644 --- a/BoneSync/Networking/LobbyManager/LobbyManager.cs +++ b/BoneSync/Networking/LobbyManager/LobbyManager.cs @@ -11,15 +11,11 @@ namespace BoneSync.Networking.LobbyManager { public abstract class LobbyManager { + public abstract ulong[] GetPeers(); public abstract ulong GetLobbyId(); public abstract ulong GetHostId(); public abstract ulong GetLocalId(); - public virtual void CreateLobby() - { - - } - public virtual void Initialize() { diff --git a/BoneSync/Networking/LobbyManager/SteamLobbyManager.cs b/BoneSync/Networking/LobbyManager/SteamLobbyManager.cs index 216db29..5afd397 100644 --- a/BoneSync/Networking/LobbyManager/SteamLobbyManager.cs +++ b/BoneSync/Networking/LobbyManager/SteamLobbyManager.cs @@ -10,36 +10,52 @@ namespace BoneSync.Networking.LobbyManager { internal class SteamLobbyManager : LobbyManager { - public SteamId[] Peers; - private Lobby lobbyInstance; - - public override ulong GetLocalId() + private Lobby _lobbyInstance; + public Friend[] LobbyMembers { - return SteamClient.SteamId.Value; + get; + private set; } - public override ulong GetHostId() + public SteamId[] steamIds { - return lobbyInstance.Owner.Id; - } - public override ulong GetLobbyId() - { - return lobbyInstance.Id; - } - public override void CreateLobby() - { - + get; + private set; } - public SteamId? getPeerFromId(ulong id) + public override ulong[] GetPeers() => steamIds.Select(x => x.Value).ToArray(); + public override ulong GetLocalId() => SteamClient.SteamId.Value; + public override ulong GetHostId() => _lobbyInstance.Owner.Id.Value; + public override ulong GetLobbyId() => _lobbyInstance.Id.Value; + + private void UpdateLobbyData() { - foreach (SteamId peer in Peers) + LobbyMembers = _lobbyInstance.Members.ToArray(); + steamIds = LobbyMembers.Select(x => x.Id).ToArray(); + } + public override void Initialize() + { + SteamMatchmaking.OnLobbyCreated += (Result result, Lobby lobby) => { - if (peer.Value == id) + _lobbyInstance = lobby; + UpdateLobbyData(); + }; + SteamMatchmaking.OnLobbyEntered += (Lobby lobby) => + { + _lobbyInstance = lobby; + UpdateLobbyData(); + }; + SteamMatchmaking.OnLobbyMemberLeave += (Lobby lobby, Friend friend) => + { + if (friend.Id == SteamClient.SteamId) { - return peer; + _lobbyInstance = new Lobby(); } - } - return null; + UpdateLobbyData(); + }; + SteamMatchmaking.OnLobbyMemberJoined += (Lobby lobby, Friend friend) => + { + UpdateLobbyData(); + }; } } diff --git a/BoneSync/Networking/Messages/NetworkMessage.cs b/BoneSync/Networking/Messages/NetworkMessage.cs index cf085c4..b426714 100644 --- a/BoneSync/Networking/Messages/NetworkMessage.cs +++ b/BoneSync/Networking/Messages/NetworkMessage.cs @@ -22,7 +22,7 @@ namespace BoneSync.Networking.Messages public abstract class NetworkMessage { - private static bool _packetTypesRegistered = false; + private static bool PacketTypesRegistered => PacketTypeMap.Count > 0; internal static Dictionary PacketTypeMap = new Dictionary(); @@ -34,25 +34,26 @@ namespace BoneSync.Networking.Messages public PacketType GetPacketType() { + RegisterPacketTypes(); if (_packetType == PacketType.Unknown) { - Type type = GetType(); - _packetType = PacketTypeMap.FirstOrDefault(x => x.Value == type).Key; - if (_packetType == PacketType.Unknown) + string typeName = GetType().Name; + KeyValuePair found = PacketTypeMap.FirstOrDefault(x => x.Value.Name == typeName); + if (found.Value == null) { - throw new Exception("Cannot find packetType for " + type.Name); + throw new Exception("Cannot find packetType for " + typeName); } + _packetType = found.Key; } return _packetType; } public static void RegisterPacketTypes() { - if (_packetTypesRegistered) + if (PacketTypesRegistered) { return; } - _packetTypesRegistered = true; Assembly assembly = Assembly.GetExecutingAssembly(); Type[] types = assembly.GetTypes(); foreach (Type type in types) @@ -61,7 +62,7 @@ namespace BoneSync.Networking.Messages if (type.IsSubclassOf(typeof(NetworkMessage))) { PacketType? packetType = type.GetCustomAttributesData().Where(x => x.AttributeType == typeof(PacketTypeAttribute)).Select(x => (PacketType)x.ConstructorArguments[0].Value).FirstOrDefault(); - PacketTypeMap.Add((PacketType)packetType, type); + PacketTypeMap[packetType.Value] = type; } } } @@ -75,12 +76,7 @@ namespace BoneSync.Networking.Messages } Type type = PacketTypeMap[packet.Info.packetType]; // get the constructor that takes a Packet - ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(Packet) }); - // create an instance of the class - if (constructor == null) - { - throw new Exception("No constructor found for type " + type.Name); - } + ConstructorInfo constructor = type.GetConstructor(new Type[] { typeof(Packet) }) ?? throw new Exception("No constructor found for type " + type.Name); NetworkMessage networkMessage = (NetworkMessage)constructor.Invoke(new object[] { packet }); return networkMessage; } @@ -95,7 +91,7 @@ namespace BoneSync.Networking.Messages } public void Broadcast() { - Send(0); + Send(TransportBase.BORADCAST_ID); } public void Send(ulong receiverId) { diff --git a/BoneSync/Networking/Packet.cs b/BoneSync/Networking/Packet.cs index 4a55bd4..87b3946 100644 --- a/BoneSync/Networking/Packet.cs +++ b/BoneSync/Networking/Packet.cs @@ -1,4 +1,5 @@ -using System; +using BoneSync.Networking.Messages; +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -33,7 +34,6 @@ namespace BoneSync.Networking private PacketInfo _packetInfo; private byte[] _dataBytes; - private PacketInfo packetInfo; public Packet(PacketInfo packetInfo, byte[] data) { @@ -45,21 +45,34 @@ namespace BoneSync.Networking { ByteEncoder byteEncoder = new ByteEncoder(); byteEncoder.WriteBytes(bytes); - PacketInfo packetInfo = new PacketInfo(byteEncoder.ReadInt(), byteEncoder.ReadUlong(), byteEncoder.ReadUlong(), (PacketType)byteEncoder.ReadInt()); + + int packetType = byteEncoder.ReadInt(); + int id = byteEncoder.ReadInt(); + ulong senderId = byteEncoder.ReadUlong(); + ulong receiverId = byteEncoder.ReadUlong(); + + PacketInfo packetInfo = new PacketInfo(id, senderId, receiverId, (PacketType)packetType); return new Packet(packetInfo, byteEncoder.ToArray()); } public byte[] ToBytes() { ByteEncoder byteEncoder = new ByteEncoder(); - byteEncoder.WriteInt(packetInfo.id); - byteEncoder.WriteUlong(packetInfo.senderId); - byteEncoder.WriteUlong(packetInfo.receiverId); - byteEncoder.WriteInt((int)packetInfo.packetType); + byteEncoder.WriteInt((int)_packetInfo.packetType); + byteEncoder.WriteInt(_packetInfo.id); + byteEncoder.WriteUlong(_packetInfo.senderId); + byteEncoder.WriteUlong(_packetInfo.receiverId); byteEncoder.WriteBytes(_dataBytes); return byteEncoder.ToArray(); } + public static bool OnPacketReceived(Packet packet) + { + NetworkMessage networkMessage = NetworkMessage.ParsePacket(packet); + networkMessage.Execute(); + return true; + } + public byte[] Data => _dataBytes; public static int GenerateId() @@ -77,15 +90,21 @@ namespace BoneSync.Networking byte[] randomDataBytes = new byte[1024]; random.NextBytes(randomDataBytes); - PacketInfo originalPacketInfo = new PacketInfo(1, 2, 3, PacketType.LobbyInfo); + PacketInfo originalPacketInfo = new PacketInfo(Packet.GenerateId(), 1, 2, PacketType.LobbyInfo); Packet originalPacket = new Packet(originalPacketInfo, randomDataBytes); byte[] bytes = originalPacket.ToBytes(); Packet parsedPacket = Packet.FromBytes(bytes); - Assert.Equal(originalPacket.Info, parsedPacket.Info); + + Assert.Equal(originalPacket.Info.id, parsedPacket.Info.id); + Assert.Equal(originalPacket.Info.senderId, parsedPacket.Info.senderId); + Assert.Equal(originalPacket.Info.receiverId, parsedPacket.Info.receiverId); + Assert.Equal(originalPacket.Info.packetType, parsedPacket.Info.packetType); + Assert.Equal(originalPacket.Data, parsedPacket.Data); + Assert.Equal(randomDataBytes, parsedPacket.Data); Assert.NotEqual(bytes, randomDataBytes); } diff --git a/BoneSync/Networking/Transport/SteamTransport.cs b/BoneSync/Networking/Transport/SteamTransport.cs index 7b64fcb..56303af 100644 --- a/BoneSync/Networking/Transport/SteamTransport.cs +++ b/BoneSync/Networking/Transport/SteamTransport.cs @@ -1,62 +1,82 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Net.Sockets; using System.Text; using System.Threading.Tasks; using BoneSync.Networking.LobbyManager; using Facepunch.Steamworks; using Facepunch.Steamworks.Data; +using MelonLoader; namespace BoneSync.Networking.Transport { internal class SteamTransport : TransportBase { - SteamLobbyManager _instance; - public override event Action OnReceive; - public SteamTransport(SteamLobbyManager lobbyManager) + public SteamTransport() { SteamNetworking.OnP2PSessionRequest += OnP2PSessionRequest; } private void OnP2PSessionRequest(SteamId steamId) { - SteamNetworking.AcceptP2PSessionWithUser(steamId); + MelonLogger.Msg("P2P Request from " + steamId); + if (BoneSync.lobby.GetPeers().Contains(steamId)) + SteamNetworking.AcceptP2PSessionWithUser(steamId); } private void ProcessPacket(P2Packet steamPacket) { Packet packet = Packet.FromBytes(steamPacket.Data); - bool isTarget = packet.Info.receiverId == 0 || packet.Info.receiverId == _instance.GetLocalId(); + bool isTarget = packet.Info.receiverId == BORADCAST_ID || packet.Info.receiverId == BoneSync.lobby.GetLocalId(); if (isTarget) { - OnReceive?.Invoke(packet); + Packet.OnPacketReceived(packet); } } public override bool Tick() { + int processed = 0; while (SteamNetworking.IsP2PPacketAvailable()) { - P2Packet packet = (P2Packet)SteamNetworking.ReadP2PPacket(); - ProcessPacket(packet); + P2Packet? packet = SteamNetworking.ReadP2PPacket(); + if (!packet.HasValue) continue; + ProcessPacket(packet.Value); + processed++; } - return true; + return processed > 0; + } + + public void SendP2P(SteamId peer, byte[] data) + { + if (peer == BoneSync.lobby.GetLocalId()) + { + //MelonLogger.Msg("Trying to send packet to self"); + return; + } + SteamNetworking.SendP2PPacket(peer, data, data.Length, 0, P2PSend.Reliable); } public override void Send(Packet packet) { - if (packet.Info.receiverId == 0) + LobbyManager.LobbyManager _instance = BoneSync.lobby; + if (_instance == null) { - foreach (SteamId peer in _instance.Peers) + MelonLogger.Msg("Lobby instance is null"); + return; + } + if (packet.Info.receiverId == BORADCAST_ID) + { + foreach (SteamId peer in _instance.GetPeers()) { - byte[] packetBytes = packet.ToBytes(); - SteamNetworking.SendP2PPacket(peer, packetBytes, packetBytes.Length, 0, P2PSend.Reliable); + SendP2P(peer, packet.ToBytes()); } + return; } else { - SteamId peer = (SteamId)_instance.getPeerFromId(packet.Info.receiverId); - SteamNetworking.SendP2PPacket(peer, packet.ToBytes(), packet.ToBytes().Length, 0, P2PSend.Reliable); + SendP2P(packet.Info.receiverId, packet.ToBytes()); } } diff --git a/BoneSync/Networking/Transport/TransportBase.cs b/BoneSync/Networking/Transport/TransportBase.cs index 891e1d4..e6bedde 100644 --- a/BoneSync/Networking/Transport/TransportBase.cs +++ b/BoneSync/Networking/Transport/TransportBase.cs @@ -8,9 +8,8 @@ namespace BoneSync.Networking.Transport { public abstract class TransportBase { + public const int BORADCAST_ID = 0; public abstract void Send(Packet packet); public abstract bool Tick(); - - public abstract event Action OnReceive; } } diff --git a/BoneSync/packages.config b/BoneSync/packages.config index a400c1b..a5081ad 100644 --- a/BoneSync/packages.config +++ b/BoneSync/packages.config @@ -1,11 +1,13 @@  + + - + diff --git a/Facepunch.Steamworks/Facepunch.Steamworks.Win64.csproj b/Facepunch.Steamworks/Facepunch.Steamworks.Win64.csproj index 701650c..8f21335 100644 --- a/Facepunch.Steamworks/Facepunch.Steamworks.Win64.csproj +++ b/Facepunch.Steamworks/Facepunch.Steamworks.Win64.csproj @@ -24,11 +24,15 @@ https://github.com/Facepunch/Facepunch.Steamworks.git git + + + + - - Always - + + Never + diff --git a/testEnvironments.json b/testEnvironments.json new file mode 100644 index 0000000..a110b57 --- /dev/null +++ b/testEnvironments.json @@ -0,0 +1,17 @@ +{ + "version": "1", + "environments": [ + // See https://aka.ms/remotetesting for more details + // about how to configure remote environments. + //{ + // "name": "WSL Ubuntu", + // "type": "wsl", + // "wslDistribution": "Ubuntu" + //}, + //{ + // "name": "Docker dotnet/sdk", + // "type": "docker", + // "dockerImage": "mcr.microsoft.com/dotnet/sdk" + //} + ] +} \ No newline at end of file