Initial commit: Client Doc docs Server Tools
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace XWorld.Framework.Protocol
|
||||
{
|
||||
// 与 PacketWriter 对偶;任何越界/畸形长度抛 FormatException(容错入口统一)
|
||||
public sealed class PacketReader
|
||||
{
|
||||
private readonly byte[] _buf;
|
||||
private int _pos;
|
||||
|
||||
public PacketReader(byte[] data)
|
||||
{
|
||||
_buf = data ?? Array.Empty<byte>();
|
||||
_pos = 0;
|
||||
}
|
||||
|
||||
public int Position => _pos;
|
||||
public bool HasMore => _pos < _buf.Length;
|
||||
|
||||
public byte ReadByte()
|
||||
{
|
||||
if (_pos >= _buf.Length) throw new FormatException("PacketReader: read past end");
|
||||
return _buf[_pos++];
|
||||
}
|
||||
|
||||
public bool ReadBool() => ReadByte() != 0;
|
||||
|
||||
public ushort ReadUInt16()
|
||||
{
|
||||
byte lo = ReadByte();
|
||||
byte hi = ReadByte();
|
||||
return (ushort)(lo | (hi << 8));
|
||||
}
|
||||
|
||||
public uint ReadVarUInt()
|
||||
{
|
||||
uint result = 0;
|
||||
int shift = 0;
|
||||
while (true)
|
||||
{
|
||||
if (shift > 28) throw new FormatException("PacketReader: varuint too long");
|
||||
byte b = ReadByte();
|
||||
// 第 5 字节(shift==28)只有低 4 位有效,超出即为越界 varuint
|
||||
if (shift == 28 && (b & 0x70) != 0)
|
||||
throw new FormatException("PacketReader: varuint overflow");
|
||||
result |= (uint)(b & 0x7F) << shift;
|
||||
if ((b & 0x80) == 0) break;
|
||||
shift += 7;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public int ReadVarInt()
|
||||
{
|
||||
uint zig = ReadVarUInt();
|
||||
return (int)(zig >> 1) ^ -(int)(zig & 1); // zigzag decode
|
||||
}
|
||||
|
||||
public long ReadVarLong()
|
||||
{
|
||||
ulong result = 0;
|
||||
int shift = 0;
|
||||
while (true)
|
||||
{
|
||||
if (shift > 63) throw new FormatException("PacketReader: varlong too long");
|
||||
byte b = ReadByte();
|
||||
// 第 10 字节(shift==63)只有最低 1 位有效,超出即为越界 varlong
|
||||
if (shift == 63 && (b & 0x7E) != 0)
|
||||
throw new FormatException("PacketReader: varlong overflow");
|
||||
result |= (ulong)(b & 0x7F) << shift;
|
||||
if ((b & 0x80) == 0) break;
|
||||
shift += 7;
|
||||
}
|
||||
return (long)(result >> 1) ^ -(long)(result & 1);
|
||||
}
|
||||
|
||||
public float ReadSingle()
|
||||
{
|
||||
byte[] b = new byte[4];
|
||||
b[0] = ReadByte(); b[1] = ReadByte(); b[2] = ReadByte(); b[3] = ReadByte();
|
||||
if (!BitConverter.IsLittleEndian) Array.Reverse(b);
|
||||
return BitConverter.ToSingle(b, 0);
|
||||
}
|
||||
|
||||
public byte[] ReadBytes()
|
||||
{
|
||||
uint len = ReadVarUInt();
|
||||
if (len == 0) return Array.Empty<byte>();
|
||||
if (_pos + len > _buf.Length) throw new FormatException("PacketReader: bytes length exceeds buffer");
|
||||
byte[] outv = new byte[len];
|
||||
Array.Copy(_buf, _pos, outv, 0, (int)len);
|
||||
_pos += (int)len;
|
||||
return outv;
|
||||
}
|
||||
|
||||
public string ReadString()
|
||||
{
|
||||
uint len = ReadVarUInt();
|
||||
if (len == 0) return string.Empty;
|
||||
if (_pos + len > _buf.Length) throw new FormatException("PacketReader: string length exceeds buffer");
|
||||
string s = Encoding.UTF8.GetString(_buf, _pos, (int)len);
|
||||
_pos += (int)len;
|
||||
return s;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user