using System; using System.Net; using Server.Network; using Xunit; namespace Server.Tests.Network.Packets { public class MobilePacketTests : IClassFixture { [Fact] public void TestDeathAnimation() { Serial killed = 0x1; Serial corpse = 0x1000; Span data = new DeathAnimation(killed, corpse).Compile(); Span expectedData = stackalloc byte[] { 0xAF, // Packet ID 0x00, 0x00, 0x00, 0x00, // Serial of killed 0x00, 0x00, 0x00, 0x00, // Serial of corpse 0x00, 0x00, 0x00, 0x00 }; killed.CopyTo(expectedData.Slice(1, 4)); corpse.CopyTo(expectedData.Slice(5, 4)); AssertThat.Equal(data, expectedData); } [Fact] public void TestBondStatus() { Serial petSerial = 0x1; bool bonded = true; Span data = new BondedStatus(petSerial, bonded).Compile(); Span 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) }; petSerial.CopyTo(expectedData.Slice(6, 4)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileMoving() { var m = new Mobile(0x1); m.DefaultMobileInit(); int noto = 10; Span data = new MobileMoving(m, noto).Compile(); Span 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 }; 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; AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileMovingOld() { var m = new Mobile(0x1); m.DefaultMobileInit(); int noto = 10; Span data = new MobileMoving(m, noto).Compile(); Span 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 }; 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; AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileHits() { var m = new Mobile(0x1); m.DefaultMobileInit(); Span data = new MobileHits(m).Compile(); Span expectedData = stackalloc byte[] { 0xA1, // Packet ID 0x00, 0x00, 0x00, 0x00, // Serial 0x00, 0x00, // Max Hits 0x00, 0x00 // Current Hits }; m.Serial.CopyTo(expectedData.Slice(1, 4)); AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, false, expectedData.Slice(5)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileHitsN() { var m = new Mobile(0x1); m.DefaultMobileInit(); Span data = new MobileHitsN(m).Compile(); Span expectedData = stackalloc byte[] { 0xA1, // Packet ID 0x00, 0x00, 0x00, 0x00, // Serial 0x00, 0x00, // Max Hits 0x00, 0x00 // Current Hits }; int max = AttributeNormalizer.Maximum; m.Serial.CopyTo(expectedData.Slice(1, 4)); AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, true, expectedData.Slice(5)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileMana() { var m = new Mobile(0x1); m.DefaultMobileInit(); Span data = new MobileMana(m).Compile(); Span expectedData = stackalloc byte[] { 0xA2, // Packet ID 0x00, 0x00, 0x00, 0x00, // Serial 0x00, 0x00, // Max Hits 0x00, 0x00 // Current Hits }; m.Serial.CopyTo(expectedData.Slice(1, 4)); AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, false, expectedData.Slice(5)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileManaN() { var m = new Mobile(0x1); m.DefaultMobileInit(); Span data = new MobileManaN(m).Compile(); Span expectedData = stackalloc byte[] { 0xA2, // Packet ID 0x00, 0x00, 0x00, 0x00, // Serial 0x00, 0x00, // Max Hits 0x00, 0x00 // Current Hits }; int max = AttributeNormalizer.Maximum; m.Serial.CopyTo(expectedData.Slice(1, 4)); AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, true, expectedData.Slice(5)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileStam() { var m = new Mobile(0x1); m.DefaultMobileInit(); Span data = new MobileStam(m).Compile(); Span expectedData = stackalloc byte[] { 0xA3, // Packet ID 0x00, 0x00, 0x00, 0x00, // Serial 0x00, 0x00, // Max Hits 0x00, 0x00 // Current Hits }; m.Serial.CopyTo(expectedData.Slice(1, 4)); AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, false, expectedData.Slice(5)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileStamN() { var m = new Mobile(0x1); m.DefaultMobileInit(); Span data = new MobileStamN(m).Compile(); Span expectedData = stackalloc byte[] { 0xA3, // Packet ID 0x00, 0x00, 0x00, 0x00, // Serial 0x00, 0x00, // Max Hits 0x00, 0x00 // Current Hits }; int max = AttributeNormalizer.Maximum; m.Serial.CopyTo(expectedData.Slice(1, 4)); AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, true, expectedData.Slice(5)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileAttributes() { var m = new Mobile(0x1); m.DefaultMobileInit(); Span data = new MobileAttributes(m).Compile(); Span 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 }; 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)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileAttributesN() { var m = new Mobile(0x1); m.DefaultMobileInit(); Span data = new MobileAttributesN(m).Compile(); Span 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 }; 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)); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileName() { var m = new Mobile(0x1) { Name = "Some Really Long Mobile Name That Gets Cut off", }; m.DefaultMobileInit(); Span data = new MobileName(m).Compile(); Span 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 AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileAnimation() { Serial mobile = 0x1; int action = 200; int frameCount = 5; int repeatCount = 1; bool reverse = false; bool repeat = false; byte delay = 5; Span data = new MobileAnimation( mobile, action, frameCount, repeatCount, !reverse, repeat, delay ).Compile(); Span 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); AssertThat.Equal(data, expectedData); } [Fact] public void TestNewMobileAnimation() { Serial mobile = 0x1; int action = 200; int frameCount = 5; byte delay = 5; Span data = new NewMobileAnimation( mobile, action, frameCount, delay ).Compile(); Span 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); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileStatusCompact() { var m = new Mobile(0x1); m.DefaultMobileInit(); bool canBeRenamed = false; Span data = new MobileStatusCompact(canBeRenamed, m).Compile(); Span expectedData = stackalloc byte[43]; int pos = 0; ((byte)0x11).CopyTo(ref pos, expectedData); // Packet ID ((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length m.Serial.CopyTo(ref pos, expectedData); (m.Name ?? "").CopyASCIIFixedTo(ref pos, 30, expectedData); AttributeNormalizerUtilities.WriteReverse(m.Hits, m.HitsMax, true, expectedData.Slice(pos)); pos += 4; canBeRenamed.CopyTo(ref pos, expectedData); AssertThat.Equal(data, expectedData); } [Fact] public void TestMobileStatusExtended() { var beholder = new Mobile(0x1) { Name = "Random Mobile 1" }; beholder.DefaultMobileInit(); var beheld = new Mobile(0x2) { Name = "Random Mobile 2" }; beheld.DefaultMobileInit(); NetState ns = new NetState(new AccountPacketTests.TestConnectionContext { RemoteEndPoint = IPEndPoint.Parse("127.0.0.1") }); Span data = new MobileStatus(beholder, beheld, ns).Compile(); Span expectedData = stackalloc byte[121]; // Max Size int pos = 0; ((byte)0x11).CopyTo(ref pos, expectedData); pos += 2; // Length int type; bool notSelf = beholder != beheld; if (notSelf) type = 0; else if (Core.HS && ns.ExtendedStatus) type = 6; 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); AttributeNormalizerUtilities.WriteReverse(beheld.Hits, beheld.HitsMax, notSelf, expectedData.Slice(pos)); pos += 4; beheld.CanBeRenamedBy(beheld).CopyTo(ref pos, expectedData); ((byte)type).CopyTo(ref pos, expectedData); 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); AttributeNormalizerUtilities.WriteReverse(beheld.Stam, beheld.StamMax, notSelf, expectedData.Slice(pos)); pos += 4; 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); 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 } ((ushort)beheld.StatCap).CopyTo(ref pos, expectedData); ((byte)beheld.Followers).CopyTo(ref pos, expectedData); ((byte)beheld.FollowersMax).CopyTo(ref pos, expectedData); 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); } 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); beheld.TithingPoints.CopyTo(ref pos, expectedData); if (type >= 6) for (var i = 0; i < 15; ++i) ((ushort)beheld.GetAOSStatus(i)).CopyTo(ref pos, expectedData); } ((ushort)pos).CopyTo(expectedData.Slice(1)); // Length expectedData = expectedData.Slice(0, pos); AssertThat.Equal(data, expectedData); } } }