diff --git a/Shared/Behaviours/BallBehaviour.cs b/Shared/Behaviours/BallBehaviour.cs index a4e5a8c..fdeecba 100644 --- a/Shared/Behaviours/BallBehaviour.cs +++ b/Shared/Behaviours/BallBehaviour.cs @@ -65,12 +65,12 @@ public class BallBehaviour : Behaviour2D, IFirstFrameUpdate, IPhysicsUpdate, INe public BallBehaviour() { } public BallBehaviour(float speed) => Speed = speed; - void IPacketListenerClient.OnClientPacketArrived(BallResetPacket packet) => ResetBall(); - void IPacketListenerClient.OnClientPacketArrived(BallUpdatePacket packet) + void IPacketListenerClient.OnClientPacketArrived(IConnection sender, BallResetPacket packet) => ResetBall(); + void IPacketListenerClient.OnClientPacketArrived(IConnection sender, BallUpdatePacket packet) { networkTween = Transform.TweenPositionAdditive(tweenManager, .25f, Transform.Position.FromTo(packet.Position)); RigidBody.Velocity = packet.Velocity; - physicsEngine2D.StepIndividual(RigidBody, new System.DateTime(System.DateTime.UtcNow.Ticks - packet.Timestamp).Second); + physicsEngine2D.StepIndividual(RigidBody, sender.Ping); } private class BallResetPacket : INetworkPacket; @@ -78,14 +78,12 @@ public class BallBehaviour : Behaviour2D, IFirstFrameUpdate, IPhysicsUpdate, INe { public Vector2D Position { get; set; } = Vector2D.Zero; public Vector2D Velocity { get; set; } = Vector2D.Zero; - public long Timestamp { get; set; } = 0; public BallUpdatePacket() { } public BallUpdatePacket(BallBehaviour ballBehaviour) { Position = ballBehaviour.Transform.Position; Velocity = ballBehaviour.RigidBody.Velocity; - Timestamp = System.DateTime.UtcNow.Ticks; } } } diff --git a/Shared/Behaviours/PaddleBehaviour.cs b/Shared/Behaviours/PaddleBehaviour.cs index 0182130..32a2782 100644 --- a/Shared/Behaviours/PaddleBehaviour.cs +++ b/Shared/Behaviours/PaddleBehaviour.cs @@ -70,7 +70,7 @@ public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Sp private void OnDownPressed(IButtonInputs sender, IButtonInputs.ButtonCallbackArguments args) { isDownPressed = true; networkClient?.SendToServer(new PaddleKeyStatePacket(this)); } private void OnDownReleased(IButtonInputs sender, IButtonInputs.ButtonCallbackArguments args) { isDownPressed = false; networkClient?.SendToServer(new PaddleKeyStatePacket(this)); } - public void OnServerPacketArrived(string sender, PaddleKeyStatePacket packet) + public void OnServerPacketArrived(IConnection sender, PaddleKeyStatePacket packet) { isUpPressed = packet.IsUpPressed; isDownPressed = packet.IsDownPressed; @@ -78,7 +78,7 @@ public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Sp networkServer?.SendToClient("*", new PaddleKeyStatePacket(this)); } - public void OnClientPacketArrived(PaddleKeyStatePacket packet) + public void OnClientPacketArrived(IConnection sender, PaddleKeyStatePacket packet) { isUpPressed = packet.IsUpPressed; isDownPressed = packet.IsDownPressed; diff --git a/Shared/Behaviours/PongManagerBehaviour.cs b/Shared/Behaviours/PongManagerBehaviour.cs index 246e5d8..dc952a5 100644 --- a/Shared/Behaviours/PongManagerBehaviour.cs +++ b/Shared/Behaviours/PongManagerBehaviour.cs @@ -89,7 +89,7 @@ public class PongManagerBehaviour : Behaviour, INetworkEntity, IFirstFrameUpdate return Vector2D.Right.Rotate(isBackwards ? rotation + Syntriax.Engine.Core.Math.PI : rotation); } - void IPacketListenerServer.OnServerPacketArrived(string sender, RequestStartPacket packet) + void IPacketListenerServer.OnServerPacketArrived(IConnection sender, RequestStartPacket packet) { if (ball.RigidBody.Velocity.MagnitudeSquared > 0.01f) return; diff --git a/Shared/Network/Abstract/IConnection.cs b/Shared/Network/Abstract/IConnection.cs new file mode 100644 index 0000000..7bfccc1 --- /dev/null +++ b/Shared/Network/Abstract/IConnection.cs @@ -0,0 +1,8 @@ +namespace Syntriax.Engine.Network; + +public interface IConnection +{ + string Id { get; } + float Ping { get; } + float RoundTrip { get; } +} diff --git a/Shared/Network/Abstract/INetworkCommunicator.cs b/Shared/Network/Abstract/INetworkCommunicator.cs index e99ba7b..8a63940 100644 --- a/Shared/Network/Abstract/INetworkCommunicator.cs +++ b/Shared/Network/Abstract/INetworkCommunicator.cs @@ -1,13 +1,20 @@ +using System.Collections.Generic; + using Syntriax.Engine.Core; namespace Syntriax.Engine.Network; public interface INetworkCommunicator { + Event OnConnectionEstablished { get; } + Event OnConnectionAbolished { get; } + + IReadOnlyDictionary Connections { get; } + INetworkCommunicator Stop(); - INetworkCommunicator SubscribeToPackets(Event.EventHandler callback); - INetworkCommunicator UnsubscribeFromPackets(Event.EventHandler callback); + INetworkCommunicator SubscribeToPackets(Event.EventHandler callback); + INetworkCommunicator UnsubscribeFromPackets(Event.EventHandler callback); } public interface INetworkCommunicatorClient : INetworkCommunicator diff --git a/Shared/Network/Abstract/IPacketListenerClient.cs b/Shared/Network/Abstract/IPacketListenerClient.cs index dacef44..a9e1a33 100644 --- a/Shared/Network/Abstract/IPacketListenerClient.cs +++ b/Shared/Network/Abstract/IPacketListenerClient.cs @@ -2,5 +2,5 @@ namespace Syntriax.Engine.Network; public interface IPacketListenerClient : INetworkEntity { - void OnClientPacketArrived(T packet); + void OnClientPacketArrived(IConnection sender, T packet); } diff --git a/Shared/Network/Abstract/IPacketListenerServer.cs b/Shared/Network/Abstract/IPacketListenerServer.cs index a7cfbb2..c1dae03 100644 --- a/Shared/Network/Abstract/IPacketListenerServer.cs +++ b/Shared/Network/Abstract/IPacketListenerServer.cs @@ -2,5 +2,5 @@ namespace Syntriax.Engine.Network; public interface IPacketListenerServer : INetworkEntity { - void OnServerPacketArrived(string sender, T packet); + void OnServerPacketArrived(IConnection sender, T packet); } diff --git a/Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs b/Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs index a9858aa..789a5b6 100644 --- a/Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs +++ b/Shared/Network/LiteNetLib/LiteNetLibCommunicatorBase.cs @@ -14,11 +14,16 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat { protected readonly NetPacketProcessor netPacketProcessor = new(); - private readonly Dictionary> listeners = []; + private readonly Dictionary> listeners = []; + private readonly Dictionary _connections = []; + public IReadOnlyDictionary Connections => _connections; public EventBasedNetListener Listener { get; private set; } = null!; public NetManager Manager { get; private set; } = null!; + public Event OnConnectionEstablished { get; } = new(); + public Event OnConnectionAbolished { get; } = new(); + public INetworkCommunicator Stop() { Manager.Stop(); @@ -33,10 +38,10 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat protected virtual void OnPacketArrived(T packet, NetPeer peer) where T : INetworkPacket { - if (!listeners.TryGetValue(typeof(T), out Event? @event)) + if (!listeners.TryGetValue(typeof(T), out Event? @event)) return; - @event.Invoke(peer.Id.ToString(), packet); + @event.Invoke(Connections[peer.Id.ToString()], packet); } private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod) @@ -45,6 +50,22 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat catch { } } + private void ConnectionEstablished(NetPeer peer) + { + LiteNetLibConnection connection = new(peer); + _connections.Add(connection.Id, connection); + OnConnectionEstablished.Invoke(this, connection); + } + + private void ConnectionAbolished(NetPeer peer, DisconnectInfo disconnectInfo) + { + if (!_connections.TryGetValue(peer.Id.ToString(), out var connection)) + return; + + _connections.Remove(connection.Id); + OnConnectionAbolished.Invoke(this, connection); + } + private void SetupPackets() { // Find network packets implementing INetworkPacket @@ -95,6 +116,8 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat Manager = new NetManager(Listener); Listener.NetworkReceiveEvent += NetworkReceiveEvent; + Listener.PeerConnectedEvent += ConnectionEstablished; + Listener.PeerDisconnectedEvent += ConnectionAbolished; SetupEnginePackets(); SetupPackets(); @@ -118,10 +141,10 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat netPacketProcessor.RegisterNestedType(Vector3DNetPacker.Write, Vector3DNetPacker.Read); } - public INetworkCommunicator SubscribeToPackets(Event.EventHandler callback) + public INetworkCommunicator SubscribeToPackets(Event.EventHandler callback) { Type type = typeof(T); - if (!listeners.TryGetValue(type, out Event? @event)) + if (!listeners.TryGetValue(type, out Event? @event)) { @event = new(); listeners.Add(type, @event); @@ -131,15 +154,15 @@ public abstract class LiteNetLibCommunicatorBase : Behaviour, INetworkCommunicat return this; } - public INetworkCommunicator UnsubscribeFromPackets(Event.EventHandler callback) + public INetworkCommunicator UnsubscribeFromPackets(Event.EventHandler callback) { Type type = typeof(T); - if (!listeners.TryGetValue(type, out Event? @event)) + if (!listeners.TryGetValue(type, out Event? @event)) return this; @event.RemoveListener(EventDelegateWrapper(callback)); return this; } - private static Event.EventHandler EventDelegateWrapper(Event.EventHandler callback) => (sender, @object) => callback.Invoke(sender, (T)@object); + private static Event.EventHandler EventDelegateWrapper(Event.EventHandler callback) => (sender, @object) => callback.Invoke(sender, (T)@object); } diff --git a/Shared/Network/LiteNetLib/LiteNetLibConnection.cs b/Shared/Network/LiteNetLib/LiteNetLibConnection.cs new file mode 100644 index 0000000..f668e94 --- /dev/null +++ b/Shared/Network/LiteNetLib/LiteNetLibConnection.cs @@ -0,0 +1,10 @@ +using LiteNetLib; + +namespace Syntriax.Engine.Network; + +public record class LiteNetLibConnection(NetPeer NetPeer) : IConnection +{ + public string Id { get; } = NetPeer.Id.ToString(); + public float Ping => NetPeer.Ping * .001f; + public float RoundTrip => NetPeer.RoundTripTime * .001f; +} diff --git a/Shared/Network/LiteNetLib/LiteNetLibServer.cs b/Shared/Network/LiteNetLib/LiteNetLibServer.cs index 060703c..32b348a 100644 --- a/Shared/Network/LiteNetLib/LiteNetLibServer.cs +++ b/Shared/Network/LiteNetLib/LiteNetLibServer.cs @@ -39,7 +39,7 @@ public class LiteNetLibServer : LiteNetLibCommunicatorBase, INetworkCommunicator MaxConnectionCount = maxConnectionCount; Port = port; - Manager.Start(port); + Manager.Start(8888); return this; } diff --git a/Shared/Network/NetworkManager.cs b/Shared/Network/NetworkManager.cs index f2d7a48..a84c485 100644 --- a/Shared/Network/NetworkManager.cs +++ b/Shared/Network/NetworkManager.cs @@ -73,50 +73,50 @@ public class NetworkManager : Behaviour, INetworkManager #endregion #region Packet Routing - private void OnPacketReceived(string senderClientId, T entityDataPacket) + private void OnPacketReceived(IConnection sender, T entityDataPacket) { if (entityDataPacket is IEntityNetworkPacket entityPacket) - RoutePacket(senderClientId, entityDataPacket, entityPacket); + RoutePacket(sender, entityDataPacket, entityPacket); else - BroadcastPacket(senderClientId, entityDataPacket); + BroadcastPacket(sender, entityDataPacket); } - private void RoutePacket(string senderClientId, T entityDataPacket, IEntityNetworkPacket entityPacket) + private void RoutePacket(IConnection sender, T entityDataPacket, IEntityNetworkPacket entityPacket) { if (NetworkCommunicator is INetworkCommunicatorClient) - RoutePacket(clientPacketRouters, entityPacket.EntityId, senderClientId, entityDataPacket); + RoutePacket(clientPacketRouters, entityPacket.EntityId, sender, entityDataPacket); if (NetworkCommunicator is INetworkCommunicatorServer) - RoutePacket(serverPacketRouters, entityPacket.EntityId, senderClientId, entityDataPacket); + RoutePacket(serverPacketRouters, entityPacket.EntityId, sender, entityDataPacket); } - private void BroadcastPacket(string senderClientId, T entityDataPacket) + private void BroadcastPacket(IConnection sender, T entityDataPacket) { if (NetworkCommunicator is INetworkCommunicatorClient) - BroadcastPacket(clientPacketRouters, senderClientId, entityDataPacket); + BroadcastPacket(clientPacketRouters, sender, entityDataPacket); if (NetworkCommunicator is INetworkCommunicatorServer) - BroadcastPacket(serverPacketRouters, senderClientId, entityDataPacket); + BroadcastPacket(serverPacketRouters, sender, entityDataPacket); } private static void BroadcastPacket( Dictionary> packetRouters, - string senderClientId, + IConnection sender, T entityDataPacket) { if (!packetRouters.TryGetValue(entityDataPacket!.GetType(), out Dictionary? routers)) return; - foreach ((string id, object routerEventReference) in routers) + foreach ((string behaviourId, object routerEventReference) in routers) { - Event routerEvent = (Event)routerEventReference; - routerEvent.Invoke(senderClientId, entityDataPacket!); + Event routerEvent = (Event)routerEventReference; + routerEvent.Invoke(sender, entityDataPacket!); } } private static void RoutePacket( Dictionary> packetRouters, string entityId, - string senderClientId, + IConnection sender, T entityDataPacket) { if (!packetRouters.TryGetValue(entityDataPacket!.GetType(), out Dictionary? routers)) @@ -125,8 +125,8 @@ public class NetworkManager : Behaviour, INetworkManager if (!routers.TryGetValue(entityId, out object? routerEventReference)) return; - Event routerEvent = (Event)routerEventReference; - routerEvent.Invoke(senderClientId, entityDataPacket!); + Event routerEvent = (Event)routerEventReference; + routerEvent.Invoke(sender, entityDataPacket!); } #endregion @@ -156,7 +156,7 @@ public class NetworkManager : Behaviour, INetworkManager private object CreateEventAndRegister(Type packetType, INetworkEntity behaviour, NetworkType networkType) { - Type genericEventType = typeof(Event<,>).MakeGenericType(typeof(string), packetType); + Type genericEventType = typeof(Event<,>).MakeGenericType(typeof(IConnection), packetType); object packetListenerEvent = Activator.CreateInstance(genericEventType)!; if (!registerPacketListenersMethods.TryGetValue(packetType, out MethodInfo? registerPacketListenerMethod)) @@ -168,12 +168,12 @@ public class NetworkManager : Behaviour, INetworkManager private static void RegisterPacketListenerEvent( INetworkEntity behaviour, - Event packetListenerEvent, + Event packetListenerEvent, NetworkType networkType) { switch (networkType) { - case NetworkType.Client: packetListenerEvent.AddListener((sender, packet) => ((IPacketListenerClient)behaviour).OnClientPacketArrived(packet)); break; + case NetworkType.Client: packetListenerEvent.AddListener((sender, packet) => ((IPacketListenerClient)behaviour).OnClientPacketArrived(sender, packet)); break; case NetworkType.Server: packetListenerEvent.AddListener((sender, packet) => ((IPacketListenerServer)behaviour).OnServerPacketArrived(sender, packet)); break; } } @@ -203,7 +203,7 @@ public class NetworkManager : Behaviour, INetworkManager private static void ClearRouter(object routerEventReference) { - Event routerEvent = (Event)routerEventReference; + Event routerEvent = (Event)routerEventReference; routerEvent.Clear(); } @@ -262,7 +262,7 @@ public class NetworkManager : Behaviour, INetworkManager { MethodInfo genericOnPacketArrivedMethod = onPacketArrivedMethod.MakeGenericMethod(packetType); - Type genericDelegateType = typeof(Event<,>.EventHandler).MakeGenericType(typeof(string), packetType); + Type genericDelegateType = typeof(Event<,>.EventHandler).MakeGenericType(typeof(IConnection), packetType); Delegate genericPacketReceivedDelegate = Delegate.CreateDelegate(genericDelegateType, this, genericOnPacketArrivedMethod); packetRetrievalDelegates.Add((packetType, genericPacketReceivedDelegate));