Test
This commit is contained in:
parent
73ae55e1d4
commit
91d301677f
|
@ -21,6 +21,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Apos.Shapes" Version="0.2.3" />
|
||||
<PackageReference Include="LiteNetLib" Version="1.2.0" />
|
||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
|
||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
using Syntriax.Engine.Core.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkBehaviour : IBehaviour, INetworkEntity
|
||||
{
|
||||
bool IsServer { get; }
|
||||
bool IsClient { get; }
|
||||
|
||||
INetworkCommunicator NetworkCommunicator { get; }
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
using LiteNetLib;
|
||||
using LiteNetLib.Utils;
|
||||
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkCommunicator
|
||||
{
|
||||
EventBasedNetListener Listener { get; }
|
||||
NetManager Manager { get; }
|
||||
|
||||
void PollEvents();
|
||||
void Stop();
|
||||
|
||||
void RegisterEntityPacketListener<T>(INetworkEntity networkEntity, EntityPacketReceivedDelegate onPacketReceived) where T : INetSerializable;
|
||||
void UnregisterEntityPacketListener<T>(INetworkEntity networkEntity, EntityPacketReceivedDelegate onPacketReceived) where T : INetSerializable;
|
||||
void SendEntityPacket<T>(INetworkEntity networkEntity, T packet, params NetPeer[] netPeer) where T : INetSerializable;
|
||||
|
||||
delegate void EntityPacketReceivedDelegate(INetworkEntity networkEntity, object packet, NetPeer netPeer);
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkCommunicatorClient : INetworkCommunicator
|
||||
{
|
||||
void Connect(string address, int port, string? password = null);
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkCommunicatorServer : INetworkCommunicator
|
||||
{
|
||||
string Password { get; }
|
||||
int MaxConnectionCount { get; }
|
||||
int Port { get; }
|
||||
|
||||
void Start(int port, int maxConnectionCount, string? password = null);
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using LiteNetLib.Utils;
|
||||
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkEntity
|
||||
{
|
||||
event OnNetworkIdChangedDelegate? OnNetworkIdChanged;
|
||||
|
||||
uint NetworkId { get; set; }
|
||||
|
||||
delegate void OnNetworkIdChangedDelegate(INetworkEntity sender, uint previousId);
|
||||
delegate void PacketReceivedDelegate(INetworkEntity entity, object packet);
|
||||
|
||||
void RegisterPacketListener<T>(PacketReceivedDelegate onPacketReceived) where T : INetSerializable;
|
||||
void UnregisterPacketListener<T>(PacketReceivedDelegate onPacketReceived) where T : INetSerializable;
|
||||
void SendPacket<T>(T packet) where T : INetSerializable;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public interface INetworkManager
|
||||
{
|
||||
// Action<IGameObject>? OnNetworkGameObjectInstantiated { get; set; }
|
||||
|
||||
INetworkCommunicator NetworkCommunicator { get; }
|
||||
|
||||
// Task<T> Instantiate<T>(params object?[]? args) where T : class, IGameObject;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using LiteNetLib.Utils;
|
||||
|
||||
namespace Syntriax.Engine.Network.Abstract;
|
||||
|
||||
public class NetworkPacket<T>()
|
||||
: INetSerializable
|
||||
where T : INetSerializable
|
||||
{
|
||||
public uint NetworkId = 0;
|
||||
public T Data = default!;
|
||||
|
||||
public void Deserialize(NetDataReader reader)
|
||||
{
|
||||
NetworkId = reader.GetUInt();
|
||||
}
|
||||
|
||||
public void Serialize(NetDataWriter writer)
|
||||
{
|
||||
writer.Put(NetworkId);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
using LiteNetLib;
|
||||
using LiteNetLib.Utils;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator
|
||||
{
|
||||
private readonly NetPacketProcessor netPacketProcessor = new();
|
||||
|
||||
private readonly Dictionary<uint, INetworkEntity> networkEntities = [];
|
||||
private readonly Dictionary<Type, List<INetworkCommunicator.EntityPacketReceivedDelegate>> callbacks = [];
|
||||
|
||||
private BehaviourCollector<INetworkEntity> networkEntityCollector = null!;
|
||||
|
||||
public EventBasedNetListener Listener { get; private set; } = null!;
|
||||
public NetManager Manager { get; private set; } = null!;
|
||||
|
||||
public NetworkBase()
|
||||
{
|
||||
Priority = 10;
|
||||
|
||||
Listener = new EventBasedNetListener();
|
||||
Manager = new NetManager(Listener);
|
||||
|
||||
Listener.NetworkReceiveEvent += NetworkReceiveEvent;
|
||||
}
|
||||
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
base.OnInitialize();
|
||||
|
||||
networkEntityCollector = new(GameObject.GameManager);
|
||||
networkEntityCollector.OnCollected += OnNetworkEntityCollected;
|
||||
networkEntityCollector.OnRemoved += OnNetworkEntityRemoved;
|
||||
}
|
||||
protected override void OnFinalize()
|
||||
{
|
||||
networkEntityCollector.OnCollected -= OnNetworkEntityCollected;
|
||||
networkEntityCollector.OnRemoved -= OnNetworkEntityRemoved;
|
||||
Stop();
|
||||
}
|
||||
|
||||
private void OnNetworkEntityCollected(BehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourCollected)
|
||||
=> networkEntities.Add(behaviourCollected.NetworkId, behaviourCollected);
|
||||
|
||||
private void OnNetworkEntityRemoved(BehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourRemoved)
|
||||
=> networkEntities.Remove(behaviourRemoved.NetworkId);
|
||||
|
||||
private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
|
||||
{
|
||||
netPacketProcessor.ReadAllPackets(reader, peer);
|
||||
}
|
||||
|
||||
public void PollEvents() => Manager.PollEvents();
|
||||
public void Stop() => Manager.Stop();
|
||||
|
||||
protected override void OnUpdate() => PollEvents();
|
||||
|
||||
public void RegisterEntityPacketListener<T>(INetworkEntity networkEntity, INetworkCommunicator.EntityPacketReceivedDelegate onPacketReceived) where T : INetSerializable
|
||||
{
|
||||
if (!callbacks.TryGetValue(typeof(T), out var list))
|
||||
{
|
||||
list = [];
|
||||
callbacks.Add(typeof(T), list);
|
||||
netPacketProcessor.SubscribeReusable<NetworkPacket<T>, NetPeer>(OnPacketReceived);
|
||||
}
|
||||
|
||||
if (list.Contains(onPacketReceived))
|
||||
return;
|
||||
|
||||
list.Add(onPacketReceived);
|
||||
}
|
||||
|
||||
public void UnregisterEntityPacketListener<T>(INetworkEntity networkEntity, INetworkCommunicator.EntityPacketReceivedDelegate onPacketReceived) where T : INetSerializable
|
||||
{
|
||||
if (!callbacks.TryGetValue(typeof(T), out var list))
|
||||
return;
|
||||
|
||||
list.Remove(onPacketReceived);
|
||||
}
|
||||
|
||||
public void SendEntityPacket<T>(INetworkEntity networkEntity, T packet, params NetPeer[] netPeers) where T : INetSerializable
|
||||
{
|
||||
NetworkPacket<T> networkPacket = new() { NetworkId = networkEntity.NetworkId, Data = packet };
|
||||
NetDataWriter netDataWriter = new();
|
||||
netPacketProcessor.Write(netDataWriter, networkPacket);
|
||||
foreach (var netPeer in netPeers)
|
||||
netPeer.Send(netDataWriter, DeliveryMethod.ReliableOrdered);
|
||||
}
|
||||
|
||||
private void OnPacketReceived<T>(NetworkPacket<T> packet, NetPeer peer) where T : INetSerializable
|
||||
{
|
||||
Debug.WriteLine($"Packet Received: {packet.NetworkId} - {typeof(T)}");
|
||||
|
||||
if (!callbacks.TryGetValue(typeof(T), out var list))
|
||||
return;
|
||||
|
||||
INetworkEntity networkEntity = networkEntities[packet.NetworkId];
|
||||
foreach (INetworkCommunicator.EntityPacketReceivedDelegate callback in list)
|
||||
callback.Invoke(networkEntity, packet, peer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using LiteNetLib;
|
||||
using LiteNetLib.Utils;
|
||||
using Syntriax.Engine.Core;
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public abstract class NetworkBehaviour : BehaviourOverride, INetworkBehaviour
|
||||
{
|
||||
public event INetworkEntity.OnNetworkIdChangedDelegate? OnNetworkIdChanged = null;
|
||||
|
||||
private uint _networkId = 0;
|
||||
public uint NetworkId
|
||||
{
|
||||
get => _networkId;
|
||||
set
|
||||
{
|
||||
if (!IsServer)
|
||||
return;
|
||||
|
||||
if (value == _networkId)
|
||||
return;
|
||||
|
||||
uint previousNetworkId = _networkId;
|
||||
_networkId = value;
|
||||
OnNetworkIdChanged?.Invoke(this, previousNetworkId);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsServer { get; private set; } = false;
|
||||
public bool IsClient { get; private set; } = false;
|
||||
|
||||
public INetworkCommunicator NetworkCommunicator { get; private set; } = null!;
|
||||
|
||||
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
NetworkCommunicator = BehaviourController.GetBehaviourInParent<INetworkCommunicator>()
|
||||
?? GameObject.GameManager.FindBehaviour<INetworkCommunicator>()
|
||||
?? throw new Exception($"Could not find an {nameof(INetworkCommunicator)}.");
|
||||
|
||||
if (NetworkCommunicator is INetworkCommunicatorClient client)
|
||||
{
|
||||
IsClient = true;
|
||||
return;
|
||||
}
|
||||
|
||||
IsServer = true;
|
||||
}
|
||||
|
||||
public void RegisterPacketListener<T>(INetworkEntity.PacketReceivedDelegate onPacketReceived) where T : INetSerializable
|
||||
|
||||
private void OnEntityPacketReceived(INetworkEntity networkEntity, object packet, NetPeer netPeer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void UnregisterPacketListener<T>(INetworkEntity.PacketReceivedDelegate onPacketReceived) where T : INetSerializable
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void SendPacket<T>(T packet) where T : INetSerializable
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public class NetworkClient : NetworkBase, INetworkCommunicatorClient
|
||||
{
|
||||
public void Connect(string address, int port, string? password = null)
|
||||
{
|
||||
Manager.Start();
|
||||
Manager.Connect(address, port, password ?? string.Empty);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
using LiteNetLib;
|
||||
using LiteNetLib.Utils;
|
||||
|
||||
using Syntriax.Engine.Core;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public static class NetworkExtensions
|
||||
{
|
||||
public static Vector2D GetVector2D(this NetPacketReader reader)
|
||||
=> new(reader.GetFloat(), reader.GetFloat());
|
||||
|
||||
public static void GetVector2D(this NetPacketReader reader, out Vector2D vector2D)
|
||||
=> vector2D = new(reader.GetFloat(), reader.GetFloat());
|
||||
|
||||
public static void Put(this NetDataWriter writer, Vector2D vector)
|
||||
{
|
||||
writer.Put(vector.X);
|
||||
writer.Put(vector.Y);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
using Syntriax.Engine.Core;
|
||||
|
||||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public class NetworkManager : NetworkBehaviour, INetworkManager
|
||||
{
|
||||
private BehaviourCollector<INetworkEntity> entities = null!;
|
||||
|
||||
private static uint networkIdIndex = 0;
|
||||
|
||||
protected override void OnInitialize()
|
||||
{
|
||||
base.OnInitialize();
|
||||
|
||||
NetworkId = networkIdIndex++;
|
||||
|
||||
entities = new(GameObject.GameManager);
|
||||
foreach (var entity in entities)
|
||||
entity.NetworkId = networkIdIndex++;
|
||||
|
||||
entities.OnCollected += OnCollected;
|
||||
}
|
||||
|
||||
private void OnCollected(BehaviourCollector<INetworkEntity> collector, INetworkEntity entity)
|
||||
=> entity.NetworkId = networkIdIndex++;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
using Syntriax.Engine.Network.Abstract;
|
||||
|
||||
namespace Syntriax.Engine.Network;
|
||||
|
||||
public class NetworkServer : NetworkBase, INetworkCommunicatorServer
|
||||
{
|
||||
public string Password { get; private set; } = string.Empty;
|
||||
public int MaxConnectionCount { get; private set; } = 0;
|
||||
public int Port { get; private set; } = 8888;
|
||||
|
||||
public NetworkServer() : base()
|
||||
{
|
||||
Listener.ConnectionRequestEvent += request =>
|
||||
{
|
||||
if (Manager.ConnectedPeersCount < MaxConnectionCount)
|
||||
request.AcceptIfKey(Password);
|
||||
else
|
||||
request.Reject();
|
||||
};
|
||||
}
|
||||
|
||||
public void Start(int port, int maxConnectionCount, string? password = null)
|
||||
{
|
||||
Password = password ?? string.Empty;
|
||||
MaxConnectionCount = maxConnectionCount;
|
||||
Port = port;
|
||||
|
||||
Manager.Start(port);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue