fix(core): Cleans up serialization (#606)
This commit is contained in:
parent
8418d4a7db
commit
cb66bef0e5
7 changed files with 177 additions and 218 deletions
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
|
|
@ -35,14 +34,6 @@ namespace Server
|
|||
return intern ? Utility.Intern(str) : str;
|
||||
}
|
||||
|
||||
public DateTime ReadDateTime() => new(_reader.ReadInt64(), DateTimeKind.Utc);
|
||||
|
||||
public TimeSpan ReadTimeSpan() => new(_reader.ReadInt64());
|
||||
|
||||
public DateTime ReadDeltaTime() => new(_reader.ReadInt64() + DateTime.UtcNow.Ticks, DateTimeKind.Utc);
|
||||
|
||||
public decimal ReadDecimal() => _reader.ReadDecimal();
|
||||
|
||||
public long ReadLong() => _reader.ReadInt64();
|
||||
|
||||
public ulong ReadULong() => _reader.ReadUInt64();
|
||||
|
|
@ -65,43 +56,6 @@ namespace Server
|
|||
|
||||
public bool ReadBool() => _reader.ReadBoolean();
|
||||
|
||||
public int ReadEncodedInt()
|
||||
{
|
||||
int v = 0, shift = 0;
|
||||
byte b;
|
||||
|
||||
do
|
||||
{
|
||||
b = _reader.ReadByte();
|
||||
v |= (b & 0x7F) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
while (b >= 0x80);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public IPAddress ReadIPAddress()
|
||||
{
|
||||
byte length = ReadByte();
|
||||
// Either 2 ushorts, or 8 ushorts
|
||||
Span<byte> integer = stackalloc byte[length];
|
||||
Read(integer);
|
||||
return Utility.Intern(new IPAddress(integer));
|
||||
}
|
||||
|
||||
public Point3D ReadPoint3D() => new(ReadInt(), ReadInt(), ReadInt());
|
||||
|
||||
public Point2D ReadPoint2D() => new(ReadInt(), ReadInt());
|
||||
|
||||
public Rectangle2D ReadRect2D() => new(ReadPoint2D(), ReadPoint2D());
|
||||
|
||||
public Rectangle3D ReadRect3D() => new(ReadPoint3D(), ReadPoint3D());
|
||||
|
||||
public Map ReadMap() => Map.Maps[ReadByte()];
|
||||
|
||||
public Race ReadRace() => Race.Races[ReadByte()];
|
||||
|
||||
public int Read(Span<byte> buffer) => _reader.Read(buffer);
|
||||
|
||||
public long Seek(long offset, SeekOrigin origin) => _reader.BaseStream.Seek(offset, origin);
|
||||
|
|
|
|||
|
|
@ -17,7 +17,6 @@ using System;
|
|||
using System.Buffers.Binary;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
using Server.Text;
|
||||
|
||||
|
|
@ -52,7 +51,7 @@ namespace Server
|
|||
return null;
|
||||
}
|
||||
|
||||
var length = ReadEncodedInt();
|
||||
var length = ((IGenericReader)this).ReadEncodedInt();
|
||||
if (length <= 0)
|
||||
{
|
||||
return intern ? Utility.Intern("") : "";
|
||||
|
|
@ -63,14 +62,6 @@ namespace Server
|
|||
return intern ? Utility.Intern(str) : str;
|
||||
}
|
||||
|
||||
public DateTime ReadDateTime() => new(ReadLong(), DateTimeKind.Utc);
|
||||
|
||||
public TimeSpan ReadTimeSpan() => new(ReadLong());
|
||||
|
||||
public DateTime ReadDeltaTime() => new(ReadLong() + DateTime.UtcNow.Ticks, DateTimeKind.Utc);
|
||||
|
||||
public decimal ReadDecimal() => new(stackalloc int[4] { ReadInt(), ReadInt(), ReadInt(), ReadInt() });
|
||||
|
||||
public long ReadLong()
|
||||
{
|
||||
var v = BinaryPrimitives.ReadInt64LittleEndian(_buffer.AsSpan(_position, 8));
|
||||
|
|
@ -133,42 +124,6 @@ namespace Server
|
|||
|
||||
public bool ReadBool() => _buffer[_position++] != 0;
|
||||
|
||||
public int ReadEncodedInt()
|
||||
{
|
||||
int v = 0, shift = 0;
|
||||
byte b;
|
||||
|
||||
do
|
||||
{
|
||||
b = ReadByte();
|
||||
v |= (b & 0x7F) << shift;
|
||||
shift += 7;
|
||||
} while (b >= 0x80);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
public IPAddress ReadIPAddress()
|
||||
{
|
||||
byte length = ReadByte();
|
||||
// Either 2 ushorts, or 8 ushorts
|
||||
Span<byte> integer = stackalloc byte[length];
|
||||
Read(integer);
|
||||
return Utility.Intern(new IPAddress(integer));
|
||||
}
|
||||
|
||||
public Point3D ReadPoint3D() => new(ReadInt(), ReadInt(), ReadInt());
|
||||
|
||||
public Point2D ReadPoint2D() => new(ReadInt(), ReadInt());
|
||||
|
||||
public Rectangle2D ReadRect2D() => new(ReadPoint2D(), ReadPoint2D());
|
||||
|
||||
public Rectangle3D ReadRect3D() => new(ReadPoint3D(), ReadPoint3D());
|
||||
|
||||
public Map ReadMap() => Map.Maps[ReadByte()];
|
||||
|
||||
public Race ReadRace() => Race.Races[ReadByte()];
|
||||
|
||||
public int Read(Span<byte> buffer)
|
||||
{
|
||||
var length = buffer.Length;
|
||||
|
|
|
|||
|
|
@ -158,19 +158,6 @@ namespace Server
|
|||
});
|
||||
}
|
||||
|
||||
public void WriteEncodedInt(int value)
|
||||
{
|
||||
var v = (uint)value;
|
||||
|
||||
while (v >= 0x80)
|
||||
{
|
||||
Write((byte)(v | 0x80));
|
||||
v >>= 7;
|
||||
}
|
||||
|
||||
Write((byte)v);
|
||||
}
|
||||
|
||||
public void Write(string value)
|
||||
{
|
||||
if (m_PrefixStrings)
|
||||
|
|
@ -191,56 +178,6 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
public void Write(DateTime value)
|
||||
{
|
||||
var ticks = (value.Kind switch
|
||||
{
|
||||
DateTimeKind.Local => value.ToUniversalTime(),
|
||||
DateTimeKind.Unspecified => value.ToLocalTime().ToUniversalTime(),
|
||||
_ => value
|
||||
}).Ticks;
|
||||
|
||||
Write(ticks);
|
||||
}
|
||||
|
||||
// TODO: Find a way to speed this up.
|
||||
// Maybe used a special cached value?
|
||||
public void WriteDeltaTime(DateTime value)
|
||||
{
|
||||
var ticks = (value.Kind switch
|
||||
{
|
||||
DateTimeKind.Local => value.ToUniversalTime(),
|
||||
DateTimeKind.Unspecified => value.ToLocalTime().ToUniversalTime(),
|
||||
_ => value
|
||||
}).Ticks;
|
||||
|
||||
// Technically supports negative deltas for times in the past
|
||||
Write(ticks - DateTime.UtcNow.Ticks);
|
||||
}
|
||||
|
||||
public void Write(IPAddress value)
|
||||
{
|
||||
Span<byte> stack = stackalloc byte[16];
|
||||
value.TryWriteBytes(stack, out var bytesWritten);
|
||||
Write((byte)bytesWritten);
|
||||
Write(stack[..bytesWritten]);
|
||||
}
|
||||
|
||||
public void Write(TimeSpan value)
|
||||
{
|
||||
Write(value.Ticks);
|
||||
}
|
||||
|
||||
public void Write(decimal value)
|
||||
{
|
||||
var bits = decimal.GetBits(value);
|
||||
|
||||
for (var i = 0; i < 4; ++i)
|
||||
{
|
||||
Write(bits[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public void Write(long value)
|
||||
{
|
||||
FlushIfNeeded(8);
|
||||
|
|
@ -350,46 +287,11 @@ namespace Server
|
|||
_buffer[Index++] = *(byte*)&value; // up to 30% faster to dereference the raw value on the stack
|
||||
}
|
||||
|
||||
public void Write(Point3D value)
|
||||
{
|
||||
Write(value.m_X);
|
||||
Write(value.m_Y);
|
||||
Write(value.m_Z);
|
||||
}
|
||||
|
||||
public void Write(Point2D value)
|
||||
{
|
||||
Write(value.m_X);
|
||||
Write(value.m_Y);
|
||||
}
|
||||
|
||||
public void Write(Rectangle2D value)
|
||||
{
|
||||
Write(value.Start);
|
||||
Write(value.End);
|
||||
}
|
||||
|
||||
public void Write(Rectangle3D value)
|
||||
{
|
||||
Write(value.Start);
|
||||
Write(value.End);
|
||||
}
|
||||
|
||||
public void Write(Map value)
|
||||
{
|
||||
Write((byte)(value?.MapIndex ?? 0xFF));
|
||||
}
|
||||
|
||||
public void Write(Race value)
|
||||
{
|
||||
Write((byte)(value?.RaceIndex ?? 0xFF));
|
||||
}
|
||||
|
||||
internal void InternalWriteString(string value)
|
||||
{
|
||||
var remaining = m_Encoding.GetByteCount(value);
|
||||
|
||||
WriteEncodedInt(remaining);
|
||||
((IGenericWriter)this).WriteEncodedInt(remaining);
|
||||
|
||||
if (remaining == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -22,10 +22,6 @@ namespace Server
|
|||
public interface IGenericReader
|
||||
{
|
||||
string ReadString(bool intern = false);
|
||||
DateTime ReadDateTime();
|
||||
TimeSpan ReadTimeSpan();
|
||||
DateTime ReadDeltaTime();
|
||||
decimal ReadDecimal();
|
||||
long ReadLong();
|
||||
ulong ReadULong();
|
||||
int ReadInt();
|
||||
|
|
@ -37,15 +33,69 @@ namespace Server
|
|||
byte ReadByte();
|
||||
sbyte ReadSByte();
|
||||
bool ReadBool();
|
||||
int ReadEncodedInt();
|
||||
IPAddress ReadIPAddress();
|
||||
Point3D ReadPoint3D();
|
||||
Point2D ReadPoint2D();
|
||||
Rectangle2D ReadRect2D();
|
||||
Rectangle3D ReadRect3D();
|
||||
Map ReadMap();
|
||||
Race ReadRace();
|
||||
|
||||
DateTime ReadDateTime() => new(ReadLong(), DateTimeKind.Utc);
|
||||
TimeSpan ReadTimeSpan() => new(ReadLong());
|
||||
DateTime ReadDeltaTime() => new(ReadLong() + DateTime.UtcNow.Ticks, DateTimeKind.Utc);
|
||||
decimal ReadDecimal() => new(stackalloc int[4] { ReadInt(), ReadInt(), ReadInt(), ReadInt() });
|
||||
int ReadEncodedInt()
|
||||
{
|
||||
int v = 0, shift = 0;
|
||||
byte b;
|
||||
|
||||
do
|
||||
{
|
||||
b = ReadByte();
|
||||
v |= (b & 0x7F) << shift;
|
||||
shift += 7;
|
||||
}
|
||||
while (b >= 0x80);
|
||||
|
||||
return v;
|
||||
}
|
||||
IPAddress ReadIPAddress()
|
||||
{
|
||||
byte length = ReadByte();
|
||||
// Either 2 ushorts, or 8 ushorts
|
||||
Span<byte> integer = stackalloc byte[length];
|
||||
Read(integer);
|
||||
return Utility.Intern(new IPAddress(integer));
|
||||
}
|
||||
Point3D ReadPoint3D() => new(ReadInt(), ReadInt(), ReadInt());
|
||||
Point2D ReadPoint2D() => new(ReadInt(), ReadInt());
|
||||
Rectangle2D ReadRect2D() => new(ReadPoint2D(), ReadPoint2D());
|
||||
Rectangle3D ReadRect3D() => new(ReadPoint3D(), ReadPoint3D());
|
||||
Map ReadMap() => Map.Maps[ReadByte()];
|
||||
Race ReadRace() => Race.Races[ReadByte()];
|
||||
int Read(Span<byte> buffer);
|
||||
unsafe T ReadEnum<T>() where T : unmanaged, Enum
|
||||
{
|
||||
switch (ReadByte())
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
var num = ReadByte();
|
||||
return *(T*)#
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
var num = ReadShort();
|
||||
return *(T*)#
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
var num = ReadEncodedInt();
|
||||
return *(T*)#
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
var num = ReadLong();
|
||||
return *(T*)#
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
long Seek(long offset, SeekOrigin origin);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,9 +24,6 @@ namespace Server
|
|||
long Position { get; }
|
||||
void Close();
|
||||
void Write(string value);
|
||||
void Write(DateTime value);
|
||||
void Write(TimeSpan value);
|
||||
void Write(decimal value);
|
||||
void Write(long value);
|
||||
void Write(ulong value);
|
||||
void Write(int value);
|
||||
|
|
@ -38,17 +35,120 @@ namespace Server
|
|||
void Write(byte value);
|
||||
void Write(sbyte value);
|
||||
void Write(bool value);
|
||||
void WriteEncodedInt(int value);
|
||||
void Write(IPAddress value);
|
||||
void WriteDeltaTime(DateTime value);
|
||||
void Write(Point3D value);
|
||||
void Write(Point2D value);
|
||||
void Write(Rectangle2D value);
|
||||
void Write(Rectangle3D value);
|
||||
void Write(Map value);
|
||||
void Write(Race value);
|
||||
void Write(ReadOnlySpan<byte> bytes);
|
||||
|
||||
void Write(DateTime value)
|
||||
{
|
||||
var ticks = (value.Kind switch
|
||||
{
|
||||
DateTimeKind.Local => value.ToUniversalTime(),
|
||||
DateTimeKind.Unspecified => value.ToLocalTime().ToUniversalTime(),
|
||||
_ => value
|
||||
}).Ticks;
|
||||
|
||||
Write(ticks);
|
||||
}
|
||||
void WriteDeltaTime(DateTime value)
|
||||
{
|
||||
var ticks = (value.Kind switch
|
||||
{
|
||||
DateTimeKind.Local => value.ToUniversalTime(),
|
||||
DateTimeKind.Unspecified => value.ToLocalTime().ToUniversalTime(),
|
||||
_ => value
|
||||
}).Ticks;
|
||||
|
||||
// Technically supports negative deltas for times in the past
|
||||
Write(ticks - DateTime.UtcNow.Ticks);
|
||||
}
|
||||
void Write(IPAddress value)
|
||||
{
|
||||
Span<byte> stack = stackalloc byte[16];
|
||||
value.TryWriteBytes(stack, out var bytesWritten);
|
||||
Write((byte)bytesWritten);
|
||||
Write(stack[..bytesWritten]);
|
||||
}
|
||||
void Write(TimeSpan value)
|
||||
{
|
||||
Write(value.Ticks);
|
||||
}
|
||||
|
||||
public void Write(decimal value)
|
||||
{
|
||||
var bits = decimal.GetBits(value);
|
||||
|
||||
for (var i = 0; i < 4; ++i)
|
||||
{
|
||||
Write(bits[i]);
|
||||
}
|
||||
}
|
||||
void WriteEncodedInt(int value)
|
||||
{
|
||||
var v = (uint)value;
|
||||
|
||||
while (v >= 0x80)
|
||||
{
|
||||
Write((byte)(v | 0x80));
|
||||
v >>= 7;
|
||||
}
|
||||
|
||||
Write((byte)v);
|
||||
}
|
||||
void Write(Point3D value)
|
||||
{
|
||||
Write(value.m_X);
|
||||
Write(value.m_Y);
|
||||
Write(value.m_Z);
|
||||
}
|
||||
void Write(Point2D value)
|
||||
{
|
||||
Write(value.m_X);
|
||||
Write(value.m_Y);
|
||||
}
|
||||
void Write(Rectangle2D value)
|
||||
{
|
||||
Write(value.Start);
|
||||
Write(value.End);
|
||||
}
|
||||
void Write(Rectangle3D value)
|
||||
{
|
||||
Write(value.Start);
|
||||
Write(value.End);
|
||||
}
|
||||
void Write(Map value) => Write((byte)(value?.MapIndex ?? 0xFF));
|
||||
void Write(Race value) => Write((byte)(value?.RaceIndex ?? 0xFF));
|
||||
void Write(ReadOnlySpan<byte> bytes);
|
||||
unsafe void Write<T>(T value) where T : unmanaged, Enum
|
||||
{
|
||||
var size = sizeof(T);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
default: throw new ArgumentException($"Argument of type {typeof(T)} is not a normal enum");
|
||||
case 1:
|
||||
{
|
||||
Write((byte)1);
|
||||
Write(*(byte*)&value);
|
||||
break;
|
||||
}
|
||||
case 2:
|
||||
{
|
||||
Write((byte)2);
|
||||
Write(*(ushort*)&value);
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
Write((byte)3);
|
||||
WriteEncodedInt(*(int*)&value);
|
||||
break;
|
||||
}
|
||||
case 8:
|
||||
{
|
||||
Write((byte)4);
|
||||
Write(*(ulong*)&value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
long Seek(long offset, SeekOrigin origin);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue