141 lines
4.8 KiB
C#
141 lines
4.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using LiteNetLib;
|
|
using LiteNetLib.Utils;
|
|
|
|
using Syntriax.Engine.Core;
|
|
using Syntriax.Engine.Network.Abstract;
|
|
|
|
namespace Syntriax.Engine.Network;
|
|
|
|
public abstract class NetworkBase : BehaviourOverride, INetworkCommunicator
|
|
{
|
|
public event INetworkCommunicator.OnPacketReceivedDelegate? OnPacketReceived = null;
|
|
|
|
protected readonly NetPacketProcessor netPacketProcessor = new();
|
|
|
|
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!;
|
|
|
|
public NetworkBase()
|
|
{
|
|
Priority = 10;
|
|
|
|
Listener = new EventBasedNetListener();
|
|
Manager = new NetManager(Listener);
|
|
|
|
Listener.NetworkReceiveEvent += NetworkReceiveEvent;
|
|
|
|
netPacketProcessor.RegisterNestedType<Pong.Behaviours.PaddleBehaviour.PaddleInputs>();
|
|
RegisterPackets();
|
|
}
|
|
|
|
public void RegisterPackets()
|
|
{
|
|
var packetTypes = Assembly.GetExecutingAssembly().GetTypes()
|
|
.Where(t => typeof(INetworkPacket).IsAssignableFrom(t) && !t.IsInterface)
|
|
.ToList();
|
|
|
|
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<,>)
|
|
) ?? throw new Exception();
|
|
|
|
MethodInfo[] methodInfos = typeof(NetworkBase)
|
|
.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
|
|
|
|
MethodInfo method = methodInfos
|
|
.FirstOrDefault(
|
|
m => m.Name == nameof(OnPacketArrived) &&
|
|
m.IsGenericMethodDefinition
|
|
) ?? 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) =>
|
|
{
|
|
MethodInfo handlerMethod = method.MakeGenericMethod(packetType);
|
|
handlerMethod.Invoke(this, [packet, peer]);
|
|
};
|
|
genericSubscribe.Invoke(netPacketProcessor, [handler]);
|
|
}
|
|
}
|
|
|
|
private void OnPacketArrived<T>(NetworkPacket<T> packet, NetPeer peer) where T : INetworkPacket
|
|
{
|
|
if (networkEntities.TryGetValue(packet.NetworkId, out INetworkEntity? entity))
|
|
entity.ReceiveData(packet.Data);
|
|
|
|
OnPacketReceived?.Invoke(this, packet);
|
|
}
|
|
|
|
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)
|
|
{
|
|
if (behaviourCollected.NetworkId != 0)
|
|
networkEntities.Add(behaviourCollected.NetworkId, behaviourCollected);
|
|
|
|
behaviourCollected.OnNetworkIdChanged += OnNetworkIdChanged;
|
|
}
|
|
|
|
private void OnNetworkIdChanged(INetworkEntity sender, uint previousId)
|
|
{
|
|
if (networkEntities.TryGetValue(previousId, out INetworkEntity? networkEntity) && sender == networkEntity)
|
|
networkEntities.Remove(previousId);
|
|
|
|
networkEntities.Add(sender.NetworkId, sender);
|
|
}
|
|
|
|
private void OnNetworkEntityRemoved(BehaviourCollector<INetworkEntity> sender, INetworkEntity behaviourRemoved)
|
|
{
|
|
networkEntities.Remove(behaviourRemoved.NetworkId);
|
|
behaviourRemoved.OnNetworkIdChanged -= OnNetworkIdChanged;
|
|
}
|
|
|
|
private void NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
|
|
{
|
|
try
|
|
{
|
|
netPacketProcessor.ReadAllPackets(reader, peer);
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
public void PollEvents() => Manager.PollEvents();
|
|
public void Stop() => Manager.Stop();
|
|
|
|
protected override void OnUpdate() => PollEvents();
|
|
|
|
public abstract void Send<T>(NetworkPacket<T> packet);
|
|
}
|