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

@ -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)