Files
Articulate-Network/Managers/PacketManager.cs

181 lines
5.8 KiB
C#

using Articulate_Network.Attributes;
using Articulate_Network.Interfaces;
using Articulate_Network.Packets;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Articulate_Network.Managers
{
public class PacketManager : IManager
{
Dictionary<Type, List<PropertyInfo>> packetInfo = new Dictionary<Type, List<PropertyInfo>>();
Dictionary<string, Packet> packetInstances = new Dictionary<string, Packet>();
public void Initialize()
{
var @interface = typeof(IPacket);
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
var packetsFound = assembly.GetTypes().Where(t => @interface.IsAssignableFrom(t) && !t.IsAbstract);
foreach (var p in packetsFound)
{
var packet = (Packet)Activator.CreateInstance(p);
packetInstances.Add(p.Name, packet);
LoadPacketInfo(packet);
}
}
Console.WriteLine($"Registered {packetInstances.Count} packet{(packetInstances.Count == 1 ? "" : "s")}");
}
public void LoadPacketInfo(IPacket packet)
{
packetInfo.Add(packet.GetType(), packet.GetType().GetProperties().Where(f => !Attribute.IsDefined(f, typeof(PacketIgnore))).OrderBy(f => f.Name).ToList());
}
public void Send(Packet packet)
{
Stopwatch watch = new Stopwatch();
watch.Start();
if (!packetInfo.ContainsKey(packet.GetType()))
LoadPacketInfo(packet);
watch.Stop();
Console.WriteLine($"Reflection time: {watch.ElapsedTicks / 10} microseconds");
//send packet
var serialized = SerializePacket(packet);
//var deserialized = DeserializePacket<T>(serialized);
//return (T)deserialized;
}
public byte[] SerializePacket(Packet packet)
{
if (!packetInfo.ContainsKey(packet.GetType()))
LoadPacketInfo(packet);
Stopwatch watch = new Stopwatch();
watch.Start();
var fields = packetInfo[packet.GetType()];
MemoryStream buffer = new MemoryStream();
BinaryWriter binaryWriter = new BinaryWriter(buffer);
binaryWriter.Write(packet.GetType().Name);
foreach (var field in fields)
{
if (field.PropertyType == typeof(bool))
binaryWriter.Write((bool)field.GetValue(packet));
if (field.PropertyType == typeof(int))
binaryWriter.Write((int)field.GetValue(packet));
if (field.PropertyType == typeof(long))
binaryWriter.Write((long)field.GetValue(packet));
if (field.PropertyType == typeof(string))
binaryWriter.Write(((string)field.GetValue(packet)) ?? string.Empty);
if (field.PropertyType.IsEnum)
binaryWriter.Write((int)field.GetValue(packet));
if (field.PropertyType == typeof(byte[]))
{
byte[] buf = (byte[])field.GetValue(packet);
binaryWriter.Write(buf.Length);
binaryWriter.Write(buf);
}
//Console.WriteLine(field.Name);
}
long length = buffer.Length;
byte[] packetData = buffer.ToArray();
buffer.SetLength(0);
binaryWriter.Write(length);
binaryWriter.Write(packetData);
binaryWriter.Write(length);
watch.Stop();
//Console.WriteLine($"Serialize time: {watch.ElapsedTicks / 10} microseconds");
return buffer.ToArray();
}
public Packet DeserializePacket(MemoryStream stream)
{
Stopwatch watch = new Stopwatch();
watch.Start();
BinaryReader reader = new BinaryReader(stream);
string typeName = reader.ReadString();
Console.WriteLine(typeName);
Packet packet = packetInstances[typeName];/*(IPacket)Activator.CreateInstance(typeof(T));*/
var fields = packetInfo[packet.GetType()];
//Console.WriteLine($"Stream length: {stream.Length}");
//Console.WriteLine($"Stream position: {stream.Position}");
foreach (var field in fields)
{
if (field.PropertyType == typeof(bool))
field.SetValue(packet, reader.ReadBoolean());
if (field.PropertyType == typeof(int))
field.SetValue(packet, reader.ReadInt32());
if (field.PropertyType == typeof(long))
field.SetValue(packet, reader.ReadInt64());
if (field.PropertyType == typeof(string))
field.SetValue(packet, reader.ReadString());
if (field.PropertyType.IsEnum)
field.SetValue(packet, reader.ReadInt32());
if (field.PropertyType == typeof(byte[]))
{
int length = reader.ReadInt32();
field.SetValue(packet, reader.ReadBytes(length));
}
}
watch.Stop();
//Console.WriteLine($"Deserialize time: {watch.ElapsedTicks / 10} microseconds");
return packet;
}
public Packet DeserializePacket(byte[] bytes)
{
return DeserializePacket(new MemoryStream(bytes));
}
public void HandlePacket(Packet packet)
{
Console.WriteLine(packet.GetType().Name);
}
}
}