Streamlines packet tests (#175)

This commit is contained in:
Kamron Batman 2020-07-11 00:29:53 -07:00 committed by GitHub
parent 6a727c3401
commit 7d20cf7642
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
29 changed files with 1782 additions and 1684 deletions

View file

@ -1,38 +1,39 @@
using System;
using System.Buffers;
using Server.Network;
namespace Server.Tests.Network.Packets
{
public static class AttributeNormalizerUtilities
{
public static void Write(int cur, int max, bool normalize, Span<byte> data)
public static void WriteAttribute(this Span<byte> data, ref int pos, int cur, int max, bool normalize)
{
if (normalize && AttributeNormalizer.Enabled && max != 0)
{
int maximum = AttributeNormalizer.Maximum;
((ushort)maximum).CopyTo(data.Slice(0, 2));
((ushort)(cur * maximum / max)).CopyTo(data.Slice(2, 2));
data.Write(ref pos, (ushort)maximum);
data.Write(ref pos, (ushort)(cur * maximum / max));
return;
}
((ushort)max).CopyTo(data.Slice(0, 2));
((ushort)cur).CopyTo(data.Slice(2, 2));
data.Write(ref pos, (ushort)max);
data.Write(ref pos, (ushort)cur);
}
public static void WriteReverse(int cur, int max, bool normalize, Span<byte> data)
public static void WriteReverseAttribute(this Span<byte> data, ref int pos, int cur, int max, bool normalize)
{
if (normalize && AttributeNormalizer.Enabled && max != 0)
{
int maximum = AttributeNormalizer.Maximum;
((ushort)(cur * maximum / max)).CopyTo(data.Slice(0, 2));
((ushort)maximum).CopyTo(data.Slice(2, 2));
data.Write(ref pos, (ushort)(cur * maximum / max));
data.Write(ref pos, (ushort)maximum);
return;
}
((ushort)cur).CopyTo(data.Slice(0, 2));
((ushort)max).CopyTo(data.Slice(2, 2));
data.Write(ref pos, (ushort)cur);
data.Write(ref pos, (ushort)max);
}
}
}

View file

@ -1,10 +1,11 @@
using System;
using System.Buffers;
using System.IO.Compression;
using System.Text;
namespace Server.Tests.Network.Packets
{
public class GumpUtilities
public static class GumpUtilities
{
public static readonly byte[] NoMoveBuffer = Encoding.ASCII.GetBytes("{ nomove }");
public static readonly byte[] NoCloseBuffer = Encoding.ASCII.GetBytes("{ noclose }");
@ -16,25 +17,28 @@ namespace Server.Tests.Network.Packets
public const string NoDispose = "{ nodispose }";
public const string NoResize = "{ noresize }";
public static int WritePacked(ReadOnlySpan<byte> source, Span<byte> dest)
public static void WritePacked(this Span<byte> dest, ref int pos, ReadOnlySpan<byte> source)
{
int length = source.Length;
if (length == 0)
{
dest.Slice(0, 4).Clear();
return 4;
#if NO_LOCAL_INIT
dest.Write(ref pos, 0);
#else
pos += 4;
#endif
return;
}
ulong packLength = (ulong)dest.Length - 8;
ZlibError ce = Zlib.Pack(dest.Slice(8), ref packLength, source, ZlibQuality.Default);
ZlibError ce = Zlib.Pack(dest.Slice(pos + 8), ref packLength, source, ZlibQuality.Default);
if (ce != ZlibError.Okay) Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce);
((int)(4 + packLength)).CopyTo(dest.Slice(0, 4));
length.CopyTo(dest.Slice(4, 4));
return (int)(8 + packLength);
dest.Write(ref pos, (int)(4 + packLength));
dest.Write(ref pos, length);
pos += (int)packLength;
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.IO.Pipelines;
using System.Linq;
@ -114,22 +115,30 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[5 + account.Length * 60];
int pos = 0;
((byte)0x81).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
((byte)1).CopyTo(ref pos, expectedData); // Count of non-null characters
((byte)0).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x81); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
expectedData.Write(ref pos, (byte)1); // Count of non-null characters
expectedData.Write(ref pos, (byte)0);
for (var i = 0; i < account.Length; ++i)
{
Mobile m = account[i];
if (m == null)
{
#if NO_LOCAL_INIT
expectedData.Clear(ref pos, 60);
#else
pos += 60;
#endif
}
else
{
m.Name.CopyASCIIFixedTo(ref pos, 30, expectedData);
expectedData.WriteAsciiFixed(ref pos, m.Name, 30);
#if NO_LOCAL_INIT
expectedData.Clear(ref pos, 30); // Password (empty)
#else
pos += 30;
#endif
}
}
@ -155,11 +164,11 @@ namespace Server.Tests.Network.Packets
{
Span<byte> data = new DeleteResult(DeleteResultType.BadRequest).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x85, // Packet ID
(byte)DeleteResultType.BadRequest
};
Span<byte> expectedData = stackalloc byte[2];
int pos = 0;
expectedData.Write(ref pos, (byte)0x85); // Packet ID
expectedData.Write(ref pos, (byte)DeleteResultType.BadRequest);
AssertThat.Equal(data, expectedData);
}
@ -169,11 +178,11 @@ namespace Server.Tests.Network.Packets
{
Span<byte> data = new PopupMessage(PMMessage.IdleWarning).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x53, // Packet ID
(byte)PMMessage.IdleWarning
};
Span<byte> expectedData = stackalloc byte[2];
int pos = 0;
expectedData.Write(ref pos, (byte)0x53); // Packet ID
expectedData.Write(ref pos, (byte)PMMessage.IdleWarning);
AssertThat.Equal(data, expectedData);
}
@ -201,7 +210,9 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new SupportedFeatures(ns).Compile();
Span<byte> expectedData = stackalloc byte[ns.ExtendedSupportedFeatures ? 5 : 3];
expectedData[0] = 0xB9; // Packet ID
int pos = 0;
expectedData[pos++] = 0xB9; // Packet ID
var flags = ExpansionInfo.GetFeatures(Expansion.EJ);
@ -217,9 +228,9 @@ namespace Server.Tests.Network.Packets
}
if (ns.ExtendedSupportedFeatures)
((uint)flags).CopyTo(expectedData.Slice(1, 4));
expectedData.Write(ref pos, (uint)flags);
else
((ushort)flags).CopyTo(expectedData.Slice(1, 2));
expectedData.Write(ref pos, (ushort)flags);
AssertThat.Equal(data, expectedData);
}
@ -238,41 +249,40 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new LoginConfirm(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x1B, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, // Body
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, 0x00, // Z
0x00, // Direction
0x00,
0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, // Map Width
0x00, 0x00, // Map Height
0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
Span<byte> expectedData = stackalloc byte[37];
int pos = 1;
m.Serial.CopyTo(ref pos, expectedData);
int pos = 0;
expectedData.Write(ref pos, (byte)0x1B); // Packet ID
expectedData.Write(ref pos, m.Serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
#else
pos += 4;
((ushort)m.Body).CopyTo(ref pos, expectedData);
((ushort)m.X).CopyTo(ref pos, expectedData);
((ushort)m.Y).CopyTo(ref pos, expectedData);
((ushort)m.Z).CopyTo(ref pos, expectedData);
((byte)m.Direction).CopyTo(ref pos, expectedData);
pos += 9;
#endif
expectedData.Write(ref pos, (ushort)m.Body);
expectedData.Write(ref pos, (ushort)m.X);
expectedData.Write(ref pos, (ushort)m.Y);
expectedData.Write(ref pos, (ushort)m.Z);
expectedData.Write(ref pos, (byte)m.Direction);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
#endif
expectedData.Write(ref pos, 0xFFFFFFFF);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
#else
pos += 4;
#endif
var map = m.Map;
if (map == null || map == Map.Internal)
map = m.LogoutMap;
((ushort)(map?.Width ?? Map.Felucca.Width)).CopyTo(ref pos, expectedData);
((ushort)(map?.Height ?? Map.Felucca.Height)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)(map?.Width ?? Map.Felucca.Width));
expectedData.Write(ref pos, (ushort)(map?.Height ?? Map.Felucca.Height));
AssertThat.Equal(data, expectedData);
}
@ -304,8 +314,8 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[4 + account.Length * 60];
int pos = 0;
((byte)0x86).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
expectedData.Write(ref pos, (byte)0x86); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
int highSlot = -1;
for (int i = account.Length - 1; i >= 0; i--)
@ -316,19 +326,39 @@ namespace Server.Tests.Network.Packets
}
int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5);
((byte)count).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)count);
for (int i = 0; i < count; i++)
{
var m = account[i];
if (m != null)
{
m.Name.CopyASCIIFixedTo(ref pos, 30, expectedData);
expectedData.Clear(ref pos, 30);
expectedData.WriteAsciiFixed(ref pos, m.Name, 30);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, (ushort)0);
#else
pos += 30;
#endif
}
else
{
expectedData.Clear(ref pos, 60);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, 0);
#else
pos += 60;
#endif
}
}
@ -351,10 +381,10 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new CharacterList(account, info).Compile();
Span<byte> expectedData = stackalloc byte[11 + account.Length * 60 + info.Length * 89];
int pos = 0;
((byte)0xA9).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
expectedData.Write(ref pos, (byte)0xA9); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
int highSlot = -1;
for (int i = account.Length - 1; i >= 0; i--)
@ -365,36 +395,59 @@ namespace Server.Tests.Network.Packets
}
int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5);
((byte)count).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)count);
for (int i = 0; i < count; i++)
{
var m = account[i];
if (m != null)
{
m.Name.CopyASCIIFixedTo(ref pos, 30, expectedData);
expectedData.Clear(ref pos, 30);
expectedData.WriteAsciiFixed(ref pos, m.Name, 30);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, (ushort)0);
#else
pos += 30;
#endif
}
else
{
expectedData.Clear(ref pos, 60);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, 0);
#else
pos += 60;
#endif
}
}
((byte)info.Length).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)info.Length);
for (int i = 0; i < info.Length; i++)
{
var ci = info[i];
((byte)i).CopyTo(ref pos, expectedData);
ci.City.CopyASCIIFixedTo(ref pos, 32, expectedData);
ci.Building.CopyASCIIFixedTo(ref pos, 32, expectedData);
ci.X.CopyTo(ref pos, expectedData);
ci.Y.CopyTo(ref pos, expectedData);
ci.Z.CopyTo(ref pos, expectedData);
ci.Map.MapID.CopyTo(ref pos, expectedData);
ci.Description.CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 4);
expectedData.Write(ref pos, (byte)i);
expectedData.WriteAsciiFixed(ref pos, ci.City, 32);
expectedData.WriteAsciiFixed(ref pos, ci.Building, 32);
expectedData.Write(ref pos, ci.X);
expectedData.Write(ref pos, ci.Y);
expectedData.Write(ref pos, ci.Z);
expectedData.Write(ref pos, ci.Map.MapID);
expectedData.Write(ref pos, ci.Description);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
#else
pos += 4;
#endif
}
var flags = ExpansionInfo.GetInfo(Expansion.EJ).CharacterListFlags;
@ -407,8 +460,8 @@ namespace Server.Tests.Network.Packets
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
((int)flags).CopyTo(ref pos, expectedData);
((short)-1).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (int)flags);
expectedData.Write(ref pos, (short)-1);
AssertThat.Equal(data, expectedData);
}
@ -431,8 +484,8 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[9 + account.Length * 60 + info.Length * 63];
int pos = 0;
((byte)0xA9).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
expectedData.Write(ref pos, (byte)0xA9); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
int highSlot = -1;
for (int i = account.Length - 1; i >= 0; i--)
@ -443,30 +496,49 @@ namespace Server.Tests.Network.Packets
}
int count = Math.Max(Math.Max(highSlot + 1, account.Limit), 5);
((byte)count).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)count);
for (int i = 0; i < count; i++)
{
var m = account[i];
if (m != null)
{
m.Name.CopyASCIIFixedTo(ref pos, 30, expectedData);
expectedData.Clear(ref pos, 30);
expectedData.WriteAsciiFixed(ref pos, m.Name, 30);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, (ushort)0);
#else
pos += 30;
#endif
}
else
{
expectedData.Clear(ref pos, 60);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, 0);
#else
pos += 60;
#endif
}
}
((byte)info.Length).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)info.Length);
for (int i = 0; i < info.Length; i++)
{
var ci = info[i];
((byte)i).CopyTo(ref pos, expectedData);
ci.City.CopyASCIIFixedTo(ref pos, 31, expectedData);
ci.Building.CopyASCIIFixedTo(ref pos, 31, expectedData);
expectedData.Write(ref pos, (byte)i);
expectedData.WriteAsciiFixed(ref pos, ci.City, 31);
expectedData.WriteAsciiFixed(ref pos, ci.Building, 31);
}
var flags = ExpansionInfo.GetInfo(Expansion.EJ).CharacterListFlags;
@ -479,7 +551,7 @@ namespace Server.Tests.Network.Packets
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
((int)flags).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (int)flags);
AssertThat.Equal(data, expectedData);
}
@ -490,11 +562,11 @@ namespace Server.Tests.Network.Packets
var reason = ALRReason.BadComm;
Span<byte> data = new AccountLoginRej(reason).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x82, // Packet ID
(byte)reason
};
Span<byte> expectedData = stackalloc byte[2];
int pos = 0;
expectedData.Write(ref pos, (byte)0x82); // Packet ID
expectedData.Write(ref pos, (byte)reason);
AssertThat.Equal(data, expectedData);
}
@ -512,19 +584,19 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[6 + info.Length * 40];
int pos = 0;
((byte)0xA8).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData);
((byte)0x5D).CopyTo(ref pos, expectedData); // Unknown
((ushort)info.Length).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0xA8); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length);
expectedData.Write(ref pos, (byte)0x5D); // Unknown
expectedData.Write(ref pos, (ushort)info.Length);
for (int i = 0; i < info.Length; i++)
{
var si = info[i];
((ushort)i).CopyTo(ref pos, expectedData);
si.Name.CopyASCIIFixedTo(ref pos, 32, expectedData);
((byte)si.FullPercent).CopyTo(ref pos, expectedData);
((byte)si.TimeZone).CopyTo(ref pos, expectedData);
Utility.GetAddressValue(si.Address.Address).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)i);
expectedData.WriteAsciiFixed(ref pos, si.Name, 32);
expectedData.Write(ref pos, (byte)si.FullPercent);
expectedData.Write(ref pos, (byte)si.TimeZone);
expectedData.Write(ref pos, Utility.GetAddressValue(si.Address.Address));
}
AssertThat.Equal(data, expectedData);
@ -539,19 +611,13 @@ namespace Server.Tests.Network.Packets
var addr = Utility.GetAddressValue(si.Address.Address);
Span<byte> expectedData = stackalloc byte[]
{
0x8C, // Packet ID
(byte)addr, // IP Address in LE
(byte)(addr >> 8),
(byte)(addr >> 16),
(byte)(addr >> 24),
0x00, 0x00, // Port
0x00, 0x00, 0x00, 0x00 // Auth ID
};
Span<byte> expectedData = stackalloc byte[11];
int pos = 0;
((ushort)si.Address.Port).CopyTo(expectedData.Slice(5, 2));
(-1).CopyTo(expectedData.Slice(7, 4)); // Auth ID
expectedData.Write(ref pos,(byte)0x8C); // Packet ID
expectedData.WriteLE(ref pos, addr);
expectedData.Write(ref pos, (ushort)si.Address.Port);
expectedData.Write(ref pos, -1); // Auth ID
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Network;
using Xunit;
@ -11,13 +12,12 @@ namespace Server.Tests.Network.Packets
{
Span<byte> data = new CancelArrow().Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBA, // Packet ID
0x00, // Command
0xFF, 0xFF, // X
0xFF, 0xFF // Y
};
Span<byte> expectedData = stackalloc byte[6];
int pos = 0;
expectedData.Write(ref pos, (byte)0xBA); // Packet ID
expectedData.Write(ref pos, (byte)0); // Command
expectedData.Write(ref pos, 0xFFFFFFFF); // X, Y
AssertThat.Equal(data, expectedData);
}
@ -30,16 +30,13 @@ namespace Server.Tests.Network.Packets
{
Span<byte> data = new SetArrow(x, y).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBA, // Packet ID
0x01, // Command
0x00, 0x00, // X
0x00, 0x00 // Y
};
Span<byte> expectedData = stackalloc byte[6];
int pos = 0;
((ushort)x).CopyTo(expectedData.Slice(2, 2));
((ushort)y).CopyTo(expectedData.Slice(4, 2));
expectedData.Write(ref pos, (byte)0xBA); // Packet ID
expectedData.Write(ref pos, (byte)0x01); // Command
expectedData.Write(ref pos, (ushort)x);
expectedData.Write(ref pos, (ushort)y);
AssertThat.Equal(data, expectedData);
}
@ -50,19 +47,21 @@ namespace Server.Tests.Network.Packets
[InlineData(100000, 100000)]
public void TestCancelArrowHS(int x, int y)
{
Span<byte> data = new CancelArrowHS(x, y, 0x1).Compile();
Serial serial = 0x01;
Span<byte> data = new CancelArrowHS(x, y, serial).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBA, // Packet ID
0x00, // Command
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, 0x00, 0x00, 0x01 // Serial
};
Span<byte> expectedData = stackalloc byte[10];
int pos = 0;
((ushort)x).CopyTo(expectedData.Slice(2, 2));
((ushort)y).CopyTo(expectedData.Slice(4, 2));
expectedData.Write(ref pos, (byte)0xBA); // Packet ID
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Command
#else
pos++;
#endif
expectedData.Write(ref pos, (ushort)x);
expectedData.Write(ref pos, (ushort)y);
expectedData.Write(ref pos, serial);
AssertThat.Equal(data, expectedData);
}
@ -73,19 +72,17 @@ namespace Server.Tests.Network.Packets
[InlineData(100000, 100000)]
public void TestSetArrowHS(int x, int y)
{
Span<byte> data = new SetArrowHS(x, y, 0x1).Compile();
Serial serial = 0x01;
Span<byte> data = new SetArrowHS(x, y, serial).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBA, // Packet ID
0x01, // Command
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, 0x00, 0x00, 0x01 // Serial
};
Span<byte> expectedData = stackalloc byte[10];
int pos = 0;
((ushort)x).CopyTo(expectedData.Slice(2, 2));
((ushort)y).CopyTo(expectedData.Slice(4, 2));
expectedData.Write(ref pos, (byte)0xBA); // Packet ID
expectedData.Write(ref pos, (byte)0x01); // Command
expectedData.Write(ref pos, (ushort)x);
expectedData.Write(ref pos, (ushort)y);
expectedData.Write(ref pos, serial);
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Network;
using Xunit;
@ -14,19 +15,15 @@ namespace Server.Tests.Network.Packets
PacketWriter stream = new PacketWriter(4);
const short cur = 50;
const short max = 100;
const ushort cur = 50;
const ushort max = 100;
AttributeNormalizer.Write(stream, cur, max);
Span<byte> expectedData = stackalloc byte[]
{
0x00, 0x00, // Maximum Normalized
0x00, 0x00 // Current Normalized
};
((short)AttributeNormalizer.Maximum).CopyTo(expectedData.Slice(0, 2));
((short)(cur * 25 / max)).CopyTo(expectedData.Slice(2, 2));
Span<byte> expectedData = stackalloc byte[4];
int pos = 0;
expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum);
expectedData.Write(ref pos, (ushort)(cur * 25 / max));
AssertThat.Equal(stream.ToArray(), expectedData);
}
@ -39,19 +36,15 @@ namespace Server.Tests.Network.Packets
PacketWriter stream = new PacketWriter(4);
const short cur = 50;
const short max = 100;
const ushort cur = 50;
const ushort max = 100;
AttributeNormalizer.WriteReverse(stream, cur, max);
Span<byte> expectedData = stackalloc byte[]
{
0x00, 0x00, // Current Normalized
0x00, 0x00 // Maximum Normalized
};
((short)AttributeNormalizer.Maximum).CopyTo(expectedData.Slice(2, 2));
((short)(cur * 25 / max)).CopyTo(expectedData.Slice(0, 2));
Span<byte> expectedData = stackalloc byte[4];
int pos = 0;
expectedData.Write(ref pos, (ushort)(cur * 25 / max));
expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum);
AssertThat.Equal(stream.ToArray(), expectedData);
}
@ -63,19 +56,15 @@ namespace Server.Tests.Network.Packets
PacketWriter stream = new PacketWriter(4);
const short cur = 50;
const short max = 100;
const ushort cur = 50;
const ushort max = 100;
AttributeNormalizer.Write(stream, cur, max);
Span<byte> expectedData = stackalloc byte[]
{
0x00, 0x00, // Maximum
0x00, 0x00 // Current
};
max.CopyTo(expectedData.Slice(0, 2));
cur.CopyTo(expectedData.Slice(2, 2));
Span<byte> expectedData = stackalloc byte[4];
int pos = 0;
expectedData.Write(ref pos, max);
expectedData.Write(ref pos, cur);
AssertThat.Equal(stream.ToArray(), expectedData);
}
@ -87,19 +76,15 @@ namespace Server.Tests.Network.Packets
PacketWriter stream = new PacketWriter(4);
const short cur = 50;
const short max = 100;
const ushort cur = 50;
const ushort max = 100;
AttributeNormalizer.WriteReverse(stream, cur, max);
Span<byte> expectedData = stackalloc byte[]
{
0x00, 0x00, // Current
0x00, 0x00 // Maximum
};
max.CopyTo(expectedData.Slice(2, 2));
cur.CopyTo(expectedData.Slice(0, 2));
Span<byte> expectedData = stackalloc byte[4];
int pos = 0;
expectedData.Write(ref pos, cur);
expectedData.Write(ref pos, max);
AssertThat.Equal(stream.ToArray(), expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Network;
using Xunit;
@ -14,16 +15,18 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new Swing(attacker, defender).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x2F, // Packet ID
0x00, // Unknown
0x00, 0x00, 0x00, 0x00, // Attacker
0x00, 0x00, 0x00, 0x00, // Defender
};
Span<byte> expectedData = stackalloc byte[10];
int pos = 0;
attacker.CopyTo(expectedData.Slice(2, 4));
defender.CopyTo(expectedData.Slice(6, 4));
expectedData.Write(ref pos, (byte)0x2F); // Packet ID
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
#endif
expectedData.Write(ref pos, attacker);
expectedData.Write(ref pos, defender);
AssertThat.Equal(data, expectedData);
}
@ -35,12 +38,25 @@ namespace Server.Tests.Network.Packets
{
Span<byte> data = new SetWarMode(warmode).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x72, // Packet ID
warmode ? (byte)0x01 : (byte)0x00, // Mode
0x00, 0x32, 0x00 // Unknown
};
Span<byte> expectedData = stackalloc byte[5];
int pos = 0;
expectedData.Write(ref pos, (byte)0x72); // Packet ID
expectedData.Write(ref pos, warmode);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
#endif
expectedData.Write(ref pos, (byte)0x32);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
#endif
AssertThat.Equal(data, expectedData);
}
@ -52,13 +68,11 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new ChangeCombatant(combatant).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xAA, // Packet ID
0x00, 0x00, 0x00, 0x00 // Combatant
};
Span<byte> expectedData = stackalloc byte[5];
int pos = 0;
combatant.CopyTo(expectedData.Slice(1, 4));
expectedData.Write(ref pos, (byte)0xAA); // Packet ID
expectedData.Write(ref pos, combatant);
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Network;
using Xunit;
@ -17,17 +18,16 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DamagePacketOld(m.Serial, inputAmount).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBF, // Packet ID
0x00, 0x0B, // Length
0x00, 0x22, // Sub-packet
0x01, // Command
0x00, 0x00, 0x00, 0x00, // Mobile Serial
expectedAmount // Amount
};
Span<byte> expectedData = stackalloc byte[11];
int pos = 0;
expectedData.Write(ref pos, (byte)0xBF); // Packet ID
expectedData.Write(ref pos, (ushort)11); // Length
expectedData.Write(ref pos, (ushort)0x22); // Sub-packet
expectedData.Write(ref pos, (byte)0x01); // Command
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, expectedAmount);
m.Serial.CopyTo(expectedData.Slice(6, 4));
AssertThat.Equal(data, expectedData);
}
@ -43,15 +43,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DamagePacket(m.Serial, inputAmount).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x0B, // Packet ID
0x00, 0x00, 0x00, 0x00, // Mobile Serial
0x00, 0x00 // Amount
};
Span<byte> expectedData = stackalloc byte[7];
int pos = 0;
m.Serial.CopyTo(expectedData.Slice(1, 4));
expectedAmount.CopyTo(expectedData.Slice(5, 2));
expectedData.Write(ref pos, (byte)0x0B); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, expectedAmount);
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.HuePickers;
using Server.Network;
using Xunit;
@ -15,16 +16,17 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DisplayHuePicker(huePicker).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x95, // Packet ID
0x00, 0x00, 0x00, 0x00, // Hue Picker Serial
0x00, 0x00, // Nothing
0x00, 0x00 // Item ID
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
huePicker.Serial.CopyTo(expectedData.Slice(1, 4));
itemID.CopyTo(expectedData.Slice(7, 2));
expectedData.Write(ref pos, (byte)0x95);
expectedData.Write(ref pos, huePicker.Serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
#else
pos += 2;
#endif
expectedData.Write(ref pos, itemID);
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Network;
using Xunit;
@ -39,30 +40,34 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[49];
int pos = 0;
((byte)0xC7).CopyTo(ref pos, expectedData); // Packet ID
((byte)effectType).CopyTo(ref pos, expectedData);
from.CopyTo(ref pos, expectedData);
to.CopyTo(ref pos, expectedData);
((ushort)itemId).CopyTo(ref pos, expectedData);
((ushort)fromPoint.X).CopyTo(ref pos, expectedData);
((ushort)fromPoint.Y).CopyTo(ref pos, expectedData);
((byte)fromPoint.Z).CopyTo(ref pos, expectedData);
((ushort)toPoint.X).CopyTo(ref pos, expectedData);
((ushort)toPoint.Y).CopyTo(ref pos, expectedData);
((byte)toPoint.Z).CopyTo(ref pos, expectedData);
speed.CopyTo(ref pos, expectedData);
duration.CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 2);
direction.CopyTo(ref pos, expectedData);
explode.CopyTo(ref pos, expectedData);
hue.CopyTo(ref pos, expectedData);
renderMode.CopyTo(ref pos, expectedData);
effect.CopyTo(ref pos, expectedData);
explodeEffect.CopyTo(ref pos, expectedData);
explodeSound.CopyTo(ref pos, expectedData);
serial.CopyTo(ref pos, expectedData);
layer.CopyTo(ref pos, expectedData);
unknown.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0xC7); // Packet ID
expectedData.Write(ref pos, (byte)effectType);
expectedData.Write(ref pos, from);
expectedData.Write(ref pos, to);
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, (ushort)fromPoint.X);
expectedData.Write(ref pos, (ushort)fromPoint.Y);
expectedData.Write(ref pos, (byte)fromPoint.Z);
expectedData.Write(ref pos, (ushort)toPoint.X);
expectedData.Write(ref pos, (ushort)toPoint.Y);
expectedData.Write(ref pos, (byte)toPoint.Z);
expectedData.Write(ref pos, speed);
expectedData.Write(ref pos, duration);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
#else
pos += 2;
#endif
expectedData.Write(ref pos, direction);
expectedData.Write(ref pos, explode);
expectedData.Write(ref pos, hue);
expectedData.Write(ref pos, renderMode);
expectedData.Write(ref pos, effect);
expectedData.Write(ref pos, explodeEffect);
expectedData.Write(ref pos, explodeSound);
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, layer);
expectedData.Write(ref pos, unknown);
AssertThat.Equal(data, expectedData);
}
@ -93,24 +98,28 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[36];
int pos = 0;
((byte)0xC0).CopyTo(ref pos, expectedData); // Packet ID
((byte)effectType).CopyTo(ref pos, expectedData);
from.CopyTo(ref pos, expectedData);
to.CopyTo(ref pos, expectedData);
((ushort)itemId).CopyTo(ref pos, expectedData);
((ushort)fromPoint.X).CopyTo(ref pos, expectedData);
((ushort)fromPoint.Y).CopyTo(ref pos, expectedData);
((byte)fromPoint.Z).CopyTo(ref pos, expectedData);
((ushort)toPoint.X).CopyTo(ref pos, expectedData);
((ushort)toPoint.Y).CopyTo(ref pos, expectedData);
((byte)toPoint.Z).CopyTo(ref pos, expectedData);
speed.CopyTo(ref pos, expectedData);
duration.CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 2);
direction.CopyTo(ref pos, expectedData);
explode.CopyTo(ref pos, expectedData);
hue.CopyTo(ref pos, expectedData);
renderMode.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0xC0); // Packet ID
expectedData.Write(ref pos, (byte)effectType);
expectedData.Write(ref pos, from);
expectedData.Write(ref pos, to);
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, (ushort)fromPoint.X);
expectedData.Write(ref pos, (ushort)fromPoint.Y);
expectedData.Write(ref pos, (byte)fromPoint.Z);
expectedData.Write(ref pos, (ushort)toPoint.X);
expectedData.Write(ref pos, (ushort)toPoint.Y);
expectedData.Write(ref pos, (byte)toPoint.Z);
expectedData.Write(ref pos, speed);
expectedData.Write(ref pos, duration);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
#else
pos += 2;
#endif
expectedData.Write(ref pos, direction);
expectedData.Write(ref pos, explode);
expectedData.Write(ref pos, hue);
expectedData.Write(ref pos, renderMode);
AssertThat.Equal(data, expectedData);
}
@ -121,20 +130,26 @@ namespace Server.Tests.Network.Packets
var type = ScreenEffectType.FadeOut;
Span<byte> data = new ScreenEffect(type).Compile();
Span<byte> expectedData = stackalloc byte[28]
{
0x70, // Packet ID
0x04,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, // Screen Effect Type
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00
};
Span<byte> expectedData = stackalloc byte[28];
int pos = 0;
((ushort)type).CopyTo(expectedData.Slice(10, 2));
expectedData.Write(ref pos, (byte)0x70); // Packet ID
expectedData.Write(ref pos, (byte)0x04); // Effect
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, 0);
#else
pos += 8;
#endif
expectedData.Write(ref pos, (ushort)type); // Screen Effect Type
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, 0);
#endif
AssertThat.Equal(data, expectedData);
}
@ -146,31 +161,32 @@ namespace Server.Tests.Network.Packets
var hue = 0x1024;
Span<byte> data = new BoltEffect(entity, hue).Compile();
Span<byte> expectedData = stackalloc byte[36]
{
0xC0, // Packet ID
0x01, // Effect
0x00, 0x00, 0x00, 0x00, // From Serial
0x00, 0x00, 0x00, 0x00, // To Serial
0x00, 0x00, // Item ID
0x00, 0x00, 0x00, 0x00, 0x00, // From Point
0x00, 0x00, 0x00, 0x00, 0x00, // To Point
0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, // Hue
0x00, 0x00, 0x00, 0x00
};
Span<byte> expectedData = stackalloc byte[36];
int pos = 0;
expectedData.Write(ref pos, (byte)0xC0); // Packet ID
expectedData.Write(ref pos, (byte)0x01); // Effect
int pos = 2;
entity.Serial.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, entity.Serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, (ushort)0);
#else
pos += 6;
((ushort)entity.X).CopyTo(ref pos, expectedData);
((ushort)entity.Y).CopyTo(ref pos, expectedData);
((byte)entity.Z).CopyTo(ref pos, expectedData);
((ushort)entity.X).CopyTo(ref pos, expectedData);
((ushort)entity.Y).CopyTo(ref pos, expectedData);
((byte)entity.Z).CopyTo(ref pos, expectedData);
#endif
expectedData.Write(ref pos, (ushort)entity.X);
expectedData.Write(ref pos, (ushort)entity.Y);
expectedData.Write(ref pos, (byte)entity.Z);
expectedData.Write(ref pos, (ushort)entity.X);
expectedData.Write(ref pos, (ushort)entity.Y);
expectedData.Write(ref pos, (byte)entity.Z);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
expectedData.Write(ref pos, (ushort)0);
#else
pos += 6;
hue.CopyTo(ref pos, expectedData);
#endif
expectedData.Write(ref pos, hue);
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Network;
using Xunit;
@ -37,28 +38,29 @@ namespace Server.Tests.Network.Packets
int pos = 0;
((byte)0xBF).CopyTo(ref pos, expectedData); // Packet ID
((ushort)length).CopyTo(ref pos, expectedData); // Length
((ushort)0x10).CopyTo(ref pos, expectedData); // Subcommand
item.Serial.CopyTo(ref pos, expectedData);
info.Number.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0xBF); // Packet ID
expectedData.Write(ref pos, (ushort)length); // Length
expectedData.Write(ref pos, (ushort)0x10); // Subcommand
expectedData.Write(ref pos, item.Serial);
expectedData.Write(ref pos, info.Number);
if (info.Crafter != null)
{
var name = info.Crafter.Name ?? "";
(-3).CopyTo(ref pos, expectedData);
name.CopyASCIITo(ref pos, expectedData);
expectedData.Write(ref pos, -3);
expectedData.Write(ref pos, (ushort)name.Length);
expectedData.WriteAscii(ref pos, name);
}
if (info.Unidentified) (-4).CopyTo(ref pos, expectedData);
if (info.Unidentified) expectedData.Write(ref pos, -4);
for (var i = 0; i < attrs.Length; i++)
{
var attr = attrs[i];
attr.Number.CopyTo(ref pos, expectedData);
((ushort)attr.Charges).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, attr.Number);
expectedData.Write(ref pos, (ushort)attr.Charges);
}
(-1).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (-1));
AssertThat.Equal(data, expectedData);
}
@ -73,20 +75,21 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new EquipUpdate(item).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x2E, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Item ID
0x00, (byte)item.Layer,
0x00, 0x00, 0x00, 0x00, // Parent Serial
0x00, 0x00, // Hue
};
Span<byte> expectedData = stackalloc byte[15];
int pos = 0;
expectedData.Write(ref pos, (byte)0x2E); // Packet ID
expectedData.Write(ref pos, item.Serial);
expectedData.Write(ref pos, (ushort)item.ItemID);
item.Serial.CopyTo(expectedData.Slice(1, 4));
((ushort)item.ItemID).CopyTo(expectedData.Slice(5, 2));
item.Parent.Serial.CopyTo(expectedData.Slice(9, 4));
((ushort)item.Hue).CopyTo(expectedData.Slice(13, 2));
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
#endif
expectedData.Write(ref pos, (byte)item.Layer);
expectedData.Write(ref pos, item.Parent.Serial);
expectedData.Write(ref pos, (ushort)item.Hue);
AssertThat.Equal(data, expectedData);
}

View file

@ -19,17 +19,14 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new CloseGump(typeId, buttonId).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBF, // Packet ID
0x00, 0xD, // Length
0x00, 0x04, // Close
0x00, 0x00, 0x00, 0x00, // Type Id
0x00, 0x00, 0x00, 0x00, // Button Id
};
Span<byte> expectedData = stackalloc byte[13];
int pos = 0;
typeId.CopyTo(expectedData.Slice(5, 4));
buttonId.CopyTo(expectedData.Slice(9, 4));
expectedData.Write(ref pos, (byte)0xBF); // Packet ID
expectedData.Write(ref pos, (ushort)0xD); // Length
expectedData.Write(ref pos, (ushort)0x4); // Close Gump
expectedData.Write(ref pos, typeId);
expectedData.Write(ref pos, buttonId);
AssertThat.Equal(data, expectedData);
}
@ -45,14 +42,16 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DisplaySignGump(gumpSerial, gumpId, unknownString, caption).Compile();
Span<byte> expectedData = stackalloc byte[15 + unknownString.Length + caption.Length];
int pos = 0;
((byte)0x8B).CopyTo(ref pos, expectedData);
((ushort)expectedData.Length).CopyTo(ref pos, expectedData);
gumpSerial.CopyTo(ref pos, expectedData);
((ushort)gumpId).CopyTo(ref pos, expectedData);
unknownString.CopyASCIINullTo(ref pos, expectedData);
caption.CopyASCIINullTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x8B);
expectedData.Write(ref pos, (ushort)expectedData.Length);
expectedData.Write(ref pos, gumpSerial);
expectedData.Write(ref pos, (ushort)gumpId);
expectedData.Write(ref pos, (ushort)(unknownString.Length + 1));
expectedData.WriteAsciiNull(ref pos, unknownString);
expectedData.Write(ref pos, (ushort)(caption.Length + 1));
expectedData.WriteAsciiNull(ref pos, caption);
AssertThat.Equal(data, expectedData);
}
@ -76,52 +75,52 @@ namespace Server.Tests.Network.Packets
expectedData[pos++] = 0xB0; // Packet ID
pos += 2; // Length
gump.Serial.CopyTo(ref pos, expectedData);
gump.TypeID.CopyTo(ref pos, expectedData);
gump.X.CopyTo(ref pos, expectedData);
gump.Y.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, gump.Serial);
expectedData.Write(ref pos, gump.TypeID);
expectedData.Write(ref pos, gump.X);
expectedData.Write(ref pos, gump.Y);
pos += 2; // Layout Length
int layoutLength = 0;
if (!gump.Draggable)
{
GumpUtilities.NoMoveBuffer.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, GumpUtilities.NoMoveBuffer);
layoutLength += GumpUtilities.NoMove.Length;
}
if (!gump.Closable)
{
GumpUtilities.NoCloseBuffer.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, GumpUtilities.NoCloseBuffer);
layoutLength += GumpUtilities.NoClose.Length;
}
if (!gump.Disposable)
{
GumpUtilities.NoDisposeBuffer.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, GumpUtilities.NoDisposeBuffer);
layoutLength += GumpUtilities.NoDispose.Length;
}
if (!gump.Resizable)
{
GumpUtilities.NoResizeBuffer.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, GumpUtilities.NoResizeBuffer);
layoutLength += GumpUtilities.NoResize.Length;
}
foreach (var entry in gump.Entries)
{
var str = entry.Compile(ns);
str.CopyRawASCIITo(ref pos, expectedData);
expectedData.WriteAscii(ref pos, str);
layoutLength += str.Length; // ASCII so 1:1
}
((ushort)layoutLength).CopyTo(expectedData.Slice(19, 2));
((ushort)gump.Strings.Count).CopyTo(ref pos, expectedData);
expectedData.Slice(19, 2).Write((ushort)layoutLength);
expectedData.Write(ref pos, (ushort)gump.Strings.Count);
for (var i = 0; i < gump.Strings.Count; ++i)
(gump.Strings[i] ?? "").CopyUnicodeBigEndianTo(ref pos, expectedData);
expectedData.WriteBigUni(ref pos, gump.Strings[i] ?? "");
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
expectedData.Slice(1, 2).Write((ushort)pos); // Length
expectedData = expectedData.Slice(0, pos);
@ -134,9 +133,10 @@ namespace Server.Tests.Network.Packets
NetState ns = new NetState(new AccountPacketTests.TestConnectionContext
{
RemoteEndPoint = IPEndPoint.Parse("127.0.0.1"),
});
ns.ProtocolChanges = ProtocolChanges.Unpack;
})
{
ProtocolChanges = ProtocolChanges.Unpack
};
var gump = new ResurrectGump(2);
@ -149,10 +149,10 @@ namespace Server.Tests.Network.Packets
expectedData[pos++] = 0xDD; // Packet ID
pos += 2; // Length
gump.Serial.CopyTo(ref pos, expectedData);
gump.TypeID.CopyTo(ref pos, expectedData);
gump.X.CopyTo(ref pos, expectedData);
gump.Y.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, gump.Serial);
expectedData.Write(ref pos, gump.TypeID);
expectedData.Write(ref pos, gump.X);
expectedData.Write(ref pos, gump.Y);
var layoutList = new List<string>();
int bufferLength = 1; // Null terminated
@ -194,24 +194,30 @@ namespace Server.Tests.Network.Packets
int bufferPos = 0;
foreach (var layout in layoutList)
layout.CopyRawASCIITo(ref bufferPos, buffer);
buffer.WriteAscii(ref bufferPos, layout);
pos += GumpUtilities.WritePacked(buffer.Slice(0, bufferPos + 1), expectedData.Slice(pos));
#if NO_LOCAL_INIT
buffer.Write(ref bufferPos, (byte)0); // Layout terminator
#else
bufferPos++;
#endif
expectedData.WritePacked(ref pos, buffer.Slice(0, bufferPos));
memOwner.Dispose();
gump.Strings.Count.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, gump.Strings.Count);
bufferLength = gump.Strings.Sum(str => 2 + str.Length * 2);
memOwner = SlabMemoryPool.Shared.Rent(bufferLength);
buffer = memOwner.Memory.Span;
bufferPos = 0;
foreach (var str in gump.Strings)
str.CopyUnicodeBigEndianTo(ref bufferPos, buffer);
buffer.WriteBigUni(ref bufferPos, str);
pos += GumpUtilities.WritePacked(buffer.Slice(0, bufferPos), expectedData.Slice(pos));
expectedData.WritePacked(ref pos, buffer.Slice(0, bufferPos));
// Length
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
expectedData.Slice(1, 2).Write((ushort)pos);
expectedData = expectedData.Slice(0, pos);
AssertThat.Equal(data, expectedData);

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Items;
using Server.Network;
using Xunit;
@ -32,21 +33,21 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[20]; // Max size
int pos = 0;
((byte)0x1A).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x1A);
pos += 2; // Length
if (item.Amount != 0)
(serial | 0x80000000).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, serial | 0x80000000);
else
(serial & 0x7FFFFFFF).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, serial & 0x7FFFFFFF);
if (item is BaseMulti)
((ushort)(item.ItemID | 0x4000)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)(item.ItemID | 0x4000));
else
((ushort)item.ItemID).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)item.ItemID);
if (item.Amount != 0)
((ushort)item.Amount).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)item.Amount);
byte direction = (byte)item.Direction;
ushort x = (ushort)(item.X & 0x7FFF);
@ -54,7 +55,7 @@ namespace Server.Tests.Network.Packets
if (direction != 0)
x |= 0x8000;
x.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, x);
int hue = item.Hue;
int flags = item.GetPacketFlags();
@ -63,21 +64,21 @@ namespace Server.Tests.Network.Packets
if (hue != 0) y |= 0x8000;
if (flags != 0) y |= 0x4000;
y.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, y);
if (direction != 0)
direction.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, direction);
((byte)item.Z).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)item.Z);
if (hue != 0)
((ushort)hue).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)hue);
if (flags != 0)
((byte)flags).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)flags);
// Length
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
expectedData.Slice(1, 2).Write((ushort)pos);
// Slice the data to match in size
data = data.Slice(0, pos);
@ -109,34 +110,29 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new WorldItemSA(item).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xF3, // Packet ID
0x00, 0x01,
(byte)(isMulti ? 0x02 : 0x00), // Item Type (Regular, or Multi)
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Item ID
0x00,
0x00, 0x00, // Amount (min?)
0x00, 0x00, // Amount (max?)
0x00, 0x00, // X
0x00, 0x00, // Y
(byte)loc.Z, // Z
(byte)item.Light, // Light
0x00, 0x00, // Hue
(byte)item.GetPacketFlags() // Flags
};
Span<byte> expectedData = stackalloc byte[24];
int pos = 0;
serial.CopyTo(expectedData.Slice(4, 4));
((ushort)(itemId & (isMulti ? 0x3FFF : 0xFFFF))).CopyTo(expectedData.Slice(8, 2));
expectedData.Write(ref pos, (byte)0xF3); // Packet ID
expectedData.Write(ref pos, (ushort)0x1);
expectedData.Write(ref pos, (byte)(isMulti ? 0x2 : 0x00)); // Item Type (Regular, or Multi)
expectedData.Write(ref pos, item.Serial);
expectedData.Write(ref pos, (ushort)(item.ItemID & (isMulti ? 0x3FFF : 0xFFFF)));
ushort amount = (ushort)item.Amount;
amount.CopyTo(expectedData.Slice(11, 2));
amount.CopyTo(expectedData.Slice(13, 2));
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0)
#else
pos++;
#endif
((ushort)loc.X).CopyTo(expectedData.Slice(15, 2));
((ushort)loc.Y).CopyTo(expectedData.Slice(17, 2));
((ushort)item.Hue).CopyTo(expectedData.Slice(21, 2));
expectedData.Write(ref pos, (ushort)item.Amount); // Amount (min?)
expectedData.Write(ref pos, (ushort)item.Amount); // Amount (max?)
expectedData.Write(ref pos, (ushort)loc.X); // X
expectedData.Write(ref pos, (ushort)loc.Y); // Y
expectedData.Write(ref pos, (byte)loc.Z); // Z
expectedData.Write(ref pos, (byte)item.Light); // Light
expectedData.Write(ref pos, (ushort)item.Hue); // Hue
expectedData.Write(ref pos, (byte)item.GetPacketFlags()); // Flags
AssertThat.Equal(data, expectedData);
}
@ -165,35 +161,33 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new WorldItemHS(item).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xF3, // Packet ID
0x00, 0x01,
(byte)(isMulti ? 0x02 : 0x00), // Item Type (Regular, or Multi)
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Item ID
0x00,
0x00, 0x00, // Amount (min?)
0x00, 0x00, // Amount (max?)
0x00, 0x00, // X
0x00, 0x00, // Y
(byte)loc.Z, // Z
(byte)item.Light, // Light
0x00, 0x00, // Hue
(byte)item.GetPacketFlags(), // Flags
00, 00 // ???
};
Span<byte> expectedData = stackalloc byte[26];
int pos = 0;
serial.CopyTo(expectedData.Slice(4, 4));
((ushort)(itemId & (isMulti ? 0x3FFF : 0xFFFF))).CopyTo(expectedData.Slice(8, 2));
expectedData.Write(ref pos, (byte)0xF3); // Packet ID
expectedData.Write(ref pos, (ushort)0x1);
expectedData.Write(ref pos, (byte)(isMulti ? 0x2 : 0x00)); // Item Type (Regular, or Multi)
expectedData.Write(ref pos, item.Serial);
expectedData.Write(ref pos, (ushort)(item.ItemID & (isMulti ? 0x3FFF : 0xFFFF)));
ushort amount = (ushort)item.Amount;
amount.CopyTo(expectedData.Slice(11, 2));
amount.CopyTo(expectedData.Slice(13, 2));
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
#endif
((ushort)loc.X).CopyTo(expectedData.Slice(15, 2));
((ushort)loc.Y).CopyTo(expectedData.Slice(17, 2));
((ushort)item.Hue).CopyTo(expectedData.Slice(21, 2));
expectedData.Write(ref pos, (ushort)item.Amount); // Amount (min?)
expectedData.Write(ref pos, (ushort)item.Amount); // Amount (max?)
expectedData.Write(ref pos, (ushort)loc.X); // X
expectedData.Write(ref pos, (ushort)loc.Y); // Y
expectedData.Write(ref pos, (byte)loc.Z); // Z
expectedData.Write(ref pos, (byte)item.Light); // Light
expectedData.Write(ref pos, (ushort)item.Hue); // Hue
expectedData.Write(ref pos, (byte)item.GetPacketFlags()); // Flags
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0); // ??
#endif
AssertThat.Equal(data, expectedData);
}
@ -206,15 +200,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new ContainerDisplay(serial, gumpId).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x24, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00 // Gump ID
};
Span<byte> expectedData = stackalloc byte[7];
int pos = 0;
serial.CopyTo(expectedData.Slice(1, 4));
gumpId.CopyTo(expectedData.Slice(5, 2));
expectedData.Write(ref pos, (byte)0x24); // Packet ID
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, gumpId);
AssertThat.Equal(data, expectedData);
}
@ -227,16 +218,13 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new ContainerDisplayHS(serial, gumpId).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x24, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Gump ID
0x00, 0x7D // Max Items?
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
serial.CopyTo(expectedData.Slice(1, 4));
gumpId.CopyTo(expectedData.Slice(5, 2));
expectedData.Write(ref pos, (byte)0x24); // Packet ID
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, gumpId);
expectedData.Write(ref pos, (ushort)0x7D); // Max Items?
AssertThat.Equal(data, expectedData);
}
@ -248,14 +236,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DisplaySpellbook(serial).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x24, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0xFF, 0xFF // Gump ID
};
Span<byte> expectedData = stackalloc byte[7];
int pos = 0;
serial.CopyTo(expectedData.Slice(1, 4));
expectedData.Write(ref pos, (byte)0x24); // Packet ID
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, (ushort)0xFFFF); // Gump ID
AssertThat.Equal(data, expectedData);
}
@ -267,15 +253,13 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DisplaySpellbookHS(serial).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x24, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0xFF, 0xFF, // Gump ID
0x00, 0x7D // Max Items?
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
serial.CopyTo(expectedData.Slice(1, 4));
expectedData.Write(ref pos, (byte)0x24); // Packet ID
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, (ushort)0xFFFF); // Gump ID
expectedData.Write(ref pos, (ushort)0x7D); // Max Items?
AssertThat.Equal(data, expectedData);
}
@ -290,23 +274,17 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new NewSpellbookContent(serial, graphic, offset, content).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBF, // Packet ID
0x00, 0x17, // Length
0x00, 0x1B, // Sub-packet
0x00, 0x01,
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Graphic
0x00, 0x00, // Offset
0x00, 0x00, 0x00, 0x00, // Content
0x00, 0x00, 0x00, 0x00 // Content
};
Span<byte> expectedData = stackalloc byte[23];
int pos = 0;
serial.CopyTo(expectedData.Slice(7, 4));
graphic.CopyTo(expectedData.Slice(11, 2));
offset.CopyTo(expectedData.Slice(13, 2));
content.CopyToLE(expectedData.Slice(15, 8));
expectedData.Write(ref pos, (byte)0xBF); // Packet ID
expectedData.Write(ref pos, (ushort)0x17); // Length
expectedData.Write(ref pos, (ushort)0x1B); // Sub-packet
expectedData.Write(ref pos, (ushort)0x1); // Command
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, graphic);
expectedData.Write(ref pos, offset);
expectedData.WriteLE(ref pos, content);
AssertThat.Equal(data, expectedData);
}
@ -323,7 +301,7 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[5 + 64 * 19]; // Max size
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
expectedData.Write(ref pos, (byte)0x3C); // Packet ID
pos += 4; // Length + spell count
ushort count = 0;
@ -331,17 +309,30 @@ namespace Server.Tests.Network.Packets
for (var i = 0; i < 64; i++)
if ((content & (1ul << i)) != 0)
{
(0x7FFFFFFF - i).CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 3);
((ushort)(i + offset)).CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 4); // X, Y
serial.CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 2);
expectedData.Write(ref pos, 0x7FFFFFFF - i);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
expectedData.Write(ref pos, (byte)0);
#else
pos += 3;
#endif
expectedData.Write(ref pos, (ushort)(i + offset));
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0); // X. Y
#else
pos += 4;
#endif
expectedData.Write(ref pos, serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
#else
pos += 2;
#endif
count++;
}
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
count.CopyTo(expectedData.Slice(3, 2));
expectedData.Slice(1, 2).Write((ushort)pos); // Length
expectedData.Slice(3, 2).Write(count); // Count
expectedData = expectedData.Slice(0, pos);
@ -357,10 +348,10 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new SpellbookContent6017(serial, offset, content).Compile();
Span<byte> expectedData = stackalloc byte[5 + 64 * 19]; // Max size
Span<byte> expectedData = stackalloc byte[5 + 64 * 20]; // Max size
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
expectedData.Write(ref pos, (byte)0x3C); // Packet ID
pos += 4; // Length + spell count
ushort count = 0;
@ -368,17 +359,31 @@ namespace Server.Tests.Network.Packets
for (var i = 0; i < 64; i++)
if ((content & (1ul << i)) != 0)
{
(0x7FFFFFFF - i).CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 3);
((ushort)(i + offset)).CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 5); // X, Y, Grid Location
serial.CopyTo(ref pos, expectedData);
expectedData.Clear(ref pos, 2);
expectedData.Write(ref pos, 0x7FFFFFFF - i);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
expectedData.Write(ref pos, (byte)0);
#else
pos += 3;
#endif
expectedData.Write(ref pos, (ushort)(i + offset));
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0); // X. Y
expectedData.Write(ref pos, (byte)0); // Grid Location
#else
pos += 5;
#endif
expectedData.Write(ref pos, serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
#else
pos += 2;
#endif
count++;
}
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
count.CopyTo(expectedData.Slice(3, 2));
expectedData.Slice(1, 2).Write((ushort)pos); // Length
expectedData.Slice(3, 2).Write(count); // Count
expectedData = expectedData.Slice(0, pos);
@ -396,15 +401,19 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[20];
int pos = 0;
((byte)0x25).CopyTo(ref pos, expectedData); // Packet ID
item.Serial.CopyTo(ref pos, expectedData);
((ushort)item.ItemID).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // signed, itemID offset
((ushort)Math.Min(item.Amount, ushort.MaxValue)).CopyTo(ref pos, expectedData);
((ushort)item.X).CopyTo(ref pos, expectedData);
((ushort)item.Y).CopyTo(ref pos, expectedData);
(item.Parent?.Serial ?? Serial.Zero).CopyTo(ref pos, expectedData);
((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x25); // Packet ID
expectedData.Write(ref pos, item.Serial);
expectedData.Write(ref pos, (ushort)item.ItemID);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // ItemID offset
#else
pos++;
#endif
expectedData.Write(ref pos, (ushort)Math.Min(item.Amount, ushort.MaxValue));
expectedData.Write(ref pos, (ushort)item.X);
expectedData.Write(ref pos, (ushort)item.Y);
expectedData.Write(ref pos, item.Parent?.Serial ?? Serial.Zero);
expectedData.Write(ref pos, (ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
AssertThat.Equal(data, expectedData);
}
@ -420,16 +429,24 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[21];
int pos = 0;
((byte)0x25).CopyTo(ref pos, expectedData); // Packet ID
item.Serial.CopyTo(ref pos, expectedData);
((ushort)item.ItemID).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // signed, itemID offset
((ushort)Math.Min(item.Amount, ushort.MaxValue)).CopyTo(ref pos, expectedData);
((ushort)item.X).CopyTo(ref pos, expectedData);
((ushort)item.Y).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // Grid Location?
(item.Parent?.Serial ?? Serial.Zero).CopyTo(ref pos, expectedData);
((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x25); // Packet ID
expectedData.Write(ref pos, item.Serial);
expectedData.Write(ref pos, (ushort)item.ItemID);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // ItemID offset
#else
pos++;
#endif
expectedData.Write(ref pos, (ushort)Math.Min(item.Amount, ushort.MaxValue));
expectedData.Write(ref pos, (ushort)item.X);
expectedData.Write(ref pos, (ushort)item.Y);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Grid Location?
#else
pos++;
#endif
expectedData.Write(ref pos, item.Parent?.Serial ?? Serial.Zero);
expectedData.Write(ref pos, (ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
AssertThat.Equal(data, expectedData);
}
@ -445,36 +462,39 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new ContainerContent(m, cont).Compile();
int count = cont.Items.Count;
Span<byte> expectedData = stackalloc byte[5 + cont.Items.Count * 19]; // Max Size
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
expectedData.Write(ref pos, (byte)0x3C); // Packet ID
pos += 4; // Length + Count
ushort written = 0;
ushort count = 0;
for (var i = 0; i < count; i++)
int itemCount = cont.Items.Count;
for (var i = 0; i < itemCount; i++)
{
var child = cont.Items[i];
if (child.Deleted || !m.CanSee(child))
continue;
child.Serial.CopyTo(ref pos, expectedData);
((ushort)child.ItemID).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // signed, itemID offset
((ushort)Math.Min(child.Amount, ushort.MaxValue)).CopyTo(ref pos, expectedData);
((ushort)child.X).CopyTo(ref pos, expectedData);
((ushort)child.Y).CopyTo(ref pos, expectedData);
cont.Serial.CopyTo(ref pos, expectedData);
((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, child.Serial);
expectedData.Write(ref pos, (ushort)child.ItemID);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // ItemID offset
#else
pos++;
#endif
expectedData.Write(ref pos, (ushort)Math.Min(child.Amount, ushort.MaxValue));
expectedData.Write(ref pos, (ushort)child.X);
expectedData.Write(ref pos, (ushort)child.Y);
expectedData.Write(ref pos, cont.Serial);
expectedData.Write(ref pos, (ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
written++;
count++;
}
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
written.CopyTo(expectedData.Slice(3, 2));
expectedData.Slice(1, 2).Write((ushort)pos); // Length
expectedData.Slice(3, 2).Write(count); // Count
expectedData = expectedData.Slice(0, pos);
@ -492,37 +512,44 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new ContainerContent6017(m, cont).Compile();
int count = cont.Items.Count;
Span<byte> expectedData = stackalloc byte[5 + cont.Items.Count * 20];
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
expectedData.Write(ref pos, (byte)0x3C); // Packet ID
pos += 4; // Length + Count
ushort written = 0;
ushort count = 0;
for (var i = 0; i < count; i++)
int itemCount = cont.Items.Count;
for (var i = 0; i < itemCount; i++)
{
var child = cont.Items[i];
if (child.Deleted || !m.CanSee(child))
continue;
child.Serial.CopyTo(ref pos, expectedData);
((ushort)child.ItemID).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // signed, itemID offset
((ushort)Math.Min(child.Amount, ushort.MaxValue)).CopyTo(ref pos, expectedData);
((ushort)child.X).CopyTo(ref pos, expectedData);
((ushort)child.Y).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // Grid Location?
cont.Serial.CopyTo(ref pos, expectedData);
((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, child.Serial);
expectedData.Write(ref pos, (ushort)child.ItemID);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // ItemID offset
#else
pos++;
#endif
expectedData.Write(ref pos, (ushort)Math.Min(child.Amount, ushort.MaxValue));
expectedData.Write(ref pos, (ushort)child.X);
expectedData.Write(ref pos, (ushort)child.Y);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Grid Location?
#else
pos++;
#endif
expectedData.Write(ref pos, cont.Serial);
expectedData.Write(ref pos, (ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
written++;
count++;
}
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
written.CopyTo(expectedData.Slice(3, 2));
expectedData.Slice(1, 2).Write((ushort)pos); // Length
expectedData.Slice(3, 2).Write(count); // Count
expectedData = expectedData.Slice(0, pos);

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Network;
using Xunit;
@ -12,11 +13,11 @@ namespace Server.Tests.Network.Packets
byte lightLevel = 5;
Span<byte> data = new GlobalLightLevel(lightLevel).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x4F, // Packet ID
lightLevel
};
Span<byte> expectedData = stackalloc byte[2];
int pos = 0;
expectedData.Write(ref pos, (byte)0x4F); // Packet ID
expectedData.Write(ref pos, lightLevel);
AssertThat.Equal(data, expectedData);
}
@ -28,14 +29,12 @@ namespace Server.Tests.Network.Packets
byte lightLevel = 5;
Span<byte> data = new PersonalLightLevel(serial, lightLevel).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x4E, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
lightLevel
};
Span<byte> expectedData = stackalloc byte[6];
int pos = 0;
serial.CopyTo(expectedData.Slice(1, 4));
expectedData.Write(ref pos, (byte)0x4E); // Packet ID
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, lightLevel);
AssertThat.Equal(data, expectedData);
}

View file

@ -53,7 +53,7 @@ namespace Server.Tests.Network.Packets
0xBF, // Packet ID
0x00, 0x06, // Length
0x00, 0x08, // Sub-packet
0x00, // Felucca
0x00 // Felucca
};
AssertThat.Equal(data, expectedData);

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using Server.ContextMenus;
@ -40,29 +41,40 @@ namespace Server.Tests.Network.Packets
}
);
string question = menu.Question?.Trim() ?? "";
int questionLength = Math.Min(255, question.Length);
int length = 11 + questionLength + menu.Entries.Sum(entry => 5 + entry.Name?.Trim().Length ?? 0);
Span<byte> data = new DisplayItemListMenu(menu).Compile();
Span<byte> expectedData = stackalloc byte[length];
string question = menu.Question;
int questionLength = Math.Min(255, question.Length);
int entriesCount = 0;
int length = 11 + questionLength;
foreach (var entry in menu.Entries)
{
length += 5 + entry.Name.Length;
if (entriesCount == 255)
break;
entriesCount++;
}
Span<byte> expectedData = stackalloc byte[length];
int pos = 0;
((byte)0x7C).CopyTo(ref pos, expectedData); // Packet ID
((ushort)length).CopyTo(ref pos, expectedData);
menu.Serial.CopyTo(ref pos, expectedData);
((ushort)0x00).CopyTo(ref pos, expectedData);
question.CopySmallASCIITo(ref pos, expectedData);
((byte)menu.Entries.Length).CopyTo(ref pos, expectedData);
for (int i = 0; i < menu.Entries.Length; i++)
expectedData.Write(ref pos, (byte)0x7C); // Packet ID
expectedData.Write(ref pos, (ushort)length);
expectedData.Write(ref pos, menu.Serial);
expectedData.Write(ref pos, (ushort)0x00);
expectedData.Write(ref pos, (byte)questionLength);
expectedData.WriteAscii(ref pos, question, 255);
expectedData.Write(ref pos, (byte)entriesCount);
for (int i = 0; i < entriesCount; i++)
{
var entry = menu.Entries[i];
((ushort)entry.ItemID).CopyTo(ref pos, expectedData);
((ushort)entry.Hue).CopyTo(ref pos, expectedData);
(entry.Name?.Trim() ?? "").CopySmallASCIITo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)entry.ItemID);
expectedData.Write(ref pos, (ushort)entry.Hue);
string name = entry.Name?.Trim() ?? "";
expectedData.Write(ref pos, (byte)Math.Min(255, name.Length));
expectedData.WriteAscii(ref pos, name, 255);
}
AssertThat.Equal(data, expectedData);
@ -81,27 +93,43 @@ namespace Server.Tests.Network.Packets
}
);
string question = menu.Question?.Trim() ?? "";
int questionLength = Math.Min(255, question.Length);
int length = 11 + questionLength + menu.Answers.Sum(answer => 5 + answer?.Trim().Length ?? 0);
Span<byte> data = new DisplayQuestionMenu(menu).Compile();
string question = menu.Question;
int questionLength = Math.Min(255, question.Length);
int answersCount = 0;
int length = 11 + questionLength;
foreach (var answer in menu.Answers)
{
length += 5 + answer.Length;
if (answersCount == 255)
break;
answersCount++;
}
Span<byte> expectedData = stackalloc byte[length];
int pos = 0;
((byte)0x7C).CopyTo(ref pos, expectedData); // Packet ID
((ushort)length).CopyTo(ref pos, expectedData);
menu.Serial.CopyTo(ref pos, expectedData);
((ushort)0x00).CopyTo(ref pos, expectedData);
question.CopySmallASCIITo(ref pos, expectedData);
((byte)menu.Answers.Length).CopyTo(ref pos, expectedData);
for (int i = 0; i < menu.Answers.Length; i++)
expectedData.Write(ref pos, (byte)0x7C); // Packet ID
expectedData.Write(ref pos, (ushort)length);
expectedData.Write(ref pos, menu.Serial);
expectedData.Write(ref pos, (ushort)0x00);
expectedData.Write(ref pos, (byte)question.Length);
expectedData.WriteAscii(ref pos, question, 255);
expectedData.Write(ref pos, (byte)answersCount);
for (int i = 0; i < answersCount; i++)
{
0x0.CopyTo(ref pos, expectedData);
(menu.Answers[i]?.Trim() ?? "").CopySmallASCIITo(ref pos, expectedData);
var answer = menu.Answers[i];
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
#else
pos += 4;
#endif
expectedData.Write(ref pos, (byte)Math.Min(255, answer.Length));
expectedData.WriteAscii(ref pos, answer, 255);
}
AssertThat.Equal(data, expectedData);
@ -123,20 +151,20 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[length];
int pos = 0;
((byte)0xBF).CopyTo(ref pos, expectedData); // Packet ID
((ushort)length).CopyTo(ref pos, expectedData); // Length
((ushort)0x14).CopyTo(ref pos, expectedData); // Command
((ushort)0x02).CopyTo(ref pos, expectedData); // Subcommand
menu.Target.Serial.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0xBF); // Packet ID
expectedData.Write(ref pos, (ushort)length); // Length
expectedData.Write(ref pos, (ushort)0x14); // Command
expectedData.Write(ref pos, (ushort)0x02); // Subcommand
expectedData.Write(ref pos, menu.Target.Serial);
var entries = menu.Entries;
((byte)entries.Length).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)entries.Length);
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
entry.Number.CopyTo(ref pos, expectedData);
((ushort)i).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, entry.Number);
expectedData.Write(ref pos, (ushort)i);
var flags = entry.Flags;
@ -148,7 +176,7 @@ namespace Server.Tests.Network.Packets
if (!(entry.Enabled && menu.From.InRange(item.GetWorldLocation(), range)))
flags |= CMEFlags.Disabled;
((ushort)flags).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)flags);
}
AssertThat.Equal(data, expectedData);
@ -170,20 +198,20 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[length];
int pos = 0;
((byte)0xBF).CopyTo(ref pos, expectedData); // Packet ID
((ushort)length).CopyTo(ref pos, expectedData); // Length
((ushort)0x14).CopyTo(ref pos, expectedData); // Command
((ushort)0x01).CopyTo(ref pos, expectedData); // Subcommand
menu.Target.Serial.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0xBF); // Packet ID
expectedData.Write(ref pos, (ushort)length); // Length
expectedData.Write(ref pos, (ushort)0x14); // Command
expectedData.Write(ref pos, (ushort)0x01); // Subcommand
expectedData.Write(ref pos, menu.Target.Serial);
var entries = menu.Entries;
((byte)entries.Length).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)entries.Length);
for (int i = 0; i < entries.Length; i++)
{
var entry = entries[i];
((ushort)i).CopyTo(ref pos, expectedData);
((ushort)(entry.Number - 3000000)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)i);
expectedData.Write(ref pos, (ushort)(entry.Number - 3000000));
var flags = entry.Flags;
@ -200,10 +228,10 @@ namespace Server.Tests.Network.Packets
if (!(entry.Enabled && menu.From.InRange(item.GetWorldLocation(), range)))
flags |= CMEFlags.Disabled;
((ushort)flags).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)flags);
if ((flags & CMEFlags.Colored) != 0)
((ushort)color).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)color);
}
AssertThat.Equal(data, expectedData);

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Xunit;
using Server.Network;
@ -31,18 +32,20 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[50 + args.Length * 2];
int pos = 0;
((byte)0xC1).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
expectedData.Write(ref pos, (byte)0xC1); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
serial.CopyTo(ref pos, expectedData);
((ushort)graphic).CopyTo(ref pos, expectedData);
((byte)messageType).CopyTo(ref pos, expectedData);
((ushort)hue).CopyTo(ref pos, expectedData);
((ushort)font).CopyTo(ref pos, expectedData);
number.CopyTo(ref pos, expectedData);
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
args.CopyRawUnicodeLittleEndianTo(ref pos, expectedData);
expectedData.Clear(ref pos, 2); // Terminator
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, (ushort)graphic);
expectedData.Write(ref pos, (byte)messageType);
expectedData.Write(ref pos, (ushort)hue);
expectedData.Write(ref pos, (ushort)font);
expectedData.Write(ref pos, number);
expectedData.WriteAsciiFixed(ref pos, name, 30);
expectedData.WriteLittleUni(ref pos, args);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0); // Terminator
#endif
AssertThat.Equal(data, expectedData);
}
@ -76,21 +79,27 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[52 + affix.Length + args.Length * 2];
int pos = 0;
((byte)0xCC).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
expectedData.Write(ref pos, (byte)0xCC); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
serial.CopyTo(ref pos, expectedData);
((ushort)graphic).CopyTo(ref pos, expectedData);
((byte)messageType).CopyTo(ref pos, expectedData);
((ushort)hue).CopyTo(ref pos, expectedData);
((ushort)font).CopyTo(ref pos, expectedData);
number.CopyTo(ref pos, expectedData);
((byte)affixType).CopyTo(ref pos, expectedData);
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
affix.CopyRawASCIITo(ref pos, expectedData);
expectedData.Clear(ref pos, 2); // Terminator
args.CopyRawUnicodeLittleEndianTo(ref pos, expectedData);
expectedData.Clear(ref pos, 1); // Terminator
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, (ushort)graphic);
expectedData.Write(ref pos, (byte)messageType);
expectedData.Write(ref pos, (ushort)hue);
expectedData.Write(ref pos, (ushort)font);
expectedData.Write(ref pos, number);
expectedData.Write(ref pos, (byte)affixType);
expectedData.WriteAsciiFixed(ref pos, name, 30);
expectedData.WriteAscii(ref pos, affix);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0); // Terminator
#else
pos += 2;
#endif
expectedData.WriteLittleUni(ref pos, args);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Terminator
#endif
AssertThat.Equal(data, expectedData);
}
@ -118,17 +127,19 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[45 + text.Length];
int pos = 0;
((byte)0x1C).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
expectedData.Write(ref pos, (byte)0x1C); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
serial.CopyTo(ref pos, expectedData);
((ushort)graphic).CopyTo(ref pos, expectedData);
((byte)messageType).CopyTo(ref pos, expectedData);
((ushort)hue).CopyTo(ref pos, expectedData);
((ushort)font).CopyTo(ref pos, expectedData);
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
text.CopyRawASCIITo(ref pos, expectedData);
expectedData.Clear(ref pos, 1); // Terminator
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, (ushort)graphic);
expectedData.Write(ref pos, (byte)messageType);
expectedData.Write(ref pos, (ushort)hue);
expectedData.Write(ref pos, (ushort)font);
expectedData.WriteAsciiFixed(ref pos, name, 30);
expectedData.WriteAscii(ref pos, text);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Terminator
#endif
AssertThat.Equal(data, expectedData);
}
@ -158,18 +169,20 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[50 + text.Length * 2];
int pos = 0;
((byte)0xAE).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
expectedData.Write(ref pos, (byte)0xAE); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
serial.CopyTo(ref pos, expectedData);
((ushort)graphic).CopyTo(ref pos, expectedData);
((byte)messageType).CopyTo(ref pos, expectedData);
((ushort)hue).CopyTo(ref pos, expectedData);
((ushort)font).CopyTo(ref pos, expectedData);
lang.CopyASCIIFixedTo(ref pos, 4, expectedData);
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
text.CopyRawUnicodeBigEndianTo(ref pos, expectedData);
expectedData.Clear(ref pos, 2); // Terminator
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, (ushort)graphic);
expectedData.Write(ref pos, (byte)messageType);
expectedData.Write(ref pos, (ushort)hue);
expectedData.Write(ref pos, (ushort)font);
expectedData.WriteAsciiFixed(ref pos, lang, 4);
expectedData.WriteAsciiFixed(ref pos, name, 30);
expectedData.WriteBigUni(ref pos, text);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Terminator
#endif
AssertThat.Equal(data, expectedData);
}
@ -182,15 +195,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new FollowMessage(serial, serial2).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x15, // Packet ID
0x00, 0x00, 0x00, 0x00, // Follower
0x00, 0x00, 0x00, 0x00, // Followee
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
serial.CopyTo(expectedData.Slice(1, 4));
serial2.CopyTo(expectedData.Slice(5, 4));
expectedData.Write(ref pos, (byte)0x15); // Packet ID
expectedData.Write(ref pos, serial);
expectedData.Write(ref pos, serial2);
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Net;
using Server.Network;
using Xunit;
@ -15,16 +16,15 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DeathAnimation(killed, corpse).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xAF, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial of killed
0x00, 0x00, 0x00, 0x00, // Serial of corpse
0x00, 0x00, 0x00, 0x00
};
Span<byte> expectedData = stackalloc byte[13];
int pos = 0;
killed.CopyTo(expectedData.Slice(1, 4));
corpse.CopyTo(expectedData.Slice(5, 4));
expectedData.Write(ref pos, (byte)0xAF); // Packet ID
expectedData.Write(ref pos, killed);
expectedData.Write(ref pos, corpse);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0);
#endif
AssertThat.Equal(data, expectedData);
}
@ -37,17 +37,21 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new BondedStatus(petSerial, bonded).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBF, // Packet ID
0x00, 0x0B, // Length
0x00, 0x19, // Sub-packet
0x00, // Sub command
0x00, 0x00, 0x00, 0x00, // Serial
(byte)(bonded ? 0x1 : 0x0)
};
Span<byte> expectedData = stackalloc byte[11];
int pos = 0;
petSerial.CopyTo(expectedData.Slice(6, 4));
expectedData.Write(ref pos, (byte)0xBF); // Packet ID
expectedData.Write(ref pos, (ushort)0x0B); // Length
expectedData.Write(ref pos, (ushort)0x19); // Sub-packet
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Command
#else
pos++;
#endif
expectedData.Write(ref pos, petSerial);
expectedData.Write(ref pos, bonded);
AssertThat.Equal(data, expectedData);
}
@ -62,29 +66,19 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileMoving(m, noto).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x77, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Body
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, // Z
0x00, // Direction
0x00, 0x00, // Hue
0x00, // Flags
0x00 // Noto
};
Span<byte> expectedData = stackalloc byte[17];
int pos = 0;
m.Serial.CopyTo(expectedData.Slice(1, 4));
((ushort)m.Body).CopyTo(expectedData.Slice(5, 2));
((ushort)m.X).CopyTo(expectedData.Slice(7, 2));
((ushort)m.Y).CopyTo(expectedData.Slice(9, 2));
expectedData[11] = (byte)m.Z;
expectedData[12] = (byte)m.Direction;
((ushort)m.Hue).CopyTo(expectedData.Slice(13, 2));
expectedData[15] = (byte)m.GetPacketFlags();
expectedData[16] = (byte)noto;
expectedData.Write(ref pos, (byte)0x77); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, (ushort)m.Body);
expectedData.Write(ref pos, (ushort)m.X);
expectedData.Write(ref pos, (ushort)m.Y);
expectedData.Write(ref pos, (byte)m.Z);
expectedData.Write(ref pos, (byte)m.Direction);
expectedData.Write(ref pos, (ushort)m.Hue);
expectedData.Write(ref pos, (byte)m.GetPacketFlags());
expectedData.Write(ref pos, (byte)noto);
AssertThat.Equal(data, expectedData);
}
@ -99,29 +93,19 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileMoving(m, noto).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x77, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Body
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, // Z
0x00, // Direction
0x00, 0x00, // Hue
0x00, // Flags
0x00 // Noto
};
Span<byte> expectedData = stackalloc byte[17];
int pos = 0;
m.Serial.CopyTo(expectedData.Slice(1, 4));
((ushort)m.Body).CopyTo(expectedData.Slice(5, 2));
((ushort)m.X).CopyTo(expectedData.Slice(7, 2));
((ushort)m.Y).CopyTo(expectedData.Slice(9, 2));
expectedData[11] = (byte)m.Z;
expectedData[12] = (byte)m.Direction;
((ushort)m.Hue).CopyTo(expectedData.Slice(13, 2));
expectedData[15] = (byte)m.GetOldPacketFlags();
expectedData[16] = (byte)noto;
expectedData.Write(ref pos, (byte)0x77); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, (ushort)m.Body);
expectedData.Write(ref pos, (ushort)m.X);
expectedData.Write(ref pos, (ushort)m.Y);
expectedData.Write(ref pos, (byte)m.Z);
expectedData.Write(ref pos, (byte)m.Direction);
expectedData.Write(ref pos, (ushort)m.Hue);
expectedData.Write(ref pos, (byte)m.GetOldPacketFlags());
expectedData.Write(ref pos, (byte)noto);
AssertThat.Equal(data, expectedData);
}
@ -134,16 +118,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileHits(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA1, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, false, expectedData.Slice(5));
expectedData.Write(ref pos, (byte)0xA1); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false);
AssertThat.Equal(data, expectedData);
}
@ -156,18 +136,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileHitsN(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA1, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
int max = AttributeNormalizer.Maximum;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, true, expectedData.Slice(5));
expectedData.Write(ref pos, (byte)0xA1); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true);
AssertThat.Equal(data, expectedData);
}
@ -180,16 +154,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileMana(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA2, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, false, expectedData.Slice(5));
expectedData.Write(ref pos, (byte)0xA2); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false);
AssertThat.Equal(data, expectedData);
}
@ -202,18 +172,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileManaN(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA2, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
int max = AttributeNormalizer.Maximum;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, true, expectedData.Slice(5));
expectedData.Write(ref pos, (byte)0xA2); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true);
AssertThat.Equal(data, expectedData);
}
@ -226,16 +190,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileStam(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA3, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, false, expectedData.Slice(5));
expectedData.Write(ref pos, (byte)0xA3); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false);
AssertThat.Equal(data, expectedData);
}
@ -248,18 +208,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileStamN(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA3, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
int max = AttributeNormalizer.Maximum;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, true, expectedData.Slice(5));
expectedData.Write(ref pos, (byte)0xA3); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true);
AssertThat.Equal(data, expectedData);
}
@ -272,22 +226,14 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileAttributes(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x2D, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00, // Current Hits
0x00, 0x00, // Max Mana
0x00, 0x00, // Current Mana
0x00, 0x00, // Max Stam
0x00, 0x00 // Current Stam
};
Span<byte> expectedData = stackalloc byte[17];
int pos = 0;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, false, expectedData.Slice(5));
AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, false, expectedData.Slice(9));
AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, false, expectedData.Slice(13));
expectedData.Write(ref pos, (byte)0x2D); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false);
expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false);
expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false);
AssertThat.Equal(data, expectedData);
}
@ -300,24 +246,14 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new MobileAttributesN(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x2D, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00, // Current Hits
0x00, 0x00, // Max Mana
0x00, 0x00, // Current Mana
0x00, 0x00, // Max Stam
0x00, 0x00 // Current Stam
};
Span<byte> expectedData = stackalloc byte[17];
int pos = 0;
int max = AttributeNormalizer.Maximum;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, true, expectedData.Slice(5));
AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, true, expectedData.Slice(9));
AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, true, expectedData.Slice(13));
expectedData.Write(ref pos, (byte)0x2D); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true);
expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true);
expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true);
AssertThat.Equal(data, expectedData);
}
@ -335,11 +271,13 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[37];
int pos = 0;
((byte)0x98).CopyTo(ref pos, expectedData);
((ushort)0x25).CopyTo(ref pos, expectedData);
m.Serial.CopyTo(ref pos, expectedData);
(m.Name ?? "").CopyRawASCIITo(ref pos, 29, expectedData);
((byte)0x0).CopyTo(ref pos, expectedData); // Null terminator
expectedData.Write(ref pos, (byte)0x98);
expectedData.Write(ref pos, (ushort)0x25);
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAsciiFixed(ref pos, m.Name ?? "", 29);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#endif
AssertThat.Equal(data, expectedData);
}
@ -368,14 +306,14 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[14];
int pos = 0;
((byte)0x6E).CopyTo(ref pos, expectedData);
mobile.CopyTo(ref pos, expectedData);
((ushort)action).CopyTo(ref pos, expectedData);
((ushort)frameCount).CopyTo(ref pos, expectedData);
((ushort)repeatCount).CopyTo(ref pos, expectedData);
reverse.CopyTo(ref pos, expectedData);
repeat.CopyTo(ref pos, expectedData);
delay.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x6E);
expectedData.Write(ref pos, mobile);
expectedData.Write(ref pos, (ushort)action);
expectedData.Write(ref pos, (ushort)frameCount);
expectedData.Write(ref pos, (ushort)repeatCount);
expectedData.Write(ref pos, reverse);
expectedData.Write(ref pos, repeat);
expectedData.Write(ref pos, delay);
AssertThat.Equal(data, expectedData);
}
@ -398,11 +336,11 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[10];
int pos = 0;
((byte)0xE2).CopyTo(ref pos, expectedData);
mobile.CopyTo(ref pos, expectedData);
((ushort)action).CopyTo(ref pos, expectedData);
((ushort)frameCount).CopyTo(ref pos, expectedData);
delay.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0xE2);
expectedData.Write(ref pos, mobile);
expectedData.Write(ref pos, (ushort)action);
expectedData.Write(ref pos, (ushort)frameCount);
expectedData.Write(ref pos, delay);
AssertThat.Equal(data, expectedData);
}
@ -420,21 +358,27 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[43];
int pos = 0;
((byte)0x11).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
expectedData.Write(ref pos, (byte)0x11); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
m.Serial.CopyTo(ref pos, expectedData);
(m.Name ?? "").CopyASCIIFixedTo(ref pos, 30, expectedData);
expectedData.Write(ref pos, m.Serial);
expectedData.WriteAsciiFixed(ref pos, m.Name ?? "", 30);
AttributeNormalizerUtilities.WriteReverse(m.Hits, m.HitsMax, true, expectedData.Slice(pos));
pos += 4;
canBeRenamed.CopyTo(ref pos, expectedData);
expectedData.WriteReverseAttribute(ref pos, m.Hits, m.HitsMax, true);
expectedData.Write(ref pos, canBeRenamed);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // type
#endif
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileStatusExtended()
[Theory]
[InlineData(ProtocolChanges.Version70610)]
[InlineData(ProtocolChanges.Version400a)]
[InlineData(ProtocolChanges.Version502b)]
public void TestMobileStatusExtended(ProtocolChanges changes)
{
var beholder = new Mobile(0x1)
{
@ -451,14 +395,17 @@ namespace Server.Tests.Network.Packets
NetState ns = new NetState(new AccountPacketTests.TestConnectionContext
{
RemoteEndPoint = IPEndPoint.Parse("127.0.0.1")
});
})
{
ProtocolChanges = changes
};
Span<byte> data = new MobileStatus(beholder, beheld, ns).Compile();
Span<byte> expectedData = stackalloc byte[121]; // Max Size
int pos = 0;
((byte)0x11).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x11);
pos += 2; // Length
int type;
@ -469,69 +416,460 @@ namespace Server.Tests.Network.Packets
else if (Core.ML && ns.SupportsExpansion(Expansion.ML)) type = 5;
else type = Core.AOS ? 4 : 3;
beheld.Serial.CopyTo(ref pos, expectedData);
beheld.Name.CopyASCIIFixedTo(ref pos, 30, expectedData);
expectedData.Write(ref pos, beheld.Serial);
expectedData.WriteAsciiFixed(ref pos, beheld.Name, 30);
AttributeNormalizerUtilities.WriteReverse(beheld.Hits, beheld.HitsMax, notSelf, expectedData.Slice(pos));
pos += 4;
expectedData.WriteReverseAttribute(ref pos, beheld.Hits, beheld.HitsMax, notSelf);
beheld.CanBeRenamedBy(beheld).CopyTo(ref pos, expectedData);
((byte)type).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, beheld.CanBeRenamedBy(beheld));
expectedData.Write(ref pos, (byte)type);
if (type > 0)
{
beheld.Female.CopyTo(ref pos, expectedData);
((ushort)beheld.Str).CopyTo(ref pos, expectedData);
((ushort)beheld.Dex).CopyTo(ref pos, expectedData);
((ushort)beheld.Int).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, beheld.Female);
expectedData.Write(ref pos, (ushort)beheld.Str);
expectedData.Write(ref pos, (ushort)beheld.Dex);
expectedData.Write(ref pos, (ushort)beheld.Int);
AttributeNormalizerUtilities.WriteReverse(beheld.Stam, beheld.StamMax, notSelf, expectedData.Slice(pos));
pos += 4;
expectedData.WriteReverseAttribute(ref pos, beheld.Stam, beheld.StamMax, notSelf);
expectedData.WriteReverseAttribute(ref pos, beheld.Mana, beheld.ManaMax, notSelf);
AttributeNormalizerUtilities.WriteReverse(beheld.Mana, beheld.ManaMax, notSelf, expectedData.Slice(pos));
pos += 4;
beheld.TotalGold.CopyTo(ref pos, expectedData);
((ushort)(Core.AOS ? beheld.PhysicalResistance : (int)(beheld.ArmorRating + 0.5))).CopyTo(ref pos, expectedData);
((ushort)(Mobile.BodyWeight + beheld.TotalWeight)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, beheld.TotalGold);
expectedData.Write(ref pos, (ushort)(Core.AOS ? beheld.PhysicalResistance : (int)(beheld.ArmorRating + 0.5)));
expectedData.Write(ref pos, (ushort)(Mobile.BodyWeight + beheld.TotalWeight));
if (type >= 5)
{
((ushort)beheld.MaxWeight).CopyTo(ref pos, expectedData);
((byte)(beheld.Race.RaceID + 1)).CopyTo(ref pos, expectedData); // 0x00 for a non-ML enabled account
expectedData.Write(ref pos, (ushort)beheld.MaxWeight);
expectedData.Write(ref pos, (byte)(beheld.Race.RaceID + 1)); // 0x00 for a non-ML enabled account
}
((ushort)beheld.StatCap).CopyTo(ref pos, expectedData);
((byte)beheld.Followers).CopyTo(ref pos, expectedData);
((byte)beheld.FollowersMax).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)beheld.StatCap);
expectedData.Write(ref pos, (byte)beheld.Followers);
expectedData.Write(ref pos, (byte)beheld.FollowersMax);
if (type >= 4)
{
((ushort)beheld.FireResistance).CopyTo(ref pos, expectedData);
((ushort)beheld.ColdResistance).CopyTo(ref pos, expectedData);
((ushort)beheld.PoisonResistance).CopyTo(ref pos, expectedData);
((ushort)beheld.EnergyResistance).CopyTo(ref pos, expectedData);
((ushort)beheld.Luck).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)beheld.FireResistance);
expectedData.Write(ref pos, (ushort)beheld.ColdResistance);
expectedData.Write(ref pos, (ushort)beheld.PoisonResistance);
expectedData.Write(ref pos, (ushort)beheld.EnergyResistance);
expectedData.Write(ref pos, (ushort)beheld.Luck);
}
int min = 0;
int max = 0;
beheld.Weapon?.GetStatusDamage(beheld, out min, out max);
((ushort)min).CopyTo(ref pos, expectedData);
((ushort)max).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)min);
expectedData.Write(ref pos, (ushort)max);
beheld.TithingPoints.CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, beheld.TithingPoints);
if (type >= 6)
for (var i = 0; i < 15; ++i)
((ushort)beheld.GetAOSStatus(i)).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)beheld.GetAOSStatus(i));
}
((ushort)pos).CopyTo(expectedData.Slice(1)); // Length
expectedData.Slice(1, 2).Write((ushort)pos); // Length
expectedData = expectedData.Slice(0, pos);
AssertThat.Equal(data, expectedData);
}
[Theory]
[InlineData("None", 0)]
[InlineData("Lesser", 1)]
[InlineData("Lethal", 5)]
public void TestHealthbarPoison(string pName, int level)
{
var p = Poison.GetPoison(pName);
Mobile m = new Mobile(0x1);
m.DefaultMobileInit();
m.Poison = p;
Span<byte> data = new HealthbarPoison(m).Compile();
Span<byte> expectedData = stackalloc byte[12];
int pos = 0;
expectedData.Write(ref pos, (byte)0x17); // Packet ID
expectedData.Write(ref pos, (ushort)12); // Length
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, 0x10001); // Show Bar?, Poison Bar
expectedData.Write(ref pos, (byte)((p?.Level ?? -1) + 1));
AssertThat.Equal(data, expectedData);
Assert.Equal(p?.Level, m.Poison?.Level);
}
[Theory]
[InlineData(false, false)]
[InlineData(true, false)]
[InlineData(false, true)]
[InlineData(true, true)]
public void TestYellowBar(bool isBlessed, bool isYellowHealth)
{
Mobile m = new Mobile(0x1);
m.DefaultMobileInit();
m.Blessed = isBlessed;
m.YellowHealthbar = isYellowHealth;
Span<byte> data = new HealthbarYellow(m).Compile();
Span<byte> expectedData = stackalloc byte[12];
int pos = 0;
expectedData.Write(ref pos, (byte)0x17); // Packet ID
expectedData.Write(ref pos, (ushort)12); // Length
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, 0x10002); // Show Bar?, Yellow Bar
expectedData.Write(ref pos, isBlessed || isYellowHealth);
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileUpdate()
{
Mobile m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileUpdate(m).Compile();
Span<byte> expectedData = stackalloc byte[19];
int pos = 0;
var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue;
expectedData.Write(ref pos, (byte)0x20); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, (ushort)m.Body);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Unknown
#else
pos++;
#endif
expectedData.Write(ref pos, (ushort)hue);
expectedData.Write(ref pos, (byte)m.GetPacketFlags());
expectedData.Write(ref pos, (ushort)m.X);
expectedData.Write(ref pos, (ushort)m.Y);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)2); // Unknown
#else
pos += 2;
#endif
expectedData.Write(ref pos, (byte)m.Direction);
expectedData.Write(ref pos, (byte)m.Z);
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileUpdateOld()
{
Mobile m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileUpdateOld(m).Compile();
Span<byte> expectedData = stackalloc byte[19];
int pos = 0;
var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue;
expectedData.Write(ref pos, (byte)0x20); // Packet ID
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, (ushort)m.Body);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Unknown
#else
pos++;
#endif
expectedData.Write(ref pos, (ushort)hue);
expectedData.Write(ref pos, (byte)m.GetOldPacketFlags());
expectedData.Write(ref pos, (ushort)m.X);
expectedData.Write(ref pos, (ushort)m.Y);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)2); // Unknown
#else
pos += 2;
#endif
expectedData.Write(ref pos, (byte)m.Direction);
expectedData.Write(ref pos, (byte)m.Z);
AssertThat.Equal(data, expectedData);
}
[Theory]
[InlineData(0, 0, 0, 0)]
[InlineData(10, 1024, 0, 0)]
[InlineData(10, 1024, 11, 2048)]
public void TestMobileIncoming(int hairItemId, int hairHue, int facialHairItemId, int facialHairHue)
{
var beholder = new Mobile(0x1)
{
Name = "Random Mobile 1"
};
beholder.DefaultMobileInit();
var beheld = new Mobile(0x2)
{
Name = "Random Mobile 2"
};
beheld.DefaultMobileInit();
beheld.AddItem(new Item((Serial)0x1000)
{
Layer = Layer.OneHanded
});
// Test Dupe
beheld.AddItem(new Item((Serial)0x1001)
{
Layer = Layer.OneHanded
});
beheld.HairItemID = hairItemId;
beheld.HairHue = hairHue;
beheld.FacialHairItemID = facialHairItemId;
beheld.FacialHairHue = facialHairHue;
Span<byte> data = new MobileIncoming(beholder, beheld).Compile();
Span<bool> layers = stackalloc bool[256];
#if NO_LOCAL_INIT
layers.Clear();
#endif
var items = beheld.Items;
int count = items.Count;
if (beheld.HairItemID > 0)
count++;
if (beheld.FacialHairItemID > 0)
count++;
int length = 23 + count * 9; // Max Size
Span<byte> expectedData = stackalloc byte[length];
int pos = 0;
expectedData.Write(ref pos, (byte)0x78);
pos += 2; // Length
var isSolidHue = beheld.SolidHueOverride >= 0;
expectedData.Write(ref pos, beheld.Serial);
expectedData.Write(ref pos, (ushort)beheld.Body);
expectedData.Write(ref pos, (ushort)beheld.X);
expectedData.Write(ref pos, (ushort)beheld.Y);
expectedData.Write(ref pos, (byte)beheld.Z);
expectedData.Write(ref pos, (byte)beheld.Direction);
expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.Hue));
expectedData.Write(ref pos, (byte)beheld.GetPacketFlags());
expectedData.Write(ref pos, (byte)Notoriety.Compute(beholder, beheld));
byte layer;
for (int i = 0; i < items.Count; i++)
{
var item = items[i];
layer = (byte)item.Layer;
if (!item.Deleted && !layers[layer] && beholder.CanSee(item))
{
layers[layer] = true;
expectedData.Write(ref pos, item.Serial);
expectedData.Write(ref pos, (ushort)(item.ItemID & 0xFFFF));
expectedData.Write(ref pos, layer);
expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : item.Hue));
}
}
layer = (byte)Layer.Hair;
var itemId = beheld.HairItemID & 0xFFFF;
if (itemId > 0 && !layers[layer])
{
expectedData.Write(ref pos, HairInfo.FakeSerial(beheld));
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, layer);
expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.HairHue));
}
layer = (byte)Layer.FacialHair;
itemId = beheld.FacialHairItemID & 0xFFFF;
if (itemId > 0 && !layers[layer])
{
expectedData.Write(ref pos, FacialHairInfo.FakeSerial(beheld));
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, layer);
expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.FacialHairHue));
}
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0); // Zero serial, terminate list
#else
pos += 4;
#endif
expectedData.Slice(1, 2).Write((ushort)pos); // Length
expectedData = expectedData.Slice(0, pos);
AssertThat.Equal(data, expectedData);
}
[Theory]
[InlineData(ProtocolChanges.Version6000, 0, 0, 0, 0)]
[InlineData(ProtocolChanges.Version6000, 10, 1024, 0, 0)]
[InlineData(ProtocolChanges.Version6000, 10, 1024, 11, 2048)]
[InlineData(ProtocolChanges.Version7000, 0, 0, 0, 0)]
[InlineData(ProtocolChanges.Version7000, 10, 1024, 0, 0)]
[InlineData(ProtocolChanges.Version7000, 10, 1024, 11, 2048)]
public void TestMobileIncomingOld(ProtocolChanges protocolChanges, int hairItemId, int hairHue, int facialHairItemId, int facialHairHue)
{
var beholder = new Mobile(0x1)
{
Name = "Random Mobile 1"
};
beholder.DefaultMobileInit();
var beheld = new Mobile(0x2)
{
Name = "Random Mobile 2"
};
beheld.DefaultMobileInit();
beheld.AddItem(new Item((Serial)0x1000)
{
Layer = Layer.OneHanded
});
// Test Dupe
beheld.AddItem(new Item((Serial)0x1001)
{
Layer = Layer.OneHanded
});
beheld.HairItemID = hairItemId;
beheld.HairHue = hairHue;
beheld.FacialHairItemID = facialHairItemId;
beheld.FacialHairHue = facialHairHue;
NetState ns = new NetState(new AccountPacketTests.TestConnectionContext
{
RemoteEndPoint = IPEndPoint.Parse("127.0.0.1")
})
{
ProtocolChanges = protocolChanges
};
Span<byte> data = (ns.StygianAbyss ? (Packet)new MobileIncomingSA(beholder, beheld) : new MobileIncomingOld(beholder, beheld))
.Compile();
Span<bool> layers = stackalloc bool[256];
#if NO_LOCAL_INIT
layers.Clear();
#endif
var items = beheld.Items;
int count = items.Count;
if (beheld.HairItemID > 0)
count++;
if (beheld.FacialHairItemID > 0)
count++;
int length = 23 + count * 9; // Max Size
Span<byte> expectedData = stackalloc byte[length];
int pos = 0;
expectedData.Write(ref pos, (byte)0x78);
pos += 2; // Length
var isSolidHue = beheld.SolidHueOverride >= 0;
expectedData.Write(ref pos, beheld.Serial);
expectedData.Write(ref pos, (ushort)beheld.Body);
expectedData.Write(ref pos, (ushort)beheld.X);
expectedData.Write(ref pos, (ushort)beheld.Y);
expectedData.Write(ref pos, (byte)beheld.Z);
expectedData.Write(ref pos, (byte)beheld.Direction);
expectedData.Write(ref pos, (ushort)(isSolidHue ? beheld.SolidHueOverride : beheld.Hue));
expectedData.Write(ref pos, (byte)(ns.StygianAbyss ? beheld.GetOldPacketFlags() : beheld.GetPacketFlags()));
expectedData.Write(ref pos, (byte)Notoriety.Compute(beholder, beheld));
byte layer;
int itemId;
int hue;
for (int i = 0; i < items.Count; i++)
{
var item = items[i];
layer = (byte)item.Layer;
if (!item.Deleted && !layers[layer] && beholder.CanSee(item))
{
layers[layer] = true;
itemId = item.ItemID & 0x7FFF;
hue = isSolidHue ? beheld.SolidHueOverride : item.Hue;
if (hue != 0)
itemId |= 0x8000;
expectedData.Write(ref pos, item.Serial);
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, layer);
expectedData.Write(ref pos, (ushort)hue);
}
}
layer = (byte)Layer.Hair;
itemId = beheld.HairItemID & 0x7FFF;
if (itemId > 0 && !layers[layer])
{
hue = isSolidHue ? beheld.SolidHueOverride : beheld.HairHue;
if (hue != 0)
itemId |= 0x8000;
expectedData.Write(ref pos, HairInfo.FakeSerial(beheld));
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, layer);
expectedData.Write(ref pos, (ushort)hue);
}
layer = (byte)Layer.FacialHair;
itemId = beheld.FacialHairItemID & 0x7FFF;
if (itemId > 0 && !layers[layer])
{
hue = isSolidHue ? beheld.SolidHueOverride : beheld.FacialHairHue;
if (hue != 0)
itemId |= 0x8000;
expectedData.Write(ref pos, FacialHairInfo.FakeSerial(beheld));
expectedData.Write(ref pos, (ushort)itemId);
expectedData.Write(ref pos, layer);
expectedData.Write(ref pos, (ushort)hue);
}
#if NO_LOCAL_INIT
expectedData.Write(ref pos, 0); // Zero serial, terminate list
#else
pos += 4;
#endif
expectedData.Slice(1, 2).Write((ushort)pos); // Length
expectedData = expectedData.Slice(0, pos);
AssertThat.Equal(data, expectedData);
}
}
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Items;
using Server.Network;
using Xunit;
@ -20,26 +21,20 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DisplaySecureTrade(m, firstCont, secondCont, name).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x6F, // Packet ID
0x00, 0x2F, // Length
(byte)TradeFlag.Display, // Command
0x00, 0x00, 0x00, 0x00, // Mobile Serial
0x00, 0x00, 0x00, 0x00, // First Container Serial
0x00, 0x00, 0x00, 0x00, // Second Container Serial
0x01, // true if has name
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Name
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
bool hasName = name.Length > 0;
int pos = 4;
m.Serial.CopyTo(ref pos, expectedData);
firstCont.Serial.CopyTo(ref pos, expectedData);
secondCont.Serial.CopyTo(ref pos, expectedData);
pos++;
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
Span<byte> expectedData = stackalloc byte[17 + (hasName ? 30 : 0)];
int pos = 0;
expectedData.Write(ref pos, (byte)0x6F); // Packet ID
expectedData.Write(ref pos, (ushort)0x2F); // Length
expectedData.Write(ref pos, (byte)TradeFlag.Display); // Command
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, firstCont.Serial);
expectedData.Write(ref pos, secondCont.Serial);
expectedData.Write(ref pos, hasName);
if (hasName)
expectedData.WriteAsciiFixed(ref pos, name, 30);
AssertThat.Equal(data, expectedData);
}
@ -51,15 +46,13 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new CloseSecureTrade(cont).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x6F, // Packet ID
0x00, 0x8, // Length
(byte)TradeFlag.Close, // Command
0x00, 0x00, 0x00, 0x00 // Container Serial
};
Span<byte> expectedData = stackalloc byte[8];
int pos = 0;
cont.Serial.CopyTo(expectedData.Slice(4, 4));
expectedData.Write(ref pos, (byte)0x6F); // Packet ID
expectedData.Write(ref pos, (ushort)0x8); // Length
expectedData.Write(ref pos, (byte)TradeFlag.Close); // Command
expectedData.Write(ref pos, cont.Serial);
AssertThat.Equal(data, expectedData);
}
@ -75,17 +68,15 @@ namespace Server.Tests.Network.Packets
Container cont = first ? firstCont : secondCont;
Span<byte> data = new UpdateSecureTrade(cont, first, second).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x6F, // Packet ID
0x00, 0x10, // Length
(byte)TradeFlag.Update, // Command
0x00, 0x00, 0x00, 0x00, // Container Serial
0x00, 0x00, 0x00, first ? (byte)0x01 : (byte)0x00, // (int)1 if first
0x00, 0x00, 0x00, second ? (byte)0x01 : (byte)0x00 // (int)1 if second
};
Span<byte> expectedData = stackalloc byte[16];
int pos = 0;
cont.Serial.CopyTo(expectedData.Slice(4, 4));
expectedData.Write(ref pos, (byte)0x6F); // Packet ID
expectedData.Write(ref pos, (ushort)0x10); // Length
expectedData.Write(ref pos, (byte)TradeFlag.Update); // Command
expectedData.Write(ref pos, cont.Serial);
expectedData.Write(ref pos, first ? 1 : 0); // true if first
expectedData.Write(ref pos, second ? 1 : 0); // true if second
AssertThat.Equal(data, expectedData);
}
@ -97,20 +88,16 @@ namespace Server.Tests.Network.Packets
{
var cont = new Container(Serial.LastItem + 1);
Span<byte> data = new UpdateSecureTrade(cont, flag, gold, plat).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x6F, // Packet ID
0x00, 0x10, // Length
(byte)flag, // Command
0x00, 0x00, 0x00, 0x00, // Container Serial
0x00, 0x00, 0x00, 0x00, // Gold
0x00, 0x00, 0x00, 0x00 // Platinum
};
int pos = 4;
cont.Serial.CopyTo(ref pos, expectedData);
gold.CopyTo(ref pos, expectedData);
plat.CopyTo(ref pos, expectedData);
Span<byte> expectedData = stackalloc byte[16];
int pos = 0;
expectedData.Write(ref pos, (byte)0x6F); // Packet ID
expectedData.Write(ref pos, (ushort)0x10); // Length
expectedData.Write(ref pos, (byte)flag); // Command
expectedData.Write(ref pos, cont.Serial);
expectedData.Write(ref pos, gold);
expectedData.Write(ref pos, plat);
AssertThat.Equal(data, expectedData);
}
@ -125,28 +112,22 @@ namespace Server.Tests.Network.Packets
var itemInCont = new Item(Serial.LastItem + 2) { Parent = cont };
Span<byte> data = new SecureTradeEquip(itemInCont, m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x25, // Packet ID
0x00, 0x00, 0x00, 0x00, // Item Serial
0x00, 0x00, // Item ItemID
0x00,
0x00, 0x00, // Item Amount
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, 0x00, 0x00, 0x00, // Mobile Serial
0x00, 0x00 // Item Hue
};
Span<byte> expectedData = stackalloc byte[20];
int pos = 0;
int pos = 1;
itemInCont.Serial.CopyTo(ref pos, expectedData);
((short)itemInCont.ItemID).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x25); // Packet ID
expectedData.Write(ref pos, itemInCont.Serial);
expectedData.Write(ref pos, (short)itemInCont.ItemID);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
((short)itemInCont.Amount).CopyTo(ref pos, expectedData);
((short)itemInCont.X).CopyTo(ref pos, expectedData);
((short)itemInCont.Y).CopyTo(ref pos, expectedData);
m.Serial.CopyTo(ref pos, expectedData);
((short)itemInCont.Hue).CopyTo(ref pos, expectedData);
#endif
expectedData.Write(ref pos, (short)itemInCont.Amount);
expectedData.Write(ref pos, (short)itemInCont.X);
expectedData.Write(ref pos, (short)itemInCont.Y);
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, (short)itemInCont.Hue);
AssertThat.Equal(data, expectedData);
}
@ -161,30 +142,28 @@ namespace Server.Tests.Network.Packets
var itemInCont = new Item(Serial.LastItem + 2) { Parent = cont };
Span<byte> data = new SecureTradeEquip6017(itemInCont, m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x25, // Packet ID
0x00, 0x00, 0x00, 0x00, // Item Serial
0x00, 0x00, // Item ItemID
0x00, // Unknown
0x00, 0x00, // Item Amount
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, // Grid Location
0x00, 0x00, 0x00, 0x00, // Mobile Serial
0x00, 0x00 // Item Hue
};
int pos = 1;
itemInCont.Serial.CopyTo(ref pos, expectedData);
((short)itemInCont.ItemID).CopyTo(ref pos, expectedData);
Span<byte> expectedData = stackalloc byte[21];
int pos = 0;
expectedData.Write(ref pos, (byte)0x25); // Packet ID
expectedData.Write(ref pos, itemInCont.Serial);
expectedData.Write(ref pos, (short)itemInCont.ItemID);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
((short)itemInCont.Amount).CopyTo(ref pos, expectedData);
((short)itemInCont.X).CopyTo(ref pos, expectedData);
((short)itemInCont.Y).CopyTo(ref pos, expectedData);
#endif
expectedData.Write(ref pos, (short)itemInCont.Amount);
expectedData.Write(ref pos, (short)itemInCont.X);
expectedData.Write(ref pos, (short)itemInCont.Y);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#else
pos++;
m.Serial.CopyTo(ref pos, expectedData);
((short)itemInCont.Hue).CopyTo(ref pos, expectedData);
#endif
expectedData.Write(ref pos, m.Serial);
expectedData.Write(ref pos, (short)itemInCont.Hue);
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using Server.Network;
using Server.Prompts;
using Xunit;
@ -17,19 +18,18 @@ namespace Server.Tests.Network.Packets
var prompt = new TestPrompt();
Span<byte> data = new UnicodePrompt(prompt).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xC2, // Packet ID
0x00, 0x15, // Length
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, 0x00, 0x00, // Prompt Serial
0x00, 0x00, 0x00, 0x00, // Unused
0x00, 0x00, 0x00, 0x00, // Unused
0x00, 0x00 // Unused
};
Span<byte> expectedData = stackalloc byte[21];
int pos = 0;
prompt.Serial.CopyTo(expectedData.Slice(3, 4));
prompt.Serial.CopyTo(expectedData.Slice(7, 4));
expectedData.Write(ref pos, (byte)0xC2); // Packet ID
expectedData.Write(ref pos, (ushort)0x15); // Length
expectedData.Write(ref pos, prompt.Serial);
expectedData.Write(ref pos, prompt.Serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ulong)0);
expectedData.Write(ref pos, (ushort)0);
#endif
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using Server.Items;
@ -27,23 +28,22 @@ namespace Server.Tests.Network.Packets
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
((ushort)buyStates.Count).CopyTo(ref pos, expectedData); // Count
expectedData.Write(ref pos, (byte)0x3C); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
expectedData.Write(ref pos, (ushort)buyStates.Count); // Count
for (int i = buyStates.Count - 1; i >= 0; i--)
{
BuyItemState buyState = buyStates[i];
buyState.MySerial.CopyTo(ref pos, expectedData);
((ushort)buyState.ItemID).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, buyState.MySerial);
expectedData.Write(ref pos, (ushort)buyState.ItemID);
pos++; // ItemID Offset
((ushort)buyState.Amount).CopyTo(ref pos, expectedData);
((ushort)(i + 1)).CopyTo(ref pos, expectedData); // X
((byte)0).CopyTo(ref pos, expectedData);
((byte)1).CopyTo(ref pos, expectedData); // Y
buyState.ContainerSerial.CopyTo(ref pos, expectedData);
((ushort)buyState.Hue).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)buyState.Amount);
expectedData.Write(ref pos, (ushort)(i + 1)); // X
expectedData.Write(ref pos, (ushort)1); // Y
expectedData.Write(ref pos, buyState.ContainerSerial);
expectedData.Write(ref pos, (ushort)buyState.Hue);
}
AssertThat.Equal(data, expectedData);
@ -67,24 +67,27 @@ namespace Server.Tests.Network.Packets
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
((ushort)buyStates.Count).CopyTo(ref pos, expectedData); // Count
expectedData.Write(ref pos, (byte)0x3C); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
expectedData.Write(ref pos, (ushort)buyStates.Count); // Count
for (int i = buyStates.Count - 1; i >= 0; i--)
{
BuyItemState buyState = buyStates[i];
buyState.MySerial.CopyTo(ref pos, expectedData);
((ushort)buyState.ItemID).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, buyState.MySerial);
expectedData.Write(ref pos, (ushort)buyState.ItemID);
pos++; // ItemID Offset
((ushort)buyState.Amount).CopyTo(ref pos, expectedData);
((ushort)(i + 1)).CopyTo(ref pos, expectedData); // X
((byte)0).CopyTo(ref pos, expectedData);
((byte)1).CopyTo(ref pos, expectedData); // Y
((byte)0).CopyTo(ref pos, expectedData); // Grid Location
buyState.ContainerSerial.CopyTo(ref pos, expectedData);
((ushort)buyState.Hue).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)buyState.Amount);
expectedData.Write(ref pos, (ushort)(i + 1)); // X
expectedData.Write(ref pos, (ushort)1); // Y
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0); // Grid Location?
#else
pos++;
#endif
expectedData.Write(ref pos, buyState.ContainerSerial);
expectedData.Write(ref pos, (ushort)buyState.Hue);
}
AssertThat.Equal(data, expectedData);
@ -98,14 +101,12 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DisplayBuyList(vendor).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x24, // Packet ID
0x00, 0x00, 0x00, 0x00, // Vendor Serial
0x00, 0x30 // Buy Window Gump Id
};
Span<byte> expectedData = stackalloc byte[7];
int pos = 0;
vendor.Serial.CopyTo(expectedData.Slice(1, 4));
expectedData.Write(ref pos, (byte)0x24); // Packet ID
expectedData.Write(ref pos, vendor.Serial);
expectedData.Write(ref pos, (ushort)0x30); // Buy gump
AssertThat.Equal(data, expectedData);
}
@ -118,15 +119,16 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new DisplayBuyListHS(vendor).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x24, // Packet ID
0x00, 0x00, 0x00, 0x00, // Vendor Serial
0x00, 0x30, // Buy Window Gump Id
0x00, 0x00
};
Span<byte> expectedData = stackalloc byte[9];
int pos = 0;
vendor.Serial.CopyTo(expectedData.Slice(1, 4));
expectedData.Write(ref pos, (byte)0x24); // Packet ID
expectedData.Write(ref pos, vendor.Serial);
expectedData.Write(ref pos, (ushort)0x30); // Buy gump
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (ushort)0);
#endif
AssertThat.Equal(data, expectedData);
}
@ -154,16 +156,18 @@ namespace Server.Tests.Network.Packets
int pos = 0;
((byte)0x74).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
Serial.MinusOne.CopyTo(ref pos, expectedData); // Vendor Buy Pack Serial or -1
((byte)buyStates.Count).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x74); // Packet ID
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
expectedData.Write(ref pos, Serial.MinusOne); // Vendor Buy Pack Serial or -1
expectedData.Write(ref pos, (byte)buyStates.Count);
for (int i = 0; i < buyStates.Count; i++)
{
BuyItemState state = buyStates[i];
state.Price.CopyTo(ref pos, expectedData);
(state.Description ?? "").CopySmallASCIINullTo(ref pos, expectedData);
expectedData.Write(ref pos, state.Price);
var description = state.Description ?? "";
expectedData.Write(ref pos, (byte)Math.Min(255, description.Length + 1));
expectedData.WriteAsciiNull(ref pos, description, 255);
}
AssertThat.Equal(data, expectedData);
@ -177,15 +181,16 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new EndVendorBuy(vendor).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x3B, // Packet ID
0x00, 0x08, // Length
0x00, 0x00, 0x00, 0x00, // Vendor Serial
0x00
};
Span<byte> expectedData = stackalloc byte[8];
int pos = 0;
vendor.Serial.CopyTo(expectedData.Slice(3, 4));
expectedData.Write(ref pos, (byte)0x3B); // Packet ID
expectedData.Write(ref pos, (ushort)0x8); // Length
expectedData.Write(ref pos, vendor.Serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)-);
#endif
AssertThat.Equal(data, expectedData);
}

View file

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using Server.Network;
@ -32,23 +33,24 @@ namespace Server.Tests.Network.Packets
);
Span<byte> expectedData = stackalloc byte[length];
int pos = 0;
((byte)0x9E).CopyTo(ref pos, expectedData); // Packet ID
((ushort)length).CopyTo(ref pos, expectedData);
vendor.Serial.CopyTo(ref pos, expectedData);
((ushort)sellStates.Count).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, (byte)0x9E); // Packet ID
expectedData.Write(ref pos, (ushort)length);
expectedData.Write(ref pos, vendor.Serial);
expectedData.Write(ref pos, (ushort)sellStates.Count);
for (int i = 0; i < sellStates.Count; i++)
{
SellItemState state = sellStates[i];
state.Item.Serial.CopyTo(ref pos, expectedData);
((ushort)state.Item.ItemID).CopyTo(ref pos, expectedData);
((ushort)state.Item.Hue).CopyTo(ref pos, expectedData);
((ushort)state.Item.Amount).CopyTo(ref pos, expectedData);
((ushort)state.Price).CopyTo(ref pos, expectedData);
expectedData.Write(ref pos, state.Item.Serial);
expectedData.Write(ref pos, (ushort)state.Item.ItemID);
expectedData.Write(ref pos, (ushort)state.Item.Hue);
expectedData.Write(ref pos, (ushort)state.Item.Amount);
expectedData.Write(ref pos, (ushort)state.Price);
string name = string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim();
name.CopyASCIITo(ref pos, expectedData);
expectedData.Write(ref pos, (ushort)name.Length);
expectedData.WriteAscii(ref pos, name);
}
AssertThat.Equal(data, expectedData);
@ -62,15 +64,16 @@ namespace Server.Tests.Network.Packets
Span<byte> data = new EndVendorBuy(vendor).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x3B, // Packet ID
0x00, 0x08, // Length
0x00, 0x00, 0x00, 0x00, // Vendor Serial
0x00
};
Span<byte> expectedData = stackalloc byte[8];
int pos = 0;
vendor.Serial.CopyTo(expectedData.Slice(3, 4));
expectedData.Write(ref pos, (byte)0x3B); // Packet ID
expectedData.Write(ref pos, (ushort)0x08); // Length
expectedData.Write(ref pos, vendor.Serial);
#if NO_LOCAL_INIT
expectedData.Write(ref pos, (byte)0);
#endif
AssertThat.Equal(data, expectedData);
}

View file

@ -11,250 +11,5 @@ namespace Server.Tests.Network.Packets
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<byte> Compile(this Packet p) =>
p.Compile(false, out int length).AsSpan(0, length);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this byte value, Span<byte> bytes) => bytes[0] = value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this bool value, Span<byte> bytes) => bytes[0] = (byte)(value ? 0x1 : 0x0);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this ushort number, Span<byte> bytes) => BinaryPrimitives.WriteUInt16BigEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this short number, Span<byte> bytes) => BinaryPrimitives.WriteInt16BigEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this Serial s, Span<byte> bytes) => BinaryPrimitives.WriteUInt32BigEndian(bytes, s);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this uint number, Span<byte> bytes) => BinaryPrimitives.WriteUInt32BigEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this int number, Span<byte> bytes) => BinaryPrimitives.WriteInt32BigEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this ulong number, Span<byte> bytes) => BinaryPrimitives.WriteUInt64BigEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this long number, Span<byte> bytes) => BinaryPrimitives.WriteInt64BigEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyToLE(this ushort number, Span<byte> bytes) => BinaryPrimitives.WriteUInt16LittleEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyToLE(this short number, Span<byte> bytes) => BinaryPrimitives.WriteInt16LittleEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyToLE(this Serial s, Span<byte> bytes) => BinaryPrimitives.WriteUInt32LittleEndian(bytes, s);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyToLE(this uint number, Span<byte> bytes) => BinaryPrimitives.WriteUInt32LittleEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyToLE(this int number, Span<byte> bytes) => BinaryPrimitives.WriteInt32LittleEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyToLE(this ulong number, Span<byte> bytes) => BinaryPrimitives.WriteUInt64LittleEndian(bytes, number);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyToLE(this long number, Span<byte> bytes) => BinaryPrimitives.WriteInt64LittleEndian(bytes, number);
// With Position Reference
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this byte value, ref int pos, Span<byte> bytes) => bytes[pos++] = value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this bool value, ref int pos, Span<byte> bytes) => bytes[pos++] = (byte)(value ? 0x1 : 0x0);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this ushort number, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), number);
pos += 2;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this short number, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteInt16BigEndian(bytes.Slice(pos, 2), number);
pos += 2;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this Serial s, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt32BigEndian(bytes.Slice(pos, 4), s);
pos += 4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this uint number, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt32BigEndian(bytes.Slice(pos, 4), number);
pos += 4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this int number, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteInt32BigEndian(bytes.Slice(pos, 4), number);
pos += 4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this ulong number, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt64BigEndian(bytes.Slice(pos, 8), number);
pos += 8;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this long number, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteInt64BigEndian(bytes.Slice(pos, 8), number);
pos += 8;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyRawASCIITo(this string str, ref int pos, Span<byte> bytes)
{
pos += Encoding.ASCII.GetBytes(str, bytes.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyRawASCIITo(this string str, ref int pos, int max, Span<byte> bytes)
{
pos += Encoding.ASCII.GetBytes(str.AsSpan(0, Math.Min(str.Length, max)), bytes.Slice(pos));
}
// Ascii prepended with two-byte length
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyASCIITo(this string str, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)str.Length);
pos += 2 + Encoding.ASCII.GetBytes(str, bytes.Slice(pos + 2));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyASCIITo(this string str, ref int pos, int max, Span<byte> bytes)
{
var length = Math.Min(str.Length, max);
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)length);
pos += 2 + Encoding.ASCII.GetBytes(str.AsSpan(0, length), bytes.Slice(pos + 2));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyASCIINullTo(this string str, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)(str.Length + 1));
pos += 3 + Encoding.ASCII.GetBytes(str, bytes.Slice(pos + 2));
bytes[pos - 1] = 0; // null terminator
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyASCIINullTo(this string str, ref int pos, int max, Span<byte> bytes)
{
var length = Math.Min(str.Length, max - 1);
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)(length + 1));
pos += 3 + Encoding.ASCII.GetBytes(str.AsSpan(0, length), bytes.Slice(pos + 2));
bytes[pos - 1] = 0; // null terminator
}
// Ascii prepended with one-byte length
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopySmallASCIITo(this string str, ref int pos, Span<byte> bytes)
{
bytes[pos++] = (byte)str.Length;
pos += Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopySmallASCIITo(this string str, ref int pos, int max, Span<byte> bytes)
{
var length = Math.Min(255, Math.Min(str.Length, max));
bytes[pos++] = (byte)length;
pos += Encoding.ASCII.GetBytes(str.AsSpan(0, length), bytes.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopySmallASCIINullTo(this string str, ref int pos, Span<byte> bytes)
{
bytes[pos++] = (byte)(str.Length + 1);
pos += Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos));
bytes[pos++] = 0; // null terminator
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopySmallASCIINullTo(this string str, ref int pos, int max, Span<byte> bytes)
{
var length = Math.Min(255, Math.Min(str.Length, max));
bytes[pos++] = (byte)length;
pos += Encoding.ASCII.GetBytes(str.AsSpan(0, length), bytes.Slice(pos));
bytes[pos++] = 0; // null terminator
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyASCIIFixedTo(this string str, ref int pos, int max, Span<byte> bytes)
{
int bytesWritten = Encoding.ASCII.GetBytes(str.AsSpan(0, Math.Min(str.Length, max)), bytes.Slice(pos));
// This is not needed in the current stackalloc implementation, but not guaranteed in the future.
if (bytesWritten < max)
bytes.Slice(pos + bytesWritten, max - bytesWritten).Clear();
pos += max;
}
// Unicode prepended with two-byte length
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyUnicodeBigEndianTo(this string str, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)str.Length);
pos += 2 + Encoding.BigEndianUnicode.GetBytes(str, bytes.Slice(pos + 2));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyRawUnicodeBigEndianTo(this string str, ref int pos, Span<byte> bytes)
{
pos += Encoding.BigEndianUnicode.GetBytes(str, bytes.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyRawUnicodeLittleEndianTo(this string str, ref int pos, Span<byte> bytes)
{
pos += Encoding.Unicode.GetBytes(str, bytes.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this byte[] src, ref int pos, Span<byte> bytes) =>
src.CopyTo(bytes.Slice(pos, src.Length));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this byte[] src, ref int pos, int max, Span<byte> bytes) =>
src.CopyTo(bytes.Slice(pos, Math.Min(max, src.Length)));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this Span<byte> src, ref int pos, Span<byte> bytes) =>
src.CopyTo(bytes.Slice(pos, src.Length));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this Span<byte> src, ref int pos, int max, Span<byte> bytes) =>
src.CopyTo(bytes.Slice(pos, Math.Min(max, src.Length)));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this ReadOnlySpan<byte> src, ref int pos, Span<byte> bytes) =>
src.CopyTo(bytes.Slice(pos, src.Length));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyTo(this ReadOnlySpan<byte> src, ref int pos, int max, Span<byte> bytes) =>
src.CopyTo(bytes.Slice(pos, Math.Min(max, src.Length)));
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clear(this Span<byte> span, ref int pos, int amount)
{
span.Slice(pos, amount).Clear();
pos += amount;
}
}
}

View file

@ -0,0 +1,195 @@
using System.Buffers.Binary;
using System.Runtime.CompilerServices;
using System.Text;
using Server;
namespace System.Buffers
{
public static class SpanExtensions
{
// Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ushort value) => BinaryPrimitives.WriteUInt16BigEndian(span, value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, short value) => BinaryPrimitives.WriteInt16BigEndian(span, value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, uint value) => BinaryPrimitives.WriteUInt32BigEndian(span, value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, int value) => BinaryPrimitives.WriteInt32BigEndian(span, value);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, byte value) => span[0] = value;
// Ref Extensions
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, ReadOnlySpan<byte> data)
{
data.CopyTo(span.Slice(pos, data.Length));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, bool value)
{
span[pos++] = value ? (byte)1 : (byte)0;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, byte value) => span[pos++] = value;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, ushort value)
{
BinaryPrimitives.WriteUInt16BigEndian(span.Slice(pos, 2), value);
pos += 2;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, short value)
{
BinaryPrimitives.WriteInt16BigEndian(span.Slice(pos, 2), value);
pos += 2;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, uint value)
{
BinaryPrimitives.WriteUInt32BigEndian(span.Slice(pos, 4), value);
pos += 4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteLE(this Span<byte> span, ref int pos, uint value)
{
BinaryPrimitives.WriteUInt32LittleEndian(span.Slice(pos, 4), value);
pos += 4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, int value)
{
BinaryPrimitives.WriteInt32BigEndian(span.Slice(pos, 4), value);
pos += 4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteLE(this Span<byte> span, ref int pos, int value)
{
BinaryPrimitives.WriteInt32LittleEndian(span.Slice(pos, 4), value);
pos += 4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, Serial value)
{
BinaryPrimitives.WriteUInt32BigEndian(span.Slice(pos, 4), value);
pos += 4;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, ulong value)
{
BinaryPrimitives.WriteUInt64BigEndian(span.Slice(pos, 8), value);
pos += 8;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Write(this Span<byte> span, ref int pos, long value)
{
BinaryPrimitives.WriteInt64BigEndian(span.Slice(pos, 8), value);
pos += 8;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteLE(this Span<byte> span, ref int pos, ulong value)
{
BinaryPrimitives.WriteUInt64LittleEndian(span.Slice(pos, 8), value);
pos += 8;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteLE(this Span<byte> span, ref int pos, long value)
{
BinaryPrimitives.WriteInt64LittleEndian(span.Slice(pos, 8), value);
pos += 8;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAscii(this Span<byte> span, ref int pos, string value)
{
int length = value.Length;
pos += Encoding.ASCII.GetBytes(value.AsSpan(0, length), span.Slice(pos, length));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAscii(this Span<byte> span, ref int pos, string value, int max)
{
int length = value.Length <= max ? value.Length : max;
pos += Encoding.ASCII.GetBytes(value.AsSpan(0, length), span.Slice(pos, length));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAsciiNull(this Span<byte> span, ref int pos, string value)
{
int length = value.Length;
pos += Encoding.ASCII.GetBytes(value.AsSpan(0, length), span.Slice(pos, length));
span[pos++] = 0; // Null terminator
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAsciiNull(this Span<byte> span, ref int pos, string value, int max)
{
var length = value.Length < max ? value.Length : max - 1;
pos += Encoding.ASCII.GetBytes(value.AsSpan(0, length), span.Slice(pos, length));
span[pos++] = 0; // Null terminator
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAsciiFixed(this Span<byte> span, ref int pos, string value, int amount)
{
var length = value.Length <= amount ? value.Length : amount;
#if NO_LOCAL_INIT
int bytesWritten = Encoding.ASCII.GetBytes(value.AsSpan(0, length), span.Slice(pos, length));
if (bytesWritten < amount)
span.Slice(pos + bytesWritten, amount - bytesWritten).Clear();
#else
Encoding.ASCII.GetBytes(value.AsSpan(0, length), span.Slice(pos, length));
#endif
pos += amount;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAsciiFixedNull(this Span<byte> span, ref int pos, string value, int amount)
{
var length = value.Length < amount ? value.Length : amount - 1;
#if NO_LOCAL_INIT
int bytesWritten = Encoding.ASCII.GetBytes(value.AsSpan(0, amount), span.Slice(pos, amount));
if (bytesWritten < amount)
span.Slice(pos + bytesWritten, amount - bytesWritten).Clear();
#else
Encoding.ASCII.GetBytes(value.AsSpan(0, length), span.Slice(pos, length));
#endif
pos += amount;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteBigUni(this Span<byte> span, ref int pos, string value)
{
pos += Encoding.BigEndianUnicode.GetBytes(value, span.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteLittleUni(this Span<byte> span, ref int pos, string value)
{
pos += Encoding.Unicode.GetBytes(value, span.Slice(pos));
}
}
}

View file

@ -1,300 +0,0 @@
/*************************************************************************
* ModernUO *
* Copyright (C) 2019-2020 - ModernUO Development Team *
* Email: hi@modernuo.com *
* File: SpanWriter.cs - Created: 2019/08/05 - Updated: 2019/12/24 *
* *
* 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. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* 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.Text;
namespace Server.Buffers
{
/// <summary>
/// Provides functionality for writing primitive binary data.
/// </summary>
public ref struct SpanWriter
{
private int m_Position;
/// <summary>
/// Underlying Span.
/// </summary>
public Span<byte> RawSpan { get; }
/// <summary>
/// Underlying Span up to the bytes written.
/// </summary>
public Span<byte> Span => RawSpan.Slice(0, WrittenCount);
/// <summary>
/// Gets the total length of the span.
/// </summary>
public int Length => RawSpan.Length;
/// <summary>
/// Total bytes written to the span.
/// </summary>
public int WrittenCount { get; private set; }
/// <summary>
/// Current position in the the span.
/// </summary>
public int Position
{
get => m_Position;
set
{
m_Position = value;
if (value > WrittenCount)
WrittenCount = value;
}
}
/// <summary>
/// Instantiates a new SpanWriter instance.
/// </summary>
public SpanWriter(Span<byte> span)
{
RawSpan = span;
m_Position = 0;
WrittenCount = 0;
}
/// <summary>
/// Writes a 1-byte boolean value to the span.
/// </summary>
public unsafe void Write(bool value)
{
RawSpan[Position++] = *(byte*)&value;
}
/// <summary>
/// Writes a 1-byte unsigned integer value to the span.
/// </summary>
public void Write(byte value)
{
RawSpan[Position++] = value;
}
/// <summary>
/// Writes a 1-byte signed integer value to the span.
/// </summary>
public void Write(sbyte value)
{
RawSpan[Position++] = (byte)value;
}
/// <summary>
/// Writes a 2-byte signed integer value to the span.
/// </summary>
public void Write(short value)
{
Write((byte)(value >> 8));
Write((byte)value);
}
/// <summary>
/// Writes a 2-byte unsigned integer value to the span.
/// </summary>
public void Write(ushort value)
{
Write((byte)(value >> 8));
Write((byte)value);
}
/// <summary>
/// Writes a 4-byte signed integer value to the span.
/// </summary>
public void Write(int value)
{
Write((byte)(value >> 24));
Write((byte)(value >> 16));
Write((byte)(value >> 8));
Write((byte)value);
}
/// <summary>
/// Writes a 4-byte unsigned integer value to the span.
/// </summary>
public void Write(uint value)
{
Write((byte)(value >> 24));
Write((byte)(value >> 16));
Write((byte)(value >> 8));
Write((byte)value);
}
/// <summary>
/// Writes an 8-byte signed integer value to the span.
/// </summary>
public void Write(long 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);
}
/// <summary>
/// Writes an 8-byte unsigned integer value to the span.
/// </summary>
public void Write(ulong 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);
}
/// <summary>
/// Writes a sequence of bytes to the span.
/// </summary>
public void Write(ReadOnlySpan<byte> input)
{
var size = Math.Min(input.Length, Length - Position);
input.Slice(0, size).CopyTo(RawSpan.Slice(Position));
Position += size;
}
/// <summary>
/// Writes an ASCII-encoded string value to the span.
/// </summary>
public void WriteAscii(string value)
{
Position += Encoding.ASCII.GetBytes(value ?? "", RawSpan.Slice(Position));
}
/// <summary>
/// Writes a fixed-length ASCII-encoded string value to the span.
/// </summary>
public void WriteAsciiFixed(string value, int size, bool zero = false)
{
value ??= "";
var length = Math.Min(size, value.Length);
Encoding.ASCII.GetBytes(value.AsSpan(0, length), RawSpan.Slice(Position));
if (zero)
{
Position += length;
Fill(size - length);
}
else
{
Position += size;
}
}
/// <summary>
/// Writes a dynamic-length ASCII-encoded string value to the span, followed by a 1-byte null character.
/// </summary>
public void WriteAsciiNull(string value)
{
Position += Encoding.ASCII.GetBytes(value ?? "", RawSpan.Slice(Position));
Write((byte)0);
}
/// <summary>
/// Writes a dynamic-length ASCII-encoded string value to the span, followed by a 1-byte null character.
/// </summary>
public void WriteAsciiNull(string value, int size)
{
value ??= "";
size = Math.Min(size, value.Length);
Position += Encoding.ASCII.GetBytes(value.AsSpan(0, size), RawSpan.Slice(Position));
Write((byte)0);
}
/// <summary>
/// Writes a dynamic-length little-endian unicode string value to the span.
/// </summary>
public void WriteLittleUni(string value)
{
Position += Encoding.Unicode.GetBytes(value ?? "", RawSpan.Slice(Position));
}
/// <summary>
/// Writes a dynamic-length little-endian unicode string value to the span, followed by a 2-byte null character.
/// </summary>
public void WriteLittleUniNull(string value)
{
WriteLittleUni(value);
Write((ushort)0);
}
/// <summary>
/// Writes a dynamic-length big-endian unicode string value to the span.
/// </summary>
public void WriteBigUni(string value)
{
Position += Encoding.BigEndianUnicode.GetBytes(value ?? "", RawSpan.Slice(Position));
}
/// <summary>
/// Writes a dynamic-length big-endian unicode string value to the span, followed by a 2-byte null character.
/// </summary>
public void WriteBigUniNull(string value, bool zero = false)
{
WriteBigUni(value);
if (zero)
Fill(2);
else
Position += 2;
}
/// <summary>
/// Writes a dynamic-length utf-8 string value, followed by a 1-byte null character.
/// </summary>
public void WriteUTF8Null(string value)
{
Position += Encoding.UTF8.GetBytes(value ?? "", RawSpan.Slice(Position)) + 1;
}
/// <summary>
/// Copies the span to the destination.
/// </summary>
public void CopyTo(Span<byte> destination)
{
RawSpan.CopyTo(destination);
}
/// <summary>
/// Fills the buffer with zeroes up to count
/// </summary>
public void Fill(int count)
{
count = Math.Min(count, RawSpan.Length - Position);
RawSpan.Slice(Position, count).Clear();
Position += count;
}
}
}

View file

@ -76,7 +76,7 @@ namespace Server
{
}
// TOOD: Can we make this higher for newer clients?
// TODO: Can we make this higher for newer clients?
public static uint FakeSerial(Mobile parent) => 0x7FFFFFFF - 0x400 - parent.Serial * 4;
}

View file

@ -26,7 +26,7 @@ namespace Server.Menus.ItemLists
{
public ItemListEntry(string name, int itemID, int hue = 0)
{
Name = name;
Name = name?.Trim() ?? "";
ItemID = itemID;
Hue = hue;
}
@ -44,7 +44,7 @@ namespace Server.Menus.ItemLists
public ItemListMenu(string question, ItemListEntry[] entries)
{
Question = question;
Question = question.Trim();
Entries = entries;
do

View file

@ -28,7 +28,7 @@ namespace Server.Menus.Questions
public QuestionMenu(string question, string[] answers)
{
Question = question;
Question = question?.Trim() ?? "";
Answers = answers;
do
@ -38,7 +38,7 @@ namespace Server.Menus.Questions
} while (Serial == 0);
}
public string Question { get; set; }
public string Question { get; }
public string[] Answers { get; }

View file

@ -449,9 +449,9 @@ namespace Server.Network
EnsureCapacity(12);
Stream.Write(m.Serial);
Stream.Write((short)1);
Stream.Write((short)1); // Show Bar?
Stream.Write((short)1);
Stream.Write((short)1); // Poison Bar
var p = m.Poison;
@ -527,7 +527,7 @@ namespace Server.Network
public sealed class MobileIncoming : Packet
{
private static readonly ThreadLocal<int[]> m_DupedLayersTL = new ThreadLocal<int[]>(() => { return new int[256]; });
private static readonly ThreadLocal<int[]> m_DupedLayersTL = new ThreadLocal<int[]>(() => new int[256]);
private static readonly ThreadLocal<int> m_VersionTL = new ThreadLocal<int>();
public MobileIncoming(Mobile beholder, Mobile beheld) : base(0x78)
@ -636,7 +636,7 @@ namespace Server.Network
public sealed class MobileIncomingSA : Packet
{
private static readonly ThreadLocal<int[]> m_DupedLayersTL = new ThreadLocal<int[]>(() => { return new int[256]; });
private static readonly ThreadLocal<int[]> m_DupedLayersTL = new ThreadLocal<int[]>(() => new int[256]);
private static readonly ThreadLocal<int> m_VersionTL = new ThreadLocal<int>();
public MobileIncomingSA(Mobile beholder, Mobile beheld) : base(0x78)
@ -754,7 +754,7 @@ namespace Server.Network
// Pre-7.0.0.0 Mobile Incoming
public sealed class MobileIncomingOld : Packet
{
private static readonly ThreadLocal<int[]> m_DupedLayersTL = new ThreadLocal<int[]>(() => { return new int[256]; });
private static readonly ThreadLocal<int[]> m_DupedLayersTL = new ThreadLocal<int[]>(() => new int[256]);
private static readonly ThreadLocal<int> m_VersionTL = new ThreadLocal<int>();
public MobileIncomingOld(Mobile beholder, Mobile beheld) : base(0x78)

View file

@ -14,32 +14,14 @@ jobs:
vmImage: 'windows-latest'
steps:
- task: NuGetToolInstaller@1
inputs:
versionSpec: '5.x'
displayName: 'Install latest NuGet'
- task: DotNetCoreCLI@2
inputs:
command: 'custom'
custom: 'restore'
arguments: '--force-evaluate'
- task: NuGetAuthenticate@0
- script: dotnet restore --force-evaluate
displayName: 'Restore NuGet Packages'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
arguments: '-c $(buildConfiguration) --no-restore'
projects: '**/Projects/Server/Server.csproj'
- script: dotnet build -c $(buildConfiguration) --no-restore Projects/Server/Server.csproj
displayName: 'Build Server'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
arguments: '-c $(buildConfiguration) --no-restore'
projects: '**/Projects/UOContent/UOContent.csproj'
- script: dotnet build -c $(buildConfiguration) --no-restore Projects/UOContent/UOContent.csproj
displayName: 'Build UO Content'
- task: DotNetCoreCLI@2
inputs:
command: 'test'
arguments: '--no-restore'
- script: dotnet test --no-restore
displayName: 'Test'
- job: BuildLinux
@ -60,26 +42,12 @@ jobs:
container: $[ variables['containerImage'] ]
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'custom'
custom: 'restore'
arguments: '--force-evaluate'
- task: NuGetAuthenticate@0
- script: dotnet restore --force-evaluate
displayName: 'Restore NuGet Packages'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
arguments: '-c $(buildConfiguration) --no-restore'
projects: '**/Projects/Server/Server.csproj'
- script: dotnet build -c $(buildConfiguration) --no-restore Projects/Server/Server.csproj
displayName: 'Build Server'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
arguments: '-c $(buildConfiguration) --no-restore'
projects: '**/Projects/UOContent/UOContent.csproj'
- script: dotnet build -c $(buildConfiguration) --no-restore Projects/UOContent/UOContent.csproj
displayName: 'Build UO Content'
- task: DotNetCoreCLI@2
inputs:
command: 'test'
arguments: '--no-restore'
- script: dotnet test --no-restore
displayName: 'Test'