Test
This commit is contained in:
parent
73ae55e1d4
commit
91d301677f
|
@ -21,6 +21,7 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Apos.Shapes" Version="0.2.3" />
|
<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.Framework.DesktopGL" Version="3.8.1.303" />
|
||||||
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
<PackageReference Include="MonoGame.Content.Builder.Task" Version="3.8.1.303" />
|
||||||
</ItemGroup>
|
</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