Update Readers/Writers for Buffers & Fixes bugs (#283)
- [X] Renames PacketReader to CircularBufferReader - [X] Fixes bugs with CircularBufferReader - [X] Adds CircularBufferWriter - [X] Adds SpanWriter - [X] Adds SpanReader Bumps release version
This commit is contained in:
parent
3b7f648c27
commit
6bd4f0d265
26 changed files with 1302 additions and 351 deletions
119
Projects/Server.Tests/Buffers/CircularBufferReaderTests.cs
Normal file
119
Projects/Server.Tests/Buffers/CircularBufferReaderTests.cs
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests.Network
|
||||
{
|
||||
public class CircularBufferReaderTests
|
||||
{
|
||||
[Theory]
|
||||
// First only, beginning
|
||||
[InlineData("Test String", "us-ascii", false, -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-u", false, -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16BE", false, -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16", false, -1, 1024, 1024, 0)]
|
||||
|
||||
// Second only
|
||||
[InlineData("Test String", "us-ascii", false, -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-u", false, -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16BE", false, -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16", false, -1, 1024, 1024, 1030)]
|
||||
|
||||
// Split
|
||||
[InlineData("Test String", "us-ascii", false, -1, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-u", false, -1, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16BE", false, -1, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16", false, -1, 1024, 1024, 1020)]
|
||||
|
||||
// First only, beginning, fixed length smaller
|
||||
[InlineData("Test String", "us-ascii", false, 8, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-u", false, 8, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16BE", false, 8, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16", false, 8, 1024, 1024, 0)]
|
||||
|
||||
// Second only, fixed length smaller
|
||||
[InlineData("Test String", "us-ascii", false, 8, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-u", false, 8, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16BE", false, 8, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16", false, 8, 1024, 1024, 1030)]
|
||||
|
||||
// Split, fixed length smaller
|
||||
[InlineData("Test String", "us-ascii", false, 8, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-u", false, 8, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16BE", false, 8, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16", false, 8, 1024, 1024, 1020)]
|
||||
|
||||
// First only, beginning, fixed length bigger
|
||||
[InlineData("Test String", "us-ascii", false, 20, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-u", false, 20, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16BE", false, 20, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16", false, 20, 1024, 1024, 0)]
|
||||
|
||||
// Second only, fixed length bigger
|
||||
[InlineData("Test String", "us-ascii", false, 20, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-u", false, 20, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16BE", false, 20, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16", false, 20, 1024, 1024, 1030)]
|
||||
|
||||
// Split, fixed length bigger
|
||||
[InlineData("Test String", "us-ascii", false, 20, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-u", false, 20, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16BE", false, 20, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16", false, 20, 1024, 1024, 1020)]
|
||||
public void TestReadString(
|
||||
string value,
|
||||
string encodingStr,
|
||||
bool isSafe,
|
||||
int fixedLength,
|
||||
int firstSize,
|
||||
int secondSize,
|
||||
int offset
|
||||
)
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[firstSize + secondSize];
|
||||
buffer.Clear();
|
||||
|
||||
var encoding = EncodingHelpers.GetEncoding(encodingStr);
|
||||
|
||||
var strLength = fixedLength > -1 ? Math.Min(value.Length, fixedLength) : value.Length;
|
||||
var chars = value.AsSpan(0, strLength);
|
||||
;
|
||||
encoding.GetBytes(chars, buffer.Slice(offset));
|
||||
|
||||
var reader = new CircularBufferReader(buffer.Slice(0, firstSize), buffer.Slice(firstSize));
|
||||
reader.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
var actual = reader.ReadString(encoding, isSafe, fixedLength);
|
||||
|
||||
Assert.Equal(value.Substring(0, strLength), actual);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestReadStringBetween()
|
||||
{
|
||||
Span<byte> expected = stackalloc byte[19];
|
||||
expected[0] = 0x1;
|
||||
expected[1] = 0x1;
|
||||
expected[2] = 0x1;
|
||||
expected[3] = 0x1;
|
||||
Encoding.ASCII.GetBytes("TestString", expected.Slice(4, 10));
|
||||
expected[14] = 0x0; // Null
|
||||
expected[15] = 0x2;
|
||||
expected[16] = 0x2;
|
||||
expected[17] = 0x2;
|
||||
expected[18] = 0x2;
|
||||
|
||||
var reader = new CircularBufferReader(expected, stackalloc byte[0]);
|
||||
|
||||
var num1 = reader.ReadInt32();
|
||||
var str = reader.ReadAscii();
|
||||
var num2 = reader.ReadInt32();
|
||||
|
||||
Assert.Equal(0x01010101, num1);
|
||||
Assert.Equal("TestString", str);
|
||||
Assert.Equal(0x02020202, num2);
|
||||
}
|
||||
}
|
||||
}
|
||||
99
Projects/Server.Tests/Buffers/CircularBufferWriterTests.cs
Normal file
99
Projects/Server.Tests/Buffers/CircularBufferWriterTests.cs
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests.Buffers
|
||||
{
|
||||
public class CircularBufferWriterTests
|
||||
{
|
||||
[Theory]
|
||||
// First only, beginning
|
||||
[InlineData("Test String", "us-ascii", -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-8", -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16BE", -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16", -1, 1024, 1024, 0)]
|
||||
|
||||
// Second only
|
||||
[InlineData("Test String", "us-ascii", -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-8", -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16BE", -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16", -1, 1024, 1024, 1030)]
|
||||
|
||||
// Split
|
||||
[InlineData("Test String", "us-ascii", -1, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-8", -1, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16BE", -1, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16", -1, 1024, 1024, 1020)]
|
||||
|
||||
// First only, beginning, fixed length smaller
|
||||
[InlineData("Test String", "us-ascii", 8, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16BE", 8, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16", 8, 1024, 1024, 0)]
|
||||
|
||||
// Second only, fixed length smaller
|
||||
[InlineData("Test String", "us-ascii", 8, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16BE", 8, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16", 8, 1024, 1024, 1030)]
|
||||
|
||||
// Split, fixed length smaller
|
||||
[InlineData("Test String", "us-ascii", 8, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16BE", 8, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16", 8, 1024, 1024, 1020)]
|
||||
|
||||
// First only, beginning, fixed length bigger
|
||||
[InlineData("Test String", "us-ascii", 20, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16BE", 20, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-16", 20, 1024, 1024, 0)]
|
||||
|
||||
// Second only, fixed length bigger
|
||||
[InlineData("Test String", "us-ascii", 20, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16BE", 20, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-16", 20, 1024, 1024, 1030)]
|
||||
|
||||
// Split, fixed length bigger
|
||||
[InlineData("Test String", "us-ascii", 20, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16BE", 20, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-16", 20, 1024, 1024, 1020)]
|
||||
public void TestWriteString(
|
||||
string value,
|
||||
string encodingStr,
|
||||
int fixedLength,
|
||||
int firstSize,
|
||||
int secondSize,
|
||||
int offset
|
||||
)
|
||||
{
|
||||
Span<byte> buffer = stackalloc byte[firstSize + secondSize];
|
||||
buffer.Clear();
|
||||
|
||||
var encoding = EncodingHelpers.GetEncoding(encodingStr);
|
||||
var strLength = fixedLength > -1 ? Math.Min(value.Length, fixedLength) : value.Length;
|
||||
var chars = value.AsSpan(0, strLength);
|
||||
|
||||
var writer = new CircularBufferWriter(buffer.Slice(0, firstSize), buffer.Slice(firstSize));
|
||||
writer.Seek(offset, SeekOrigin.Begin);
|
||||
writer.WriteString(chars, encoding);
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
Span<byte> testEmpty = stackalloc byte[offset];
|
||||
testEmpty.Clear();
|
||||
AssertThat.Equal(buffer.Slice(0, offset), testEmpty);
|
||||
}
|
||||
|
||||
Span<byte> expectedStr = stackalloc byte[encoding.GetByteCount(chars)];
|
||||
encoding.GetBytes(chars, expectedStr.Slice(0));
|
||||
|
||||
AssertThat.Equal(buffer.Slice(offset, expectedStr.Length), expectedStr);
|
||||
offset += expectedStr.Length;
|
||||
|
||||
if (offset < buffer.Length)
|
||||
{
|
||||
Span<byte> testEmpty = stackalloc byte[buffer.Length - offset];
|
||||
testEmpty.Clear();
|
||||
AssertThat.Equal(buffer.Slice(offset), testEmpty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace Server.Tests.Network
|
||||
{
|
||||
public class PacketReaderTests
|
||||
{
|
||||
private (Encoding, Type) GetEncoding(string value) =>
|
||||
value.ToUpper() switch
|
||||
{
|
||||
"UTF8" => (Utility.UTF8, typeof(byte)),
|
||||
"UNICODELE" => (Utility.UnicodeLE, typeof(char)),
|
||||
"UNICODE" => (Utility.Unicode, typeof(char)),
|
||||
_ => (Encoding.ASCII, typeof(byte))
|
||||
};
|
||||
|
||||
private ITestOutputHelper _outputHelper;
|
||||
|
||||
public PacketReaderTests(ITestOutputHelper outputHelper) => _outputHelper = outputHelper;
|
||||
|
||||
[Theory]
|
||||
// First only, beginning
|
||||
[InlineData("Test String", "ASCII", false, -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "UTF8", false, -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "Unicode", false, -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "UnicodeLE", false, -1, 1024, 1024, 0)]
|
||||
|
||||
// Second only
|
||||
[InlineData("Test String", "ASCII", false, -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "UTF8", false, -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "Unicode", false, -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "UnicodeLE", false, -1, 1024, 1024, 1030)]
|
||||
public void TestReadString(
|
||||
string value,
|
||||
string encodingStr,
|
||||
bool isSafe,
|
||||
int fixedLength,
|
||||
int firstSize,
|
||||
int secondSize,
|
||||
int offset
|
||||
)
|
||||
{
|
||||
var (encoding, byteType) = GetEncoding(encodingStr);
|
||||
var bytes = encoding.GetBytes(value);
|
||||
Span<byte> expectedBytes = bytes.AsSpan(0, fixedLength > -1 ? Math.Min(fixedLength, bytes.Length) : bytes.Length);
|
||||
|
||||
if (offset + expectedBytes.Length > firstSize + secondSize)
|
||||
{
|
||||
throw new ArgumentException("Test failed due to bad assumptions. Out of memory exception would be thrown");
|
||||
}
|
||||
|
||||
Span<byte> first = stackalloc byte[firstSize];
|
||||
first.Clear(); // Just in case
|
||||
|
||||
int bytesWrittenFirst = 0;
|
||||
|
||||
if (offset < first.Length)
|
||||
{
|
||||
bytesWrittenFirst = Math.Min(first.Length, expectedBytes.Length);
|
||||
expectedBytes.Slice(offset, bytesWrittenFirst).CopyTo(first);
|
||||
}
|
||||
|
||||
Span<byte> second = stackalloc byte[secondSize];
|
||||
second.Clear(); // Just in case
|
||||
|
||||
if (offset > first.Length || expectedBytes.Length > bytesWrittenFirst)
|
||||
{
|
||||
var secondOffset = Math.Max(offset - first.Length, 0);
|
||||
var secondSlice = second.Slice(secondOffset, second.Length - secondOffset);
|
||||
expectedBytes.Slice(bytesWrittenFirst, expectedBytes.Length - bytesWrittenFirst).CopyTo(secondSlice);
|
||||
}
|
||||
|
||||
// _outputHelper.WriteLine(HexStringConverter.GetString(first));
|
||||
// _outputHelper.WriteLine(HexStringConverter.GetString(second));
|
||||
|
||||
var reader = new PacketReader(first, second);
|
||||
reader.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
_outputHelper.WriteLine(reader.Position.ToString());
|
||||
|
||||
var actual = byteType switch
|
||||
{
|
||||
var b when b == typeof(char) => reader.ReadString<char>(encoding, isSafe, fixedLength),
|
||||
_ => reader.ReadString<byte>(encoding, isSafe, fixedLength)
|
||||
};
|
||||
|
||||
_outputHelper.WriteLine(actual);
|
||||
|
||||
if (fixedLength > 0 && fixedLength < value.Length)
|
||||
{
|
||||
value = value.Substring(0, fixedLength);
|
||||
}
|
||||
|
||||
Assert.Equal(value, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -131,28 +131,28 @@ namespace Server.Tests.Network
|
|||
|
||||
var result = writer.GetAvailable();
|
||||
Assert.True(result.Length == 9);
|
||||
Assert.True(reader.GetRemaining() == 0);
|
||||
Assert.True(reader.GetAvailable() == 0);
|
||||
result = reader.TryRead();
|
||||
Assert.True(result.Length == 0);
|
||||
|
||||
writer.Advance(7);
|
||||
result = writer.GetAvailable();
|
||||
Assert.True(result.Length == 2);
|
||||
Assert.True(reader.GetRemaining() == 7);
|
||||
Assert.True(reader.GetAvailable() == 7);
|
||||
result = reader.TryRead();
|
||||
Assert.True(result.Length == 7);
|
||||
|
||||
reader.Advance(4);
|
||||
result = writer.GetAvailable();
|
||||
Assert.True(result.Length == 6);
|
||||
Assert.True(reader.GetRemaining() == 3);
|
||||
Assert.True(reader.GetAvailable() == 3);
|
||||
result = reader.TryRead();
|
||||
Assert.True(result.Length == 3);
|
||||
|
||||
writer.Advance(3);
|
||||
result = writer.GetAvailable();
|
||||
Assert.True(result.Length == 3);
|
||||
Assert.True(reader.GetRemaining() == 6);
|
||||
Assert.True(reader.GetAvailable() == 6);
|
||||
result = reader.TryRead();
|
||||
Assert.True(result.Length == 6);
|
||||
|
||||
|
|
@ -171,7 +171,7 @@ namespace Server.Tests.Network
|
|||
writer.Advance(i);
|
||||
writer.Flush();
|
||||
|
||||
Assert.True(reader.GetRemaining() == i);
|
||||
Assert.True(reader.GetAvailable() == i);
|
||||
reader.Advance(i);
|
||||
}
|
||||
}
|
||||
|
|
@ -192,7 +192,7 @@ namespace Server.Tests.Network
|
|||
writer.Advance(9);
|
||||
writer.Flush();
|
||||
|
||||
Assert.True(reader.GetRemaining() == 9);
|
||||
Assert.True(reader.GetAvailable() == 9);
|
||||
|
||||
buffer = reader.TryRead();
|
||||
|
||||
|
|
|
|||
17
Projects/Server.Tests/Utility/EncodingHelpers.cs
Normal file
17
Projects/Server.Tests/Utility/EncodingHelpers.cs
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Tests
|
||||
{
|
||||
public static class EncodingHelpers
|
||||
{
|
||||
public static Encoding GetEncoding(string bodyname) =>
|
||||
bodyname switch
|
||||
{
|
||||
"utf-8" => Utility.UTF8,
|
||||
"utf-16" => Utility.UnicodeLE,
|
||||
"utf-16BE" => Utility.Unicode,
|
||||
_ => Encoding.ASCII
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -15,35 +15,29 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public ref struct PacketReader
|
||||
public ref struct CircularBufferReader
|
||||
{
|
||||
public Span<byte> First;
|
||||
public Span<byte> Second;
|
||||
private readonly ReadOnlySpan<byte> _first;
|
||||
private readonly ReadOnlySpan<byte> _second;
|
||||
|
||||
public int Length { get; }
|
||||
public int Position { get; private set; }
|
||||
public int Remaining => Length - Position;
|
||||
|
||||
public PacketReader(ArraySegment<byte>[] buffers)
|
||||
public CircularBufferReader(ArraySegment<byte>[] buffers) : this(buffers[0], buffers[1])
|
||||
{
|
||||
First = buffers[0];
|
||||
Second = buffers[1];
|
||||
Position = 0;
|
||||
Length = First.Length + Second.Length;
|
||||
}
|
||||
|
||||
public PacketReader(Span<byte> first, Span<byte> second)
|
||||
public CircularBufferReader(ReadOnlySpan<byte> first, ReadOnlySpan<byte> second)
|
||||
{
|
||||
First = first;
|
||||
Second = second;
|
||||
_first = first;
|
||||
_second = second;
|
||||
Position = 0;
|
||||
Length = first.Length + second.Length;
|
||||
}
|
||||
|
|
@ -51,7 +45,7 @@ namespace Server.Network
|
|||
public void Trace(NetState state)
|
||||
{
|
||||
// We don't have data, so nothing to trace
|
||||
if (First.Length == 0)
|
||||
if (_first.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -60,9 +54,9 @@ namespace Server.Network
|
|||
{
|
||||
using var sw = new StreamWriter("Packets.log", true);
|
||||
|
||||
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", state, First[0]);
|
||||
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", state, _first[0]);
|
||||
|
||||
Utility.FormatBuffer(sw, First.ToArray(), new Memory<byte>(Second.ToArray()));
|
||||
Utility.FormatBuffer(sw, _first.ToArray(), new Memory<byte>(_second.ToArray()));
|
||||
|
||||
sw.WriteLine();
|
||||
sw.WriteLine();
|
||||
|
|
@ -76,14 +70,14 @@ namespace Server.Network
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte ReadByte()
|
||||
{
|
||||
if (Position < First.Length)
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
return First[Position++];
|
||||
return _first[Position++];
|
||||
}
|
||||
|
||||
if (Position < Length)
|
||||
{
|
||||
return Second[Position++ - First.Length];
|
||||
return _second[Position++ - _first.Length];
|
||||
}
|
||||
|
||||
throw new OutOfMemoryException();
|
||||
|
|
@ -100,15 +94,15 @@ namespace Server.Network
|
|||
{
|
||||
short value;
|
||||
|
||||
if (Position < First.Length)
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadInt16BigEndian(First.Slice(Position), out value))
|
||||
if (!BinaryPrimitives.TryReadInt16BigEndian(_first.Slice(Position), out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return (short)((ReadByte() >> 8) | ReadByte());
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadInt16BigEndian(Second.Slice(Position - First.Length), out value))
|
||||
else if (!BinaryPrimitives.TryReadInt16BigEndian(_second.Slice(Position - _first.Length), out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
|
@ -122,15 +116,15 @@ namespace Server.Network
|
|||
{
|
||||
ushort value;
|
||||
|
||||
if (Position < First.Length)
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadUInt16BigEndian(First.Slice(Position), out value))
|
||||
if (!BinaryPrimitives.TryReadUInt16BigEndian(_first.Slice(Position), out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return (ushort)((ReadByte() >> 8) | ReadByte());
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadUInt16BigEndian(Second.Slice(Position - First.Length), out value))
|
||||
else if (!BinaryPrimitives.TryReadUInt16BigEndian(_second.Slice(Position - _first.Length), out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
|
@ -144,15 +138,15 @@ namespace Server.Network
|
|||
{
|
||||
int value;
|
||||
|
||||
if (Position < First.Length)
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadInt32BigEndian(First.Slice(Position), out value))
|
||||
if (!BinaryPrimitives.TryReadInt32BigEndian(_first.Slice(Position), out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return (ReadByte() >> 24) | (ReadByte() >> 16) | (ReadByte() >> 8) | ReadByte();
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadInt32BigEndian(Second.Slice(Position - First.Length), out value))
|
||||
else if (!BinaryPrimitives.TryReadInt32BigEndian(_second.Slice(Position - _first.Length), out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
|
@ -166,15 +160,15 @@ namespace Server.Network
|
|||
{
|
||||
uint value;
|
||||
|
||||
if (Position < First.Length)
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadUInt32BigEndian(First.Slice(Position), out value))
|
||||
if (!BinaryPrimitives.TryReadUInt32BigEndian(_first.Slice(Position), out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return (uint)((ReadByte() >> 24) | (ReadByte() >> 16) | (ReadByte() >> 8) | ReadByte());
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadUInt32BigEndian(Second.Slice(Position - First.Length), out value))
|
||||
else if (!BinaryPrimitives.TryReadUInt32BigEndian(_second.Slice(Position - _first.Length), out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
|
@ -183,28 +177,20 @@ namespace Server.Network
|
|||
return value;
|
||||
}
|
||||
|
||||
private static bool IsSafeChar(ushort c) => c >= 0x20 && c < 0xFFFE;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadString<T>(Encoding encoding, bool safeString = false, int fixedLength = -1) where T : struct, IEquatable<T>
|
||||
public string ReadString(Encoding encoding, bool safeString = false, int fixedLength = -1)
|
||||
{
|
||||
int sizeT = Unsafe.SizeOf<T>();
|
||||
|
||||
if (sizeT > 2)
|
||||
{
|
||||
throw new InvalidConstraintException("ReadString only accepts byte, sbyte, char, short, and ushort as a constraint");
|
||||
}
|
||||
int sizeT = Utility.GetByteLengthForEncoding(encoding);
|
||||
|
||||
bool isFixedLength = fixedLength > -1;
|
||||
|
||||
var remaining = Remaining;
|
||||
int size;
|
||||
|
||||
// Not fixed length
|
||||
if (isFixedLength)
|
||||
{
|
||||
size = fixedLength * sizeT;
|
||||
if (fixedLength > Remaining)
|
||||
if (size > Remaining)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
|
@ -214,130 +200,107 @@ namespace Server.Network
|
|||
size = remaining - (remaining & (sizeT - 1));
|
||||
}
|
||||
|
||||
Span<byte> span;
|
||||
ReadOnlySpan<byte> span;
|
||||
int index;
|
||||
|
||||
if (Position < First.Length)
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
var firstLength = Math.Min(_first.Length - Position, size);
|
||||
|
||||
// Find terminator
|
||||
index = MemoryMarshal
|
||||
.Cast<byte, T>(First.Slice(Position, Math.Min(size, First.Length)))
|
||||
.IndexOf(default(T)) * sizeT;
|
||||
index = Utility.IndexOfTerminator(_first.Slice(Position, firstLength), sizeT);
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
remaining = size - First.Length;
|
||||
remaining = size - firstLength;
|
||||
// We don't have a terminator, but a fixed size to the end of the first span, so stop there
|
||||
if (remaining <= 0)
|
||||
{
|
||||
index = First.Length;
|
||||
index = firstLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = MemoryMarshal
|
||||
.Cast<byte, T>(Second.Slice(0, remaining))
|
||||
.IndexOf(default(T)) * sizeT;
|
||||
index = Utility.IndexOfTerminator(_second.Slice(0, remaining), sizeT);
|
||||
|
||||
int secondLength = index < 0 ? remaining : index;
|
||||
int length = First.Length + secondLength;
|
||||
int length = firstLength + secondLength;
|
||||
|
||||
// Assume no strings should be too long for the stack
|
||||
Span<byte> bytes = stackalloc byte[length];
|
||||
First.Slice(Position).CopyTo(bytes);
|
||||
Second.Slice(0, secondLength).CopyTo(bytes.Slice(First.Length));
|
||||
_first.Slice(Position).CopyTo(bytes);
|
||||
_second.Slice(0, secondLength).CopyTo(bytes.Slice(firstLength));
|
||||
|
||||
Position += length;
|
||||
return GetString(bytes, encoding, safeString);
|
||||
Position += length + (index >= 0 ? sizeT : 0);
|
||||
return Utility.GetString(bytes, encoding, safeString);
|
||||
}
|
||||
}
|
||||
|
||||
span = First.Slice(Position, index);
|
||||
span = _first.Slice(Position, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
span = Second.Slice( Position - First.Length, Math.Min(remaining, size));
|
||||
index = MemoryMarshal.Cast<byte, T>(span).IndexOf(default(T)) * sizeT;
|
||||
size = Math.Min(remaining, size);
|
||||
span = _second.Slice( Position - _first.Length, size);
|
||||
index = Utility.IndexOfTerminator(span, sizeT);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
span = span.Slice(0, index);
|
||||
}
|
||||
}
|
||||
|
||||
Position += isFixedLength ? size : index;
|
||||
return GetString(span, encoding, safeString);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static string GetString(Span<byte> span, Encoding encoding, bool safeString = false)
|
||||
{
|
||||
string s = encoding.GetString(span);
|
||||
|
||||
if (!safeString)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
ReadOnlySpan<char> chars = s.AsSpan();
|
||||
|
||||
StringBuilder stringBuilder = null;
|
||||
|
||||
for (int i = 0, last = 0; i < chars.Length; i++)
|
||||
{
|
||||
if (!IsSafeChar(chars[i]) || stringBuilder != null && i == chars.Length - 1)
|
||||
else
|
||||
{
|
||||
(stringBuilder ??= new StringBuilder()).Append(chars.Slice(last, i - last));
|
||||
last = i + 1; // Skip the unsafe char
|
||||
index = size;
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder?.ToString() ?? s;
|
||||
Position += isFixedLength ? size : index + sizeT;
|
||||
return Utility.GetString(span, encoding, safeString);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUniSafe(int fixedLength) => ReadString<char>(Utility.UnicodeLE, true, fixedLength);
|
||||
public string ReadLittleUniSafe(int fixedLength) => ReadString(Utility.UnicodeLE, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUniSafe() => ReadString<char>(Utility.UnicodeLE, true);
|
||||
public string ReadLittleUniSafe() => ReadString(Utility.UnicodeLE, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUni(int fixedLength) => ReadString<char>(Utility.UnicodeLE, false, fixedLength);
|
||||
public string ReadLittleUni(int fixedLength) => ReadString(Utility.UnicodeLE, false, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUni() => ReadString<char>(Utility.UnicodeLE);
|
||||
public string ReadLittleUni() => ReadString(Utility.UnicodeLE);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUniSafe(int fixedLength) => ReadString<char>(Utility.Unicode, true, fixedLength);
|
||||
public string ReadBigUniSafe(int fixedLength) => ReadString(Utility.Unicode, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUniSafe() => ReadString<char>(Utility.Unicode, true);
|
||||
public string ReadBigUniSafe() => ReadString(Utility.Unicode, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUni(int fixedLength) => ReadString<char>(Utility.Unicode, false, fixedLength);
|
||||
public string ReadBigUni(int fixedLength) => ReadString(Utility.Unicode, false, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUni() => ReadString<char>(Utility.Unicode);
|
||||
public string ReadBigUni() => ReadString(Utility.Unicode);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8Safe(int fixedLength) => ReadString<byte>(Utility.UTF8, true, fixedLength);
|
||||
public string ReadUTF8Safe(int fixedLength) => ReadString(Utility.UTF8, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8Safe() => ReadString<byte>(Utility.UTF8, true);
|
||||
public string ReadUTF8Safe() => ReadString(Utility.UTF8, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8() => ReadString<byte>(Utility.UTF8);
|
||||
public string ReadUTF8() => ReadString(Utility.UTF8);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadAsciiSafe(int fixedLength) => ReadString<byte>(Encoding.ASCII, true, fixedLength);
|
||||
public string ReadAsciiSafe(int fixedLength) => ReadString(Encoding.ASCII, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadAsciiSafe() => ReadString<byte>(Encoding.ASCII, true);
|
||||
public string ReadAsciiSafe() => ReadString(Encoding.ASCII, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadAscii(int fixedLength) => ReadString<byte>(Encoding.ASCII, false, fixedLength);
|
||||
public string ReadAscii(int fixedLength) => ReadString(Encoding.ASCII, false, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadAscii() => ReadString<byte>(Encoding.ASCII);
|
||||
public string ReadAscii() => ReadString(Encoding.ASCII);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Seek(int offset, SeekOrigin origin) =>
|
||||
372
Projects/Server/Buffers/CircularBufferWriter.cs
Normal file
372
Projects/Server/Buffers/CircularBufferWriter.cs
Normal file
|
|
@ -0,0 +1,372 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: CircularBufferWriter.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Server;
|
||||
|
||||
namespace System.Buffers
|
||||
{
|
||||
public ref struct CircularBufferWriter
|
||||
{
|
||||
private readonly Span<byte> _first;
|
||||
private readonly Span<byte> _second;
|
||||
|
||||
public int Length { get; }
|
||||
public int Position { get; private set; }
|
||||
|
||||
public CircularBufferWriter(ArraySegment<byte>[] buffers) : this(buffers[0], buffers[1])
|
||||
{
|
||||
}
|
||||
|
||||
public CircularBufferWriter(Span<byte> first, Span<byte> second)
|
||||
{
|
||||
_first = first;
|
||||
_second = second;
|
||||
Position = 0;
|
||||
Length = first.Length + second.Length;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(byte value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
_first[Position++] = value;
|
||||
}
|
||||
else if (Position < Length)
|
||||
{
|
||||
_second[Position++ - _first.Length] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(bool value)
|
||||
{
|
||||
if (value)
|
||||
{
|
||||
Write((byte)1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Write((byte)0);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(sbyte value)
|
||||
{
|
||||
Write((byte)value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(short value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteInt16BigEndian(_first.Slice(Position), value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 2;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteInt16BigEndian(_second.Slice(Position - _first.Length), value))
|
||||
{
|
||||
Position += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(ushort value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteUInt16BigEndian(_first.Slice(Position), value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 2;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteUInt16BigEndian(_second.Slice(Position - _first.Length), value))
|
||||
{
|
||||
Position += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(int value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteInt32BigEndian(_first.Slice(Position), value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
Write((byte)(value >> 24));
|
||||
Write((byte)(value >> 16));
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteInt32BigEndian(_second.Slice(Position - _first.Length), value))
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 4-byte unsigned integer value to the underlying stream.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(uint value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteUInt32BigEndian(_first.Slice(Position), value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
Write((byte)(value >> 24));
|
||||
Write((byte)(value >> 16));
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteUInt32BigEndian(_second.Slice(Position - _first.Length), value))
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
if (Position + buffer.Length > Length)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
var sz = Math.Min(buffer.Length, _first.Length - Position);
|
||||
buffer.CopyTo(_first.Slice(Position));
|
||||
buffer.Slice(sz).CopyTo(_second);
|
||||
Position += buffer.Length;
|
||||
}
|
||||
else if (Position < Length)
|
||||
{
|
||||
buffer.CopyTo(_second.Slice(Position - _first.Length));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteString(ReadOnlySpan<char> value, Encoding encoding)
|
||||
{
|
||||
var byteCount = encoding.GetByteCount(value);
|
||||
|
||||
if (Position + byteCount > Length)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Span<byte> bytes = stackalloc byte[byteCount];
|
||||
encoding.GetBytes(value, bytes);
|
||||
|
||||
int count;
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
count = Math.Min(_first.Length - Position, byteCount);
|
||||
bytes.Slice(0, count).CopyTo(_first.Slice(Position));
|
||||
byteCount -= count;
|
||||
Position += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
if (byteCount > 0)
|
||||
{
|
||||
bytes.Slice(count).CopyTo(_second.Slice(Math.Max(0, Position - _first.Length)));
|
||||
Position += byteCount;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteLittleUni(string value, int fixedLength = -1)
|
||||
{
|
||||
if (fixedLength < 0) { fixedLength = value.Length; }
|
||||
|
||||
WriteString(value.AsSpan(0, Math.Min(fixedLength, value.Length)), Utility.UnicodeLE);
|
||||
var count = fixedLength - value.Length;
|
||||
if (count > 0)
|
||||
{
|
||||
Clear(count * 2);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteLittleUniNull(string value)
|
||||
{
|
||||
WriteString(value, Utility.UnicodeLE);
|
||||
Write((ushort)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteBigUni(string value, int fixedLength = -1)
|
||||
{
|
||||
if (fixedLength < 0) { fixedLength = value.Length; }
|
||||
|
||||
WriteString(value.AsSpan(0, Math.Min(fixedLength, value.Length)), Utility.Unicode);
|
||||
var count = fixedLength - value.Length;
|
||||
if (count > 0)
|
||||
{
|
||||
Clear(count * 2);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteBigUniNull(string value)
|
||||
{
|
||||
WriteString(value, Utility.Unicode);
|
||||
Write((ushort)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUTF8(string value) => WriteString(value, Utility.UTF8);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUTF8Null(string value)
|
||||
{
|
||||
WriteString(value, Utility.UTF8);
|
||||
Write((byte)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteAscii(string value, int fixedLength = -1)
|
||||
{
|
||||
if (fixedLength < 0) { fixedLength = value.Length; }
|
||||
|
||||
WriteString(value.AsSpan(0, Math.Min(fixedLength, value.Length)), Encoding.ASCII);
|
||||
var count = fixedLength - value.Length;
|
||||
if (count > 0)
|
||||
{
|
||||
Clear(count);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteAsciiNull(string value)
|
||||
{
|
||||
WriteString(value, Encoding.ASCII);
|
||||
Write((byte)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Clear()
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
_first.Slice(Position).Clear();
|
||||
_second.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
_second.Slice(Position - _first.Length).Clear();
|
||||
}
|
||||
|
||||
Position = Length;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Clear(int amount)
|
||||
{
|
||||
if (Position + amount > Length)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
int count;
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
count = Math.Min(amount, _first.Length - Position);
|
||||
_first.Slice(Position, count).Clear();
|
||||
count = amount - count;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = amount;
|
||||
}
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
_second.Slice(Position - _first.Length, count).Clear();
|
||||
}
|
||||
|
||||
Position += amount;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Seek(int offset, SeekOrigin origin) =>
|
||||
Position = origin switch
|
||||
{
|
||||
SeekOrigin.Begin => offset,
|
||||
SeekOrigin.End => Length - offset,
|
||||
_ => Position + offset // Current
|
||||
};
|
||||
}
|
||||
}
|
||||
187
Projects/Server/Buffers/SpanReader.cs
Normal file
187
Projects/Server/Buffers/SpanReader.cs
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: SpanReader.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Buffers
|
||||
{
|
||||
ref struct SpanReader
|
||||
{
|
||||
private readonly ReadOnlySpan<byte> _buffer;
|
||||
|
||||
public int Length { get; }
|
||||
public int Position { get; private set; }
|
||||
public int Remaining => Length - Position;
|
||||
|
||||
public SpanReader(ReadOnlySpan<byte> span)
|
||||
{
|
||||
_buffer = span;
|
||||
Position = 0;
|
||||
Length = span.Length;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte ReadByte()
|
||||
{
|
||||
if (Position >= Length)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
return _buffer[Position++];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool ReadBoolean() => ReadByte() > 0;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public sbyte ReadSByte() => (sbyte)ReadByte();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public short ReadInt16()
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadInt16BigEndian(_buffer.Slice(Position), out var value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ushort ReadUInt16()
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadUInt16BigEndian(_buffer.Slice(Position), out var value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int ReadInt32()
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadInt32BigEndian(_buffer.Slice(Position), out var value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint ReadUInt32()
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadUInt32BigEndian(_buffer.Slice(Position), out var value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadString(Encoding encoding, bool safeString = false, int fixedLength = -1)
|
||||
{
|
||||
int sizeT = Utility.GetByteLengthForEncoding(encoding);
|
||||
|
||||
bool isFixedLength = fixedLength > -1;
|
||||
|
||||
var remaining = Remaining;
|
||||
int size;
|
||||
|
||||
if (isFixedLength)
|
||||
{
|
||||
size = fixedLength * sizeT;
|
||||
if (size > Remaining)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size = remaining - (remaining & (sizeT - 1));
|
||||
}
|
||||
|
||||
int index = Utility.IndexOfTerminator(_buffer.Slice(Position, size), sizeT);
|
||||
|
||||
Position += isFixedLength || index < 0 ? size : index + sizeT;
|
||||
return Utility.GetString(_buffer.Slice(Position, index < 0 ? size : index), encoding, safeString);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUniSafe(int fixedLength) => ReadString(Utility.UnicodeLE, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUniSafe() => ReadString(Utility.UnicodeLE, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUni(int fixedLength) => ReadString(Utility.UnicodeLE, false, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUni() => ReadString(Utility.UnicodeLE);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUniSafe(int fixedLength) => ReadString(Utility.Unicode, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUniSafe() => ReadString(Utility.Unicode, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUni(int fixedLength) => ReadString(Utility.Unicode, false, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUni() => ReadString(Utility.Unicode);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8Safe(int fixedLength) => ReadString(Utility.UTF8, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8Safe() => ReadString(Utility.UTF8, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8() => ReadString(Utility.UTF8);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadAsciiSafe(int fixedLength) => ReadString(Encoding.ASCII, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadAsciiSafe() => ReadString(Encoding.ASCII, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadAscii(int fixedLength) => ReadString(Encoding.ASCII, false, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadAscii() => ReadString(Encoding.ASCII);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Seek(int offset, SeekOrigin origin) =>
|
||||
Position = origin switch
|
||||
{
|
||||
SeekOrigin.Begin => offset,
|
||||
SeekOrigin.End => Length - offset,
|
||||
_ => Position + offset // Current
|
||||
};
|
||||
}
|
||||
}
|
||||
244
Projects/Server/Buffers/SpanWriter.cs
Normal file
244
Projects/Server/Buffers/SpanWriter.cs
Normal file
|
|
@ -0,0 +1,244 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2020 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: SpanWriter.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers.Binary;
|
||||
using System.Data;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Server.Buffers
|
||||
{
|
||||
public ref struct SpanWriter
|
||||
{
|
||||
private readonly Span<byte> _buffer;
|
||||
|
||||
public int Length => _buffer.Length;
|
||||
|
||||
public ReadOnlySpan<byte> Span => _buffer.Slice(0, Position);
|
||||
|
||||
public int Position { get; private set; }
|
||||
|
||||
public SpanWriter(Span<byte> span)
|
||||
{
|
||||
_buffer = span;
|
||||
Position = 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public unsafe void Write(bool value)
|
||||
{
|
||||
if (Position >= Length)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
_buffer[Position++] = *(byte*) & value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(byte value)
|
||||
{
|
||||
_buffer[Position++] = value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(sbyte value)
|
||||
{
|
||||
_buffer[Position++] = (byte)value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(short value)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteInt16BigEndian(_buffer.Slice(Position), value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 2;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(ushort value)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteUInt16BigEndian(_buffer.Slice(Position), value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 2;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(int value)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteInt32BigEndian(_buffer.Slice(Position), value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 4;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(uint value)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteUInt32BigEndian(_buffer.Slice(Position), value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 4;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(long value)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteInt64BigEndian(_buffer.Slice(Position), value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 8;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(ulong value)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteUInt64BigEndian(_buffer.Slice(Position), value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 8;
|
||||
}
|
||||
|
||||
public void Write(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
var size = buffer.Length;
|
||||
if (Position + size > Length)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
buffer.Slice(0, size).CopyTo(_buffer.Slice(Position));
|
||||
Position += size;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteString<T>(string value, Encoding encoding, int fixedLength = -1) where T : struct, IEquatable<T>
|
||||
{
|
||||
int sizeT = Unsafe.SizeOf<T>();
|
||||
|
||||
if (sizeT > 2)
|
||||
{
|
||||
throw new InvalidConstraintException("WriteString only accepts byte, sbyte, char, short, and ushort as a constraint");
|
||||
}
|
||||
|
||||
value ??= string.Empty;
|
||||
|
||||
var charLength = Math.Min(fixedLength > -1 ? fixedLength : value.Length, value.Length);
|
||||
var src = value.AsSpan(0, charLength);
|
||||
|
||||
var byteCount = fixedLength > -1 ? fixedLength * sizeT : encoding.GetByteCount(value);
|
||||
|
||||
if (Position + byteCount > Length)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += encoding.GetBytes(src, _buffer.Slice(Position));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteLittleUni(string value) => WriteString<char>(value, Utility.UnicodeLE);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteLittleUniNull(string value)
|
||||
{
|
||||
WriteString<char>(value, Utility.UnicodeLE);
|
||||
Write((ushort)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteLittleUni(string value, int fixedLength) => WriteString<char>(value, Utility.UnicodeLE, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteBigUni(string value) => WriteString<char>(value, Utility.Unicode);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteBigUniNull(string value)
|
||||
{
|
||||
WriteString<char>(value, Utility.Unicode);
|
||||
Write((ushort)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteBigUni(string value, int fixedLength) => WriteString<char>(value, Utility.Unicode, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUTF8(string value) => WriteString<byte>(value, Utility.UTF8);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUTF8Null(string value)
|
||||
{
|
||||
WriteString<byte>(value, Utility.UTF8);
|
||||
Write((byte)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteAscii(string value) => WriteString<byte>(value, Encoding.ASCII);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteAsciiNull(string value)
|
||||
{
|
||||
WriteString<byte>(value, Encoding.ASCII);
|
||||
Write((byte)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteAscii(string value, int fixedLength) => WriteString<byte>(value, Encoding.ASCII, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Clear()
|
||||
{
|
||||
_buffer.Slice(Position).Clear();
|
||||
Position = Length;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Clear(int amount)
|
||||
{
|
||||
if (Position + amount > Length)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
_buffer.Slice(Position, amount).Clear();
|
||||
Position += amount;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Seek(int offset, SeekOrigin origin) =>
|
||||
Position = origin switch
|
||||
{
|
||||
SeekOrigin.Begin => offset,
|
||||
SeekOrigin.End => Length - offset,
|
||||
_ => Position + offset // Current
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
@ -2,9 +2,9 @@ namespace Server.Network
|
|||
{
|
||||
public ref struct EncodedReader
|
||||
{
|
||||
private PacketReader m_Reader;
|
||||
private CircularBufferReader m_Reader;
|
||||
|
||||
public EncodedReader(PacketReader reader) => m_Reader = reader;
|
||||
public EncodedReader(CircularBufferReader reader) => m_Reader = reader;
|
||||
|
||||
public void Trace(NetState state)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
|
|
|||
|
|
@ -227,22 +227,22 @@ namespace Server.Network
|
|||
m_CompiledLength = length;
|
||||
}
|
||||
|
||||
if (length > 0)
|
||||
if (m_CompiledLength > 0)
|
||||
{
|
||||
var old = m_CompiledBuffer;
|
||||
|
||||
if ((m_State & State.Static) != 0)
|
||||
{
|
||||
m_CompiledBuffer = new byte[length];
|
||||
m_CompiledBuffer = new byte[m_CompiledLength];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Release it later using Release()
|
||||
m_CompiledBuffer = ArrayPool<byte>.Shared.Rent(length);
|
||||
m_CompiledBuffer = ArrayPool<byte>.Shared.Rent(m_CompiledLength);
|
||||
m_State |= State.Buffered;
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(old, 0, m_CompiledBuffer, 0, length);
|
||||
Buffer.BlockCopy(old, 0, m_CompiledBuffer, 0, m_CompiledLength);
|
||||
|
||||
if (compress)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using System;
|
|||
|
||||
namespace Server.Network
|
||||
{
|
||||
public delegate void OnPacketReceive(NetState state, PacketReader reader);
|
||||
public delegate void OnPacketReceive(NetState state, CircularBufferReader reader);
|
||||
|
||||
public delegate TimeSpan ThrottlePacketCallback(NetState state);
|
||||
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ namespace Server.Network
|
|||
|
||||
public static int ProcessPacket(NetState ns, ArraySegment<byte>[] segments)
|
||||
{
|
||||
var reader = new PacketReader(segments);
|
||||
var reader = new CircularBufferReader(segments);
|
||||
|
||||
var packetId = reader.ReadByte();
|
||||
|
||||
|
|
@ -360,11 +360,11 @@ namespace Server.Network
|
|||
return packetLength;
|
||||
}
|
||||
|
||||
private static void UnhandledBF(NetState state, PacketReader reader)
|
||||
private static void UnhandledBF(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Empty(NetState state, PacketReader reader)
|
||||
public static void Empty(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -383,7 +383,7 @@ namespace Server.Network
|
|||
EventSink.InvokeQuestGumpRequest(state.Mobile);
|
||||
}
|
||||
|
||||
public static void EncodedCommand(NetState state, PacketReader reader)
|
||||
public static void EncodedCommand(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var e = World.FindEntity(reader.ReadUInt32());
|
||||
int packetId = reader.ReadUInt16();
|
||||
|
|
@ -415,7 +415,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void RenameRequest(NetState state, PacketReader reader)
|
||||
public static void RenameRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var targ = World.FindMobile(reader.ReadUInt32());
|
||||
|
|
@ -426,7 +426,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void SecureTrade(NetState state, PacketReader reader)
|
||||
public static void SecureTrade(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
switch (reader.ReadByte())
|
||||
{
|
||||
|
|
@ -498,7 +498,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void VendorBuyReply(NetState state, PacketReader reader)
|
||||
public static void VendorBuyReply(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var vendor = World.FindMobile(reader.ReadUInt32());
|
||||
var flag = reader.ReadByte();
|
||||
|
|
@ -545,7 +545,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void VendorSellReply(NetState state, PacketReader reader)
|
||||
public static void VendorSellReply(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
Serial serial = reader.ReadUInt32();
|
||||
var vendor = World.FindMobile(serial);
|
||||
|
|
@ -587,7 +587,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void DeleteCharacter(NetState state, PacketReader reader)
|
||||
public static void DeleteCharacter(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
reader.Seek(30, SeekOrigin.Current);
|
||||
var index = reader.ReadInt32();
|
||||
|
|
@ -595,12 +595,12 @@ namespace Server.Network
|
|||
EventSink.InvokeDeleteRequest(state, index);
|
||||
}
|
||||
|
||||
public static void DeathStatusResponse(NetState state, PacketReader reader)
|
||||
public static void DeathStatusResponse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
|
||||
public static void ObjectHelpRequest(NetState state, PacketReader reader)
|
||||
public static void ObjectHelpRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -629,7 +629,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void MobileNameRequest(NetState state, PacketReader reader)
|
||||
public static void MobileNameRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var m = World.FindMobile(reader.ReadUInt32());
|
||||
|
||||
|
|
@ -639,13 +639,13 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void RequestScrollWindow(NetState state, PacketReader reader)
|
||||
public static void RequestScrollWindow(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int lastTip = reader.ReadInt16();
|
||||
int type = reader.ReadByte();
|
||||
}
|
||||
|
||||
public static void AttackReq(NetState state, PacketReader reader)
|
||||
public static void AttackReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var m = World.FindMobile(reader.ReadUInt32());
|
||||
|
|
@ -656,7 +656,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void HuePickerResponse(NetState state, PacketReader reader)
|
||||
public static void HuePickerResponse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
_ = reader.ReadInt16(); // Item ID
|
||||
|
|
@ -677,7 +677,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void SystemInfo(NetState state, PacketReader reader)
|
||||
public static void SystemInfo(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int v1 = reader.ReadByte();
|
||||
int v2 = reader.ReadUInt16();
|
||||
|
|
@ -693,11 +693,11 @@ namespace Server.Network
|
|||
var v8 = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public static void AccountID(NetState state, PacketReader reader)
|
||||
public static void AccountID(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
}
|
||||
|
||||
public static void TextCommand(NetState state, PacketReader reader)
|
||||
public static void TextCommand(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int type = reader.ReadByte();
|
||||
var command = reader.ReadAscii();
|
||||
|
|
@ -790,7 +790,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void AsciiPromptResponse(NetState state, PacketReader reader)
|
||||
public static void AsciiPromptResponse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
var prompt = reader.ReadInt32();
|
||||
|
|
@ -820,7 +820,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void UnicodePromptResponse(NetState state, PacketReader reader)
|
||||
public static void UnicodePromptResponse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
var prompt = reader.ReadInt32();
|
||||
|
|
@ -851,7 +851,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void MenuResponse(NetState state, PacketReader reader)
|
||||
public static void MenuResponse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
int menuID = reader.ReadInt16(); // unused in our implementation
|
||||
|
|
@ -881,7 +881,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void ProfileReq(NetState state, PacketReader reader)
|
||||
public static void ProfileReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int type = reader.ReadByte();
|
||||
Serial serial = reader.ReadUInt32();
|
||||
|
|
@ -921,12 +921,12 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void Disconnect(NetState state, PacketReader reader)
|
||||
public static void Disconnect(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var minusOne = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public static void LiftReq(NetState state, PacketReader reader)
|
||||
public static void LiftReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
Serial serial = reader.ReadUInt32();
|
||||
int amount = reader.ReadUInt16();
|
||||
|
|
@ -935,7 +935,7 @@ namespace Server.Network
|
|||
state.Mobile.Lift(item, amount, out var rejected, out var reject);
|
||||
}
|
||||
|
||||
public static void EquipReq(NetState state, PacketReader reader)
|
||||
public static void EquipReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var item = from.Holding;
|
||||
|
|
@ -960,7 +960,7 @@ namespace Server.Network
|
|||
item.ClearBounce();
|
||||
}
|
||||
|
||||
public static void DropReq(NetState state, PacketReader reader)
|
||||
public static void DropReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
reader.ReadInt32(); // serial, ignored
|
||||
int x = reader.ReadInt16();
|
||||
|
|
@ -997,7 +997,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void DropReq6017(NetState state, PacketReader reader)
|
||||
public static void DropReq6017(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
reader.ReadInt32(); // serial, ignored
|
||||
int x = reader.ReadInt16();
|
||||
|
|
@ -1035,28 +1035,28 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void ConfigurationFile(NetState state, PacketReader reader)
|
||||
public static void ConfigurationFile(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
}
|
||||
|
||||
public static void LogoutReq(NetState state, PacketReader reader)
|
||||
public static void LogoutReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
state.Send(new LogoutAck());
|
||||
}
|
||||
|
||||
public static void ChangeSkillLock(NetState state, PacketReader reader)
|
||||
public static void ChangeSkillLock(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var s = state.Mobile.Skills[reader.ReadInt16()];
|
||||
|
||||
s?.SetLockNoRelay((SkillLock)reader.ReadByte());
|
||||
}
|
||||
|
||||
public static void HelpRequest(NetState state, PacketReader reader)
|
||||
public static void HelpRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
EventSink.InvokeHelpRequest(state.Mobile);
|
||||
}
|
||||
|
||||
public static void TargetResponse(NetState state, PacketReader reader)
|
||||
public static void TargetResponse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int type = reader.ReadByte();
|
||||
var targetID = reader.ReadInt32();
|
||||
|
|
@ -1170,7 +1170,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void DisplayGumpResponse(NetState state, PacketReader reader)
|
||||
public static void DisplayGumpResponse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
var typeID = reader.ReadInt32();
|
||||
|
|
@ -1292,12 +1292,12 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void SetWarMode(NetState state, PacketReader reader)
|
||||
public static void SetWarMode(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
state.Mobile.DelayChangeWarmode(reader.ReadBoolean());
|
||||
}
|
||||
|
||||
public static void Resynchronize(NetState state, PacketReader reader)
|
||||
public static void Resynchronize(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var m = state.Mobile;
|
||||
|
||||
|
|
@ -1319,7 +1319,7 @@ namespace Server.Network
|
|||
m.ClearFastwalkStack();
|
||||
}
|
||||
|
||||
public static void AsciiSpeech(NetState state, PacketReader reader)
|
||||
public static void AsciiSpeech(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -1341,7 +1341,7 @@ namespace Server.Network
|
|||
from.DoSpeech(text, m_EmptyInts, type, Utility.ClipDyedHue(hue));
|
||||
}
|
||||
|
||||
public static void UnicodeSpeech(NetState state, PacketReader reader)
|
||||
public static void UnicodeSpeech(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -1420,7 +1420,7 @@ namespace Server.Network
|
|||
from.DoSpeech(text, keywords, type, Utility.ClipDyedHue(hue));
|
||||
}
|
||||
|
||||
public static void UseReq(NetState state, PacketReader reader)
|
||||
public static void UseReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -1464,7 +1464,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void LookReq(NetState state, PacketReader reader)
|
||||
public static void LookReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -1513,17 +1513,17 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void PingReq(NetState state, PacketReader reader)
|
||||
public static void PingReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
state.Send(PingAck.Instantiate(reader.ReadByte()));
|
||||
}
|
||||
|
||||
public static void SetUpdateRange(NetState state, PacketReader reader)
|
||||
public static void SetUpdateRange(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
state.Send(ChangeUpdateRange.Instantiate(18));
|
||||
}
|
||||
|
||||
public static void MovementReq(NetState state, PacketReader reader)
|
||||
public static void MovementReq(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var dir = (Direction)reader.ReadByte();
|
||||
int seq = reader.ReadByte();
|
||||
|
|
@ -1551,7 +1551,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void Animate(NetState state, PacketReader reader)
|
||||
public static void Animate(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var action = reader.ReadInt32();
|
||||
|
|
@ -1569,7 +1569,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void QuestArrow(NetState state, PacketReader reader)
|
||||
public static void QuestArrow(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var rightClick = reader.ReadBoolean();
|
||||
var from = state.Mobile;
|
||||
|
|
@ -1577,7 +1577,7 @@ namespace Server.Network
|
|||
from?.QuestArrow?.OnClick(rightClick);
|
||||
}
|
||||
|
||||
public static void ExtendedCommand(NetState state, PacketReader reader)
|
||||
public static void ExtendedCommand(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int packetID = reader.ReadUInt16();
|
||||
|
||||
|
|
@ -1607,7 +1607,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void CastSpell(NetState state, PacketReader reader)
|
||||
public static void CastSpell(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -1628,7 +1628,7 @@ namespace Server.Network
|
|||
EventSink.InvokeCastSpellRequest(from, spellID, spellbook);
|
||||
}
|
||||
|
||||
public static void BandageTarget(NetState state, PacketReader reader)
|
||||
public static void BandageTarget(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -1663,12 +1663,12 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void ToggleFlying(NetState state, PacketReader reader)
|
||||
public static void ToggleFlying(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
state.Mobile.ToggleFlying();
|
||||
}
|
||||
|
||||
public static void BatchQueryProperties(NetState state, PacketReader reader)
|
||||
public static void BatchQueryProperties(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (!ObjectPropertyList.Enabled)
|
||||
{
|
||||
|
|
@ -1710,7 +1710,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void QueryProperties(NetState state, PacketReader reader)
|
||||
public static void QueryProperties(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (!ObjectPropertyList.Enabled)
|
||||
{
|
||||
|
|
@ -1742,7 +1742,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void PartyMessage(NetState state, PacketReader reader)
|
||||
public static void PartyMessage(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (state.Mobile == null)
|
||||
{
|
||||
|
|
@ -1778,17 +1778,17 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void PartyMessage_AddMember(NetState state, PacketReader reader)
|
||||
public static void PartyMessage_AddMember(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
PartyCommands.Handler?.OnAdd(state.Mobile);
|
||||
}
|
||||
|
||||
public static void PartyMessage_RemoveMember(NetState state, PacketReader reader)
|
||||
public static void PartyMessage_RemoveMember(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
PartyCommands.Handler?.OnRemove(state.Mobile, World.FindMobile(reader.ReadUInt32()));
|
||||
}
|
||||
|
||||
public static void PartyMessage_PrivateMessage(NetState state, PacketReader reader)
|
||||
public static void PartyMessage_PrivateMessage(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
PartyCommands.Handler?.OnPrivateMessage(
|
||||
state.Mobile,
|
||||
|
|
@ -1797,37 +1797,37 @@ namespace Server.Network
|
|||
);
|
||||
}
|
||||
|
||||
public static void PartyMessage_PublicMessage(NetState state, PacketReader reader)
|
||||
public static void PartyMessage_PublicMessage(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
PartyCommands.Handler?.OnPublicMessage(state.Mobile, reader.ReadBigUniSafe());
|
||||
}
|
||||
|
||||
public static void PartyMessage_SetCanLoot(NetState state, PacketReader reader)
|
||||
public static void PartyMessage_SetCanLoot(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
PartyCommands.Handler?.OnSetCanLoot(state.Mobile, reader.ReadBoolean());
|
||||
}
|
||||
|
||||
public static void PartyMessage_Accept(NetState state, PacketReader reader)
|
||||
public static void PartyMessage_Accept(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
PartyCommands.Handler?.OnAccept(state.Mobile, World.FindMobile(reader.ReadUInt32()));
|
||||
}
|
||||
|
||||
public static void PartyMessage_Decline(NetState state, PacketReader reader)
|
||||
public static void PartyMessage_Decline(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
PartyCommands.Handler?.OnDecline(state.Mobile, World.FindMobile(reader.ReadUInt32()));
|
||||
}
|
||||
|
||||
public static void StunRequest(NetState state, PacketReader reader)
|
||||
public static void StunRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
EventSink.InvokeStunRequest(state.Mobile);
|
||||
}
|
||||
|
||||
public static void DisarmRequest(NetState state, PacketReader reader)
|
||||
public static void DisarmRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
EventSink.InvokeDisarmRequest(state.Mobile);
|
||||
}
|
||||
|
||||
public static void StatLockChange(NetState state, PacketReader reader)
|
||||
public static void StatLockChange(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int stat = reader.ReadByte();
|
||||
int lockValue = reader.ReadByte();
|
||||
|
|
@ -1856,13 +1856,13 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void ScreenSize(NetState state, PacketReader reader)
|
||||
public static void ScreenSize(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var width = reader.ReadInt32();
|
||||
var unk = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public static void ContextMenuResponse(NetState state, PacketReader reader)
|
||||
public static void ContextMenuResponse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -1918,7 +1918,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void ContextMenuRequest(NetState state, PacketReader reader)
|
||||
public static void ContextMenuRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var target = World.FindEntity(reader.ReadUInt32());
|
||||
|
|
@ -1962,12 +1962,12 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void CloseStatus(NetState state, PacketReader reader)
|
||||
public static void CloseStatus(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
Serial serial = reader.ReadUInt32();
|
||||
}
|
||||
|
||||
public static void Language(NetState state, PacketReader reader)
|
||||
public static void Language(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var lang = reader.ReadAscii(4);
|
||||
|
||||
|
|
@ -1977,20 +1977,20 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void AssistVersion(NetState state, PacketReader reader)
|
||||
public static void AssistVersion(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var unk = reader.ReadInt32();
|
||||
var av = reader.ReadAscii();
|
||||
}
|
||||
|
||||
public static void ClientVersion(NetState state, PacketReader reader)
|
||||
public static void ClientVersion(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var version = state.Version = new CV(reader.ReadAscii());
|
||||
|
||||
EventSink.InvokeClientVersionReceived(state, version);
|
||||
}
|
||||
|
||||
public static void ClientType(NetState state, PacketReader reader)
|
||||
public static void ClientType(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
reader.ReadUInt16();
|
||||
|
||||
|
|
@ -2000,7 +2000,7 @@ namespace Server.Network
|
|||
EventSink.InvokeClientVersionReceived(state, version);
|
||||
}
|
||||
|
||||
public static void MobileQuery(NetState state, PacketReader reader)
|
||||
public static void MobileQuery(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -2031,7 +2031,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void PlayCharacter(NetState state, PacketReader reader)
|
||||
public static void PlayCharacter(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
reader.ReadInt32(); // 0xEDEDEDED
|
||||
|
||||
|
|
@ -2093,7 +2093,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void ShowPublicHouseContent(NetState state, PacketReader reader)
|
||||
public static void ShowPublicHouseContent(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var showPublicHouseContent = reader.ReadBoolean();
|
||||
}
|
||||
|
|
@ -2201,7 +2201,7 @@ namespace Server.Network
|
|||
m.ClearFastwalkStack();
|
||||
}
|
||||
|
||||
public static void CreateCharacter(NetState state, PacketReader reader)
|
||||
public static void CreateCharacter(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var unk1 = reader.ReadInt32();
|
||||
var unk2 = reader.ReadInt32();
|
||||
|
|
@ -2337,7 +2337,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void CreateCharacter70160(NetState state, PacketReader reader)
|
||||
public static void CreateCharacter70160(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var unk1 = reader.ReadInt32();
|
||||
var unk2 = reader.ReadInt32();
|
||||
|
|
@ -2499,7 +2499,7 @@ namespace Server.Network
|
|||
return authID;
|
||||
}
|
||||
|
||||
public static void GameLogin(NetState state, PacketReader reader)
|
||||
public static void GameLogin(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (state.SentFirstPacket)
|
||||
{
|
||||
|
|
@ -2567,7 +2567,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void PlayServer(NetState state, PacketReader reader)
|
||||
public static void PlayServer(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int index = reader.ReadInt16();
|
||||
var info = state.ServerInfo;
|
||||
|
|
@ -2588,7 +2588,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void LoginServerSeed(NetState state, PacketReader reader)
|
||||
public static void LoginServerSeed(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
state.m_Seed = reader.ReadInt32();
|
||||
state.Seeded = true;
|
||||
|
|
@ -2608,7 +2608,7 @@ namespace Server.Network
|
|||
state.Version = new ClientVersion(clientMaj, clientMin, clientRev, clientPat);
|
||||
}
|
||||
|
||||
public static void CrashReport(NetState state, PacketReader reader)
|
||||
public static void CrashReport(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var clientMaj = reader.ReadByte();
|
||||
var clientMin = reader.ReadByte();
|
||||
|
|
@ -2642,7 +2642,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void AccountLogin(NetState state, PacketReader reader)
|
||||
public static void AccountLogin(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (state.SentFirstPacket)
|
||||
{
|
||||
|
|
@ -2696,7 +2696,7 @@ namespace Server.Network
|
|||
state.Dispose();
|
||||
}
|
||||
|
||||
public static void EquipMacro(NetState state, PacketReader reader)
|
||||
public static void EquipMacro(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int count = reader.ReadByte();
|
||||
var serialList = new List<Serial>(count);
|
||||
|
|
@ -2708,7 +2708,7 @@ namespace Server.Network
|
|||
EventSink.InvokeEquipMacro(state.Mobile, serialList);
|
||||
}
|
||||
|
||||
public static void UnequipMacro(NetState state, PacketReader reader)
|
||||
public static void UnequipMacro(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int count = reader.ReadByte();
|
||||
var layers = new List<Layer>(count);
|
||||
|
|
@ -2720,21 +2720,21 @@ namespace Server.Network
|
|||
EventSink.InvokeUnequipMacro(state.Mobile, layers);
|
||||
}
|
||||
|
||||
public static void TargetedSpell(NetState state, PacketReader reader)
|
||||
public static void TargetedSpell(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var spellId = (short)(reader.ReadInt16() - 1); // zero based;
|
||||
|
||||
EventSink.InvokeTargetedSpell(state.Mobile, World.FindEntity(reader.ReadUInt32()), spellId);
|
||||
}
|
||||
|
||||
public static void TargetedSkillUse(NetState state, PacketReader reader)
|
||||
public static void TargetedSkillUse(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var skillId = reader.ReadInt16();
|
||||
|
||||
EventSink.InvokeTargetedSkillUse(state.Mobile, World.FindEntity(reader.ReadUInt32()), skillId);
|
||||
}
|
||||
|
||||
public static void TargetByResourceMacro(NetState state, PacketReader reader)
|
||||
public static void TargetByResourceMacro(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
Serial serial = reader.ReadUInt32();
|
||||
|
||||
|
|
|
|||
|
|
@ -118,55 +118,55 @@ namespace Server.Network
|
|||
return result;
|
||||
}
|
||||
|
||||
public void Advance(uint bytes)
|
||||
public void Advance(uint count)
|
||||
{
|
||||
var read = _pipe._readIdx;
|
||||
var write = _pipe._writeIdx;
|
||||
|
||||
if (bytes == 0)
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytes > _pipe.Size - 1)
|
||||
if (count > _pipe.Size - 1)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
if (read <= write)
|
||||
{
|
||||
if (bytes > read + _pipe.Size - write - 1)
|
||||
if (count > read + _pipe.Size - write - 1)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
var sz = Math.Min(bytes, _pipe.Size - write);
|
||||
var sz = Math.Min(count, _pipe.Size - write);
|
||||
|
||||
write += sz;
|
||||
if (write > _pipe.Size - 1)
|
||||
{
|
||||
write = 0;
|
||||
}
|
||||
bytes -= sz;
|
||||
count -= sz;
|
||||
|
||||
if (bytes > 0)
|
||||
if (count > 0)
|
||||
{
|
||||
if (bytes >= read)
|
||||
if (count >= read)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
write = bytes;
|
||||
write = count;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bytes > read - write - 1)
|
||||
if (count > read - write - 1)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
write += bytes;
|
||||
write += count;
|
||||
}
|
||||
|
||||
// It's never valid to advance the write pointer to become equal to
|
||||
|
|
@ -216,7 +216,7 @@ namespace Server.Network
|
|||
internal PipeReader(Pipe<T> pipe) => _pipe = pipe;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint GetRemaining()
|
||||
public uint GetAvailable()
|
||||
{
|
||||
var read = _pipe._readIdx;
|
||||
var write = _pipe._writeIdx;
|
||||
|
|
@ -260,39 +260,39 @@ namespace Server.Network
|
|||
return this;
|
||||
}
|
||||
|
||||
public void Advance(uint bytes)
|
||||
public void Advance(uint count)
|
||||
{
|
||||
var read = _pipe._readIdx;
|
||||
var write = _pipe._writeIdx;
|
||||
|
||||
if (read <= write)
|
||||
{
|
||||
if (bytes > write - read)
|
||||
if (count > write - read)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
read += bytes;
|
||||
read += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
var sz = Math.Min(bytes, _pipe.Size - read);
|
||||
var sz = Math.Min(count, _pipe.Size - read);
|
||||
|
||||
read += sz;
|
||||
if (read > _pipe.Size - 1)
|
||||
{
|
||||
read = 0;
|
||||
}
|
||||
bytes -= sz;
|
||||
count -= sz;
|
||||
|
||||
if (bytes > 0)
|
||||
if (count > 0)
|
||||
{
|
||||
if (bytes > write)
|
||||
if (count > write)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
read = bytes;
|
||||
read = count;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -309,7 +309,7 @@ namespace Server.Network
|
|||
{
|
||||
get
|
||||
{
|
||||
if (GetRemaining() > 0)
|
||||
if (GetAvailable() > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using System.Linq;
|
|||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using Server.Random;
|
||||
|
|
@ -106,6 +107,55 @@ namespace Server
|
|||
public static Encoding Unicode => m_Unicode ??= new UnicodeEncoding(true, false, false);
|
||||
public static Encoding UnicodeLE => m_UnicodeLE ??= new UnicodeEncoding(false, false, false);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int GetByteLengthForEncoding(Encoding encoding) =>
|
||||
encoding.BodyName switch
|
||||
{
|
||||
"utf-16BE" => 2,
|
||||
"utf-16" => 2,
|
||||
"utf-32BE" => 4,
|
||||
"utf-32" => 4,
|
||||
_ => 1
|
||||
};
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int IndexOfTerminator(ReadOnlySpan<byte> buffer, int sizeT) =>
|
||||
sizeT switch
|
||||
{
|
||||
2 => MemoryMarshal.Cast<byte, char>(buffer).IndexOf((char)0) * 2,
|
||||
4 => MemoryMarshal.Cast<byte, uint>(buffer).IndexOf((uint)0) * 4,
|
||||
_ => buffer.IndexOf((byte)0)
|
||||
};
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsSafeChar(ushort c) => c >= 0x20 && c < 0xFFFE;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string GetString(ReadOnlySpan<byte> span, Encoding encoding, bool safeString = false)
|
||||
{
|
||||
string s = encoding.GetString(span);
|
||||
|
||||
if (!safeString)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
ReadOnlySpan<char> chars = s.AsSpan();
|
||||
|
||||
StringBuilder stringBuilder = null;
|
||||
|
||||
for (int i = 0, last = 0; i < chars.Length; i++)
|
||||
{
|
||||
if (!IsSafeChar(chars[i]) || stringBuilder != null && i == chars.Length - 1)
|
||||
{
|
||||
(stringBuilder ??= new StringBuilder()).Append(chars.Slice(last, i - last));
|
||||
last = i + 1; // Skip the unsafe char
|
||||
}
|
||||
}
|
||||
|
||||
return stringBuilder?.ToString() ?? s;
|
||||
}
|
||||
|
||||
public static void Separate(StringBuilder sb, string value, string separator)
|
||||
{
|
||||
if (sb.Length > 0)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ namespace Server.Engines.Chat
|
|||
to?.Send(new ChatMessagePacket(null, (int)type + 20, param1, param2));
|
||||
}
|
||||
|
||||
public static void OpenChatWindowRequest(NetState state, PacketReader reader)
|
||||
public static void OpenChatWindowRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ namespace Server.Engines.Chat
|
|||
return user;
|
||||
}
|
||||
|
||||
public static void ChatAction(NetState state, PacketReader reader)
|
||||
public static void ChatAction(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (!Enabled)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ namespace Server.Engines.MLQuests.Gumps
|
|||
return false;
|
||||
}
|
||||
|
||||
private static void RaceChangeReply(NetState state, PacketReader reader)
|
||||
private static void RaceChangeReply(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (!m_Pending.TryGetValue(state, out var raceChangeState))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -366,7 +366,7 @@ namespace Server.Items
|
|||
PacketHandlers.Register(0x93, 99, true, OldHeaderChange);
|
||||
}
|
||||
|
||||
public static void OldHeaderChange(NetState state, PacketReader reader)
|
||||
public static void OldHeaderChange(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -385,7 +385,7 @@ namespace Server.Items
|
|||
book.Author = Utility.FixHtml(author);
|
||||
}
|
||||
|
||||
public static void HeaderChange(NetState state, PacketReader reader)
|
||||
public static void HeaderChange(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -419,7 +419,7 @@ namespace Server.Items
|
|||
book.Author = Utility.FixHtml(author);
|
||||
}
|
||||
|
||||
public static void ContentChange(NetState state, PacketReader reader)
|
||||
public static void ContentChange(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ using Server.Network;
|
|||
|
||||
namespace Server.Engines.Mahjong
|
||||
{
|
||||
public delegate void OnMahjongPacketReceive(MahjongGame game, NetState state, PacketReader reader);
|
||||
public delegate void OnMahjongPacketReceive(MahjongGame game, NetState state, CircularBufferReader reader);
|
||||
|
||||
public sealed class MahjongPacketHandlers
|
||||
{
|
||||
|
|
@ -41,7 +41,7 @@ namespace Server.Engines.Mahjong
|
|||
RegisterSubCommand(0x18, MoveDealerIndicator);
|
||||
}
|
||||
|
||||
public static void OnPacket(NetState state,PacketReader reader)
|
||||
public static void OnPacket(NetState state,CircularBufferReader reader)
|
||||
{
|
||||
var game = World.FindItem(reader.ReadUInt32()) as MahjongGame;
|
||||
|
||||
|
|
@ -85,7 +85,7 @@ namespace Server.Engines.Mahjong
|
|||
};
|
||||
}
|
||||
|
||||
public static void ExitGame(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void ExitGame(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game == null)
|
||||
{
|
||||
|
|
@ -97,7 +97,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.LeaveGame(from);
|
||||
}
|
||||
|
||||
public static void GivePoints(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void GivePoints(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGamePlayer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -110,7 +110,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.TransferScore(state.Mobile, to, amount);
|
||||
}
|
||||
|
||||
public static void RollDice(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void RollDice(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGamePlayer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -120,7 +120,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Dices.RollDices(state.Mobile);
|
||||
}
|
||||
|
||||
public static void BuildWalls(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void BuildWalls(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -130,7 +130,7 @@ namespace Server.Engines.Mahjong
|
|||
game.ResetWalls(state.Mobile);
|
||||
}
|
||||
|
||||
public static void ResetScores(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void ResetScores(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -140,7 +140,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.ResetScores(MahjongGame.BaseScore);
|
||||
}
|
||||
|
||||
public static void AssignDealer(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void AssignDealer(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -152,7 +152,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.AssignDealer(position);
|
||||
}
|
||||
|
||||
public static void OpenSeat(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void OpenSeat(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -169,7 +169,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.OpenSeat(position);
|
||||
}
|
||||
|
||||
public static void ChangeOption(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void ChangeOption(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -185,7 +185,7 @@ namespace Server.Engines.Mahjong
|
|||
game.SpectatorVision = (options & 0x2) != 0;
|
||||
}
|
||||
|
||||
public static void MoveWallBreakIndicator(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void MoveWallBreakIndicator(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -198,7 +198,7 @@ namespace Server.Engines.Mahjong
|
|||
game.WallBreakIndicator.Move(new Point2D(x, y));
|
||||
}
|
||||
|
||||
public static void TogglePublicHand(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void TogglePublicHand(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGamePlayer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -213,7 +213,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.SetPublic(game.Players.GetPlayerIndex(state.Mobile), publicHand);
|
||||
}
|
||||
|
||||
public static void MoveTile(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void MoveTile(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGamePlayer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -248,7 +248,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Tiles[number].Move(new Point2D(x, y), direction, flip, game.Players.GetPlayerIndex(state.Mobile));
|
||||
}
|
||||
|
||||
public static void MoveDealerIndicator(MahjongGame game, NetState state, PacketReader reader)
|
||||
public static void MoveDealerIndicator(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -334,7 +334,7 @@ namespace Server.Items
|
|||
PacketHandlers.Register(0x56, 11, true, OnMapCommand);
|
||||
}
|
||||
|
||||
private static void OnMapCommand(NetState state, PacketReader reader)
|
||||
private static void OnMapCommand(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -232,7 +232,7 @@ namespace Server.Items
|
|||
PacketHandlers.Register(0x71, 0, true, BBClientRequest);
|
||||
}
|
||||
|
||||
public static void BBClientRequest(NetState state, PacketReader reader)
|
||||
public static void BBClientRequest(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -260,7 +260,7 @@ namespace Server.Items
|
|||
}
|
||||
}
|
||||
|
||||
public static void BBRequestContent(Mobile from, BaseBulletinBoard board, PacketReader reader)
|
||||
public static void BBRequestContent(Mobile from, BaseBulletinBoard board, CircularBufferReader reader)
|
||||
{
|
||||
if (!(World.FindItem(reader.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board)
|
||||
{
|
||||
|
|
@ -270,7 +270,7 @@ namespace Server.Items
|
|||
from.Send(new BBMessageContent(board, msg));
|
||||
}
|
||||
|
||||
public static void BBRequestHeader(Mobile from, BaseBulletinBoard board, PacketReader reader)
|
||||
public static void BBRequestHeader(Mobile from, BaseBulletinBoard board, CircularBufferReader reader)
|
||||
{
|
||||
if (!(World.FindItem(reader.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board)
|
||||
{
|
||||
|
|
@ -280,7 +280,7 @@ namespace Server.Items
|
|||
from.Send(new BBMessageHeader(board, msg));
|
||||
}
|
||||
|
||||
public static void BBPostMessage(Mobile from, BaseBulletinBoard board, PacketReader reader)
|
||||
public static void BBPostMessage(Mobile from, BaseBulletinBoard board, CircularBufferReader reader)
|
||||
{
|
||||
var thread = World.FindItem(reader.ReadUInt32()) as BulletinMessage;
|
||||
|
||||
|
|
@ -337,7 +337,7 @@ namespace Server.Items
|
|||
board.PostMessage(from, thread, subject, lines);
|
||||
}
|
||||
|
||||
public static void BBRemoveMessage(Mobile from, BaseBulletinBoard board, PacketReader reader)
|
||||
public static void BBRemoveMessage(Mobile from, BaseBulletinBoard board, CircularBufferReader reader)
|
||||
{
|
||||
if (!(World.FindItem(reader.ReadUInt32()) is BulletinMessage msg) || msg.Parent != board)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
public static void OnReceive(NetState state, PacketReader reader)
|
||||
public static void OnReceive(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
reader.ReadByte(); // 1: <4.0.1a, 2>=4.0.1a
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace Server.Misc
|
|||
}
|
||||
}
|
||||
|
||||
private static void OnPartyTrack(NetState state, PacketReader reader)
|
||||
private static void OnPartyTrack(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var party = Party.Get(from);
|
||||
|
|
@ -36,7 +36,7 @@ namespace Server.Misc
|
|||
}
|
||||
}
|
||||
|
||||
private static void OnGuildTrack(NetState state, PacketReader reader)
|
||||
private static void OnGuildTrack(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace Server.Misc
|
|||
public static PacketHandler GetHandler(int packetID) =>
|
||||
packetID >= 0 && packetID < m_Handlers.Length ? m_Handlers[packetID] : null;
|
||||
|
||||
public static void DecodeBundledPacket(NetState state, PacketReader reader)
|
||||
public static void DecodeBundledPacket(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
int packetID = reader.ReadByte();
|
||||
|
||||
|
|
|
|||
|
|
@ -1770,7 +1770,7 @@ namespace Server.Multis
|
|||
context.Foundation.SendInfoTo(state);
|
||||
}
|
||||
|
||||
public static void QueryDesignDetails(NetState state, PacketReader reader)
|
||||
public static void QueryDesignDetails(NetState state, CircularBufferReader reader)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue