quakeball/Assets/Scripts/TeaNet/Packets/Packet.cs

155 lines
3.9 KiB
C#

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<byte> Bytes;
private int pos = 0;
public ByteBuffer() {
Bytes = new List<byte>();
}
public ByteBuffer(byte[] bytes) {
Bytes = new List<byte>(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;
}
}
}