feat: Adds a memory mirrored ring buffer for networking. (#1533)
## Breaking Changes
Incoming packet registration signature has changed to:
```cs
delegate* void OnReceiveCallback(NetState state, SpanReader reader, int packetLength);
IncomingPackets.Register(int packetID, int length, bool ingame, OnReceiveCallback onReceive);
```
For example, an incoming packet handler signature would now look like this:
```cs
public static void SomeIncomingPacket(NetState state, SpanReader reader, int packetLength)
{
// Parse the data
}
```
## Summary
Updates the network Pipe class to use a mirrored memory technique. This technique involves mapping the same physical memory to two contiguous virtual memory spaces so the byte buffer appears duplicated. This allows writing to a double-sized array to wrap around without the need for the `CircularBuffer` classes.
In practice this allows us to use `Span<byte>` as if the buffer was a regular array.
### Bug Fixes
- [X] Fixes bad fixed length string parsing
This commit is contained in:
parent
629a5008c3
commit
10a69bf754
83 changed files with 958 additions and 2432 deletions
2
.github/workflows/build-test.yml
vendored
2
.github/workflows/build-test.yml
vendored
|
|
@ -80,7 +80,7 @@ jobs:
|
|||
- name: Setup .NET 7
|
||||
uses: actions/setup-dotnet@v3
|
||||
with:
|
||||
dotnet-version: 7.0.400
|
||||
dotnet-version: 7.0.401
|
||||
- name: Build
|
||||
run: ./publish.sh Release
|
||||
- name: Test
|
||||
|
|
|
|||
|
|
@ -1,103 +0,0 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests.Network
|
||||
{
|
||||
public class CircularBufferReaderTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("Test String", "us-ascii", false, -1, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("Test String", "us-ascii", false, -1, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("Test String", "us-ascii", false, -1, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("Test String", "us-ascii", false, 8, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("Test String", "us-ascii", false, 8, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("Test String", "us-ascii", false, 8, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("Test String", "us-ascii", false, 20, 1024, 1024, 0)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("Test String", "us-ascii", false, 20, 1024, 1024, 1030)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("Test String", "us-ascii", false, 20, 1024, 1024, 1020)]
|
||||
[InlineData("Test String", "utf-8", 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)]
|
||||
[InlineData("测试", "utf-8", true, -1, 1024, 1024, 0)]
|
||||
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[offset..]);
|
||||
|
||||
var reader = new CircularBufferReader(buffer[..firstSize], buffer[firstSize..]);
|
||||
reader.Seek(offset, SeekOrigin.Begin);
|
||||
|
||||
var actual = reader.ReadString(encoding, isSafe, fixedLength);
|
||||
|
||||
Assert.Equal(value[..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[4..14]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests.Buffers
|
||||
{
|
||||
public class CircularBufferWriterTests
|
||||
{
|
||||
[Theory]
|
||||
[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)]
|
||||
[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)]
|
||||
[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)]
|
||||
[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)]
|
||||
[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)]
|
||||
[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)]
|
||||
[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)]
|
||||
[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)]
|
||||
[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[..firstSize], buffer[firstSize..]);
|
||||
writer.Seek(offset, SeekOrigin.Begin);
|
||||
writer.WriteString(chars, encoding);
|
||||
|
||||
if (offset > 0)
|
||||
{
|
||||
Span<byte> testEmpty = stackalloc byte[offset];
|
||||
testEmpty.Clear();
|
||||
AssertThat.Equal(buffer[..offset], testEmpty);
|
||||
}
|
||||
|
||||
Span<byte> expectedStr = stackalloc byte[encoding.GetByteCount(chars)];
|
||||
encoding.GetBytes(chars, expectedStr[..]);
|
||||
|
||||
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[offset..], testEmpty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -84,8 +84,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendChangeCharacter(account);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -97,8 +97,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
|
||||
ns.SendClientVersionRequest();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -109,8 +109,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCharacterDeleteResult(DeleteResultType.BadRequest);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -121,8 +121,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPopupMessage(PMMessage.LoginSyncError);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory, InlineData(ProtocolChanges.Version70610), InlineData(ProtocolChanges.Version6000)]
|
||||
|
|
@ -148,8 +148,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
var expected = new SupportedFeatures(ns).Compile();
|
||||
ns.SendSupportedFeature();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -169,8 +169,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendLoginConfirmation(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -181,8 +181,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendLoginComplete();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -206,8 +206,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCharacterListUpdate(account);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -240,8 +240,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
|
||||
ns.SendCharacterList();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -273,8 +273,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
|
||||
ns.SendCharacterList();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -286,8 +286,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendAccountLoginRejected(reason);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -305,8 +305,8 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
|
||||
ns.SendAccountLoginAck();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -321,7 +321,7 @@ public class AccountPacketTests : IClassFixture<ServerFixture>
|
|||
|
||||
ns.SendPlayServerAck(si, authId);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSwing(attacker, defender);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory, InlineData(true), InlineData(false)]
|
||||
|
|
@ -29,8 +29,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSetWarMode(warmode);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -43,8 +43,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendChangeCombatant(serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayContainer(serial, gumpId);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -36,8 +36,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges = ns.ProtocolChanges | ProtocolChanges.ContainerGridLines | ProtocolChanges.HighSeas;
|
||||
ns.SendDisplayContainer(serial, gumpId);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -50,8 +50,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplaySpellbook(serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -65,8 +65,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges = ns.ProtocolChanges | ProtocolChanges.ContainerGridLines | ProtocolChanges.HighSeas;
|
||||
ns.SendDisplaySpellbook(serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -86,8 +86,8 @@ namespace Server.Tests.Network
|
|||
ns.SendSpellbookContent(serial, graphic, offset, content);
|
||||
ObjectPropertyList.Enabled = opl;
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -103,8 +103,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSpellbookContent(serial, graphic, offset, content);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -121,8 +121,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
|
||||
ns.SendSpellbookContent(serial, graphic, offset, content);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -136,8 +136,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendContainerContentUpdate(item);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -152,8 +152,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
|
||||
ns.SendContainerContentUpdate(item);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -173,8 +173,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendContainerContent(m, cont);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -195,8 +195,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
|
||||
ns.SendContainerContent(m, cont);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDamage(serial, inputAmount);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory, InlineData(10), InlineData(-5), InlineData(1024), InlineData(100000)]
|
||||
|
|
@ -32,8 +32,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendDamage(serial, inputAmount);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSoundEffect(soundID, p);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -98,8 +98,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendScreenEffect(screenType);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ namespace Server.Tests.Network
|
|||
new List<EquipInfoAttribute>(info.Attributes)
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -59,8 +59,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendEquipUpdate(item);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCloseGump(typeId, buttonId);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -33,8 +33,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplaySignGump(gumpSerial, gumpId, unknownString, caption);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -51,8 +51,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendDisplayGump(gump, out _, out _);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -74,8 +74,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendDisplayGump(gump, out _, out _);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendWorldItem(item);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -74,8 +74,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges = ProtocolChanges.StygianAbyss;
|
||||
ns.SendWorldItem(item);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -110,8 +110,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges = ProtocolChanges.StygianAbyss | ProtocolChanges.HighSeas;
|
||||
ns.SendWorldItem(item);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendGlobalLightLevel(lightLevel);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -29,8 +29,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPersonalLightLevel(serial, lightLevel);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendMapPatches();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -27,8 +27,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendInvalidMap();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -42,8 +42,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMapChange(map);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayItemListMenu(menu);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -70,8 +70,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayQuestionMenu(menu);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -98,8 +98,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendDisplayContextMenu(menu);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -42,8 +42,8 @@ namespace Server.Tests.Network
|
|||
args
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -87,8 +87,8 @@ namespace Server.Tests.Network
|
|||
args
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -125,8 +125,8 @@ namespace Server.Tests.Network
|
|||
text
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -165,8 +165,8 @@ namespace Server.Tests.Network
|
|||
text
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -180,8 +180,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendFollowMessage(serial, serial2);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -195,8 +195,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendHelpResponse(s, text);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
internal class TestPrompt : Prompt
|
||||
|
|
@ -214,8 +214,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPrompt(prompt);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDeathAnimation(killed, corpse);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -33,8 +33,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendBondedStatus(petSerial, bonded);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -53,8 +53,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendMobileMoving(m, noto);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -71,8 +71,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileName(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -103,8 +103,8 @@ namespace Server.Tests.Network
|
|||
delay
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -129,8 +129,8 @@ namespace Server.Tests.Network
|
|||
delay
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -149,8 +149,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileHealthbar(m, Healthbar.Poison);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -170,8 +170,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileHealthbar(m, Healthbar.Yellow);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -193,8 +193,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileStatusCompact(m, canBeRenamed);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -227,8 +227,8 @@ namespace Server.Tests.Network
|
|||
var expected = new MobileStatus(beholder, beheld, ns).Compile();
|
||||
ns.SendMobileStatus(beholder, beheld);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -266,8 +266,8 @@ namespace Server.Tests.Network
|
|||
var expected = new MobileStatusExtended(m, ns).Compile();
|
||||
ns.SendMobileStatus(m, m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
Core.Expansion = oldExpansion;
|
||||
expansionInfo.MobileStatusVersion = oldVersion;
|
||||
}
|
||||
|
|
@ -287,8 +287,8 @@ namespace Server.Tests.Network
|
|||
var expected = new MobileUpdate(m, ns.StygianAbyss).Compile();
|
||||
ns.SendMobileUpdate(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -342,8 +342,8 @@ namespace Server.Tests.Network
|
|||
var expected = new MobileIncoming(ns, beholder, beheld).Compile();
|
||||
ns.SendMobileIncoming(beholder, beheld);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -359,8 +359,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileHits(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -376,8 +376,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileHits(m, true);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -393,8 +393,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileMana(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -410,8 +410,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileMana(m, true);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -427,8 +427,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileStam(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -444,8 +444,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileStam(m, true);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -465,8 +465,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileAttributes(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -486,8 +486,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMobileAttributes(m, true);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -499,8 +499,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendRemoveEntity(e);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSpeedControl((SpeedControlSetting)speedControl);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -30,8 +30,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMovePlayer(d);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -47,8 +47,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMovementRej(seq, m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -64,8 +64,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMovementAck(seq, m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendStatLockInfo(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -38,8 +38,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendChangeUpdateRange((byte)range);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -52,8 +52,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDeathStatus(dead);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -66,8 +66,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayProfile((Serial)serial, header, body, footer);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -80,8 +80,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendLiftReject(reason);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -92,8 +92,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendLogoutAck();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -107,8 +107,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendWeather((byte)type, (byte)density, (byte)temp);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -122,8 +122,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendServerChange(p, map);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -137,8 +137,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSequence(num);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -153,8 +153,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendLaunchBrowser(uri);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -177,8 +177,8 @@ namespace Server.Tests.Network
|
|||
itemId, hue, amount
|
||||
);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -191,8 +191,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSeasonChange((byte)season, playSound);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -206,8 +206,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayPaperdoll((Serial)m, title, warmode, canLift);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -221,8 +221,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPlayMusic(music);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -235,8 +235,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendScrollMessage(type, tip ,text);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -249,8 +249,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCurrentTime(date);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -263,8 +263,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPathfindMessage(p);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -278,8 +278,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPingAck(ping);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -293,8 +293,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayHuePicker(huePicker.Serial, huePicker.ItemID);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplaySecureTrade(m, firstCont, secondCont, name);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -37,8 +37,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCloseSecureTrade(cont);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory, InlineData(true, false), InlineData(false, true)]
|
||||
|
|
@ -55,8 +55,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendUpdateSecureTrade(cont, first, second);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -70,8 +70,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendUpdateSecureTrade(cont, flag, gold, plat);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -88,8 +88,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSecureTradeEquip(itemInCont, m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -108,8 +108,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendSecureTradeEquip(itemInCont, m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,8 +44,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges |= ProtocolChanges.HighSeas;
|
||||
ns.SendMultiTargetReq(t);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -60,8 +60,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMultiTargetReq(t);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -71,8 +71,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCancelTarget();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -84,8 +84,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendTargetReq(t);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,8 +30,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendVendorBuyContent(buyStates);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -49,8 +49,8 @@ namespace Server.Tests.Network
|
|||
|
||||
ns.SendDisplayBuyList(vendor.Serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -73,8 +73,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendVendorBuyList(vendor, buyStates);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -88,8 +88,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendEndVendorBuy(vendor.Serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendVendorSellList(vendor.Serial, sellStates);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -46,8 +46,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendEndVendorSell(vendor.Serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ namespace Server.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendHairEquipUpdatePacket(m, HairInfo.FakeSerial(m.Serial), m.HairItemID, m.HairHue, Layer.Hair);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -35,8 +35,8 @@ namespace Server.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendRemoveHairPacket(HairInfo.FakeSerial(m.Serial));
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,244 +1,89 @@
|
|||
using System;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests.Network
|
||||
namespace Server.Tests.Network;
|
||||
|
||||
public class PipeTests
|
||||
{
|
||||
[Collection("Sequential Tests")]
|
||||
public class PipeTests
|
||||
[Fact]
|
||||
public void TestSizeMatchesPageSize()
|
||||
{
|
||||
private async void DelayedExecute(Action action)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
var pageSize = (uint)Environment.SystemPageSize;
|
||||
using var pipe = new Pipe(128);
|
||||
|
||||
action();
|
||||
// Available memory should be in increments of system page size minus one.
|
||||
Assert.Equal(pageSize, pipe.Size);
|
||||
Assert.Equal(pageSize - 1, (uint)pipe.Writer.AvailableToWrite().Length);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteReadsWrap()
|
||||
{
|
||||
var pageSize = (uint)Environment.SystemPageSize;
|
||||
using var pipe = new Pipe(pageSize);
|
||||
|
||||
var span = pipe.Writer.AvailableToWrite();
|
||||
|
||||
for (var i = 0; i < span.Length; i++)
|
||||
{
|
||||
span[i] = (byte)(i % 256);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void AwaitRead()
|
||||
pipe.Writer.Advance((uint)(span.Length - 10));
|
||||
|
||||
var readBytes = pipe.Reader.AvailableToRead();
|
||||
|
||||
// Make a sequence from what we expect.
|
||||
Span<byte> seq = new byte[readBytes.Length];
|
||||
for (var i = 0; i < readBytes.Length; i++)
|
||||
{
|
||||
var pipe = new Pipe<byte>(new byte[128]);
|
||||
|
||||
var reader = pipe.Reader;
|
||||
var writer = pipe.Writer;
|
||||
|
||||
DelayedExecute(() =>
|
||||
{
|
||||
// Write some data into the pipe
|
||||
var buffer = writer.TryGetMemory();
|
||||
Assert.Equal(127, buffer.Length);
|
||||
|
||||
buffer.CopyFrom(new byte[] { 1 });
|
||||
buffer.CopyFrom(new byte[] { 2 });
|
||||
buffer.CopyFrom(new byte[] { 3 });
|
||||
|
||||
writer.Advance(3);
|
||||
writer.Flush();
|
||||
});
|
||||
|
||||
var result = await reader.Read();
|
||||
|
||||
Assert.Equal(3, result.Buffer[0].Count);
|
||||
seq[i] = (byte)(i % 256);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void AwaitWrite()
|
||||
AssertThat.Equal(readBytes, seq);
|
||||
|
||||
// Advance by half. Expected writer length should be half + 10
|
||||
pipe.Reader.Advance(pageSize / 2);
|
||||
|
||||
span = pipe.Writer.AvailableToWrite();
|
||||
|
||||
var halfStart = pageSize / 2 + 10;
|
||||
|
||||
Assert.Equal(halfStart, (uint)span.Length);
|
||||
|
||||
seq = new byte[20];
|
||||
|
||||
for (var i = 0; i < 10; i++)
|
||||
{
|
||||
var pipe = new Pipe<byte>(new byte[128]);
|
||||
|
||||
var reader = pipe.Reader;
|
||||
var writer = pipe.Writer;
|
||||
|
||||
// Fill the entire pipe up
|
||||
writer.Advance(127);
|
||||
|
||||
DelayedExecute(() =>
|
||||
{
|
||||
// Read some data from the pipe
|
||||
var buffer = reader.TryRead();
|
||||
Assert.Equal(127, buffer.Length);
|
||||
|
||||
reader.Advance(50);
|
||||
reader.Commit();
|
||||
});
|
||||
|
||||
var result = await writer.GetMemory();
|
||||
Assert.Equal(50, result.Length);
|
||||
seq[i] = (byte)(0xF5 + i);
|
||||
}
|
||||
|
||||
private bool _signal;
|
||||
|
||||
private void Consumer(object state)
|
||||
// The last element, the sentinel, is excluded.
|
||||
// The wrap around values start at 11
|
||||
for (var i = 11; i < 20; i++)
|
||||
{
|
||||
var reader = ((Pipe<byte>)state).Reader;
|
||||
|
||||
int count = 0;
|
||||
byte expected_value = 0xFA;
|
||||
|
||||
while (count < 0x8000000)
|
||||
{
|
||||
var result = reader.TryRead();
|
||||
|
||||
for (int i = 0; i < result.Buffer[0].Count; i++)
|
||||
{
|
||||
Assert.Equal(expected_value, result.Buffer[0][i]);
|
||||
count++;
|
||||
|
||||
if (count == 0x1000)
|
||||
{
|
||||
expected_value = 0xAC;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < result.Buffer[1].Count; i++)
|
||||
{
|
||||
Assert.Equal(expected_value, result.Buffer[1][i]);
|
||||
count++;
|
||||
|
||||
if (count == 0x1000)
|
||||
{
|
||||
expected_value = 0xAC;
|
||||
}
|
||||
}
|
||||
|
||||
reader.Advance((uint)result.Length);
|
||||
}
|
||||
|
||||
_signal = true;
|
||||
seq[i] = (byte)(i - 11);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async void Threading()
|
||||
// Test the uncommitted overwritten memory and shifted offset to make sure the ring is working
|
||||
AssertThat.Equal(span[..20], seq[..20]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestWriteReadMatches()
|
||||
{
|
||||
var pipe = new Pipe(16);
|
||||
|
||||
var reader = pipe.Reader;
|
||||
var writer = pipe.Writer;
|
||||
|
||||
for (uint i = 0; i < 16; i++)
|
||||
{
|
||||
var pipe = new Pipe<byte>(new byte[0x1000]);
|
||||
writer.Advance(i);
|
||||
|
||||
ThreadPool.UnsafeQueueUserWorkItem(Consumer, pipe);
|
||||
|
||||
var writer = pipe.Writer;
|
||||
|
||||
int count = 0;
|
||||
byte expected_value = 0xFA;
|
||||
|
||||
while (count < 0x8000000)
|
||||
{
|
||||
var result = writer.TryGetMemory();
|
||||
|
||||
if (result.Length < 16)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.CopyFrom(new[] {
|
||||
expected_value, expected_value, expected_value, expected_value,
|
||||
expected_value, expected_value, expected_value, expected_value,
|
||||
expected_value, expected_value, expected_value, expected_value,
|
||||
expected_value, expected_value, expected_value, expected_value
|
||||
});
|
||||
|
||||
writer.Advance(16);
|
||||
count += 16;
|
||||
|
||||
if (count == 0x1000)
|
||||
{
|
||||
expected_value = 0xAC;
|
||||
}
|
||||
}
|
||||
|
||||
while (_signal == false) { }
|
||||
|
||||
_signal = false;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Wrap()
|
||||
{
|
||||
var pipe = new Pipe<byte>(new byte[16]);
|
||||
|
||||
var reader = pipe.Reader;
|
||||
var writer = pipe.Writer;
|
||||
|
||||
var result = writer.TryGetMemory();
|
||||
Assert.Equal(15, result.Length);
|
||||
Assert.Equal(0u, reader.GetAvailable());
|
||||
result = reader.TryRead();
|
||||
Assert.Equal(0, result.Length);
|
||||
|
||||
writer.Advance(7);
|
||||
result = writer.TryGetMemory();
|
||||
Assert.Equal(8, result.Length);
|
||||
Assert.Equal(7u, reader.GetAvailable());
|
||||
result = reader.TryRead();
|
||||
Assert.Equal(7, result.Length);
|
||||
|
||||
reader.Advance(4);
|
||||
result = writer.TryGetMemory();
|
||||
Assert.Equal(12, result.Length);
|
||||
Assert.Equal(3u, reader.GetAvailable());
|
||||
result = reader.TryRead();
|
||||
Assert.Equal(3, result.Length);
|
||||
|
||||
writer.Advance(3);
|
||||
result = writer.TryGetMemory();
|
||||
Assert.Equal(9, result.Length);
|
||||
Assert.Equal(6u, reader.GetAvailable());
|
||||
result = reader.TryRead();
|
||||
Assert.Equal(6, result.Length);
|
||||
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Match()
|
||||
{
|
||||
var pipe = new Pipe<byte>(new byte[16]);
|
||||
|
||||
var reader = pipe.Reader;
|
||||
var writer = pipe.Writer;
|
||||
|
||||
for (uint i = 0; i < 16; i++)
|
||||
{
|
||||
writer.Advance(i);
|
||||
writer.Flush();
|
||||
|
||||
Assert.Equal(i, reader.GetAvailable());
|
||||
reader.Advance(i);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Sequence()
|
||||
{
|
||||
var pipe = new Pipe<byte>(new byte[16]);
|
||||
|
||||
var reader = pipe.Reader;
|
||||
var writer = pipe.Writer;
|
||||
|
||||
var buffer = writer.TryGetMemory();
|
||||
Assert.Equal(15, buffer.Length);
|
||||
|
||||
buffer.CopyFrom(new byte[] { 0, 1, 2, 3, 4, 5, 6, 7, 8 });
|
||||
|
||||
writer.Advance(9);
|
||||
writer.Flush();
|
||||
|
||||
Assert.Equal(9u, reader.GetAvailable());
|
||||
|
||||
buffer = reader.TryRead();
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
Assert.Equal(i, buffer.Buffer[0][i]);
|
||||
}
|
||||
|
||||
reader.Advance(4);
|
||||
buffer = reader.TryRead();
|
||||
Assert.Equal(5, buffer.Length);
|
||||
Assert.Equal(4, buffer.Buffer[0][0]);
|
||||
Assert.Equal(5, buffer.Buffer[0][1]);
|
||||
Assert.Equal(6, buffer.Buffer[0][2]);
|
||||
Assert.Equal(7, buffer.Buffer[0][3]);
|
||||
Assert.Equal(8, buffer.Buffer[0][4]);
|
||||
Assert.Equal((int)i, reader.AvailableToRead().Length);
|
||||
reader.Advance(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,139 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2023 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: CircularBuffer.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/>. *
|
||||
*************************************************************************/
|
||||
|
||||
namespace System.Buffers;
|
||||
|
||||
public readonly ref struct CircularBuffer<T>
|
||||
{
|
||||
private readonly Span<T> _first;
|
||||
private readonly Span<T> _second;
|
||||
|
||||
public int Length { get; }
|
||||
|
||||
public CircularBuffer(ArraySegment<T>[] buffers) : this(buffers[0], buffers[1])
|
||||
{
|
||||
}
|
||||
|
||||
public CircularBuffer(Span<T> first, Span<T> second)
|
||||
{
|
||||
_first = first;
|
||||
_second = second;
|
||||
Length = first.Length + second.Length;
|
||||
}
|
||||
|
||||
public T this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (index < 0 || index > Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
return index < _first.Length ? _first[index] : _second[index - _first.Length];
|
||||
}
|
||||
set
|
||||
{
|
||||
if (index < 0 || index > Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
if (index < _first.Length)
|
||||
{
|
||||
_first[index] = value;
|
||||
}
|
||||
else
|
||||
{
|
||||
_second[index - _first.Length] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyFrom(ReadOnlySpan<T> bytes)
|
||||
{
|
||||
var remaining = bytes.Length;
|
||||
var offset = 0;
|
||||
|
||||
if (remaining == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
var buffer = i == 0 ? _first : _second;
|
||||
|
||||
if (buffer.Length == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var sz = Math.Min(remaining, buffer.Length);
|
||||
bytes.Slice(offset, sz).CopyTo(buffer);
|
||||
|
||||
remaining -= sz;
|
||||
offset += sz;
|
||||
|
||||
if (remaining == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
public void CopyTo(Span<T> bytes)
|
||||
{
|
||||
if (bytes.Length < Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(bytes));
|
||||
}
|
||||
|
||||
if (_first.Length > 0)
|
||||
{
|
||||
_first.CopyTo(bytes);
|
||||
}
|
||||
|
||||
if (_second.Length > 0)
|
||||
{
|
||||
_second.CopyTo(bytes[_first.Length..]);
|
||||
}
|
||||
}
|
||||
|
||||
public CircularBuffer<T> Slice(int offset, int count)
|
||||
{
|
||||
var firstCount = Math.Min(count, _first.Length - offset);
|
||||
var first = offset < _first.Length
|
||||
? _first.Slice(offset, firstCount)
|
||||
: Span<T>.Empty;
|
||||
|
||||
var secondCount = offset > _first.Length ? count : count - firstCount;
|
||||
var second = secondCount > 0 ? _second.Slice(Math.Max(0, offset - _first.Length), secondCount) : Span<T>.Empty;
|
||||
|
||||
return new CircularBuffer<T>(first, second);
|
||||
}
|
||||
|
||||
public Span<T> GetSpan(int index)
|
||||
{
|
||||
if (index is < 0 or > 1)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(index));
|
||||
}
|
||||
|
||||
return index == 0 ? _first : _second;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,394 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2023 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: PacketReader.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;
|
||||
using System.Buffers.Binary;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using Server.Text;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public ref struct CircularBufferReader
|
||||
{
|
||||
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;
|
||||
|
||||
// Only used for debugging!
|
||||
public ReadOnlySpan<byte> First => _first;
|
||||
public ReadOnlySpan<byte> Second => _second;
|
||||
|
||||
public CircularBufferReader(ref CircularBuffer<byte> buffer) : this(buffer.GetSpan(0), buffer.GetSpan(1))
|
||||
{
|
||||
}
|
||||
|
||||
public CircularBufferReader(ArraySegment<byte>[] buffer) : this(buffer[0], buffer[1])
|
||||
{
|
||||
}
|
||||
|
||||
public CircularBufferReader(ReadOnlySpan<byte> first, ReadOnlySpan<byte> second)
|
||||
{
|
||||
_first = first;
|
||||
_second = second;
|
||||
Position = 0;
|
||||
Length = first.Length + second.Length;
|
||||
}
|
||||
|
||||
public void Trace(NetState state)
|
||||
{
|
||||
// We don't have data, so nothing to trace
|
||||
if (_first.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var sw = new StreamWriter("unhandled-packets.log", true);
|
||||
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", state, _first[0]);
|
||||
sw.FormatBuffer(_first, _second, Length);
|
||||
sw.WriteLine();
|
||||
sw.WriteLine();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte ReadByte()
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
return _first[Position++];
|
||||
}
|
||||
|
||||
if (Position < Length)
|
||||
{
|
||||
return _second[Position++ - _first.Length];
|
||||
}
|
||||
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool ReadBoolean() => ReadByte() > 0;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public sbyte ReadSByte() => (sbyte)ReadByte();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public short ReadInt16()
|
||||
{
|
||||
short value;
|
||||
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadInt16BigEndian(_first[Position..], out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return (short)((ReadByte() >> 8) | ReadByte());
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadInt16BigEndian(_second[(Position - _first.Length)..], out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ushort ReadUInt16()
|
||||
{
|
||||
ushort value;
|
||||
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadUInt16BigEndian(_first[Position..], out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return (ushort)((ReadByte() >> 8) | ReadByte());
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadUInt16BigEndian(_second[(Position - _first.Length)..], out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 2;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int ReadInt32()
|
||||
{
|
||||
int value;
|
||||
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadInt32BigEndian(_first[Position..], out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return (ReadByte() >> 24) | (ReadByte() >> 16) | (ReadByte() >> 8) | ReadByte();
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadInt32BigEndian(_second[(Position - _first.Length)..], out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint ReadUInt32()
|
||||
{
|
||||
uint value;
|
||||
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadUInt32BigEndian(_first[Position..], out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return (uint)((ReadByte() >> 24) | (ReadByte() >> 16) | (ReadByte() >> 8) | ReadByte());
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadUInt32BigEndian(_second[(Position - _first.Length)..], out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 4;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public long ReadInt64()
|
||||
{
|
||||
long value;
|
||||
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadInt64BigEndian(_first[Position..], out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return ((long)ReadByte() >> 56) |
|
||||
((long)ReadByte() >> 48) |
|
||||
((long)ReadByte() >> 40) |
|
||||
((long)ReadByte() >> 32) |
|
||||
((long)ReadByte() >> 24) |
|
||||
((long)ReadByte() >> 16) |
|
||||
((long)ReadByte() >> 8) |
|
||||
ReadByte();
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadInt64BigEndian(_second[(Position - _first.Length)..], out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ulong ReadUInt64()
|
||||
{
|
||||
ulong value;
|
||||
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryReadUInt64BigEndian(_first[Position..], out value))
|
||||
{
|
||||
// Not enough space. Split the spans
|
||||
return ((ulong)ReadByte() >> 56) |
|
||||
((ulong)ReadByte() >> 48) |
|
||||
((ulong)ReadByte() >> 40) |
|
||||
((ulong)ReadByte() >> 32) |
|
||||
((ulong)ReadByte() >> 24) |
|
||||
((ulong)ReadByte() >> 16) |
|
||||
((ulong)ReadByte() >> 8) |
|
||||
ReadByte();
|
||||
}
|
||||
}
|
||||
else if (!BinaryPrimitives.TryReadUInt64BigEndian(_second[(Position - _first.Length)..], out value))
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += 8;
|
||||
return value;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadString(Encoding encoding, bool safeString = false, int fixedLength = -1)
|
||||
{
|
||||
int byteLength = encoding.GetByteLengthForEncoding();
|
||||
|
||||
bool isFixedLength = fixedLength > -1;
|
||||
|
||||
var remaining = Remaining;
|
||||
int size;
|
||||
|
||||
if (isFixedLength)
|
||||
{
|
||||
size = fixedLength * byteLength;
|
||||
if (size > Remaining)
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
size = remaining - (remaining & (byteLength - 1));
|
||||
}
|
||||
|
||||
ReadOnlySpan<byte> span;
|
||||
int index;
|
||||
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
var firstLength = Math.Min(_first.Length - Position, size);
|
||||
|
||||
// Find terminator
|
||||
index = _first.Slice(Position, firstLength).IndexOfTerminator(byteLength);
|
||||
|
||||
if (index < 0)
|
||||
{
|
||||
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 = firstLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
index = _second[..remaining].IndexOfTerminator(byteLength);
|
||||
|
||||
int secondLength = index < 0 ? remaining : index;
|
||||
int length = firstLength + secondLength;
|
||||
|
||||
// Assume no strings should be too long for the stack
|
||||
Span<byte> bytes = stackalloc byte[length];
|
||||
_first[Position..].CopyTo(bytes);
|
||||
_second[..secondLength].CopyTo(bytes[firstLength..]);
|
||||
|
||||
Position += length + (index >= 0 ? byteLength : 0);
|
||||
return TextEncoding.GetString(bytes, encoding, safeString);
|
||||
}
|
||||
}
|
||||
|
||||
span = _first.Slice(Position, index);
|
||||
}
|
||||
else
|
||||
{
|
||||
size = Math.Min(remaining, size);
|
||||
span = _second.Slice( Position - _first.Length, size);
|
||||
index = span.IndexOfTerminator(byteLength);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
span = span[..index];
|
||||
}
|
||||
else
|
||||
{
|
||||
index = size;
|
||||
}
|
||||
}
|
||||
|
||||
Position += isFixedLength ? size : index + byteLength;
|
||||
return TextEncoding.GetString(span, encoding, safeString);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUniSafe(int fixedLength) => ReadString(TextEncoding.UnicodeLE, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUniSafe() => ReadString(TextEncoding.UnicodeLE, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUni(int fixedLength) => ReadString(TextEncoding.UnicodeLE, false, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadLittleUni() => ReadString(TextEncoding.UnicodeLE);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUniSafe(int fixedLength) => ReadString(TextEncoding.Unicode, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUniSafe() => ReadString(TextEncoding.Unicode, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUni(int fixedLength) => ReadString(TextEncoding.Unicode, false, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadBigUni() => ReadString(TextEncoding.Unicode);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8Safe(int fixedLength) => ReadString(TextEncoding.UTF8, true, fixedLength);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8Safe() => ReadString(TextEncoding.UTF8, true);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public string ReadUTF8() => ReadString(TextEncoding.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
|
||||
};
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool Read(Span<byte> bytes)
|
||||
{
|
||||
if (bytes.Length < Length)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(bytes));
|
||||
}
|
||||
|
||||
if (_first.Length > 0 && !_first.TryCopyTo(bytes))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _second.Length <= 0 || _second.TryCopyTo(bytes[_first.Length..]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,522 +0,0 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2023 - 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.Text;
|
||||
|
||||
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(CircularBuffer<byte> buffer) : this(buffer.GetSpan(0), buffer.GetSpan(1))
|
||||
{
|
||||
}
|
||||
|
||||
public CircularBufferWriter(ArraySegment<byte>[] buffer) : this(buffer[0], buffer[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[Position..], value))
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
}
|
||||
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 2;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteInt16BigEndian(_second[(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[Position..], value))
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
}
|
||||
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 2;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteUInt16BigEndian(_second[(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[Position..], value))
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
}
|
||||
|
||||
Write((byte)(value >> 24));
|
||||
Write((byte)(value >> 16));
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteInt32BigEndian(_second[(Position - _first.Length)..], value))
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteLE(int value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteInt32LittleEndian(_first[Position..], value))
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
}
|
||||
|
||||
Write((byte)(value >> 24));
|
||||
Write((byte)(value >> 16));
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteInt32LittleEndian(_second[(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[Position..], value))
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
}
|
||||
|
||||
Write((byte)(value >> 24));
|
||||
Write((byte)(value >> 16));
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteUInt32BigEndian(_second[(Position - _first.Length)..], value))
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteLE(uint value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteUInt32LittleEndian(_first[Position..], value))
|
||||
{
|
||||
if (!BitConverter.IsLittleEndian)
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
}
|
||||
|
||||
Write((byte)(value >> 24));
|
||||
Write((byte)(value >> 16));
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteUInt32LittleEndian(_second[(Position - _first.Length)..], value))
|
||||
{
|
||||
Position += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 8-byte signed integer value to the underlying stream.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(long value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteInt64BigEndian(_first[Position..], value))
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
}
|
||||
|
||||
Write((byte)(value >> 56));
|
||||
Write((byte)(value >> 48));
|
||||
Write((byte)(value >> 40));
|
||||
Write((byte)(value >> 32));
|
||||
Write((byte)(value >> 24));
|
||||
Write((byte)(value >> 16));
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 8;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteInt64BigEndian(_second[(Position - _first.Length)..], value))
|
||||
{
|
||||
Position += 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Writes a 8-byte unsigned integer value to the underlying stream.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Write(ulong value)
|
||||
{
|
||||
if (Position < _first.Length)
|
||||
{
|
||||
if (!BinaryPrimitives.TryWriteUInt64BigEndian(_first[Position..], value))
|
||||
{
|
||||
if (BitConverter.IsLittleEndian)
|
||||
{
|
||||
value = BinaryPrimitives.ReverseEndianness(value);
|
||||
}
|
||||
|
||||
Write((byte)(value >> 56));
|
||||
Write((byte)(value >> 48));
|
||||
Write((byte)(value >> 40));
|
||||
Write((byte)(value >> 32));
|
||||
Write((byte)(value >> 24));
|
||||
Write((byte)(value >> 16));
|
||||
Write((byte)(value >> 8));
|
||||
Write((byte)value);
|
||||
}
|
||||
else
|
||||
{
|
||||
Position += 8;
|
||||
}
|
||||
}
|
||||
else if (BinaryPrimitives.TryWriteUInt64BigEndian(_second[(Position - _first.Length)..], value))
|
||||
{
|
||||
Position += 8;
|
||||
}
|
||||
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[..sz].CopyTo(_first[Position..]);
|
||||
if (sz < buffer.Length)
|
||||
{
|
||||
buffer[sz..].CopyTo(_second);
|
||||
}
|
||||
}
|
||||
else if (Position < Length)
|
||||
{
|
||||
buffer.CopyTo(_second[(Position - _first.Length)..]);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
Position += buffer.Length;
|
||||
}
|
||||
|
||||
[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[..count].CopyTo(_first[Position..]);
|
||||
byteCount -= count;
|
||||
Position += count;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
|
||||
if (byteCount > 0)
|
||||
{
|
||||
bytes[count..].CopyTo(_second[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)), TextEncoding.UnicodeLE);
|
||||
var count = fixedLength - value.Length;
|
||||
if (count > 0)
|
||||
{
|
||||
Clear(count * 2);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteLittleUniNull(string value)
|
||||
{
|
||||
WriteString(value, TextEncoding.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)), TextEncoding.Unicode);
|
||||
var count = fixedLength - value.Length;
|
||||
if (count > 0)
|
||||
{
|
||||
Clear(count * 2);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteBigUniNull(string value)
|
||||
{
|
||||
WriteString(value, TextEncoding.Unicode);
|
||||
Write((ushort)0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUTF8(string value) => WriteString(value, TextEncoding.UTF8);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void WriteUTF8Null(string value)
|
||||
{
|
||||
WriteString(value, TextEncoding.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(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
|
||||
};
|
||||
}
|
||||
|
|
@ -31,6 +31,8 @@ public ref struct SpanReader
|
|||
public int Position { get; private set; }
|
||||
public int Remaining => Length - Position;
|
||||
|
||||
public ReadOnlySpan<byte> Buffer => _buffer;
|
||||
|
||||
public SpanReader(ReadOnlySpan<byte> span)
|
||||
{
|
||||
_buffer = span;
|
||||
|
|
@ -184,13 +186,13 @@ public ref struct SpanReader
|
|||
{
|
||||
// In case the remaining is not evenly divisible
|
||||
size = remaining - (remaining & (byteLength - 1));
|
||||
int index = _buffer.Slice(Position, size).IndexOfTerminator(byteLength);
|
||||
size = index < 0 ? size : index;
|
||||
}
|
||||
|
||||
var span = _buffer.Slice(Position, size);
|
||||
Position += size;
|
||||
return TextEncoding.GetString(span, encoding, safeString);
|
||||
var index = span.IndexOfTerminator(byteLength);
|
||||
|
||||
Position += isFixedLength || index < 0 ? size : index;
|
||||
return TextEncoding.GetString(span[..index], encoding, safeString);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
|
|||
|
|
@ -13,15 +13,17 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public ref struct EncodedReader
|
||||
{
|
||||
private CircularBufferReader _reader;
|
||||
private SpanReader _reader;
|
||||
|
||||
public EncodedReader(CircularBufferReader reader) => _reader = reader;
|
||||
public EncodedReader(SpanReader reader) => _reader = reader;
|
||||
|
||||
public void Trace(NetState state) => _reader.Trace(state);
|
||||
public void Trace(NetState state) => state.Trace(_reader.Buffer);
|
||||
|
||||
public int ReadInt32() => _reader.ReadByte() != 0 ? 0 : _reader.ReadInt32();
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ namespace Server.Network;
|
|||
|
||||
public delegate void NetStateCreatedCallback(NetState ns);
|
||||
|
||||
public delegate void DecodePacket(CircularBuffer<byte> buffer, ref int length);
|
||||
public delegate void EncodePacket(ReadOnlySpan<byte> inputBuffer, CircularBuffer<byte> outputBuffer, out int length);
|
||||
public delegate void DecodePacket(Span<byte> buffer, ref int length);
|
||||
public delegate int EncodePacket(ReadOnlySpan<byte> inputBuffer, Span<byte> outputBuffer);
|
||||
|
||||
public partial class NetState : IComparable<NetState>
|
||||
{
|
||||
|
|
@ -123,8 +123,8 @@ public partial class NetState : IComparable<NetState>
|
|||
HuePickers = new List<HuePicker>();
|
||||
Menus = new List<IMenu>();
|
||||
Trades = new List<SecureTrade>();
|
||||
RecvPipe = new Pipe<byte>(GC.AllocateUninitializedArray<byte>(RecvPipeSize));
|
||||
SendPipe = new Pipe<byte>(GC.AllocateUninitializedArray<byte>(SendPipeSize));
|
||||
RecvPipe = new Pipe(RecvPipeSize);
|
||||
SendPipe = new Pipe(SendPipeSize);
|
||||
_nextActivityCheck = Core.TickCount + 30000;
|
||||
ConnectedOn = Core.Now;
|
||||
|
||||
|
|
@ -202,9 +202,9 @@ public partial class NetState : IComparable<NetState>
|
|||
|
||||
public bool Seeded { get; set; }
|
||||
|
||||
public Pipe<byte> RecvPipe { get; }
|
||||
public Pipe RecvPipe { get; }
|
||||
|
||||
public Pipe<byte> SendPipe { get; }
|
||||
public Pipe SendPipe { get; }
|
||||
|
||||
public bool Running => _running;
|
||||
|
||||
|
|
@ -454,7 +454,7 @@ public partial class NetState : IComparable<NetState>
|
|||
|
||||
public override string ToString() => _toString;
|
||||
|
||||
public bool GetSendBuffer(out CircularBuffer<byte> cBuffer)
|
||||
public bool GetSendBuffer(out Span<byte> buffer)
|
||||
{
|
||||
#if THREADGUARD
|
||||
if (Thread.CurrentThread != Core.Thread)
|
||||
|
|
@ -466,10 +466,8 @@ public partial class NetState : IComparable<NetState>
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
var result = SendPipe.Writer.TryGetMemory();
|
||||
cBuffer = new CircularBuffer<byte>(result.Buffer);
|
||||
|
||||
return !(result.IsClosed || result.Length <= 0);
|
||||
buffer = SendPipe.Writer.AvailableToWrite();
|
||||
return !(SendPipe.Writer.IsClosed || buffer.Length <= 0);
|
||||
}
|
||||
|
||||
public void Send(ReadOnlySpan<byte> span)
|
||||
|
|
@ -497,16 +495,16 @@ public partial class NetState : IComparable<NetState>
|
|||
|
||||
if (_packetEncoder != null)
|
||||
{
|
||||
_packetEncoder(span, buffer, out length);
|
||||
length = _packetEncoder(span, buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer.CopyFrom(span);
|
||||
span.CopyTo(buffer);
|
||||
}
|
||||
|
||||
if (PacketLogging)
|
||||
{
|
||||
LogPacket(span, ReadOnlySpan<byte>.Empty, span.Length, false);
|
||||
LogPacket(span, false);
|
||||
}
|
||||
|
||||
SendPipe.Writer.Advance((uint)length);
|
||||
|
|
@ -545,7 +543,7 @@ public partial class NetState : IComparable<NetState>
|
|||
}
|
||||
}
|
||||
|
||||
private void LogPacket(ReadOnlySpan<byte> first, ReadOnlySpan<byte> second, int totalLength, bool incoming)
|
||||
private void LogPacket(ReadOnlySpan<byte> buffer, bool incoming)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
|
@ -557,8 +555,8 @@ public partial class NetState : IComparable<NetState>
|
|||
const string outgoingStr = "Server -> Client";
|
||||
|
||||
using var sw = new StreamWriter(logPath, true);
|
||||
sw.WriteLine($"{Core.Now:HH:mm:ss.ffff}: {(incoming ? incomingStr : outgoingStr)} 0x{first[0]:X2} (Length: {totalLength})");
|
||||
sw.FormatBuffer(first, second, totalLength);
|
||||
sw.WriteLine($"{Core.Now:HH:mm:ss.ffff}: {(incoming ? incomingStr : outgoingStr)} 0x{buffer[0]:X2} (Length: {buffer.Length})");
|
||||
sw.FormatBuffer(buffer);
|
||||
sw.WriteLine();
|
||||
sw.WriteLine();
|
||||
}
|
||||
|
|
@ -587,15 +585,15 @@ public partial class NetState : IComparable<NetState>
|
|||
// Process as many packets as we can synchronously
|
||||
while (_running && _parserState != ParserState.Error && _protocolState != ProtocolState.Error)
|
||||
{
|
||||
var result = reader.TryRead();
|
||||
var length = result.Length;
|
||||
var buffer = reader.AvailableToRead();
|
||||
var length = buffer.Length;
|
||||
|
||||
if (length <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
var packetReader = new CircularBufferReader(result.Buffer);
|
||||
var packetReader = new SpanReader(buffer);
|
||||
var packetId = packetReader.ReadByte();
|
||||
int packetLength = length;
|
||||
|
||||
|
|
@ -744,8 +742,6 @@ public partial class NetState : IComparable<NetState>
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
reader.Commit();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
@ -771,7 +767,7 @@ public partial class NetState : IComparable<NetState>
|
|||
* length is the total buffer length. We might be able to use packetReader.Capacity() instead.
|
||||
* packetLength is the length of the packet that this function actually found.
|
||||
*/
|
||||
private unsafe ParserState HandlePacket(CircularBufferReader packetReader, byte packetId, out int packetLength)
|
||||
private unsafe ParserState HandlePacket(SpanReader packetReader, byte packetId, out int packetLength)
|
||||
{
|
||||
PacketHandler handler = IncomingPackets.GetHandler(packetId);
|
||||
int length = packetReader.Length;
|
||||
|
|
@ -842,7 +838,7 @@ public partial class NetState : IComparable<NetState>
|
|||
|
||||
if (PacketLogging)
|
||||
{
|
||||
LogPacket(packetReader.First, packetReader.Second, packetLength, true);
|
||||
LogPacket(packetReader.Buffer[..packetLength], true);
|
||||
}
|
||||
|
||||
handler.OnReceive(this, packetReader, packetLength);
|
||||
|
|
@ -861,12 +857,10 @@ public partial class NetState : IComparable<NetState>
|
|||
return true;
|
||||
}
|
||||
|
||||
SendPipe.Writer.Flush();
|
||||
|
||||
var reader = SendPipe.Reader;
|
||||
var result = reader.TryRead();
|
||||
var buffer = reader.AvailableToRead();
|
||||
|
||||
if (result.IsClosed || result.Length == 0)
|
||||
if (reader.IsClosed || buffer.Length == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -875,7 +869,7 @@ public partial class NetState : IComparable<NetState>
|
|||
|
||||
try
|
||||
{
|
||||
bytesWritten = Connection.Send(result.Buffer, SocketFlags.None);
|
||||
bytesWritten = Connection.Send(buffer, SocketFlags.None);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
|
|
@ -897,21 +891,20 @@ public partial class NetState : IComparable<NetState>
|
|||
reader.Advance((uint)bytesWritten);
|
||||
}
|
||||
|
||||
return bytesWritten == result.Length;
|
||||
return bytesWritten == buffer.Length;
|
||||
}
|
||||
|
||||
private void DecodePacket(ArraySegment<byte>[] buffer, ref int length)
|
||||
private void DecodePacket(Span<byte> buffer, ref int length)
|
||||
{
|
||||
CircularBuffer<byte> cBuffer = new CircularBuffer<byte>(buffer);
|
||||
_packetDecoder?.Invoke(cBuffer, ref length);
|
||||
_packetDecoder?.Invoke(buffer, ref length);
|
||||
}
|
||||
|
||||
private void ReceiveData()
|
||||
{
|
||||
var writer = RecvPipe.Writer;
|
||||
var result = writer.TryGetMemory();
|
||||
var buffer = writer.AvailableToWrite();
|
||||
|
||||
if (result.IsClosed || result.Length == 0)
|
||||
if (writer.IsClosed || buffer.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -920,7 +913,7 @@ public partial class NetState : IComparable<NetState>
|
|||
|
||||
try
|
||||
{
|
||||
bytesWritten = Connection.Receive(result.Buffer, SocketFlags.None);
|
||||
bytesWritten = Connection.Receive(buffer, SocketFlags.None);
|
||||
}
|
||||
catch (SocketException ex)
|
||||
{
|
||||
|
|
@ -943,7 +936,7 @@ public partial class NetState : IComparable<NetState>
|
|||
return;
|
||||
}
|
||||
|
||||
DecodePacket(result.Buffer, ref bytesWritten);
|
||||
DecodePacket(buffer, ref bytesWritten);
|
||||
|
||||
writer.Advance((uint)bytesWritten);
|
||||
_nextActivityCheck = Core.TickCount + 90000;
|
||||
|
|
@ -1042,6 +1035,28 @@ public partial class NetState : IComparable<NetState>
|
|||
}
|
||||
}
|
||||
|
||||
public void Trace(ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
// We don't have data, so nothing to trace
|
||||
if (buffer.Length == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using var sw = new StreamWriter("unhandled-packets.log", true);
|
||||
sw.WriteLine("Client: {0}: Unhandled packet 0x{1:X2}", this, buffer[0]);
|
||||
sw.FormatBuffer(buffer);
|
||||
sw.WriteLine();
|
||||
sw.WriteLine();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
public static void TraceException(Exception ex)
|
||||
{
|
||||
try
|
||||
|
|
@ -1148,6 +1163,8 @@ public partial class NetState : IComparable<NetState>
|
|||
|
||||
Connection.Close();
|
||||
_handle.Free();
|
||||
RecvPipe.Dispose();
|
||||
SendPipe.Dispose();
|
||||
|
||||
Mobile = null;
|
||||
|
||||
|
|
|
|||
|
|
@ -61,129 +61,6 @@ public static class NetworkCompression
|
|||
0x4, 0x00D
|
||||
};
|
||||
|
||||
public static void Compress(ReadOnlySpan<byte> input, CircularBuffer<byte> output, out int length)
|
||||
{
|
||||
length = Compress(input, output);
|
||||
}
|
||||
|
||||
public static int Compress(ReadOnlySpan<byte> input, CircularBuffer<byte> output)
|
||||
{
|
||||
if (input.Length > DefiniteOverflow)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bitCount = 0;
|
||||
int bitValue = 0;
|
||||
|
||||
int inputIdx = 0;
|
||||
int outputIdx = 0;
|
||||
|
||||
while (inputIdx < input.Length)
|
||||
{
|
||||
int i = input[inputIdx++] << 1;
|
||||
|
||||
bitCount += _huffmanTable[i];
|
||||
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
|
||||
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
bitCount -= 8;
|
||||
|
||||
if (output.Length < outputIdx + 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
output[outputIdx++] = (byte)(bitValue >> bitCount);
|
||||
}
|
||||
}
|
||||
|
||||
// terminal code
|
||||
bitCount += _huffmanTable[0x200];
|
||||
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
|
||||
|
||||
// align on byte boundary
|
||||
if ((bitCount & 7) != 0)
|
||||
{
|
||||
bitValue <<= 8 - (bitCount & 7);
|
||||
bitCount += 8 - (bitCount & 7);
|
||||
}
|
||||
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
bitCount -= 8;
|
||||
|
||||
if (output.Length < outputIdx + 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
output[outputIdx++] = (byte)(bitValue >> bitCount);
|
||||
}
|
||||
|
||||
return outputIdx;
|
||||
}
|
||||
|
||||
public static int Compress(CircularBuffer<byte> input, CircularBuffer<byte> output)
|
||||
{
|
||||
if (input.Length > DefiniteOverflow)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bitCount = 0;
|
||||
int bitValue = 0;
|
||||
|
||||
int inputIdx = 0;
|
||||
int outputIdx = 0;
|
||||
|
||||
while (inputIdx < input.Length)
|
||||
{
|
||||
int i = input[inputIdx++] << 1;
|
||||
|
||||
bitCount += _huffmanTable[i];
|
||||
bitValue = (bitValue << _huffmanTable[i]) | _huffmanTable[i + 1];
|
||||
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
bitCount -= 8;
|
||||
|
||||
if (output.Length < outputIdx + 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
output[outputIdx++] = (byte)(bitValue >> bitCount);
|
||||
}
|
||||
}
|
||||
|
||||
// terminal code
|
||||
bitCount += _huffmanTable[0x200];
|
||||
bitValue = (bitValue << _huffmanTable[0x200]) | _huffmanTable[0x201];
|
||||
|
||||
// align on byte boundary
|
||||
if ((bitCount & 7) != 0)
|
||||
{
|
||||
bitValue <<= 8 - (bitCount & 7);
|
||||
bitCount += 8 - (bitCount & 7);
|
||||
}
|
||||
|
||||
while (bitCount >= 8)
|
||||
{
|
||||
bitCount -= 8;
|
||||
|
||||
if (output.Length < outputIdx + 1)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
output[outputIdx++] = (byte)(bitValue >> bitCount);
|
||||
}
|
||||
|
||||
return outputIdx;
|
||||
}
|
||||
|
||||
public static int Compress(ReadOnlySpan<byte> input, Span<byte> output)
|
||||
{
|
||||
if (input.Length > DefiniteOverflow)
|
||||
|
|
|
|||
|
|
@ -13,13 +13,15 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public unsafe class PacketHandler
|
||||
{
|
||||
private readonly int _length;
|
||||
|
||||
public PacketHandler(int packetID, int length, bool ingame, delegate*<NetState, CircularBufferReader, int, void> onReceive)
|
||||
public PacketHandler(int packetID, int length, bool ingame, delegate*<NetState, SpanReader, int, void> onReceive)
|
||||
{
|
||||
_length = length;
|
||||
PacketID = packetID;
|
||||
|
|
@ -31,7 +33,7 @@ public unsafe class PacketHandler
|
|||
|
||||
public virtual int GetLength(NetState ns) => _length;
|
||||
|
||||
public delegate*<NetState, CircularBufferReader, int, void> OnReceive { get; }
|
||||
public delegate*<NetState, SpanReader, int, void> OnReceive { get; }
|
||||
|
||||
public delegate*<int, NetState, out bool, bool> ThrottleCallback { get; set; }
|
||||
|
||||
|
|
|
|||
|
|
@ -22,15 +22,6 @@ namespace Server.Network;
|
|||
|
||||
public static class PacketUtilities
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void WritePacketLength(this ref CircularBufferWriter writer)
|
||||
{
|
||||
var length = writer.Position;
|
||||
writer.Seek(1, SeekOrigin.Begin);
|
||||
writer.Write((ushort)length);
|
||||
writer.Seek(length, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void WritePacketLength(this ref SpanWriter writer)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Server.Network;
|
||||
|
|
@ -25,7 +26,7 @@ public static class IncomingPackets
|
|||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe void Register(int packetID, int length, bool ingame,
|
||||
delegate*<NetState, CircularBufferReader, int, void> onReceive) =>
|
||||
delegate*<NetState, SpanReader, int, void> onReceive) =>
|
||||
Register(new PacketHandler(packetID, length, ingame, onReceive));
|
||||
|
||||
public static void Register(PacketHandler packetHandler)
|
||||
|
|
|
|||
|
|
@ -14,137 +14,35 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public interface IPipeTask<T> : INotifyCompletion
|
||||
public partial class Pipe : IDisposable
|
||||
{
|
||||
public IPipeTask<T> GetAwaiter();
|
||||
|
||||
public bool IsCompleted { get; }
|
||||
|
||||
public T GetResult();
|
||||
}
|
||||
|
||||
public class Pipe<T>
|
||||
{
|
||||
public struct Result
|
||||
public class PipeWriter
|
||||
{
|
||||
public ArraySegment<T>[] Buffer { get; }
|
||||
public bool IsClosed { get; set; }
|
||||
private readonly Pipe _pipe;
|
||||
|
||||
public int Length
|
||||
{
|
||||
get
|
||||
{
|
||||
var length = 0;
|
||||
for (int i = 0; i < Buffer.Length; i++)
|
||||
{
|
||||
length += Buffer[i].Count;
|
||||
}
|
||||
internal PipeWriter(Pipe pipe) => _pipe = pipe;
|
||||
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyFrom(ReadOnlySpan<T> bytes)
|
||||
{
|
||||
var remaining = bytes.Length;
|
||||
var offset = 0;
|
||||
|
||||
if (remaining == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
var buffer = Buffer[i];
|
||||
var sz = Math.Min(remaining, buffer.Count);
|
||||
bytes.Slice(offset, sz).CopyTo(buffer);
|
||||
|
||||
remaining -= sz;
|
||||
offset += sz;
|
||||
|
||||
if (remaining == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new OutOfMemoryException();
|
||||
}
|
||||
|
||||
public Result(int segments)
|
||||
{
|
||||
IsClosed = false;
|
||||
Buffer = new ArraySegment<T>[segments];
|
||||
}
|
||||
}
|
||||
|
||||
public class PipeWriter : IPipeTask<Result>
|
||||
{
|
||||
private readonly Pipe<T> _pipe;
|
||||
|
||||
private Result _result = new(2);
|
||||
|
||||
internal PipeWriter(Pipe<T> pipe) => _pipe = pipe;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint GetAvailable()
|
||||
public unsafe Span<byte> AvailableToWrite()
|
||||
{
|
||||
var read = _pipe._readIdx;
|
||||
var write = _pipe._writeIdx;
|
||||
|
||||
uint sz;
|
||||
if (read <= write)
|
||||
{
|
||||
if (read == 0)
|
||||
{
|
||||
return _pipe.Size - write - 1;
|
||||
}
|
||||
|
||||
return _pipe.Size - write + (read - 1);
|
||||
}
|
||||
|
||||
return read - write - 1;
|
||||
}
|
||||
|
||||
public Result TryGetMemory()
|
||||
{
|
||||
var read = _pipe._readIdx;
|
||||
var write = _pipe._writeIdx;
|
||||
|
||||
_result.IsClosed = _pipe._closed;
|
||||
|
||||
if (read <= write)
|
||||
{
|
||||
var readZero = read == 0;
|
||||
var sz = _pipe.Size - write - (readZero ? 1 : 0);
|
||||
|
||||
_result.Buffer[0] = sz == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)write, (int)sz);
|
||||
_result.Buffer[1] = readZero ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, 0, (int)read - 1);
|
||||
sz = _pipe.Size - write + read - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
var sz = read - write - 1;
|
||||
|
||||
_result.Buffer[0] = sz == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)write, (int)sz);
|
||||
_result.Buffer[1] = ArraySegment<T>.Empty;
|
||||
sz = read - write - 1;
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
public IPipeTask<Result> GetMemory()
|
||||
{
|
||||
if (_pipe._writeAwaitBeginning)
|
||||
{
|
||||
throw new Exception("Double await on writer");
|
||||
}
|
||||
|
||||
return this;
|
||||
return new Span<byte>((void*)(_pipe._buffer + write), (int)sz);
|
||||
}
|
||||
|
||||
public void Advance(uint count)
|
||||
|
|
@ -159,14 +57,14 @@ public class Pipe<T>
|
|||
|
||||
if (count > _pipe.Size - 1)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
throw new EndOfPipeException("Unable to advance beyond the end of the pipe.");
|
||||
}
|
||||
|
||||
if (read <= write)
|
||||
{
|
||||
if (count > read + _pipe.Size - write - 1)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
throw new EndOfPipeException("Unable to advance beyond the end of the pipe.");
|
||||
}
|
||||
|
||||
var sz = Math.Min(count, _pipe.Size - write);
|
||||
|
|
@ -182,7 +80,7 @@ public class Pipe<T>
|
|||
{
|
||||
if (count >= read)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
throw new EndOfPipeException("Unable to advance beyond the end of the pipe.");
|
||||
}
|
||||
|
||||
write = count;
|
||||
|
|
@ -192,7 +90,7 @@ public class Pipe<T>
|
|||
{
|
||||
if (count > read - write - 1)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
throw new EndOfPipeException("Unable to advance beyond the end of the pipe.");
|
||||
}
|
||||
|
||||
write += count;
|
||||
|
|
@ -202,146 +100,39 @@ public class Pipe<T>
|
|||
// the read pointer. Check that here.
|
||||
if (write == read)
|
||||
{
|
||||
throw new InvalidOperationException("Write index equals read index after advance");
|
||||
throw new EndOfPipeException("Unable to advance beyond the end of the pipe.");
|
||||
}
|
||||
|
||||
_pipe._writeIdx = write;
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_pipe._closed = true;
|
||||
public void Close() => _pipe._closed = true;
|
||||
|
||||
var waiting = _pipe._readAwaitBeginning;
|
||||
|
||||
if (!waiting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Action continuation;
|
||||
|
||||
do
|
||||
{
|
||||
continuation = _pipe._readContinuation;
|
||||
} while (continuation == null);
|
||||
|
||||
_pipe._readContinuation = null;
|
||||
_pipe._readAwaitBeginning = false;
|
||||
|
||||
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
|
||||
}
|
||||
|
||||
public void Flush()
|
||||
{
|
||||
if (_pipe._readIdx == _pipe._writeIdx)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var waiting = _pipe._readAwaitBeginning;
|
||||
|
||||
if (!waiting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Action continuation;
|
||||
|
||||
do
|
||||
{
|
||||
continuation = _pipe._readContinuation;
|
||||
} while (continuation == null);
|
||||
|
||||
_pipe._readContinuation = null;
|
||||
_pipe._readAwaitBeginning = false;
|
||||
|
||||
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
|
||||
}
|
||||
|
||||
#region Awaitable
|
||||
|
||||
// The following makes it possible to await the writer. Do not use any of this directly.
|
||||
|
||||
public IPipeTask<Result> GetAwaiter() => this;
|
||||
|
||||
public bool IsCompleted
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GetAvailable() > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_pipe._closed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_pipe._writeAwaitBeginning = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Result GetResult() => TryGetMemory();
|
||||
|
||||
public void OnCompleted(Action continuation) => _pipe._writeContinuation = continuation;
|
||||
|
||||
#endregion
|
||||
public bool IsClosed => _pipe._closed;
|
||||
}
|
||||
|
||||
public class PipeReader : IPipeTask<Result>
|
||||
public class PipeReader
|
||||
{
|
||||
private readonly Pipe<T> _pipe;
|
||||
private readonly Pipe _pipe;
|
||||
|
||||
private Result _result = new(2);
|
||||
internal PipeReader(Pipe pipe) => _pipe = pipe;
|
||||
|
||||
internal PipeReader(Pipe<T> pipe) => _pipe = pipe;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public uint GetAvailable()
|
||||
public unsafe Span<byte> AvailableToRead()
|
||||
{
|
||||
var read = _pipe._readIdx;
|
||||
var write = _pipe._writeIdx;
|
||||
|
||||
uint sz;
|
||||
if (read <= write)
|
||||
{
|
||||
return write - read;
|
||||
}
|
||||
|
||||
return write + _pipe.Size - read;
|
||||
}
|
||||
|
||||
public Result TryRead()
|
||||
{
|
||||
var read = _pipe._readIdx;
|
||||
var write = _pipe._writeIdx;
|
||||
|
||||
_result.IsClosed = _pipe._closed;
|
||||
|
||||
if (read <= write)
|
||||
{
|
||||
_result.Buffer[0] = write - read == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)read, (int)(write - read));
|
||||
_result.Buffer[1] = ArraySegment<T>.Empty;
|
||||
sz = write - read;
|
||||
}
|
||||
else
|
||||
{
|
||||
_result.Buffer[0] = _pipe.Size - read == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, (int)read, (int)(_pipe.Size - read));
|
||||
_result.Buffer[1] = write == 0 ? ArraySegment<T>.Empty : new ArraySegment<T>(_pipe._buffer, 0, (int)write);
|
||||
sz = _pipe.Size - read + write;
|
||||
}
|
||||
|
||||
return _result;
|
||||
}
|
||||
|
||||
public IPipeTask<Result> Read()
|
||||
{
|
||||
if (_pipe._readAwaitBeginning)
|
||||
{
|
||||
throw new Exception("Double await on reader");
|
||||
}
|
||||
|
||||
return this;
|
||||
return new Span<byte>((void*)(_pipe._buffer + read), (int)sz);
|
||||
}
|
||||
|
||||
public void Advance(uint count)
|
||||
|
|
@ -353,7 +144,7 @@ public class Pipe<T>
|
|||
{
|
||||
if (count > write - read)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
throw new EndOfPipeException("Unable to advance beyond the end of the pipe.");
|
||||
}
|
||||
|
||||
read += count;
|
||||
|
|
@ -373,118 +164,199 @@ public class Pipe<T>
|
|||
{
|
||||
if (count > write)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
throw new EndOfPipeException("Unable to advance beyond the end of the pipe.");
|
||||
}
|
||||
|
||||
read = count;
|
||||
}
|
||||
}
|
||||
|
||||
_pipe._readIdx = read;
|
||||
}
|
||||
|
||||
public void Commit()
|
||||
{
|
||||
if (_pipe._readIdx == ((_pipe._writeIdx + 1) & (_pipe.Size - 1)))
|
||||
if (read == write)
|
||||
{
|
||||
return;
|
||||
// If the read pointer catches up to the write pointer, then the pipe is empty.
|
||||
// As a performance optimization, set both to 0. This should improve the chances cache lines are hit.
|
||||
_pipe._readIdx = 0;
|
||||
_pipe._writeIdx = 0;
|
||||
}
|
||||
|
||||
var waiting = _pipe._writeAwaitBeginning;
|
||||
|
||||
if (!waiting)
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Action continuation;
|
||||
|
||||
do
|
||||
{
|
||||
continuation = _pipe._writeContinuation;
|
||||
} while (continuation == null);
|
||||
|
||||
_pipe._writeContinuation = null;
|
||||
_pipe._writeAwaitBeginning = false;
|
||||
|
||||
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
_pipe._closed = true;
|
||||
|
||||
var waiting = _pipe._writeAwaitBeginning;
|
||||
|
||||
if (!waiting)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Action continuation;
|
||||
|
||||
do
|
||||
{
|
||||
continuation = _pipe._writeContinuation;
|
||||
} while (continuation == null);
|
||||
|
||||
_pipe._writeContinuation = null;
|
||||
_pipe._writeAwaitBeginning = false;
|
||||
|
||||
ThreadPool.UnsafeQueueUserWorkItem(_ => continuation(), true);
|
||||
}
|
||||
|
||||
#region Awaitable
|
||||
|
||||
// The following makes it possible to await the reader. Do not use any of this directly.
|
||||
|
||||
public IPipeTask<Result> GetAwaiter() => this;
|
||||
|
||||
public bool IsCompleted
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GetAvailable() > 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_pipe._closed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
_pipe._readAwaitBeginning = true;
|
||||
return false;
|
||||
_pipe._readIdx = read;
|
||||
}
|
||||
}
|
||||
|
||||
public Result GetResult() => TryRead();
|
||||
public void Close() => _pipe._closed = true;
|
||||
|
||||
public void OnCompleted(Action continuation) => _pipe._readContinuation = continuation;
|
||||
|
||||
#endregion
|
||||
public bool IsClosed => _pipe._closed;
|
||||
}
|
||||
|
||||
private readonly T[] _buffer;
|
||||
private volatile uint _writeIdx;
|
||||
private volatile uint _readIdx;
|
||||
private IntPtr _handle; // Doubles as the file descriptor for linux/darwin
|
||||
private IntPtr _buffer;
|
||||
private readonly uint _bufferSize;
|
||||
private uint _writeIdx;
|
||||
private uint _readIdx;
|
||||
private bool _closed;
|
||||
|
||||
public PipeWriter Writer { get; }
|
||||
public PipeReader Reader { get; }
|
||||
|
||||
public uint Size => (uint)_buffer.Length;
|
||||
public uint Size => _bufferSize;
|
||||
|
||||
public Pipe(T[] buf)
|
||||
public bool Closed => _closed;
|
||||
|
||||
public Pipe(uint size)
|
||||
{
|
||||
// Test if the buffer is a power of two
|
||||
if (buf.Length == 0 || (buf.Length & (buf.Length - 1)) != 0)
|
||||
var pageSize = (uint)Environment.SystemPageSize;
|
||||
|
||||
// Virtual allocation requires multiples of system page size
|
||||
// So let's adjust the requested size rounded to the next available page size
|
||||
var adjustedSize = (size + pageSize - 1) & ~(pageSize - 1);
|
||||
|
||||
if (Core.IsWindows)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(buf), "Pipe buffers must have a length that is a power of two");
|
||||
// Reserve a region of virtual memory. We need twice the size so we can later mirror.
|
||||
var region = NativeMethods_Windows.VirtualAlloc2(
|
||||
IntPtr.Zero,
|
||||
IntPtr.Zero,
|
||||
adjustedSize * 2,
|
||||
NativeMethods_Windows.MEM_RESERVE | NativeMethods_Windows.MEM_RESERVE_PLACEHOLDER,
|
||||
NativeMethods_Windows.PAGE_NOACCESS,
|
||||
IntPtr.Zero,
|
||||
0
|
||||
);
|
||||
|
||||
if (region == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException($"Allocating virtual memory failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
// Releases half of the region so we can map the same memory region twice
|
||||
var freed = NativeMethods_Windows.VirtualFree(
|
||||
region,
|
||||
adjustedSize,
|
||||
NativeMethods_Windows.MEM_RELEASE | NativeMethods_Windows.MEM_PRESERVE_PLACEHOLDER
|
||||
);
|
||||
|
||||
if (!freed)
|
||||
{
|
||||
throw new InvalidOperationException($"Creating virtual placeholder failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
// Create a file descriptor
|
||||
_handle = NativeMethods_Windows.CreateFileMappingW(
|
||||
NativeMethods_Windows.InvalidHandleValue,
|
||||
IntPtr.Zero,
|
||||
NativeMethods_Windows.PAGE_READWRITE,
|
||||
0,
|
||||
adjustedSize,
|
||||
null
|
||||
);
|
||||
|
||||
if (_handle == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException($"Creating file mapping failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
// Map the region to the first half of the virtual space
|
||||
_buffer = NativeMethods_Windows.MapViewOfFile3(
|
||||
_handle,
|
||||
IntPtr.Zero,
|
||||
region,
|
||||
0,
|
||||
adjustedSize,
|
||||
NativeMethods_Windows.MEM_REPLACE_PLACEHOLDER,
|
||||
NativeMethods_Windows.PAGE_READWRITE,
|
||||
IntPtr.Zero,
|
||||
0
|
||||
);
|
||||
|
||||
if (_buffer == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException($"Mapping file view failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
// Map the same region to the second half of the virtual space
|
||||
var view2 = NativeMethods_Windows.MapViewOfFile3(
|
||||
_handle,
|
||||
IntPtr.Zero,
|
||||
new IntPtr(_buffer + adjustedSize),
|
||||
0,
|
||||
adjustedSize,
|
||||
NativeMethods_Windows.MEM_REPLACE_PLACEHOLDER,
|
||||
NativeMethods_Windows.PAGE_READWRITE,
|
||||
IntPtr.Zero,
|
||||
0
|
||||
);
|
||||
|
||||
if (view2 == IntPtr.Zero)
|
||||
{
|
||||
throw new InvalidOperationException($"Mapping file view mirror failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
}
|
||||
else if (Core.IsLinux || Core.IsDarwin)
|
||||
{
|
||||
var anon = Core.IsLinux ? NativeMethods_Linux.MAP_ANONYMOUS : NativeMethods_Linux.MAP_ANON;
|
||||
|
||||
int fd;
|
||||
|
||||
if (Core.IsLinux)
|
||||
{
|
||||
// Create a memory-backed file descriptor
|
||||
fd = NativeMethods_Linux.memfd_create("mirrored_ring_buffer", 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
var fdName = $"/muo/ring/{GetHashCode()}";
|
||||
fd = NativeMethods_Linux.shm_open(fdName, NativeMethods_Linux.O_CREAT | NativeMethods_Linux.O_RDWR, 0600);
|
||||
|
||||
// Unlink immediately to emulate memfd_create() functionality
|
||||
NativeMethods_Linux.shm_unlink(fdName);
|
||||
}
|
||||
|
||||
if (fd == NativeMethods_Linux.InvalidPtrValue)
|
||||
{
|
||||
throw new InvalidOperationException($"Creating file descriptor failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
// Set the size of the file descriptor
|
||||
if (NativeMethods_Linux.ftruncate(fd, (int)adjustedSize) != 0)
|
||||
{
|
||||
throw new InvalidOperationException($"Setting file descriptor size failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
// Get virtual address space, must be double the size so we can map twice
|
||||
_buffer = NativeMethods_Linux.mmap(IntPtr.Zero, adjustedSize * 2,
|
||||
NativeMethods_Linux.PROT_READ | NativeMethods_Linux.PROT_WRITE,
|
||||
NativeMethods_Linux.MAP_PRIVATE | anon, NativeMethods_Linux.InvalidFileDescriptor, 0);
|
||||
|
||||
if (_buffer == NativeMethods_Linux.InvalidPtrValue)
|
||||
{
|
||||
throw new InsufficientMemoryException($"Allocating virtual memory failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
// Map the file descriptor to the first half of the virtual space
|
||||
var view1 = NativeMethods_Linux.mmap(_buffer, adjustedSize,
|
||||
NativeMethods_Linux.PROT_READ | NativeMethods_Linux.PROT_WRITE,
|
||||
NativeMethods_Linux.MAP_SHARED | NativeMethods_Linux.MAP_FIXED, fd, 0);
|
||||
|
||||
if (view1 == NativeMethods_Linux.InvalidPtrValue)
|
||||
{
|
||||
throw new InvalidOperationException($"Mapping memory failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
// Map the file descriptor to the second half of the virtual space
|
||||
var view2 = NativeMethods_Linux.mmap(new IntPtr(_buffer + adjustedSize), adjustedSize,
|
||||
NativeMethods_Linux.PROT_READ | NativeMethods_Linux.PROT_WRITE,
|
||||
NativeMethods_Linux.MAP_SHARED | NativeMethods_Linux.MAP_FIXED, fd, 0);
|
||||
|
||||
if (view2 == NativeMethods_Linux.InvalidPtrValue)
|
||||
{
|
||||
throw new InvalidOperationException($"Mapping mirrored memory failed. ({Marshal.GetLastPInvokeError()})");
|
||||
}
|
||||
|
||||
_handle = fd;
|
||||
}
|
||||
|
||||
_buffer = buf;
|
||||
_bufferSize = adjustedSize;
|
||||
_writeIdx = 0;
|
||||
_readIdx = 0;
|
||||
_closed = false;
|
||||
|
|
@ -493,12 +365,155 @@ public class Pipe<T>
|
|||
Reader = new PipeReader(this);
|
||||
}
|
||||
|
||||
#region Awaitable
|
||||
private volatile bool _readAwaitBeginning;
|
||||
private volatile Action _readContinuation;
|
||||
private static partial class NativeMethods_Windows
|
||||
{
|
||||
private const string Kernel32 = "kernel32.dll";
|
||||
private const string KernelBase = "kernelbase.dll";
|
||||
public const IntPtr InvalidHandleValue = -1;
|
||||
|
||||
private volatile bool _writeAwaitBeginning;
|
||||
private volatile Action _writeContinuation;
|
||||
[LibraryImport(Kernel32, SetLastError = true, StringMarshalling = StringMarshalling.Utf16)]
|
||||
public static partial IntPtr CreateFileMappingW(
|
||||
IntPtr hFile, IntPtr lpFileMappingAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow,
|
||||
string lpName
|
||||
);
|
||||
|
||||
#endregion
|
||||
[LibraryImport(KernelBase, SetLastError = true)]
|
||||
public static partial IntPtr MapViewOfFile3(
|
||||
IntPtr hFileMappingObject, IntPtr processHandle, IntPtr pvBaseAddress, ulong ullOffset, ulong ullSize,
|
||||
uint allocFlags, uint dwDesiredAccess,
|
||||
IntPtr hExtendedParameter, int parameterCount
|
||||
);
|
||||
|
||||
[LibraryImport(Kernel32, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static partial bool UnmapViewOfFile(IntPtr lpBaseAddress);
|
||||
|
||||
[LibraryImport(Kernel32, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static partial bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[LibraryImport(KernelBase, SetLastError = true)]
|
||||
public static partial IntPtr VirtualAlloc2(
|
||||
IntPtr process,
|
||||
IntPtr address,
|
||||
ulong size,
|
||||
uint allocationType,
|
||||
uint protect,
|
||||
IntPtr extendedParameters,
|
||||
uint parameterCount
|
||||
);
|
||||
|
||||
[LibraryImport(Kernel32, SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static partial bool VirtualFree(IntPtr lpAddress, uint dwSize, uint dwFreeType);
|
||||
|
||||
public const uint MEM_PRESERVE_PLACEHOLDER = 0x02;
|
||||
public const uint MEM_RESERVE = 0x2000;
|
||||
public const uint MEM_REPLACE_PLACEHOLDER = 0x4000;
|
||||
public const uint MEM_RELEASE = 0x8000;
|
||||
public const uint MEM_RESERVE_PLACEHOLDER = 0x40000;
|
||||
public const uint PAGE_NOACCESS = 0x01;
|
||||
public const uint PAGE_READWRITE = 0x04;
|
||||
}
|
||||
|
||||
private static partial class NativeMethods_Linux
|
||||
{
|
||||
private const string LibC = "libc";
|
||||
public const IntPtr InvalidPtrValue = -1;
|
||||
public const int InvalidFileDescriptor = -1;
|
||||
|
||||
// For MacOS
|
||||
[LibraryImport(LibC, SetLastError = true, StringMarshalling = StringMarshalling.Utf8)]
|
||||
public static partial int shm_open(string name, int oflag, int mode);
|
||||
|
||||
[LibraryImport(LibC, SetLastError = true, StringMarshalling = StringMarshalling.Utf8)]
|
||||
public static partial int shm_unlink(string name);
|
||||
|
||||
[LibraryImport(LibC, SetLastError = true, StringMarshalling = StringMarshalling.Utf8)]
|
||||
public static partial int memfd_create(string name, uint flags);
|
||||
|
||||
[LibraryImport(LibC, SetLastError = true)]
|
||||
public static partial int ftruncate(int fd, int length);
|
||||
|
||||
[LibraryImport(LibC, SetLastError = true)]
|
||||
public static partial int close(int fd);
|
||||
|
||||
[LibraryImport(LibC, SetLastError = true)]
|
||||
public static partial IntPtr mmap(IntPtr addr, ulong length, int prot, int flags, int fd, int offset);
|
||||
|
||||
[LibraryImport(LibC, SetLastError = true)]
|
||||
public static partial int munmap(IntPtr addr, ulong length);
|
||||
|
||||
public const int PROT_READ = 0x1;
|
||||
public const int PROT_WRITE = 0x2;
|
||||
public const int MAP_PRIVATE = 0x02;
|
||||
public const int MAP_SHARED = 0x01;
|
||||
public const int MAP_FIXED = 0x10;
|
||||
public const int MAP_ANONYMOUS = 0x20;
|
||||
|
||||
// Darwin
|
||||
public const int O_RDWR = 0x2;
|
||||
public const int O_CREAT = 0x200;
|
||||
public const int MAP_ANON = 0x1000;
|
||||
}
|
||||
|
||||
private void ReleaseUnmanagedResources()
|
||||
{
|
||||
if (_buffer == IntPtr.Zero)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Core.IsWindows)
|
||||
{
|
||||
if (_handle != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods_Windows.CloseHandle(_handle);
|
||||
_handle = IntPtr.Zero;
|
||||
}
|
||||
|
||||
if (_buffer != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods_Windows.UnmapViewOfFile(_buffer);
|
||||
NativeMethods_Windows.UnmapViewOfFile(new IntPtr(_buffer + _bufferSize));
|
||||
}
|
||||
}
|
||||
else if (Core.IsLinux || Core.IsDarwin)
|
||||
{
|
||||
if (_handle != NativeMethods_Linux.InvalidFileDescriptor)
|
||||
{
|
||||
#pragma warning disable CA2020
|
||||
NativeMethods_Linux.close((int)_handle);
|
||||
#pragma warning restore CA2020
|
||||
|
||||
_handle = NativeMethods_Linux.InvalidFileDescriptor;
|
||||
}
|
||||
|
||||
if (_buffer != IntPtr.Zero)
|
||||
{
|
||||
NativeMethods_Linux.munmap(_buffer, _bufferSize);
|
||||
NativeMethods_Linux.munmap(new IntPtr(_buffer + _bufferSize), _bufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
_buffer = IntPtr.Zero;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseUnmanagedResources();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~Pipe()
|
||||
{
|
||||
ReleaseUnmanagedResources();
|
||||
}
|
||||
}
|
||||
|
||||
public class EndOfPipeException : IOException
|
||||
{
|
||||
public EndOfPipeException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ public static class TextEncoding
|
|||
};
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsSafeChar(ushort c) => c >= 0x20 && c < 0xFFFE;
|
||||
private static bool IsSafeChar(ushort c) => c is >= 0x20 and < 0xFFFE;
|
||||
|
||||
public static string GetString(ReadOnlySpan<byte> span, Encoding encoding, bool safeString = false)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -677,11 +677,12 @@ public static class Utility
|
|||
}
|
||||
}
|
||||
|
||||
public static void FormatBuffer(this TextWriter op, ReadOnlySpan<byte> first, ReadOnlySpan<byte> second, int totalLength)
|
||||
public static void FormatBuffer(this TextWriter op, ReadOnlySpan<byte> data)
|
||||
{
|
||||
op.WriteLine(" 0 1 2 3 4 5 6 7 8 9 A B C D E F");
|
||||
op.WriteLine(" -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --");
|
||||
|
||||
var totalLength = data.Length;
|
||||
if (totalLength <= 0)
|
||||
{
|
||||
op.WriteLine("0000 ");
|
||||
|
|
@ -692,21 +693,8 @@ public static class Utility
|
|||
Span<char> lineChars = stackalloc char[47];
|
||||
for (var i = 0; i < totalLength; i += 16)
|
||||
{
|
||||
var length = Math.Min(totalLength - i, 16);
|
||||
if (i < first.Length)
|
||||
{
|
||||
var firstLength = Math.Min(length, first.Length - i);
|
||||
first.Slice(i, firstLength).CopyTo(lineBytes);
|
||||
|
||||
if (firstLength < length)
|
||||
{
|
||||
second[..(length - first.Length - i)].CopyTo(lineBytes[(length - firstLength)..]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
second.Slice(i - first.Length, length).CopyTo(lineBytes);
|
||||
}
|
||||
var length = Math.Min(data.Length - i, 16);
|
||||
data.Slice(i, length).CopyTo(lineBytes);
|
||||
|
||||
var charsWritten = ((ReadOnlySpan<byte>)lineBytes[..length]).ToSpacedHexString(lineChars);
|
||||
|
||||
|
|
|
|||
|
|
@ -18,8 +18,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendChatMessage(lang, number, param1, param2);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDisplayHelpTopic(topic, display);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,8 +72,8 @@ public class MLQuestPacketTests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendRaceChanger(female, race);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -84,7 +84,7 @@ public class MLQuestPacketTests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCloseRaceChanger();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPartyRemoveMember(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -40,8 +40,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPartyRemoveMember(member.Serial, p);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -61,8 +61,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPartyMemberList(p);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -78,8 +78,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPartyTextMessage(serial, text, toAll);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -92,8 +92,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendPartyInvitation(m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendStatueAnimation((Serial)s, status, anim, frame);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,8 +50,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendBookCover(m, book);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -87,8 +87,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendBookContent(book);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendBBDisplayBoard(bb);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -51,8 +51,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendBBMessage(bb, msg, content);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMahjongJoinGame(game);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -40,8 +40,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMahjongPlayersInfo(game, m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -58,8 +58,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMahjongGeneralInfo(game);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -78,8 +78,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMahjongTilesInfo(game, m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -98,8 +98,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMahjongTileInfo(game.Tiles[0], m);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -112,8 +112,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMahjongRelieve(game);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ namespace UOContent.Tests
|
|||
(Packet)new MapDetailsNew(mapItem) : new MapDetails(mapItem)).Compile();
|
||||
ns.SendMapDetails(mapItem);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -43,8 +43,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendMapCommand(mapItem, command, x, y, number > 0);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCorpseEquip(m, c);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -51,8 +51,8 @@ namespace UOContent.Tests
|
|||
|
||||
ns.SendCorpseContent(m, c);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendToggleSpecialAbility(abilityId, active);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -32,8 +32,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendClearWeaponAbility();
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ public class BoatPacketTests : IClassFixture<ServerFixture>
|
|||
|
||||
ns.SendMoveBoatHS(beholder, boat, d, speed, boat.GetMovingEntities(true), xOffset, yOffset);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -98,8 +98,8 @@ public class BoatPacketTests : IClassFixture<ServerFixture>
|
|||
|
||||
ns.SendDisplayBoatHS(beholder, boat);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
private class TestBoat : BaseBoat
|
||||
|
|
|
|||
|
|
@ -20,8 +20,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendBeginHouseCustomization((Serial)serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -33,8 +33,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendEndHouseCustomization((Serial)serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -47,8 +47,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendDesignStateGeneral((Serial)serial, revision);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -14,8 +14,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendCancelArrow(0, 0, Serial.Zero);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -29,8 +29,8 @@ namespace Server.Tests.Network
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSetArrow(x, y, Serial.Zero);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -47,8 +47,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges = ProtocolChanges.HighSeas;
|
||||
ns.SendCancelArrow(x, y, serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
|
@ -65,8 +65,8 @@ namespace Server.Tests.Network
|
|||
ns.ProtocolChanges = ProtocolChanges.HighSeas;
|
||||
ns.SendSetArrow(x, y, serial);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
BuffInfo.SendAddBuffPacket(ns, (Serial)mob, iconID, titleCliloc, secondaryCliloc, args, (int)timeSpan.TotalMilliseconds);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -36,8 +36,8 @@ namespace UOContent.Tests
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
BuffInfo.SendRemoveBuffPacket(ns, m, buffIcon);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,8 +27,8 @@ public class SkillPacketsTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSkillChange(skill);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
@ -45,7 +45,7 @@ public class SkillPacketsTests : IClassFixture<ServerFixture>
|
|||
var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendSkillsUpdate(skills);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ namespace UOContent.Tests
|
|||
var expected = g.Compile(ns).Compile();
|
||||
ns.SendDisplayGump(g, out var switches, out var entries);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
var result = ns.SendPipe.Reader.AvailableToRead();
|
||||
AssertThat.Equal(result, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ public static class AssistantHandler
|
|||
_handshakes[m] = Timer.DelayCall(TimeSpan.FromSeconds(30), OnTimeout, m);
|
||||
}
|
||||
|
||||
public static void AssistVersion(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void AssistVersion(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
// We are not supporting the old UOAssist protocol
|
||||
// var assistVersion = reader.ReadInt32();
|
||||
|
|
@ -87,7 +87,7 @@ public static class AssistantHandler
|
|||
state.Assistant = assistVersion.ContainsOrdinal(' ') ? assistVersion : $"RazorCE {assistVersion}";
|
||||
}
|
||||
|
||||
private static void HandshakeResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
private static void HandshakeResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
Mobile m = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
using System.Buffers;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public static class AssistantProtocol
|
||||
|
|
@ -10,7 +12,7 @@ public static class AssistantProtocol
|
|||
_handlers = ProtocolExtensions<AssistantsProtocolInfo>.Register(new AssistantsProtocolInfo());
|
||||
}
|
||||
|
||||
public static unsafe void Register(int cmd, bool ingame, delegate*<NetState, CircularBufferReader, int, void> onReceive) =>
|
||||
public static unsafe void Register(int cmd, bool ingame, delegate*<NetState, SpanReader, int, void> onReceive) =>
|
||||
_handlers[cmd] = new PacketHandler(cmd, 0, ingame, onReceive);
|
||||
|
||||
private struct AssistantsProtocolInfo : IProtocolExtensionsInfo
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ namespace Server.Engines.Chat
|
|||
IncomingPackets.Register(0xB3, 0, true, &ChatAction);
|
||||
}
|
||||
|
||||
public static void OpenChatWindowRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void OpenChatWindowRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ namespace Server.Engines.Chat
|
|||
ChatUser.AddChatUser(from, chatName);
|
||||
}
|
||||
|
||||
public static void ChatAction(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ChatAction(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
if (!ChatSystem.Enabled)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using ModernUO.Serialization;
|
||||
using Server.Gumps;
|
||||
|
|
@ -195,7 +196,7 @@ namespace Server.Engines.MLQuests.Gumps
|
|||
return false;
|
||||
}
|
||||
|
||||
private static void RaceChangeReply(NetState state, CircularBufferReader reader, int packetLength)
|
||||
private static void RaceChangeReply(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
if (!m_Pending.TryGetValue(state, out var raceChangeState))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Buffers;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Engines.UltimaStore
|
||||
|
|
@ -9,7 +10,7 @@ namespace Server.Engines.UltimaStore
|
|||
IncomingPackets.Register(0xFA, 1, true, &UltimaStoreOpenRequest);
|
||||
}
|
||||
|
||||
public static void UltimaStoreOpenRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void UltimaStoreOpenRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.Mobile.SendMessage("Ultima Store is not currently available.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ namespace Server.Items
|
|||
IncomingPackets.Register(0x93, 99, true, &OldHeaderChange);
|
||||
}
|
||||
|
||||
public static void OldHeaderChange(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void OldHeaderChange(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -48,7 +48,7 @@ namespace Server.Items
|
|||
book.Author = Utility.FixHtml(author);
|
||||
}
|
||||
|
||||
public static void HeaderChange(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void HeaderChange(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ namespace Server.Items
|
|||
book.Author = Utility.FixHtml(author);
|
||||
}
|
||||
|
||||
public static void ContentChange(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ContentChange(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ namespace Server.Network
|
|||
return $"{seconds} second{(seconds == 1 ? "" : "s")}";
|
||||
}
|
||||
|
||||
public static void BBClientRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void BBClientRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void BBRequestContent(Mobile from, BaseBulletinBoard board, CircularBufferReader reader)
|
||||
public static void BBRequestContent(Mobile from, BaseBulletinBoard board, SpanReader reader)
|
||||
{
|
||||
if (World.FindItem((Serial)reader.ReadUInt32()) is not BulletinMessage msg || msg.Parent != board)
|
||||
{
|
||||
|
|
@ -86,7 +86,7 @@ namespace Server.Network
|
|||
from.NetState.SendBBMessage(board, msg, true);
|
||||
}
|
||||
|
||||
public static void BBRequestHeader(Mobile from, BaseBulletinBoard board, CircularBufferReader reader)
|
||||
public static void BBRequestHeader(Mobile from, BaseBulletinBoard board, SpanReader reader)
|
||||
{
|
||||
if (World.FindItem((Serial)reader.ReadUInt32()) is not BulletinMessage msg || msg.Parent != board)
|
||||
{
|
||||
|
|
@ -96,7 +96,7 @@ namespace Server.Network
|
|||
from.NetState.SendBBMessage(board, msg);
|
||||
}
|
||||
|
||||
public static void BBPostMessage(Mobile from, BaseBulletinBoard board, CircularBufferReader reader)
|
||||
public static void BBPostMessage(Mobile from, BaseBulletinBoard board, SpanReader reader)
|
||||
{
|
||||
var thread = World.FindItem((Serial)reader.ReadUInt32()) as BulletinMessage;
|
||||
|
||||
|
|
@ -151,7 +151,7 @@ namespace Server.Network
|
|||
board.PostMessage(from, thread, subject, lines);
|
||||
}
|
||||
|
||||
public static void BBRemoveMessage(Mobile from, BaseBulletinBoard board, CircularBufferReader reader)
|
||||
public static void BBRemoveMessage(Mobile from, BaseBulletinBoard board, SpanReader reader)
|
||||
{
|
||||
if (World.FindItem((Serial)reader.ReadUInt32()) is not BulletinMessage msg || msg.Parent != board)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ using Server.Network;
|
|||
|
||||
namespace Server.Engines.Mahjong
|
||||
{
|
||||
public delegate void OnMahjongPacketReceive(MahjongGame game, NetState state, CircularBufferReader reader);
|
||||
public delegate void OnMahjongPacketReceive(MahjongGame game, NetState state, SpanReader reader);
|
||||
|
||||
public static class MahjongPackets
|
||||
{
|
||||
|
|
@ -61,7 +61,7 @@ namespace Server.Engines.Mahjong
|
|||
RegisterSubCommand(0x18, MoveDealerIndicator);
|
||||
}
|
||||
|
||||
public static void OnPacket(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void OnPacket(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var game = World.FindItem((Serial)reader.ReadUInt32()) as MahjongGame;
|
||||
|
||||
|
|
@ -79,7 +79,7 @@ namespace Server.Engines.Mahjong
|
|||
}
|
||||
else
|
||||
{
|
||||
reader.Trace(state);
|
||||
state.Trace(reader.Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +105,7 @@ namespace Server.Engines.Mahjong
|
|||
};
|
||||
}
|
||||
|
||||
public static void ExitGame(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void ExitGame(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game == null)
|
||||
{
|
||||
|
|
@ -117,7 +117,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.LeaveGame(from);
|
||||
}
|
||||
|
||||
public static void GivePoints(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void GivePoints(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGamePlayer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -130,7 +130,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.TransferScore(state.Mobile, to, amount);
|
||||
}
|
||||
|
||||
public static void RollDice(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void RollDice(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGamePlayer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -140,7 +140,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Dices.RollDices(state.Mobile);
|
||||
}
|
||||
|
||||
public static void BuildWalls(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void BuildWalls(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -150,7 +150,7 @@ namespace Server.Engines.Mahjong
|
|||
game.ResetWalls(state.Mobile);
|
||||
}
|
||||
|
||||
public static void ResetScores(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void ResetScores(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -160,7 +160,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.ResetScores(MahjongGame.BaseScore);
|
||||
}
|
||||
|
||||
public static void AssignDealer(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void AssignDealer(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -172,7 +172,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.AssignDealer(position);
|
||||
}
|
||||
|
||||
public static void OpenSeat(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void OpenSeat(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -189,7 +189,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.OpenSeat(position);
|
||||
}
|
||||
|
||||
public static void ChangeOption(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void ChangeOption(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -205,7 +205,7 @@ namespace Server.Engines.Mahjong
|
|||
game.SpectatorVision = (options & 0x2) != 0;
|
||||
}
|
||||
|
||||
public static void MoveWallBreakIndicator(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void MoveWallBreakIndicator(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -218,7 +218,7 @@ namespace Server.Engines.Mahjong
|
|||
game.WallBreakIndicator.Move(new Point2D(x, y));
|
||||
}
|
||||
|
||||
public static void TogglePublicHand(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void TogglePublicHand(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGamePlayer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -233,7 +233,7 @@ namespace Server.Engines.Mahjong
|
|||
game.Players.SetPublic(game.Players.GetPlayerIndex(state.Mobile), publicHand);
|
||||
}
|
||||
|
||||
public static void MoveTile(MahjongGame game, NetState state, CircularBufferReader reader)
|
||||
public static void MoveTile(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGamePlayer(state.Mobile) != true)
|
||||
{
|
||||
|
|
@ -268,7 +268,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, CircularBufferReader reader)
|
||||
public static void MoveDealerIndicator(MahjongGame game, NetState state, SpanReader reader)
|
||||
{
|
||||
if (game?.Players.IsInGameDealer(state.Mobile) != true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ namespace Server.Network
|
|||
IncomingPackets.Register(0x56, 11, true, &OnMapCommand);
|
||||
}
|
||||
|
||||
private static void OnMapCommand(NetState state, CircularBufferReader reader, int packetLength)
|
||||
private static void OnMapCommand(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using Server.Accounting;
|
||||
using Server.Commands;
|
||||
using Server.Gumps;
|
||||
|
|
@ -138,7 +139,7 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
public static void OnReceive(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void OnReceive(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
reader.ReadByte(); // 1: <4.0.1a, 2>=4.0.1a
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Server.Gumps;
|
||||
|
|
@ -1811,7 +1812,7 @@ namespace Server.Multis
|
|||
context.Foundation.SendInfoTo(state);
|
||||
}
|
||||
|
||||
public static void QueryDesignDetails(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void QueryDesignDetails(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,14 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public unsafe class ContainerGridPacketHandler : PacketHandler
|
||||
{
|
||||
public ContainerGridPacketHandler(int packetID, int length, bool ingame,
|
||||
delegate*<NetState, CircularBufferReader, int, void> onReceive)
|
||||
delegate*<NetState, SpanReader, int, void> onReceive)
|
||||
: base(packetID, length, ingame, onReceive)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public static class FreeshardProtocol
|
||||
|
|
@ -25,7 +27,7 @@ namespace Server.Network
|
|||
_handlers = ProtocolExtensions<FreeshardProtocolInfo>.Register(new FreeshardProtocolInfo());
|
||||
}
|
||||
|
||||
public static unsafe void Register(int cmd, bool ingame, delegate*<NetState, CircularBufferReader, int, void> onReceive) =>
|
||||
public static unsafe void Register(int cmd, bool ingame, delegate*<NetState, SpanReader, int, void> onReceive) =>
|
||||
_handlers[cmd] = new PacketHandler(cmd, 0, ingame, onReceive);
|
||||
|
||||
private struct FreeshardProtocolInfo : IProtocolExtensionsInfo
|
||||
|
|
|
|||
|
|
@ -29,14 +29,14 @@ public static class MapUO
|
|||
AssistantProtocol.Register(0x01, true, &QueryGuildMemberLocations);
|
||||
}
|
||||
|
||||
public static void QueryGuildMemberLocations(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void QueryGuildMemberLocations(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
Mobile from = state.Mobile;
|
||||
|
||||
state.SendGuildMemberLocations(from, from.Guild as Guild, reader.ReadBoolean());
|
||||
}
|
||||
|
||||
public static void QueryPartyMemberLocations(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void QueryPartyMemberLocations(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
Mobile from = state.Mobile;
|
||||
var party = Party.Get(from);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using CV = Server.ClientVersion;
|
||||
|
|
@ -54,7 +55,7 @@ public static class IncomingAccountPackets
|
|||
IncomingPackets.Register(0xF8, 106, false, &CreateCharacter);
|
||||
}
|
||||
|
||||
public static void CreateCharacter(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void CreateCharacter(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
reader.Seek(9, SeekOrigin.Current);
|
||||
/*
|
||||
|
|
@ -184,7 +185,7 @@ public static class IncomingAccountPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void DeleteCharacter(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void DeleteCharacter(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
reader.Seek(30, SeekOrigin.Current);
|
||||
var index = reader.ReadInt32();
|
||||
|
|
@ -192,18 +193,18 @@ public static class IncomingAccountPackets
|
|||
EventSink.InvokeDeleteRequest(state, index);
|
||||
}
|
||||
|
||||
public static void AccountID(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void AccountID(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
}
|
||||
|
||||
public static void ClientVersion(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ClientVersion(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var version = state.Version = new CV(reader.ReadAscii());
|
||||
|
||||
EventSink.InvokeClientVersionReceived(state, version);
|
||||
}
|
||||
|
||||
public static void ClientType(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ClientType(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
reader.ReadUInt16();
|
||||
|
||||
|
|
@ -213,7 +214,7 @@ public static class IncomingAccountPackets
|
|||
EventSink.InvokeClientVersionReceived(state, version);
|
||||
}
|
||||
|
||||
public static void PlayCharacter(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PlayCharacter(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
reader.Seek(36, SeekOrigin.Current); // 4 = 0xEDEDEDED, 30 = Name, 2 = unknown
|
||||
var flags = reader.ReadInt32();
|
||||
|
|
@ -345,7 +346,7 @@ public static class IncomingAccountPackets
|
|||
return authID;
|
||||
}
|
||||
|
||||
public static void GameLogin(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void GameLogin(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
// TODO: Connection throttling
|
||||
|
||||
|
|
@ -399,7 +400,7 @@ public static class IncomingAccountPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void PlayServer(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PlayServer(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int index = reader.ReadInt16();
|
||||
var info = state.ServerInfo;
|
||||
|
|
@ -420,7 +421,7 @@ public static class IncomingAccountPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void LoginServerSeed(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void LoginServerSeed(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.Seed = reader.ReadInt32();
|
||||
state.Seeded = true;
|
||||
|
|
@ -440,7 +441,7 @@ public static class IncomingAccountPackets
|
|||
state.Version = new ClientVersion(clientMaj, clientMin, clientRev, clientPat);
|
||||
}
|
||||
|
||||
public static void AccountLogin(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void AccountLogin(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
// TODO: Throttle Connection
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public static class IncomingEntityPackets
|
||||
|
|
@ -27,7 +29,7 @@ public static class IncomingEntityPackets
|
|||
IncomingPackets.Register(0xD6, 0, true, &BatchQueryProperties);
|
||||
}
|
||||
|
||||
public static void ObjectHelpRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ObjectHelpRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -56,7 +58,7 @@ public static class IncomingEntityPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void UseReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void UseReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -100,7 +102,7 @@ public static class IncomingEntityPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void LookReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void LookReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -149,7 +151,7 @@ public static class IncomingEntityPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void BatchQueryProperties(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void BatchQueryProperties(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
if (!ObjectPropertyList.Enabled)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
using Server.ContextMenus;
|
||||
|
||||
namespace Server.Network;
|
||||
|
|
@ -59,16 +60,16 @@ public static class IncomingExtendedCommandPackets
|
|||
RegisterExtended(0x32, true, &ToggleFlying);
|
||||
}
|
||||
|
||||
private static void UnhandledBF(NetState state, CircularBufferReader reader, int packetLength)
|
||||
private static void UnhandledBF(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
}
|
||||
|
||||
public static void Empty(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void Empty(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
}
|
||||
|
||||
public static unsafe void RegisterExtended(int packetID, bool ingame,
|
||||
delegate*<NetState, CircularBufferReader, int, void> onReceive)
|
||||
delegate*<NetState, SpanReader, int, void> onReceive)
|
||||
{
|
||||
if (packetID is >= 0 and < 0x100)
|
||||
{
|
||||
|
|
@ -87,7 +88,7 @@ public static class IncomingExtendedCommandPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static unsafe void ExtendedCommand(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static unsafe void ExtendedCommand(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int packetId = reader.ReadUInt16();
|
||||
|
||||
|
|
@ -95,7 +96,7 @@ public static class IncomingExtendedCommandPackets
|
|||
|
||||
if (ph == null)
|
||||
{
|
||||
reader.Trace(state);
|
||||
state.Trace(reader.Buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -116,14 +117,13 @@ public static class IncomingExtendedCommandPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void ScreenSize(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ScreenSize(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var width = reader.ReadInt32();
|
||||
var unk = reader.ReadInt32();
|
||||
}
|
||||
|
||||
// TODO: Move out of the core
|
||||
public static void PartyMessage(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PartyMessage(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
if (state.Mobile == null)
|
||||
{
|
||||
|
|
@ -154,22 +154,22 @@ public static class IncomingExtendedCommandPackets
|
|||
PartyMessage_Decline(state, reader, packetLength);
|
||||
break;
|
||||
default:
|
||||
reader.Trace(state);
|
||||
state.Trace(reader.Buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public static void PartyMessage_AddMember(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PartyMessage_AddMember(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
PartyCommands.Handler?.OnAdd(state.Mobile);
|
||||
}
|
||||
|
||||
public static void PartyMessage_RemoveMember(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PartyMessage_RemoveMember(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
PartyCommands.Handler?.OnRemove(state.Mobile, World.FindMobile((Serial)reader.ReadUInt32()));
|
||||
}
|
||||
|
||||
public static void PartyMessage_PrivateMessage(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PartyMessage_PrivateMessage(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
PartyCommands.Handler?.OnPrivateMessage(
|
||||
state.Mobile,
|
||||
|
|
@ -178,27 +178,27 @@ public static class IncomingExtendedCommandPackets
|
|||
);
|
||||
}
|
||||
|
||||
public static void PartyMessage_PublicMessage(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PartyMessage_PublicMessage(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
PartyCommands.Handler?.OnPublicMessage(state.Mobile, reader.ReadBigUniSafe());
|
||||
}
|
||||
|
||||
public static void PartyMessage_SetCanLoot(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PartyMessage_SetCanLoot(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
PartyCommands.Handler?.OnSetCanLoot(state.Mobile, reader.ReadBoolean());
|
||||
}
|
||||
|
||||
public static void PartyMessage_Accept(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PartyMessage_Accept(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
PartyCommands.Handler?.OnAccept(state.Mobile, World.FindMobile((Serial)reader.ReadUInt32()));
|
||||
}
|
||||
|
||||
public static void PartyMessage_Decline(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PartyMessage_Decline(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
PartyCommands.Handler?.OnDecline(state.Mobile, World.FindMobile((Serial)reader.ReadUInt32()));
|
||||
}
|
||||
|
||||
public static void Animate(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void Animate(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -222,7 +222,7 @@ public static class IncomingExtendedCommandPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void CastSpell(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void CastSpell(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -237,12 +237,12 @@ public static class IncomingExtendedCommandPackets
|
|||
EventSink.InvokeCastSpellRequest(from, spellID, spellbook);
|
||||
}
|
||||
|
||||
public static void ToggleFlying(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ToggleFlying(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.Mobile?.ToggleFlying();
|
||||
}
|
||||
|
||||
public static void StunRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void StunRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -254,7 +254,7 @@ public static class IncomingExtendedCommandPackets
|
|||
EventSink.InvokeStunRequest(from);
|
||||
}
|
||||
|
||||
public static void DisarmRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void DisarmRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -266,7 +266,7 @@ public static class IncomingExtendedCommandPackets
|
|||
EventSink.InvokeDisarmRequest(from);
|
||||
}
|
||||
|
||||
public static void StatLockChange(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void StatLockChange(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -297,12 +297,12 @@ public static class IncomingExtendedCommandPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void CloseStatus(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void CloseStatus(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = (Serial)reader.ReadUInt32();
|
||||
}
|
||||
|
||||
public static void Language(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void Language(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -314,7 +314,7 @@ public static class IncomingExtendedCommandPackets
|
|||
from.Language = reader.ReadAscii(4);
|
||||
}
|
||||
|
||||
public static void QueryProperties(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void QueryProperties(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
if (!ObjectPropertyList.Enabled)
|
||||
{
|
||||
|
|
@ -346,7 +346,7 @@ public static class IncomingExtendedCommandPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void ContextMenuResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ContextMenuResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -402,7 +402,7 @@ public static class IncomingExtendedCommandPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void ContextMenuRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ContextMenuRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var target = World.FindEntity((Serial)reader.ReadUInt32());
|
||||
|
|
@ -437,7 +437,7 @@ public static class IncomingExtendedCommandPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void BandageTarget(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void BandageTarget(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -472,21 +472,21 @@ public static class IncomingExtendedCommandPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void TargetedSpell(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void TargetedSpell(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var spellId = (short)(reader.ReadInt16() - 1); // zero based;
|
||||
|
||||
EventSink.InvokeTargetedSpell(state.Mobile, World.FindEntity((Serial)reader.ReadUInt32()), spellId);
|
||||
}
|
||||
|
||||
public static void TargetedSkillUse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void TargetedSkillUse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var skillId = reader.ReadInt16();
|
||||
|
||||
EventSink.InvokeTargetedSkillUse(state.Mobile, World.FindEntity((Serial)reader.ReadUInt32()), skillId);
|
||||
}
|
||||
|
||||
public static void TargetByResourceMacro(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void TargetByResourceMacro(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = (Serial)reader.ReadUInt32();
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public static class IncomingHousePackets
|
||||
|
|
@ -22,7 +24,7 @@ public static class IncomingHousePackets
|
|||
IncomingPackets.Register(0xFB, 2, false, &ShowPublicHouseContent);
|
||||
}
|
||||
|
||||
public static void ShowPublicHouseContent(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ShowPublicHouseContent(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var showPublicHouseContent = reader.ReadBoolean();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Server.Items;
|
||||
|
|
@ -30,7 +31,7 @@ public static class IncomingItemPackets
|
|||
IncomingPackets.Register(0xED, 0, false, &UnequipMacro);
|
||||
}
|
||||
|
||||
public static void LiftReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void LiftReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = (Serial)reader.ReadUInt32();
|
||||
int amount = reader.ReadUInt16();
|
||||
|
|
@ -39,7 +40,7 @@ public static class IncomingItemPackets
|
|||
state.Mobile.Lift(item, amount, out _, out _);
|
||||
}
|
||||
|
||||
public static void EquipReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void EquipReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var item = from.Holding;
|
||||
|
|
@ -64,7 +65,7 @@ public static class IncomingItemPackets
|
|||
item.ClearBounce();
|
||||
}
|
||||
|
||||
public static void DropReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void DropReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
reader.ReadInt32(); // serial, ignored
|
||||
int x = reader.ReadInt16();
|
||||
|
|
@ -107,7 +108,7 @@ public static class IncomingItemPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void EquipMacro(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void EquipMacro(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int count = reader.ReadByte();
|
||||
var serialList = new List<Serial>(count);
|
||||
|
|
@ -119,7 +120,7 @@ public static class IncomingItemPackets
|
|||
EventSink.InvokeEquipMacro(state.Mobile, serialList);
|
||||
}
|
||||
|
||||
public static void UnequipMacro(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void UnequipMacro(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int count = reader.ReadByte();
|
||||
var layers = new List<Layer>(count);
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
|
|
@ -27,7 +28,7 @@ public static class IncomingMessagePackets
|
|||
IncomingPackets.Register(0xAD, 0, true, &UnicodeSpeech);
|
||||
}
|
||||
|
||||
public static void AsciiSpeech(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void AsciiSpeech(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -54,7 +55,7 @@ public static class IncomingMessagePackets
|
|||
from.DoSpeech(text, Array.Empty<int>(), type, Utility.ClipDyedHue(hue));
|
||||
}
|
||||
|
||||
public static void UnicodeSpeech(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void UnicodeSpeech(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
using Server.Items;
|
||||
|
||||
namespace Server.Network;
|
||||
|
|
@ -27,7 +28,7 @@ public static class IncomingMobilePackets
|
|||
IncomingPackets.Register(0x6F, 0, true, &SecureTrade);
|
||||
}
|
||||
|
||||
public static void RenameRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void RenameRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
var targ = World.FindMobile((Serial)reader.ReadUInt32());
|
||||
|
|
@ -38,7 +39,7 @@ public static class IncomingMobilePackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void MobileNameRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void MobileNameRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var m = World.FindMobile((Serial)reader.ReadUInt32());
|
||||
|
||||
|
|
@ -48,7 +49,7 @@ public static class IncomingMobilePackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void ProfileReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ProfileReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int type = reader.ReadByte();
|
||||
var serial = (Serial)reader.ReadUInt32();
|
||||
|
|
@ -88,7 +89,7 @@ public static class IncomingMobilePackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void SecureTrade(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void SecureTrade(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
switch (reader.ReadByte())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network;
|
||||
|
||||
public static class IncomingMovementPackets
|
||||
|
|
@ -25,7 +27,7 @@ public static class IncomingMovementPackets
|
|||
// IncomingPackets.Register(0xF1, 9, true, TimeSyncReq);
|
||||
}
|
||||
|
||||
public static void NewMovementReq(NetState ns, CircularBufferReader reader)
|
||||
public static void NewMovementReq(NetState ns, SpanReader reader)
|
||||
{
|
||||
var from = ns.Mobile;
|
||||
|
||||
|
|
@ -71,14 +73,14 @@ public static class IncomingMovementPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void TimeSyncReq(NetState ns, CircularBufferReader reader)
|
||||
public static void TimeSyncReq(NetState ns, SpanReader reader)
|
||||
{
|
||||
reader.ReadUInt64(); // Client Time?
|
||||
|
||||
ns.SendTimeSyncResponse();
|
||||
}
|
||||
|
||||
public static void MovementReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void MovementReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
using Server.Diagnostics;
|
||||
|
|
@ -54,18 +55,18 @@ public static class IncomingPlayerPackets
|
|||
IncomingPackets.RegisterEncoded(0x32, true, &QuestGumpRequest);
|
||||
}
|
||||
|
||||
public static void DeathStatusResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void DeathStatusResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
// Ignored
|
||||
}
|
||||
|
||||
public static void RequestScrollWindow(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void RequestScrollWindow(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int lastTip = reader.ReadInt16();
|
||||
int type = reader.ReadByte();
|
||||
}
|
||||
|
||||
public static void AttackReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void AttackReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -82,7 +83,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void HuePickerResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void HuePickerResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
_ = reader.ReadInt16(); // Item ID
|
||||
|
|
@ -99,7 +100,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void SystemInfo(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void SystemInfo(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int v1 = reader.ReadByte();
|
||||
int v2 = reader.ReadUInt16();
|
||||
|
|
@ -115,7 +116,7 @@ public static class IncomingPlayerPackets
|
|||
var v8 = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public static void TextCommand(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void TextCommand(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -210,7 +211,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void AsciiPromptResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void AsciiPromptResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -246,7 +247,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void UnicodePromptResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void UnicodePromptResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -283,7 +284,7 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void MenuResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void MenuResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = reader.ReadUInt32();
|
||||
int menuID = reader.ReadInt16(); // unused in our implementation
|
||||
|
|
@ -313,33 +314,33 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void Disconnect(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void Disconnect(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var minusOne = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public static void ConfigurationFile(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ConfigurationFile(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
}
|
||||
|
||||
public static void LogoutReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void LogoutReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.SendLogoutAck();
|
||||
}
|
||||
|
||||
public static void ChangeSkillLock(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void ChangeSkillLock(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var s = state.Mobile.Skills[reader.ReadInt16()];
|
||||
|
||||
s?.SetLockNoRelay((SkillLock)reader.ReadByte());
|
||||
}
|
||||
|
||||
public static void HelpRequest(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void HelpRequest(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
EventSink.InvokeHelpRequest(state.Mobile);
|
||||
}
|
||||
|
||||
public static void DisplayGumpResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void DisplayGumpResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = (Serial)reader.ReadUInt32();
|
||||
var typeID = reader.ReadInt32();
|
||||
|
|
@ -481,13 +482,13 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
}
|
||||
|
||||
public static void SetWarMode(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void SetWarMode(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.Mobile?.DelayChangeWarmode(reader.ReadBoolean());
|
||||
}
|
||||
|
||||
// TODO: Throttle/make this more safe
|
||||
public static void Resynchronize(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void Resynchronize(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
|
||||
|
|
@ -504,17 +505,17 @@ public static class IncomingPlayerPackets
|
|||
state.Sequence = 0;
|
||||
}
|
||||
|
||||
public static void PingReq(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void PingReq(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.SendPingAck(reader.ReadByte());
|
||||
}
|
||||
|
||||
public static void SetUpdateRange(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void SetUpdateRange(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.SendChangeUpdateRange(18);
|
||||
}
|
||||
|
||||
public static void MobileQuery(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void MobileQuery(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var from = state.Mobile;
|
||||
if (from == null)
|
||||
|
|
@ -545,13 +546,13 @@ public static class IncomingPlayerPackets
|
|||
}
|
||||
default:
|
||||
{
|
||||
reader.Trace(state);
|
||||
state.Trace(reader.Buffer);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void CrashReport(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void CrashReport(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var clientMaj = reader.ReadByte();
|
||||
var clientMin = reader.ReadByte();
|
||||
|
|
@ -595,7 +596,7 @@ public static class IncomingPlayerPackets
|
|||
EventSink.InvokeQuestGumpRequest(state.Mobile);
|
||||
}
|
||||
|
||||
public static unsafe void EncodedCommand(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static unsafe void EncodedCommand(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var e = World.FindEntity((Serial)reader.ReadUInt32());
|
||||
int packetId = reader.ReadUInt16();
|
||||
|
|
@ -612,7 +613,7 @@ public static class IncomingPlayerPackets
|
|||
|
||||
if (ph == null)
|
||||
{
|
||||
reader.Trace(state);
|
||||
state.Trace(reader.Buffer);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
using Server.Diagnostics;
|
||||
using Server.Targeting;
|
||||
|
||||
|
|
@ -25,7 +26,7 @@ public static class IncomingTargetingPackets
|
|||
IncomingPackets.Register(0x6C, 19, true, &TargetResponse);
|
||||
}
|
||||
|
||||
public static void TargetResponse(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void TargetResponse(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int type = reader.ReadByte();
|
||||
var targetID = reader.ReadInt32();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Server.Network;
|
||||
|
|
@ -25,7 +26,7 @@ public static class IncomingVendorPackets
|
|||
IncomingPackets.Register(0x9F, 0, true, &VendorSellReply);
|
||||
}
|
||||
|
||||
public static void VendorBuyReply(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void VendorBuyReply(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var vendor = World.FindMobile((Serial)reader.ReadUInt32());
|
||||
|
||||
|
|
@ -65,7 +66,7 @@ public static class IncomingVendorPackets
|
|||
state.SendEndVendorBuy(vendor.Serial);
|
||||
}
|
||||
|
||||
public static void VendorSellReply(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void VendorSellReply(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
var serial = (Serial)reader.ReadUInt32();
|
||||
var vendor = World.FindMobile(serial);
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.Buffers;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public interface IProtocolExtensionsInfo
|
||||
|
|
@ -33,7 +35,7 @@ namespace Server.Network
|
|||
return packetHandlers;
|
||||
}
|
||||
|
||||
private static unsafe void DecodeBundledPacket(NetState state, CircularBufferReader reader, int packetLength)
|
||||
private static unsafe void DecodeBundledPacket(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
int cmd = reader.ReadByte();
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public static void QueryCompactShardStats(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void QueryCompactShardStats(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
state.SendCompactShardStats(
|
||||
(uint)(Core.Uptime / 1000),
|
||||
|
|
@ -44,7 +44,7 @@ namespace Server.Network
|
|||
);
|
||||
}
|
||||
|
||||
public static void QueryExtendedShardStats(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void QueryExtendedShardStats(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
const long ticksInHour = 1000 * 60 * 60;
|
||||
state.SendExtendedShardStats(
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using Server.Gumps;
|
||||
using Server.Mobiles;
|
||||
|
|
@ -22,7 +23,7 @@ namespace Server.SkillHandlers
|
|||
SkillInfo.Table[(int)SkillName.Tracking].Callback = OnUse;
|
||||
}
|
||||
|
||||
public static void QuestArrow(NetState state, CircularBufferReader reader, int packetLength)
|
||||
public static void QuestArrow(NetState state, SpanReader reader, int packetLength)
|
||||
{
|
||||
if (state.Mobile is PlayerMobile from)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
|
||||
"version": "0.9.9"
|
||||
"version": "0.10.1"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue