using System.Collections.Generic; using System; using NeonTea.Quakeball.TeaNet.Peers; namespace NeonTea.Quakeball.TeaNet.Packets { /// Manages a single form of conversation between clients for the Peer. Don't forget to register your packets with public abstract class Protocol { private Dictionary PacketToId = new Dictionary(); private Dictionary IdToPacket = new Dictionary(); private int PacketIdCounter; /// Refers to the peer it is registered to public Peer Peer; /// Unique identifier for the protocol. This should be different for every protocol. public abstract byte Identifier { get; } /// Version of the protocol, should be changed if existing packets are changed, new packets are registered or old packets are removed. public abstract string Version { get; } /// Called when the Peer receives a packet from a connection that uses this protocol public abstract void Receive(Connection conn, Packet packet); /// Called when a ConnectionStatus is changed for a connection that uses this protocol public abstract void ConnectionStatusChanged(ConnectionStatus oldStatus, ConnectionStatus newStatus, Connection conn); /// Called when a connection that uses this protocol is timed out suddenly. public abstract void Timeout(Connection conn); /// Register a packet for sending and receiving. public int RegisterPacket(Type t) { if (t.BaseType != typeof(Packet) || PacketToId.ContainsKey(t)) { return -1; } int id = PacketIdCounter++; PacketToId.Add(t, id); IdToPacket.Add(id, t); return id; } public ByteBuffer BuildMessage(Connection connection, int firstId, bool reliable) { ByteBuffer buffer = new ByteBuffer(); foreach (byte b in Peer.Fingerprint) { buffer.Write(b); } buffer.Write(Identifier); if (connection.Status == ConnectionStatus.Establishing) { buffer.Write((byte)PacketStage.Establishing); buffer.Write(Version); } else if (connection.Status == ConnectionStatus.Closed) { buffer.Write((byte)PacketStage.Closed); } else if (connection.Status == ConnectionStatus.Rejected) { buffer.Write((byte)PacketStage.Rejected); buffer.Write((byte)connection.ClosingReason); } else if (connection.Status == ConnectionStatus.Ready) { buffer.Write((byte)PacketStage.Ready); buffer.Write(connection.Internal.LatestInwardReliable); buffer.Write(firstId); buffer.Write(reliable); } return buffer; } public int GetPacketTypeID(Packet packet) { return PacketToId[packet.GetType()]; } public Type GetPacketType(int id) { return IdToPacket[id]; } } }