2022-12-29 10:23:24 +00:00
|
|
|
|
using System.Collections.Immutable;
|
|
|
|
|
using System.Reflection;
|
|
|
|
|
|
|
|
|
|
namespace Server.Packets;
|
|
|
|
|
|
|
|
|
|
public class PacketForwardingService
|
|
|
|
|
{
|
|
|
|
|
private ImmutableDictionary<PacketId, System.Reflection.ConstructorInfo> _packets = null!;
|
|
|
|
|
|
|
|
|
|
public PacketForwardingService()
|
|
|
|
|
{
|
|
|
|
|
InitializePackets(typeof(IPacket).Assembly);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void InitializePackets(Assembly assembly)
|
|
|
|
|
{
|
|
|
|
|
// Get all types that implement IPacket and have a PacketIdAttribute
|
|
|
|
|
_packets = assembly.GetTypes()
|
|
|
|
|
.Select(x => (attr: x.GetCustomAttribute<PacketIdAttribute>(), ctor: x.GetConstructor(Type.EmptyTypes)))
|
2022-12-29 12:54:17 +00:00
|
|
|
|
.Where(x => x.GetType().IsAssignableTo(typeof(IPacket)) && x.GetType().IsClass)
|
|
|
|
|
.Where(x => x.attr != null && x.ctor != null)
|
2022-12-29 10:23:24 +00:00
|
|
|
|
.ToImmutableDictionary(x => x.attr!.PacketId, x => x.ctor)!;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IPacket Dispatch(Span<Byte> bytes)
|
|
|
|
|
{
|
|
|
|
|
// Get constructor according to packet id
|
|
|
|
|
IPacket packet = _packets[GetPacketId(bytes)].Invoke(Array.Empty<object>()) as IPacket ??
|
|
|
|
|
throw new InvalidOperationException();
|
|
|
|
|
// Slice off packet id
|
|
|
|
|
packet.Deserialize(bytes.Slice(2));
|
|
|
|
|
return packet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private PacketId GetPacketId(Span<Byte> bytes)
|
|
|
|
|
{
|
2022-12-31 16:46:33 +00:00
|
|
|
|
var id = (PacketId)BitConverter.ToUInt16(new[] { bytes[0], bytes[1] });
|
2022-12-29 10:23:24 +00:00
|
|
|
|
return id;
|
|
|
|
|
}
|
|
|
|
|
}
|