Test
This commit is contained in:
		| @@ -1,13 +1,15 @@ | ||||
| using System; | ||||
|  | ||||
| using LiteNetLib.Utils; | ||||
| using Microsoft.Xna.Framework.Input; | ||||
|  | ||||
| using Syntriax.Engine.Core; | ||||
| using Syntriax.Engine.Input; | ||||
| using Syntriax.Engine.Network; | ||||
| using Syntriax.Engine.Network.Abstract; | ||||
|  | ||||
| namespace Pong.Behaviours; | ||||
|  | ||||
| public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Speed) : BehaviourOverride | ||||
| public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Speed) : NetworkBehaviour | ||||
| { | ||||
|     private Keys Up { get; } = Up; | ||||
|     private Keys Down { get; } = Down; | ||||
| @@ -26,10 +28,14 @@ public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Sp | ||||
|             return; | ||||
|  | ||||
|         if (isUpPressed) | ||||
|             GameObject.Transform.Position = GameObject.Transform.Position + Vector2D.Up * (float)Time.Elapsed.TotalSeconds * Speed; | ||||
|             Move(Vector2D.Up); | ||||
|         else if (isDownPressed) | ||||
|             GameObject.Transform.Position = GameObject.Transform.Position + -Vector2D.Up * (float)Time.Elapsed.TotalSeconds * Speed; | ||||
|             Move(-Vector2D.Up); | ||||
|     } | ||||
|  | ||||
|     private void Move(Vector2D vectorToMove) | ||||
|     { | ||||
|         GameObject.Transform.Position = GameObject.Transform.Position + vectorToMove * (float)Time.Elapsed.TotalSeconds * Speed; | ||||
|         GameObject.Transform.Position = new Vector2D(GameObject.Transform.Position.X, MathF.Max(MathF.Min(GameObject.Transform.Position.Y, High), Low)); | ||||
|     } | ||||
|  | ||||
| @@ -54,8 +60,35 @@ public class PaddleBehaviour(Keys Up, Keys Down, float High, float Low, float Sp | ||||
|         inputs.UnregisterOnRelease(Down, OnDownReleased); | ||||
|     } | ||||
|  | ||||
|     private void OnUpPressed(IButtonInputs<Keys> inputs, Keys keys) => isUpPressed = true; | ||||
|     private void OnUpReleased(IButtonInputs<Keys> inputs, Keys keys) => isUpPressed = false; | ||||
|     private void OnDownPressed(IButtonInputs<Keys> inputs, Keys keys) => isDownPressed = true; | ||||
|     private void OnDownReleased(IButtonInputs<Keys> inputs, Keys keys) => isDownPressed = false; | ||||
|     private void OnUpPressed(IButtonInputs<Keys> inputs, Keys keys) { isUpPressed = true; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed }); } | ||||
|     private void OnUpReleased(IButtonInputs<Keys> inputs, Keys keys) { isUpPressed = false; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed }); } | ||||
|     private void OnDownPressed(IButtonInputs<Keys> inputs, Keys keys) { isDownPressed = true; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed }); } | ||||
|     private void OnDownReleased(IButtonInputs<Keys> inputs, Keys keys) { isDownPressed = false; SendData(new PaddleInputs() { IsUpPressed = isUpPressed, IsDownPressed = isDownPressed }); } | ||||
|  | ||||
|     public override void ReceiveData<T>(T data) | ||||
|     { | ||||
|         if (data is PaddleInputs paddleInputs) | ||||
|         { | ||||
|             System.Diagnostics.Debug.WriteLine($"Paddle Inputs Arrived: {paddleInputs.IsUpPressed}, {paddleInputs.IsDownPressed}"); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     [System.Serializable] | ||||
|     public struct PaddleInputs : INetworkPacket | ||||
|     { | ||||
|         public bool IsUpPressed { get; set; } | ||||
|         public bool IsDownPressed { get; set; } | ||||
|  | ||||
|         public void Deserialize(NetDataReader reader) | ||||
|         { | ||||
|             IsUpPressed = reader.GetBool(); | ||||
|             IsDownPressed = reader.GetBool(); | ||||
|         } | ||||
|  | ||||
|         public void Serialize(NetDataWriter writer) | ||||
|         { | ||||
|             writer.Put(IsUpPressed); | ||||
|             writer.Put(IsDownPressed); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -4,9 +4,15 @@ namespace Syntriax.Engine.Network.Abstract; | ||||
|  | ||||
| public interface INetworkCommunicator | ||||
| { | ||||
|     event OnPacketReceivedDelegate? OnPacketReceived; | ||||
|  | ||||
|     EventBasedNetListener Listener { get; } | ||||
|     NetManager Manager { get; } | ||||
|  | ||||
|     void PollEvents(); | ||||
|     void Stop(); | ||||
|  | ||||
|     void Send<T>(NetworkPacket<T> Data); | ||||
|  | ||||
|     delegate void OnPacketReceivedDelegate(INetworkCommunicator sender, object packet); | ||||
| } | ||||
|   | ||||
| @@ -6,5 +6,7 @@ public interface INetworkEntity | ||||
|  | ||||
|     uint NetworkId { get; set; } | ||||
|  | ||||
|     void ReceiveData<T>(T data); | ||||
|  | ||||
|     delegate void OnNetworkIdChangedDelegate(INetworkEntity sender, uint previousId); | ||||
| } | ||||
|   | ||||
							
								
								
									
										5
									
								
								Game/Network/Abstract/INetworkPacket.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								Game/Network/Abstract/INetworkPacket.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| using LiteNetLib.Utils; | ||||
|  | ||||
| namespace Syntriax.Engine.Network.Abstract; | ||||
|  | ||||
| public interface INetworkPacket : INetSerializable; | ||||
| @@ -1,6 +1,7 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
| using System.Linq; | ||||
| using System.Reflection; | ||||
| using LiteNetLib; | ||||
| using LiteNetLib.Utils; | ||||
|  | ||||
| @@ -11,11 +12,13 @@ namespace Syntriax.Engine.Network; | ||||
|  | ||||
| public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator | ||||
| { | ||||
|     private readonly NetPacketProcessor netPacketProcessor = new(); | ||||
|     public event INetworkCommunicator.OnPacketReceivedDelegate? OnPacketReceived = null; | ||||
|  | ||||
|     private readonly Dictionary<uint, INetworkEntity> networkEntities = []; | ||||
|     protected readonly NetPacketProcessor netPacketProcessor = new(); | ||||
|  | ||||
|     private BehaviourCollector<INetworkEntity> networkEntityCollector = null!; | ||||
|     protected readonly Dictionary<uint, INetworkEntity> networkEntities = []; | ||||
|  | ||||
|     protected BehaviourCollector<INetworkEntity> networkEntityCollector = null!; | ||||
|  | ||||
|     public EventBasedNetListener Listener { get; private set; } = null!; | ||||
|     public NetManager Manager { get; private set; } = null!; | ||||
| @@ -28,12 +31,80 @@ public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator | ||||
|         Manager = new NetManager(Listener); | ||||
|  | ||||
|         Listener.NetworkReceiveEvent += NetworkReceiveEvent; | ||||
|         netPacketProcessor.SubscribeReusable<NetworkPacket<int>, NetPeer>(OnPacketArrived); | ||||
|  | ||||
|         netPacketProcessor.RegisterNestedType<Pong.Behaviours.PaddleBehaviour.PaddleInputs>(); | ||||
|         RegisterPackets(); | ||||
|     } | ||||
|  | ||||
|     private void OnPacketArrived(NetworkPacket<int> packet, NetPeer peer) | ||||
|     public void RegisterPackets() | ||||
|     { | ||||
|         Debug.WriteLine($"Packet Arrived for {packet.NetworkId}: {packet.Data}"); | ||||
|         var packetTypes = Assembly.GetExecutingAssembly().GetTypes() | ||||
|             .Where(t => typeof(INetworkPacket).IsAssignableFrom(t) && !t.IsInterface) | ||||
|             .ToList(); | ||||
|  | ||||
|         // MethodInfo subscribeMethod = netPacketProcessor.GetType() | ||||
|         //     .GetMethod(nameof(NetPacketProcessor.SubscribeReusable), [typeof(Action<,>)]); | ||||
|  | ||||
|         MethodInfo[] subscribeMethods = netPacketProcessor.GetType() | ||||
|             .GetMethods() | ||||
|             .Where(m => m.Name == nameof(NetPacketProcessor.SubscribeReusable)) | ||||
|             .ToArray(); | ||||
|  | ||||
|         MethodInfo subscribeMethod = subscribeMethods | ||||
|             .FirstOrDefault(m => m.GetParameters().Length == 1 && | ||||
|                                  m.GetParameters()[0].ParameterType.GetGenericTypeDefinition() == typeof(Action<,>)); | ||||
|  | ||||
|         MethodInfo[] methodInfos = typeof(NetworkBase) | ||||
|                                 .GetMethods(BindingFlags.NonPublic | BindingFlags.Instance); | ||||
|         MethodInfo method = methodInfos | ||||
|                         .FirstOrDefault(m => m.Name == "OnPacketArrived" && m.IsGenericMethod); | ||||
|  | ||||
|         // .GetMethod(nameof(OnPacketArrived), BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new Exception(); | ||||
|  | ||||
|         foreach (var packetType in packetTypes) | ||||
|         { | ||||
|             var networkPacketType = typeof(NetworkPacket<>).MakeGenericType(packetType); | ||||
|             MethodInfo genericSubscribe = subscribeMethod.MakeGenericMethod(networkPacketType, typeof(NetPeer)); | ||||
|  | ||||
|             Action<object, NetPeer> handler = (packet, peer) => | ||||
|             { | ||||
|                 method = method.MakeGenericMethod(packetType); | ||||
|                 method.Invoke(this, [packet, peer]); | ||||
|             }; | ||||
|             genericSubscribe.Invoke(netPacketProcessor, [handler]); | ||||
|         } | ||||
|     } | ||||
|     // private void RegisterPackets() | ||||
|     // { | ||||
|     //     IEnumerable<Type> packetTypes = Assembly.GetExecutingAssembly().GetTypes().Where( | ||||
|     //         t => t.GetInterfaces().Contains(typeof(INetworkPacket)) | ||||
|     //     ); | ||||
|  | ||||
|     //     MethodInfo subscribeMethod = netPacketProcessor.GetType() | ||||
|     //         .GetMethod(nameof(NetPacketProcessor.SubscribeReusable), [typeof(Action<,>)]) ?? throw new Exception(); | ||||
|  | ||||
|     //     foreach (var packetType in packetTypes) | ||||
|     //     { | ||||
|     //         MethodInfo genericSubscribe = subscribeMethod.MakeGenericMethod(packetType, typeof(NetPeer)); | ||||
|     //         Action<object, NetPeer> handler = (packet, peer) => | ||||
|     //         { | ||||
|     //             MethodInfo method = GetType() | ||||
|     //                 .GetMethod(nameof(OnPacketArrived), BindingFlags.NonPublic | BindingFlags.Instance) ?? throw new Exception(); | ||||
|     //             method = method.MakeGenericMethod(packetType.GetGenericArguments()[0]); | ||||
|     //             method.Invoke(this, [packet, peer]); | ||||
|     //         }; | ||||
|     //         genericSubscribe.Invoke(netPacketProcessor, [handler]); | ||||
|     //     } | ||||
|     // } | ||||
|  | ||||
|     private void OnPacketArrived<T>(NetworkPacket<T> packet, NetPeer peer) where T : INetworkPacket//OnPacketArrived<T>(NetworkPacket<T> packet, NetPeer peer) | ||||
|     { | ||||
|         // Handle packet | ||||
|         Console.WriteLine($"Packet of type {typeof(T)} arrived with data: {packet.Data}"); | ||||
|         if (networkEntities.TryGetValue(packet.NetworkId, out INetworkEntity? entity)) | ||||
|             entity.ReceiveData(packet.Data); | ||||
|  | ||||
|         OnPacketReceived?.Invoke(this, packet); | ||||
|     } | ||||
|  | ||||
|     protected override void OnInitialize() | ||||
| @@ -67,4 +138,6 @@ public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator | ||||
|     public void Stop() => Manager.Stop(); | ||||
|  | ||||
|     protected override void OnUpdate() => PollEvents(); | ||||
|  | ||||
|     public abstract void Send<T>(NetworkPacket<T> packet); | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| using System; | ||||
| using LiteNetLib; | ||||
| using LiteNetLib.Utils; | ||||
|  | ||||
| using Syntriax.Engine.Core; | ||||
| using Syntriax.Engine.Network.Abstract; | ||||
|  | ||||
| @@ -48,4 +47,9 @@ public abstract class NetworkBehaviour : BehaviourOverride, INetworkBehaviour | ||||
|  | ||||
|         IsServer = true; | ||||
|     } | ||||
|  | ||||
|     public void SendData<T>(T data) | ||||
|         => NetworkCommunicator.Send(new NetworkPacket<T>() { NetworkId = _networkId, Data = data }); | ||||
|  | ||||
|     public abstract void ReceiveData<T>(T data); | ||||
| } | ||||
|   | ||||
| @@ -1,14 +1,23 @@ | ||||
| using System.Diagnostics; | ||||
| using System.Threading.Tasks; | ||||
| using LiteNetLib.Utils; | ||||
|  | ||||
| using Syntriax.Engine.Network.Abstract; | ||||
|  | ||||
| namespace Syntriax.Engine.Network; | ||||
|  | ||||
| public class NetworkClient : NetworkBase, INetworkCommunicatorClient | ||||
| { | ||||
|     private readonly NetDataWriter netDataWriter = new(); | ||||
|  | ||||
|     public void Connect(string address, int port, string? password = null) | ||||
|     { | ||||
|         Manager.Start(); | ||||
|         Manager.Connect(address, port, password ?? string.Empty); | ||||
|     } | ||||
|  | ||||
|     public override void Send<T>(NetworkPacket<T> packet) | ||||
|     { | ||||
|         netDataWriter.Reset(); | ||||
|         netPacketProcessor.Write(netDataWriter, packet); | ||||
|         Manager.FirstPeer.Send(netDataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -25,4 +25,6 @@ public class NetworkManager : NetworkBehaviour, INetworkManager | ||||
|  | ||||
|     private void OnCollected(BehaviourCollector<INetworkEntity> collector, INetworkEntity entity) | ||||
|         => entity.NetworkId = networkIdIndex++; | ||||
|  | ||||
|     public override void ReceiveData<T>(T data) { } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System.Diagnostics; | ||||
| using System.Threading.Tasks; | ||||
| using System; | ||||
| using LiteNetLib.Utils; | ||||
|  | ||||
| using Syntriax.Engine.Network.Abstract; | ||||
|  | ||||
| namespace Syntriax.Engine.Network; | ||||
| @@ -10,15 +11,23 @@ public class NetworkServer : NetworkBase, INetworkCommunicatorServer | ||||
|     public int MaxConnectionCount { get; private set; } = 0; | ||||
|     public int Port { get; private set; } = 8888; | ||||
|  | ||||
|     public NetworkServer() : base() | ||||
|     private readonly NetDataWriter netDataWriter = new(); | ||||
|  | ||||
|     public NetworkServer() : this(8888, 0) { } | ||||
|     public NetworkServer(int port, int maxConnectionCount) : base() | ||||
|     { | ||||
|         MaxConnectionCount = maxConnectionCount; | ||||
|         Port = port; | ||||
|  | ||||
|         Listener.ConnectionRequestEvent += request => | ||||
|         { | ||||
|             if (Manager.ConnectedPeersCount < MaxConnectionCount) | ||||
|             if (Manager.ConnectedPeersCount < maxConnectionCount) | ||||
|                 request.AcceptIfKey(Password); | ||||
|             else | ||||
|                 request.Reject(); | ||||
|         }; | ||||
|  | ||||
|         OnPacketReceived += ServerOnPacketReceived; | ||||
|     } | ||||
|  | ||||
|     public void Start(int port, int maxConnectionCount, string? password = null) | ||||
| @@ -29,4 +38,14 @@ public class NetworkServer : NetworkBase, INetworkCommunicatorServer | ||||
|  | ||||
|         Manager.Start(port); | ||||
|     } | ||||
|  | ||||
|     public override void Send<T>(NetworkPacket<T> packet) | ||||
|     { | ||||
|         netDataWriter.Reset(); | ||||
|         netPacketProcessor.Write(netDataWriter, packet); | ||||
|         Manager.SendToAll(netDataWriter, LiteNetLib.DeliveryMethod.ReliableOrdered); | ||||
|     } | ||||
|  | ||||
|     private void ServerOnPacketReceived(INetworkCommunicator sender, object packet) | ||||
|         => Send((NetworkPacket<object>)packet); | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user