| namespace SilkroadBot.Core.Networking; |
|
|
| |
| |
| |
| public class Packet |
| { |
| public ushort Opcode { get; } |
| public byte[] Payload { get; } |
| public bool IsEncrypted { get; } |
| public DateTime Timestamp { get; } |
| public PacketDirection Direction { get; } |
|
|
| public Packet(ushort opcode, byte[] payload, PacketDirection direction, bool isEncrypted = false) |
| { |
| Opcode = opcode; |
| Payload = payload ?? Array.Empty<byte>(); |
| IsEncrypted = isEncrypted; |
| Timestamp = DateTime.UtcNow; |
| Direction = direction; |
| } |
|
|
| |
| public static Packet ToServer(ushort opcode, byte[] payload, bool encrypted = false) |
| => new(opcode, payload, PacketDirection.ClientToServer, encrypted); |
|
|
| |
| public static Packet FromServer(ushort opcode, byte[] payload, bool encrypted = false) |
| => new(opcode, payload, PacketDirection.ServerToClient, encrypted); |
|
|
| public override string ToString() => $"[{Direction}] 0x{Opcode:X4} ({Payload.Length} bytes)"; |
| } |
|
|
| public enum PacketDirection |
| { |
| ClientToServer, |
| ServerToClient |
| } |
|
|
| |
| |
| |
| public class PacketReader |
| { |
| private readonly byte[] _data; |
| private int _position; |
|
|
| public PacketReader(byte[] data) |
| { |
| _data = data; |
| _position = 0; |
| } |
|
|
| public int Remaining => _data.Length - _position; |
| public int Position => _position; |
|
|
| public byte ReadByte() => _data[_position++]; |
| |
| public ushort ReadUInt16() |
| { |
| var value = BitConverter.ToUInt16(_data, _position); |
| _position += 2; |
| return value; |
| } |
| |
| public uint ReadUInt32() |
| { |
| var value = BitConverter.ToUInt32(_data, _position); |
| _position += 4; |
| return value; |
| } |
| |
| public ulong ReadUInt64() |
| { |
| var value = BitConverter.ToUInt64(_data, _position); |
| _position += 8; |
| return value; |
| } |
| |
| public float ReadSingle() |
| { |
| var value = BitConverter.ToSingle(_data, _position); |
| _position += 4; |
| return value; |
| } |
| |
| public string ReadAscii() |
| { |
| ushort length = ReadUInt16(); |
| var text = System.Text.Encoding.ASCII.GetString(_data, _position, length); |
| _position += length; |
| return text; |
| } |
| |
| public string ReadUnicode() |
| { |
| ushort length = ReadUInt16(); |
| var text = System.Text.Encoding.Unicode.GetString(_data, _position, length * 2); |
| _position += length * 2; |
| return text; |
| } |
| |
| public byte[] ReadBytes(int count) |
| { |
| var bytes = new byte[count]; |
| Array.Copy(_data, _position, bytes, 0, count); |
| _position += count; |
| return bytes; |
| } |
| |
| public void Skip(int count) => _position += count; |
| } |
|
|
| |
| |
| |
| public class PacketWriter |
| { |
| private readonly MemoryStream _stream; |
|
|
| public PacketWriter(int initialCapacity = 64) |
| { |
| _stream = new MemoryStream(initialCapacity); |
| } |
|
|
| public PacketWriter WriteByte(byte value) { _stream.WriteByte(value); return this; } |
| |
| public PacketWriter WriteUInt16(ushort value) |
| { |
| _stream.Write(BitConverter.GetBytes(value)); |
| return this; |
| } |
| |
| public PacketWriter WriteUInt32(uint value) |
| { |
| _stream.Write(BitConverter.GetBytes(value)); |
| return this; |
| } |
| |
| public PacketWriter WriteUInt64(ulong value) |
| { |
| _stream.Write(BitConverter.GetBytes(value)); |
| return this; |
| } |
| |
| public PacketWriter WriteSingle(float value) |
| { |
| _stream.Write(BitConverter.GetBytes(value)); |
| return this; |
| } |
| |
| public PacketWriter WriteAscii(string text) |
| { |
| var bytes = System.Text.Encoding.ASCII.GetBytes(text); |
| WriteUInt16((ushort)bytes.Length); |
| _stream.Write(bytes); |
| return this; |
| } |
| |
| public PacketWriter WriteUnicode(string text) |
| { |
| var bytes = System.Text.Encoding.Unicode.GetBytes(text); |
| WriteUInt16((ushort)(bytes.Length / 2)); |
| _stream.Write(bytes); |
| return this; |
| } |
| |
| public PacketWriter WriteBytes(byte[] data) { _stream.Write(data); return this; } |
| |
| public byte[] ToArray() => _stream.ToArray(); |
| } |
|
|