using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq.Expressions; using TrueCraft.API.Networking; using TrueCraft.Core.Networking.Packets; namespace TrueCraft.Core.Networking { public class PacketReader : IPacketReader { public static readonly int Version = 14; public int ProtocolVersion { get { return Version; } } internal Func[] ClientboundPackets = new Func[0x100]; internal Func[] ServerboundPackets = new Func[0x100]; public ConcurrentDictionary Processors { get; private set; } private static readonly byte[] EmptyBuffer = new byte[0]; public PacketReader() { Processors = new ConcurrentDictionary(); } /// /// Registers TrueCraft.Core implementations of all packets used by vanilla Minecraft. /// public void RegisterCorePackets() { RegisterPacketType(); // 0x00 RegisterPacketType(serverbound: true, clientbound: false); // 0x01 RegisterPacketType(serverbound: false, clientbound: true); // 0x01 RegisterPacketType(serverbound: true, clientbound: false); // 0x02 RegisterPacketType(serverbound: false, clientbound: true); // 0x02 RegisterPacketType(); // 0x03 RegisterPacketType(serverbound: false, clientbound: true); // 0x04 RegisterPacketType(serverbound: false, clientbound: true); // 0x05 // NOTE: serverbound not confirmed RegisterPacketType(serverbound: false, clientbound: true); // 0x06 RegisterPacketType(serverbound: true, clientbound: false); // 0x07 RegisterPacketType(serverbound: false, clientbound: true); // 0x08 RegisterPacketType(); // 0x09 RegisterPacketType(serverbound: true, clientbound: false); // 0x0A RegisterPacketType(serverbound: true, clientbound: false); // 0x0B RegisterPacketType(serverbound: true, clientbound: false); // 0x0C RegisterPacketType(serverbound: true, clientbound: false); // 0x0D RegisterPacketType(serverbound: false, clientbound: true); // 0x0D RegisterPacketType(serverbound: true, clientbound: false); // 0x0E RegisterPacketType(serverbound: true, clientbound: false); // 0x0F RegisterPacketType(serverbound: true, clientbound: false); // 0x10 RegisterPacketType(serverbound: false, clientbound: true); // 0x11 RegisterPacketType(); // 0x12 RegisterPacketType(serverbound: true, clientbound: false); // 0x13 RegisterPacketType(serverbound: false, clientbound: true); // 0x14 RegisterPacketType(serverbound: true, clientbound: true); // 0x15 RegisterPacketType(serverbound: false, clientbound: true); // 0x16 RegisterPacketType(serverbound: false, clientbound: true); // 0x17 RegisterPacketType(serverbound: false, clientbound: true); // 0x18 RegisterPacketType(serverbound: false, clientbound: true); // 0x19 RegisterPacketType(serverbound: false, clientbound: true); // 0x1C RegisterPacketType(serverbound: false, clientbound: true); // 0x1D RegisterPacketType(serverbound: false, clientbound: true); // 0x1E RegisterPacketType(serverbound: false, clientbound: true); // 0x1F RegisterPacketType(serverbound: false, clientbound: true); // 0x20 RegisterPacketType(serverbound: false, clientbound: true); // 0x21 RegisterPacketType(serverbound: false, clientbound: true); // 0x22 RegisterPacketType(serverbound: false, clientbound: true); // 0x26 RegisterPacketType(serverbound: false, clientbound: true); // 0x27 RegisterPacketType(serverbound: false, clientbound: true); // 0x28 RegisterPacketType(serverbound: false, clientbound: true); // 0x32 RegisterPacketType(serverbound: false, clientbound: true); // 0x33 RegisterPacketType(serverbound: false, clientbound: true); // 0x34 RegisterPacketType(serverbound: false, clientbound: true); // 0x35 RegisterPacketType(serverbound: false, clientbound: true); // 0x36 RegisterPacketType(serverbound: false, clientbound: true); // 0x3C RegisterPacketType(serverbound: false, clientbound: true); // 0x3D RegisterPacketType(serverbound: false, clientbound: true); // 0x46 RegisterPacketType(serverbound: false, clientbound: true); // 0x47 RegisterPacketType(serverbound: false, clientbound: true); // 0x64 RegisterPacketType(); // 0x65 RegisterPacketType(serverbound: true, clientbound: false); // 0x66 RegisterPacketType(serverbound: false, clientbound: true); // 0x67 RegisterPacketType(serverbound: false, clientbound: true); // 0x68 RegisterPacketType(serverbound: false, clientbound: true); // 0x69 RegisterPacketType(serverbound: false, clientbound: true); // 0x6A RegisterPacketType(); // 0x82 RegisterPacketType(serverbound: false, clientbound: true); // 0x83 RegisterPacketType(serverbound: false, clientbound: true); // 0xC8 RegisterPacketType(); // 0xFF } public void RegisterPacketType(bool clientbound = true, bool serverbound = true) where T : IPacket { var func = Expression.Lambda>(Expression.Convert(Expression.New(typeof(T)), typeof(IPacket))).Compile(); var packet = func(); if (clientbound) ClientboundPackets[packet.ID] = func; if (serverbound) ServerboundPackets[packet.ID] = func; } public IEnumerable ReadPackets(object key, byte[] buffer, int offset, int length, bool serverbound = true) { if (!Processors.ContainsKey(key)) Processors[key] = new PacketSegmentProcessor(this, serverbound); IPacketSegmentProcessor processor = Processors[key]; IPacket packet; processor.ProcessNextSegment(buffer, offset, length, out packet); if (packet == null) yield break; while (true) { yield return packet; if (!processor.ProcessNextSegment(EmptyBuffer, 0, 0, out packet)) { if (packet != null) { yield return packet; } yield break; } } } public void WritePacket(IMinecraftStream stream, IPacket packet) { stream.WriteUInt8(packet.ID); packet.WritePacket(stream); stream.BaseStream.Flush(); } } }