diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs index 265a0c701..28982f24b 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs @@ -57,67 +57,32 @@ namespace Server.Tests.Network AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } - [Fact] - public void TestMobileMovingOld() + [Theory] + [InlineData(null)] + [InlineData("Kamron")] + [InlineData("Some Really Long Mobile Name That Gets Cut off")] + public void TestMobileName(string name) { - var m = new Mobile(0x1); + var m = new Mobile(0x1) { Name = name }; m.DefaultMobileInit(); - var noto = 10; + var expected = new MobileName(m).Compile(); - var data = new MobileMoving(m, noto, false).Compile(); + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileName(m); - Span expectedData = stackalloc byte[17]; - var pos = 0; - - 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(false)); - 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] - public void TestMobileName() - { - var m = new Mobile(0x1) - { - Name = "Some Really Long Mobile Name That Gets Cut off" - }; - m.DefaultMobileInit(); - - var data = new MobileName(m).Compile(); - - Span expectedData = stackalloc byte[37]; - var pos = 0; - 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); - } - - [Fact] - public void TestMobileAnimation() + [Theory] + [InlineData(200, 5, 1, false, false, 5)] + [InlineData(10, 100, 25, true, false, 0)] + public void TestMobileAnimation(int action, int frameCount, int repeatCount, bool reverse, bool repeat, byte delay) { Serial mobile = 0x1; - var action = 200; - var frameCount = 5; - var repeatCount = 1; - var reverse = false; - var repeat = false; - byte delay = 5; - var data = new MobileAnimation( + var expected = new MobileAnimation( mobile, action, frameCount, @@ -127,46 +92,45 @@ namespace Server.Tests.Network delay ).Compile(); - Span expectedData = stackalloc byte[14]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileAnimation( + mobile, + action, + frameCount, + repeatCount, + !reverse, + repeat, + delay + ); - expectedData.Write(ref pos, (byte)0x6E); // Packet ID - 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); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } - [Fact] - public void TestNewMobileAnimation() + [Theory] + [InlineData(200, 5, 5)] + [InlineData(10, 100, 20)] + public void TestNewMobileAnimation(int action, int frameCount, byte delay) { Serial mobile = 0x1; - var action = 200; - var frameCount = 5; - byte delay = 5; - var data = new NewMobileAnimation( + var expected = new NewMobileAnimation( mobile, action, frameCount, delay ).Compile(); - Span expectedData = stackalloc byte[10]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendNewMobileAnimation( + mobile, + action, + frameCount, + delay + ); - 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); + 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 11ef7c0e1..da6128ebb 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs @@ -135,4 +135,43 @@ namespace Server.Tests.Network AttributeNormalizer.Write(Stream, m.Stam, m.StamMax); } } + + public sealed class MobileName : Packet + { + public MobileName(Mobile m) : base(0x98) + { + EnsureCapacity(37); + + Stream.Write(m.Serial); + Stream.WriteAsciiFixed(m.Name ?? "", 29); + Stream.Write((byte)0); // Null terminator + } + } + + public sealed class MobileAnimation : Packet + { + public MobileAnimation( + Serial mobile, int action, int frameCount, int repeatCount, bool forward, bool repeat, int delay + ) : base(0x6E, 14) + { + Stream.Write(mobile); + Stream.Write((short)action); + Stream.Write((short)frameCount); + Stream.Write((short)repeatCount); + Stream.Write(!forward); // protocol has really "reverse" but I find this more intuitive + Stream.Write(repeat); + Stream.Write((byte)delay); + } + } + + public sealed class NewMobileAnimation : Packet + { + public NewMobileAnimation(Serial mobile, int action, int frameCount, int delay) : base(0xE2, 10) + { + Stream.Write(mobile); + Stream.Write((short)action); + Stream.Write((short)frameCount); + Stream.Write((byte)delay); + } + } } diff --git a/Projects/Server/Mobiles/Mobile.cs b/Projects/Server/Mobiles/Mobile.cs index b1f944c36..f47122699 100644 --- a/Projects/Server/Mobiles/Mobile.cs +++ b/Projects/Server/Mobiles/Mobile.cs @@ -3248,7 +3248,7 @@ namespace Server { if (hitsPacket[0] == 0) { - OutgoingMobilePackets.CreateMobileHits(ref hitsPacket, m, true); + OutgoingMobilePackets.CreateMobileHits(hitsPacket, m, true); } state.Send(hitsPacket); @@ -6867,67 +6867,64 @@ namespace Server ProcessDelta(); - Packet p = null; - // Packet pNew = null; - var eable = map.GetClientsInRange(m_Location); + Span buffer = stackalloc byte[OutgoingMobilePackets.MobileAnimationPacketLength]; + buffer.InitializePacket(); + foreach (var state in eable) { if (state.Mobile.CanSee(this)) { state.Mobile.ProcessDelta(); - if (p == null) + if (Body.IsGargoyle) { - if (Body.IsGargoyle) + frameCount = 10; + + if (Flying) { - frameCount = 10; - - if (Flying) + action = action switch { - action = action switch - { - >= 9 and <= 11 => 71, - >= 12 and <= 14 => 72, - 20 => 77, - 31 => 71, - 34 => 78, - >= 200 and <= 259 => 75, - >= 260 and <= 270 => 75, - _ => action - }; - } - else - { - action = action switch - { - >= 200 and <= 259 => 17, - >= 260 and <= 270 => 16, - _ => action - }; - } + >= 9 and <= 11 => 71, + >= 12 and <= 14 => 72, + 20 => 77, + 31 => 71, + 34 => 78, + >= 200 and <= 259 => 75, + >= 260 and <= 270 => 75, + _ => action + }; } + else + { + action = action switch + { + >= 200 and <= 259 => 17, + >= 260 and <= 270 => 16, + _ => action + }; + } + } - p = Packet.Acquire( - new MobileAnimation( - Serial, - action, - frameCount, - repeatCount, - forward, - repeat, - delay - ) + if (buffer[0] == 0) + { + OutgoingMobilePackets.CreateMobileAnimation( + buffer, + Serial, + action, + frameCount, + repeatCount, + forward, + repeat, + delay ); } - state.Send(p); + state.Send(buffer); } } - Packet.Release(p); - eable.Free(); } diff --git a/Projects/Server/Network/Packets/IncomingMobilePackets.cs b/Projects/Server/Network/Packets/IncomingMobilePackets.cs index e1ae881cd..da0e5de6b 100644 --- a/Projects/Server/Network/Packets/IncomingMobilePackets.cs +++ b/Projects/Server/Network/Packets/IncomingMobilePackets.cs @@ -44,7 +44,7 @@ namespace Server.Network if (m != null && Utility.InUpdateRange(state.Mobile, m) && state.Mobile.CanSee(m)) { - state.Send(new MobileName(m)); + state.SendMobileName(m); } } diff --git a/Projects/Server/Network/Packets/MobilePackets.cs b/Projects/Server/Network/Packets/MobilePackets.cs index bac1b8e0d..fe5546629 100644 --- a/Projects/Server/Network/Packets/MobilePackets.cs +++ b/Projects/Server/Network/Packets/MobilePackets.cs @@ -17,45 +17,6 @@ using System.Threading; namespace Server.Network { - public sealed class MobileName : Packet - { - public MobileName(Mobile m) : base(0x98) - { - EnsureCapacity(37); - - Stream.Write(m.Serial); - Stream.WriteAsciiFixed(m.Name ?? "", 29); - Stream.Write((byte)0); // Null terminator - } - } - - public sealed class MobileAnimation : Packet - { - public MobileAnimation( - Serial mobile, int action, int frameCount, int repeatCount, bool forward, bool repeat, int delay - ) : base(0x6E, 14) - { - Stream.Write(mobile); - Stream.Write((short)action); - Stream.Write((short)frameCount); - Stream.Write((short)repeatCount); - Stream.Write(!forward); // protocol has really "reverse" but I find this more intuitive - Stream.Write(repeat); - Stream.Write((byte)delay); - } - } - - public sealed class NewMobileAnimation : Packet - { - public NewMobileAnimation(Serial mobile, int action, int frameCount, int delay) : base(0xE2, 10) - { - Stream.Write(mobile); - Stream.Write((short)action); - Stream.Write((short)frameCount); - Stream.Write((byte)delay); - } - } - public sealed class MobileStatusCompact : Packet { public MobileStatusCompact(bool canBeRenamed, Mobile m) : base(0x11) diff --git a/Projects/Server/Network/Packets/OutgoingMobilePackets.cs b/Projects/Server/Network/Packets/OutgoingMobilePackets.cs index ddd004f5b..2a2921dbb 100644 --- a/Projects/Server/Network/Packets/OutgoingMobilePackets.cs +++ b/Projects/Server/Network/Packets/OutgoingMobilePackets.cs @@ -28,6 +28,8 @@ namespace Server.Network public const int AttributeMaximum = 100; public const int MobileAttributePacketLength = 9; public const int MobileAttributesPacketLength = 17; + public const int MobileAnimationPacketLength = 14; + public const int NewMobileAnimationPacketLength = 10; public static void CreateBondedStatus(Span buffer, Serial serial, bool bonded) { @@ -178,11 +180,11 @@ namespace Server.Network } Span span = stackalloc byte[MobileAttributePacketLength]; - CreateMobileHits(ref span, m, normalize); + CreateMobileHits(span, m, normalize); ns.Send(span); } - public static void CreateMobileHits(ref Span buffer, Mobile m, bool normalize = false) + public static void CreateMobileHits(Span buffer, Mobile m, bool normalize = false) { var writer = new SpanWriter(buffer); writer.Write((byte)0xA1); // Packet ID @@ -198,11 +200,11 @@ namespace Server.Network } Span span = stackalloc byte[MobileAttributePacketLength]; - CreateMobileMana(ref span, m, normalize); + CreateMobileMana(span, m, normalize); ns.Send(span); } - public static void CreateMobileMana(ref Span buffer, Mobile m, bool normalize = false) + public static void CreateMobileMana(Span buffer, Mobile m, bool normalize = false) { var writer = new SpanWriter(buffer); writer.Write((byte)0xA2); // Packet ID @@ -218,11 +220,11 @@ namespace Server.Network } Span span = stackalloc byte[MobileAttributePacketLength]; - CreateMobileStam(ref span, m, normalize); + CreateMobileStam(span, m, normalize); ns.Send(span); } - public static void CreateMobileStam(ref Span buffer, Mobile m, bool normalize = false) + public static void CreateMobileStam(Span buffer, Mobile m, bool normalize = false) { var writer = new SpanWriter(buffer); writer.Write((byte)0xA3); // Packet ID @@ -238,11 +240,11 @@ namespace Server.Network } Span span = stackalloc byte[MobileAttributesPacketLength]; - CreateMobileAttributes(ref span, m, normalize); + CreateMobileAttributes(span, m, normalize); ns.Send(span); } - public static void CreateMobileAttributes(ref Span buffer, Mobile m, bool normalize = false) + public static void CreateMobileAttributes(Span buffer, Mobile m, bool normalize = false) { var writer = new SpanWriter(buffer); writer.Write((byte)0x2D); // Packet ID @@ -252,5 +254,78 @@ namespace Server.Network writer.WriteAttribute(m.ManaMax, m.Mana, normalize); writer.WriteAttribute(m.StamMax, m.Stam, normalize); } + + public static void SendMobileName(this NetState ns, Mobile m) + { + if (ns == null || !ns.GetSendBuffer(out var buffer)) + { + return; + } + + var writer = new CircularBufferWriter(buffer); + writer.Write((byte)0x98); // Packet ID + writer.Write((ushort)37); + writer.Write(m.Serial); + writer.WriteAscii(m.Name ?? "", 29); + writer.Write((byte)0); // Null terminator + + ns.Send(ref buffer, writer.Position); + } + + public static void CreateMobileAnimation( + Span buffer, + Serial mobile, int action, int frameCount, int repeatCount, bool forward, bool repeat, int delay + ) + { + var writer = new SpanWriter(buffer); + writer.Write((byte)0x6E); // Packet ID + writer.Write(mobile); + writer.Write((short)action); + writer.Write((short)frameCount); + writer.Write((short)repeatCount); + writer.Write(!forward); // protocol has really "reverse" but I find this more intuitive + writer.Write(repeat); + writer.Write((byte)delay); + } + + public static void SendMobileAnimation( + this NetState ns, + Serial mobile, int action, int frameCount, int repeatCount, bool forward, bool repeat, int delay + ) + { + if (ns == null) + { + return; + } + + Span span = stackalloc byte[MobileAnimationPacketLength]; + CreateMobileAnimation(span, mobile, action, frameCount, repeatCount, forward, repeat, delay); + ns.Send(span); + } + + public static void CreateNewMobileAnimation( + Span buffer, + Serial mobile, int action, int frameCount, int delay + ) + { + var writer = new SpanWriter(buffer); + writer.Write((byte)0xE2); // Packet ID + writer.Write(mobile); + writer.Write((short)action); + writer.Write((short)frameCount); + writer.Write((byte)delay); + } + + public static void SendNewMobileAnimation(this NetState ns, Serial mobile, int action, int frameCount, int delay) + { + if (ns == null) + { + return; + } + + Span span = stackalloc byte[NewMobileAnimationPacketLength]; + CreateNewMobileAnimation(span, mobile, action, frameCount, delay); + ns.Send(span); + } } } diff --git a/Projects/UOContent/Engines/Party/Party.cs b/Projects/UOContent/Engines/Party/Party.cs index 7ae14cb3b..4a45b4da2 100644 --- a/Projects/UOContent/Engines/Party/Party.cs +++ b/Projects/UOContent/Engines/Party/Party.cs @@ -51,7 +51,7 @@ namespace Server.Engines.PartySystem public void OnStamChanged(Mobile m) { Span p = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength]; - OutgoingMobilePackets.CreateMobileStam(ref p, m, true); + OutgoingMobilePackets.CreateMobileStam(p, m, true); for (var i = 0; i < Members.Count; ++i) { @@ -68,7 +68,7 @@ namespace Server.Engines.PartySystem public void OnManaChanged(Mobile m) { Span p = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength]; - OutgoingMobilePackets.CreateMobileMana(ref p, m, true); + OutgoingMobilePackets.CreateMobileMana(p, m, true); for (var i = 0; i < Members.Count; ++i) { @@ -194,7 +194,7 @@ namespace Server.Engines.PartySystem var memberList = Packet.Acquire(new PartyMemberList(this)); Span attrsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributesPacketLength]; - OutgoingMobilePackets.CreateMobileAttributes(ref attrsPacket, m, true); + OutgoingMobilePackets.CreateMobileAttributes(attrsPacket, m, true); for (var i = 0; i < Members.Count; ++i) { @@ -508,7 +508,7 @@ namespace Server.Engines.PartySystem buffer.InitializePacket(); Span attrsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributesPacketLength]; - OutgoingMobilePackets.CreateMobileAttributes(ref attrsPacket, m_Mobile, true); + OutgoingMobilePackets.CreateMobileAttributes(attrsPacket, m_Mobile, true); var ns = m_Mobile.NetState;