using System.Collections.Generic; using System; using System.Text; namespace NeonTea.Quakeball.Net.Packets { public abstract class Packet { public int id; public abstract void Write(ByteBuffer buffer); public abstract void Read(ByteBuffer buffer); } public enum PacketStage { Establishing = 0, Rejected = 1, Closed = 2, Ready = 3, } public enum ClosingReason { Unknown = 0, } 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 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 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; } return reason; } } }