From 10a6e17640dc2084dff33f0ec85a5c21b848a63f Mon Sep 17 00:00:00 2001
From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com>
Date: Thu, 24 Dec 2020 17:13:55 -0800
Subject: [PATCH] fix(core): Converts mobile moving packet (#357)
- [X] Converts mobile moving packet
---
Directory.Build.props | 2 +
.../Packets/Outgoing/MobilePacketTests.cs | 49 +++-----
.../Network/Packets/Outgoing/MobilePackets.cs | 35 ++++++
Projects/Server/Mobiles/Mobile.cs | 114 +++---------------
Projects/Server/Network/PacketUtilities.cs | 13 ++
.../Server/Network/Packets/MobilePackets.cs | 35 ------
.../Network/Packets/OutgoingMobilePackets.cs | 63 ++++++++++
Projects/Server/Utilities/Utility.cs | 2 +
Projects/UOContent/Mobiles/PlayerMobile.cs | 4 +-
9 files changed, 147 insertions(+), 170 deletions(-)
diff --git a/Directory.Build.props b/Directory.Build.props
index 352e3d34c..5da56f81a 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -17,6 +17,7 @@
true
true
+
true
true
true
@@ -24,6 +25,7 @@
OSX
LINUX
UNIX
+ NO_LOCAL_INIT
true
diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs
index bd7b5502d..d14b4e604 100644
--- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs
+++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs
@@ -26,52 +26,35 @@ namespace Server.Tests.Network
public void TestBondStatus()
{
Serial petSerial = 0x1;
- var bonded = true;
+ const bool bonded = true;
- var data = new BondedStatus(petSerial, bonded).Compile();
+ var expected = new BondedStatus(petSerial, bonded).Compile();
- Span expectedData = stackalloc byte[11];
- var pos = 0;
+ using var ns = PacketTestUtilities.CreateTestNetState();
+ ns.SendBondedStatus(petSerial, bonded);
- 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);
+ var result = ns.SendPipe.Reader.TryRead();
+ AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
}
- [Fact]
- public void TestMobileMoving()
+ [Theory]
+ [InlineData(ProtocolChanges.StygianAbyss)]
+ [InlineData(ProtocolChanges.None)]
+ public void TestMobileMoving(ProtocolChanges protocolChanges)
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
var noto = 10;
- var data = new MobileMoving(m, noto, true).Compile();
+ using var ns = PacketTestUtilities.CreateTestNetState();
+ ns.ProtocolChanges = protocolChanges;
+ var expected = new MobileMoving(m, noto, ns.StygianAbyss).Compile();
- Span expectedData = stackalloc byte[17];
- var pos = 0;
+ ns.SendMobileMoving(m, 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, m.Location);
- expectedData.Write(ref pos, (byte)m.Direction);
- expectedData.Write(ref pos, (ushort)m.Hue);
- expectedData.Write(ref pos, (byte)m.GetPacketFlags(true));
- expectedData.Write(ref pos, (byte)noto);
-
- AssertThat.Equal(data, expectedData);
+ var result = ns.SendPipe.Reader.TryRead();
+ AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
}
[Fact]
diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs
index a2802dd83..6f14a62d8 100644
--- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs
+++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs
@@ -14,4 +14,39 @@ namespace Server.Tests.Network
Stream.Write((byte)(bonded ? 1 : 0));
}
}
+
+ public sealed class DeathAnimation : Packet
+ {
+ public DeathAnimation(Serial killed, Serial corpse) : base(0xAF, 13)
+ {
+ Stream.Write(killed);
+ Stream.Write(corpse);
+ Stream.Write(0);
+ }
+ }
+
+ public sealed class MobileMoving : Packet
+ {
+ public MobileMoving(Mobile m, int noto, bool stygianAbyss) : base(0x77, 17)
+ {
+ var loc = m.Location;
+
+ var hue = m.Hue;
+
+ if (m.SolidHueOverride >= 0)
+ {
+ hue = m.SolidHueOverride;
+ }
+
+ Stream.Write(m.Serial);
+ Stream.Write((short)m.Body);
+ Stream.Write((short)loc.X);
+ Stream.Write((short)loc.Y);
+ Stream.Write((sbyte)loc.Z);
+ Stream.Write((byte)m.Direction);
+ Stream.Write((short)hue);
+ Stream.Write((byte)m.GetPacketFlags(stygianAbyss));
+ Stream.Write((byte)noto);
+ }
+ }
}
diff --git a/Projects/Server/Mobiles/Mobile.cs b/Projects/Server/Mobiles/Mobile.cs
index 676a479fc..3838f73c4 100644
--- a/Projects/Server/Mobiles/Mobile.cs
+++ b/Projects/Server/Mobiles/Mobile.cs
@@ -435,12 +435,6 @@ namespace Server
private static readonly TimeSpan ExpireCombatantDelay = TimeSpan.FromMinutes(1.0);
private static readonly TimeSpan ExpireAggressorsDelay = TimeSpan.FromSeconds(5.0);
- private static readonly Packet[][] m_MovingPacketCache =
- {
- new Packet[8],
- new Packet[8]
- };
-
private static readonly List m_MoveList = new();
private static readonly List m_MoveClientList = new();
@@ -3055,7 +3049,8 @@ namespace Server
sendFacialHair = true;
}
- var cache = new[] { new Packet[8], new Packet[8] };
+ Span mobileMovingPackets = stackalloc byte[OutgoingMobilePackets.MobileMovingPacketCacheLength];
+ mobileMovingPackets.InitializePackets(OutgoingMobilePackets.MobileMovingPacketLength);
var ourState = m.m_NetState;
@@ -3072,14 +3067,13 @@ namespace Server
ourState.Send(new MobileIncoming(ourState, m, m));
}
+ if (sendMoving || !ourState.StygianAbyss && (sendHealthbarPoison || sendHealthbarYellow))
+ {
+ ourState.SendMobileMovingUsingCache(mobileMovingPackets, m, m);
+ }
+
if (ourState.StygianAbyss)
{
- if (sendMoving)
- {
- var noto = Notoriety.Compute(m, m);
- ourState.Send(cache[0][noto] = Packet.Acquire(new MobileMoving(m, noto, true)));
- }
-
if (sendHealthbarPoison)
{
ourState.Send(new HealthbarPoison(m));
@@ -3090,14 +3084,6 @@ namespace Server
ourState.Send(new HealthbarYellow(m));
}
}
- else
- {
- if (sendMoving || sendHealthbarPoison || sendHealthbarYellow)
- {
- var noto = Notoriety.Compute(m, m);
- ourState.Send(cache[1][noto] = Packet.Acquire(new MobileMoving(m, noto, false)));
- }
- }
if (sendPublicStats || sendPrivateStats)
{
@@ -3218,22 +3204,13 @@ namespace Server
}
}
+ if (sendMoving || !state.StygianAbyss && (sendHealthbarPoison || sendHealthbarYellow))
+ {
+ state.SendMobileMovingUsingCache(mobileMovingPackets, beholder, m);
+ }
+
if (state.StygianAbyss)
{
- if (sendMoving)
- {
- var noto = Notoriety.Compute(beholder, m);
-
- var p = cache[0][noto];
-
- if (p == null)
- {
- cache[0][noto] = p = Packet.Acquire(new MobileMoving(m, noto, true));
- }
-
- state.Send(p);
- }
-
if (sendHealthbarPoison)
{
hbpPacket ??= Packet.Acquire(new HealthbarPoison(m));
@@ -3248,22 +3225,6 @@ namespace Server
state.Send(hbyPacket);
}
}
- else
- {
- if (sendMoving || sendHealthbarPoison || sendHealthbarYellow)
- {
- var noto = Notoriety.Compute(beholder, m);
-
- var p = cache[1][noto];
-
- if (p == null)
- {
- cache[1][noto] = p = Packet.Acquire(new MobileMoving(m, noto, false));
- }
-
- state.Send(p);
- }
- }
if (sendPublicStats)
{
@@ -3319,17 +3280,6 @@ namespace Server
eable.Free();
}
-
- if (sendMoving || sendNonlocalMoving || sendHealthbarPoison || sendHealthbarYellow)
- {
- for (var i = 0; i < cache.Length; ++i)
- {
- for (var j = 0; j < cache[i].Length; ++j)
- {
- Packet.Release(ref cache[i][j]);
- }
- }
- }
}
public ISpawner Spawner { get; set; }
@@ -4580,11 +4530,8 @@ namespace Server
eable.Free();
- var cache = m_MovingPacketCache;
-
- /*for( int i = 0; i < cache.Length; ++i )
- for( int j = 0; j < cache[i].Length; ++j )
- Packet.Release( ref cache[i][j] );*/
+ Span mobileMovingPackets = stackalloc byte[OutgoingMobilePackets.MobileMovingPacketCacheLength];
+ mobileMovingPackets.InitializePackets(OutgoingMobilePackets.MobileMovingPacketLength);
foreach (var m in m_MoveClientList)
{
@@ -4592,38 +4539,7 @@ namespace Server
if (ns != null && Utility.InUpdateRange(m_Location, m.m_Location) && m.CanSee(this))
{
- if (ns.StygianAbyss)
- {
- var noto = Notoriety.Compute(m, this);
- var p = cache[0][noto];
-
- if (p == null)
- {
- cache[0][noto] = p = Packet.Acquire(new MobileMoving(this, noto, true));
- }
-
- ns.Send(p);
- }
- else
- {
- var noto = Notoriety.Compute(m, this);
- var p = cache[1][noto];
-
- if (p == null)
- {
- cache[1][noto] = p = Packet.Acquire(new MobileMoving(this, noto, false));
- }
-
- ns.Send(p);
- }
- }
- }
-
- for (var i = 0; i < cache.Length; ++i)
- {
- for (var j = 0; j < cache[i].Length; ++j)
- {
- Packet.Release(ref cache[i][j]);
+ ns.SendMobileMovingUsingCache(mobileMovingPackets, m, this);
}
}
diff --git a/Projects/Server/Network/PacketUtilities.cs b/Projects/Server/Network/PacketUtilities.cs
index 65d3e4301..69ff69b95 100644
--- a/Projects/Server/Network/PacketUtilities.cs
+++ b/Projects/Server/Network/PacketUtilities.cs
@@ -13,6 +13,7 @@
* along with this program. If not, see . *
*************************************************************************/
+using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
@@ -38,5 +39,17 @@ namespace Server.Network
writer.Write((ushort)length);
writer.Seek(length, SeekOrigin.Begin);
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void InitializePackets(this Span buffer, int chunkLength)
+ {
+ var index = 0;
+
+ while (index < buffer.Length)
+ {
+ buffer[index] = 0;
+ index += chunkLength;
+ }
+ }
}
}
diff --git a/Projects/Server/Network/Packets/MobilePackets.cs b/Projects/Server/Network/Packets/MobilePackets.cs
index a185f3479..4f6a5e107 100644
--- a/Projects/Server/Network/Packets/MobilePackets.cs
+++ b/Projects/Server/Network/Packets/MobilePackets.cs
@@ -17,41 +17,6 @@ using System.Threading;
namespace Server.Network
{
- public sealed class DeathAnimation : Packet
- {
- public DeathAnimation(Serial killed, Serial corpse) : base(0xAF, 13)
- {
- Stream.Write(killed);
- Stream.Write(corpse);
- Stream.Write(0);
- }
- }
-
- public sealed class MobileMoving : Packet
- {
- public MobileMoving(Mobile m, int noto, bool stygianAbyss) : base(0x77, 17)
- {
- var loc = m.Location;
-
- var hue = m.Hue;
-
- if (m.SolidHueOverride >= 0)
- {
- hue = m.SolidHueOverride;
- }
-
- Stream.Write(m.Serial);
- Stream.Write((short)m.Body);
- Stream.Write((short)loc.m_X);
- Stream.Write((short)loc.m_Y);
- Stream.Write((sbyte)loc.m_Z);
- Stream.Write((byte)m.Direction);
- Stream.Write((short)hue);
- Stream.Write((byte)m.GetPacketFlags(stygianAbyss));
- Stream.Write((byte)noto);
- }
- }
-
public sealed class MobileHits : Packet
{
public MobileHits(Mobile m) : base(0xA1, 9)
diff --git a/Projects/Server/Network/Packets/OutgoingMobilePackets.cs b/Projects/Server/Network/Packets/OutgoingMobilePackets.cs
index cf94ef353..dde0e0806 100644
--- a/Projects/Server/Network/Packets/OutgoingMobilePackets.cs
+++ b/Projects/Server/Network/Packets/OutgoingMobilePackets.cs
@@ -15,6 +15,7 @@
using System;
using System.Buffers;
+using System.Runtime.CompilerServices;
namespace Server.Network
{
@@ -22,6 +23,8 @@ namespace Server.Network
{
public const int BondedStatusPacketLength = 11;
public const int DeathAnimationPacketLength = 13;
+ public const int MobileMovingPacketLength = 17;
+ public const int MobileMovingPacketCacheLength = MobileMovingPacketLength * 8 * 2; // 8 notoriety, 2 client versions
public static void CreateBondedStatus(ref Span buffer, Serial serial, bool bonded)
{
@@ -72,5 +75,65 @@ namespace Server.Network
CreateDeathAnimation(ref span, killed, corpse);
ns.Send(span);
}
+
+ public static void CreateMobileMoving(ref Span buffer, Mobile m, int noto, bool stygianAbyss)
+ {
+ var loc = m.Location;
+ var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue;
+
+ var writer = new SpanWriter(buffer);
+ writer.Write((byte)0x77); // Packet ID
+ writer.Write(m.Serial);
+ writer.Write((short)m.Body);
+ writer.Write((short)loc.m_X);
+ writer.Write((short)loc.m_Y);
+ writer.Write((sbyte)loc.m_Z);
+ writer.Write((byte)m.Direction);
+ writer.Write((short)hue);
+ writer.Write((byte)m.GetPacketFlags(stygianAbyss));
+ writer.Write((byte)noto);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void SendMobileMoving(this NetState ns, Mobile source, Mobile target) =>
+ ns.SendMobileMoving(target, Notoriety.Compute(source, target));
+
+ public static void SendMobileMoving(this NetState ns, Mobile target, int noto)
+ {
+ if (ns == null)
+ {
+ return;
+ }
+
+ Span span = stackalloc byte[MobileMovingPacketLength];
+ CreateMobileMoving(ref span, target, noto, ns.StygianAbyss);
+ ns.Send(span);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void SendMobileMovingUsingCache(this NetState ns, Span cache, Mobile source, Mobile target) =>
+ ns.SendMobileMovingUsingCache(cache, target, Notoriety.Compute(source, target));
+
+ // Requires a buffer of 16 packets, 17bytes per packet (272 bytes).
+ // Requires cache to have the first byte of each packet zeroed.
+ public static void SendMobileMovingUsingCache(this NetState ns, Span cache, Mobile target, int noto)
+ {
+ if (ns == null)
+ {
+ return;
+ }
+
+ var stygianAbyss = ns.StygianAbyss;
+ var startIndex = (noto * 2 + (stygianAbyss ? 1 : 0)) * MobileMovingPacketLength;
+ var buffer = cache.Slice(startIndex, MobileMovingPacketLength);
+
+ // Packet not created yet
+ if (buffer[0] == 0)
+ {
+ CreateMobileMoving(ref buffer, target, noto, stygianAbyss);
+ }
+
+ ns.Send(buffer);
+ }
}
}
diff --git a/Projects/Server/Utilities/Utility.cs b/Projects/Server/Utilities/Utility.cs
index 5df39a574..32b445038 100644
--- a/Projects/Server/Utilities/Utility.cs
+++ b/Projects/Server/Utilities/Utility.cs
@@ -1438,6 +1438,7 @@ namespace Server
return string.Join(lineSeparator, parts);
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Tidy(this List list) where T : ISerializable
{
for (int i = list.Count - 1; i >= 0; i--)
@@ -1452,6 +1453,7 @@ namespace Server
list.TrimExcess();
}
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Tidy(this HashSet set) where T : ISerializable
{
set.RemoveWhere(entry => entry?.Deleted != false);
diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs
index bc348cff4..b2853dd4f 100644
--- a/Projects/UOContent/Mobiles/PlayerMobile.cs
+++ b/Projects/UOContent/Mobiles/PlayerMobile.cs
@@ -4276,9 +4276,7 @@ namespace Server.Mobiles
if (t == oldType || t == newType)
{
- var ns = NetState;
-
- ns?.Send(new MobileMoving(m, Notoriety.Compute(this, m), ns.StygianAbyss));
+ m.NetState.SendMobileMoving(this, m);
}
}
}