using System.Collections.Generic; using System; using System.Text; namespace NeonTea.Quakeball.TeaNet.Packets { public abstract class Packet { public bool Reliable = true; public int Id; public abstract void Write(ByteBuffer buffer); public abstract void Read(ByteBuffer buffer); public void ReadMeta(ByteBuffer buffer) { Id = buffer.ReadInt(); Reliable = buffer.ReadBool(); } public void WriteMeta(ByteBuffer buffer) { buffer.WriteInt(Id); buffer.WriteBool(Reliable); } } public enum PacketStage { Establishing = 0, Rejected = 1, Closed = 2, Ready = 3, } public enum ClosingReason { Unknown = 0, IncorrectVersion = 1, } public class ByteBuffer { private List Bytes; private int pos = 0; public ByteBuffer() { Bytes = new List(); } public ByteBuffer(byte[] bytes) { Bytes = new List(bytes); } public byte[] Pack() { return Bytes.ToArray(); } public bool CanRead() { return pos < Bytes.Count; } public bool ReadBool() { return Read() == 1; } public int ReadInt() { return BitConverter.ToInt32(Read(4), 0); } public string ReadString() { int length = ReadInt(); string s = Encoding.UTF8.GetString(Read(length)); return s; } public byte[] Read(int amount) { byte[] bytes = Bytes.GetRange(pos, amount).ToArray(); pos += amount; return bytes; } public byte Read() { return Bytes[pos++]; } public void WriteBool(bool b) { Write(b ? (byte)0b1 : (byte)0b0); } public void WriteInt(int i) { Bytes.AddRange(BitConverter.GetBytes(i)); } public void WriteString(string s) { byte[] bytes = Encoding.UTF8.GetBytes(s); WriteInt(bytes.Length); Bytes.AddRange(bytes); } public void Write(byte b) { Bytes.Add(b); } public bool ReadFingerprint(byte[] fingerprint) { foreach (byte b in fingerprint) { if (!(CanRead() && Read() == b)) { return false; } } return true; } public PacketStage ReadStage() { PacketStage stage = PacketStage.Closed; switch (Read()) { case 0: stage = PacketStage.Establishing; break; case 1: stage = PacketStage.Rejected; break; case 2: stage = PacketStage.Closed; break; case 3: stage = PacketStage.Ready; break; } return stage; } public ClosingReason ReadClosingReason() { ClosingReason reason = ClosingReason.Unknown; switch (Read()) { case 0: reason = ClosingReason.Unknown; break; case 1: reason = ClosingReason.IncorrectVersion; break; } return reason; } public void WritePacket(Protocol protocol, Packet p) { WriteInt(protocol.GetPacketTypeID(p)); p.WriteMeta(this); p.Write(this); } public Packet ReadPacket(Protocol protocol) { int packetType = ReadInt(); Type t = protocol.GetPacketType(packetType); Packet p = (Packet)Activator.CreateInstance(t); p.ReadMeta(this); p.Read(this); return p; } } }