From 5052bf9af312348d138b95a336e08afbdc99ea97 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sat, 18 Jul 2020 19:03:26 -0700 Subject: [PATCH] Adds more packets (#177) --- .../Old/Outgoing/AccountPacketTests.cs | 2 +- .../Packets/Old/Outgoing/EffectPacketTests.cs | 24 +- .../Packets/Old/Outgoing/ItemPacketTests.cs | 8 +- .../Packets/Old/Outgoing/MessageTests.cs | 27 +- .../Packets/Old/Outgoing/MobilePacketTests.cs | 16 +- .../Old/Outgoing/ObjectHelpResponseTests.cs | 6 +- .../Packets/Old/Outgoing/PlayerPacketTests.cs | 521 ++++++++++++++++++ .../Network/Packets/PacketTestUtilities.cs | 2 - Projects/Server/Buffers/SpanExtensions.cs | 55 +- Projects/Server/Mobile.cs | 6 +- .../Packets/Old Packets/PlayerPackets.cs | 38 +- .../Server/Network/StaticPacketHandlers.cs | 2 +- Projects/UOContent/Misc/Paperdoll.cs | 4 +- Projects/UOContent/Misc/Profile.cs | 3 +- azure-pipelines.yml | 4 +- 15 files changed, 609 insertions(+), 109 deletions(-) create mode 100644 Projects/Server.Tests/Network/Packets/Old/Outgoing/PlayerPacketTests.cs diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs index 948c7c246..9148ceb0d 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/AccountPacketTests.cs @@ -263,7 +263,7 @@ namespace Server.Tests.Network.Packets 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, (short)m.Z); expectedData.Write(ref pos, (byte)m.Direction); #if NO_LOCAL_INIT expectedData.Write(ref pos, (byte)0); diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs index df9b10662..70ca135d0 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/EffectPacketTests.cs @@ -45,12 +45,8 @@ namespace Server.Tests.Network.Packets 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, fromPoint); + expectedData.Write(ref pos, toPoint); expectedData.Write(ref pos, speed); expectedData.Write(ref pos, duration); #if NO_LOCAL_INIT @@ -103,12 +99,8 @@ namespace Server.Tests.Network.Packets 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, fromPoint); + expectedData.Write(ref pos, toPoint); expectedData.Write(ref pos, speed); expectedData.Write(ref pos, duration); #if NO_LOCAL_INIT @@ -174,12 +166,8 @@ namespace Server.Tests.Network.Packets #else pos += 6; #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); + expectedData.Write(ref pos, entity.Location); + expectedData.Write(ref pos, entity.Location); #if NO_LOCAL_INIT expectedData.Write(ref pos, 0); expectedData.Write(ref pos, (ushort)0); diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs index 51546551a..7ad5b59fb 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ItemPacketTests.cs @@ -127,9 +127,7 @@ namespace Server.Tests.Network.Packets 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, loc); // X, Y, 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 @@ -178,9 +176,7 @@ namespace Server.Tests.Network.Packets 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, loc); // X, Y, 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 diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MessageTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MessageTests.cs index 3d0f4540a..289115bdd 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MessageTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MessageTests.cs @@ -42,10 +42,7 @@ namespace Server.Tests.Network.Packets 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 + expectedData.WriteLittleUniNull(ref pos, args); AssertThat.Equal(data, expectedData); } @@ -90,16 +87,8 @@ namespace Server.Tests.Network.Packets 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 + expectedData.WriteAsciiNull(ref pos, affix); + expectedData.WriteBigUniNull(ref pos, args); AssertThat.Equal(data, expectedData); } @@ -136,10 +125,7 @@ namespace Server.Tests.Network.Packets 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 + expectedData.WriteAsciiNull(ref pos, text); AssertThat.Equal(data, expectedData); } @@ -179,10 +165,7 @@ namespace Server.Tests.Network.Packets 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 + expectedData.WriteBigUniNull(ref pos, text); AssertThat.Equal(data, expectedData); } diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MobilePacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MobilePacketTests.cs index 5c796049a..1647dc55e 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/MobilePacketTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/MobilePacketTests.cs @@ -72,9 +72,7 @@ namespace Server.Tests.Network.Packets 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, m.Location); expectedData.Write(ref pos, (byte)m.Direction); expectedData.Write(ref pos, (ushort)m.Hue); expectedData.Write(ref pos, (byte)m.GetPacketFlags()); @@ -99,9 +97,7 @@ namespace Server.Tests.Network.Packets 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, m.Location); expectedData.Write(ref pos, (byte)m.Direction); expectedData.Write(ref pos, (ushort)m.Hue); expectedData.Write(ref pos, (byte)m.GetOldPacketFlags()); @@ -478,10 +474,10 @@ namespace Server.Tests.Network.Packets } [Theory] - [InlineData("None", 0)] - [InlineData("Lesser", 1)] - [InlineData("Lethal", 5)] - public void TestHealthbarPoison(string pName, int level) + [InlineData("None")] + [InlineData("Lesser")] + [InlineData("Lethal")] + public void TestHealthbarPoison(string pName) { var p = Poison.GetPoison(pName); Mobile m = new Mobile(0x1); diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ObjectHelpResponseTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ObjectHelpResponseTests.cs index f0109ba55..6e42e857f 100644 --- a/Projects/Server.Tests/Network/Packets/Old/Outgoing/ObjectHelpResponseTests.cs +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/ObjectHelpResponseTests.cs @@ -23,11 +23,7 @@ namespace Server.Tests.Network.Packets expectedData.Write(ref pos, (byte)0xB7); // Packet ID expectedData.Write(ref pos, (ushort)length); // Length expectedData.Write(ref pos, s); - expectedData.WriteBigUni(ref pos, text); - -#if NO_LOCAL_INIT - expectedData.Write(ref pos, (ushort)0); // Terminator -#endif + expectedData.WriteBigUniNull(ref pos, text); AssertThat.Equal(data, expectedData); } diff --git a/Projects/Server.Tests/Network/Packets/Old/Outgoing/PlayerPacketTests.cs b/Projects/Server.Tests/Network/Packets/Old/Outgoing/PlayerPacketTests.cs new file mode 100644 index 000000000..978ac3c6d --- /dev/null +++ b/Projects/Server.Tests/Network/Packets/Old/Outgoing/PlayerPacketTests.cs @@ -0,0 +1,521 @@ +using System; +using System.Buffers; +using Server.Network; +using Xunit; + +namespace Server.Tests.Network.Packets +{ + public class PlayerPacketTests : IClassFixture + { + [Fact] + public void TestStatLockInfo() + { + Mobile m = new Mobile(0x1); + m.DefaultMobileInit(); + + Span data = new StatLockInfo(m).Compile(); + + Span expectedData = stackalloc byte[12]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)12); // Length + expectedData.Write(ref pos, (ushort)0x19); // Sub-packet + expectedData.Write(ref pos, (byte)2); // Command + expectedData.Write(ref pos, m.Serial); + expectedData.Write(ref pos, (ushort)(((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock)); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestChangeUpdateRange() + { + byte range = 10; + Span data = new ChangeUpdateRange(range).Compile(); + + Span expectedData = stackalloc byte[2]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xC8); // Packet ID + expectedData.Write(ref pos, range); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void TestDeathStatus(bool isDead) + { + Span data = new DeathStatus(isDead).Compile(); + + Span expectedData = stackalloc byte[2]; + int pos = 0; + + const byte dead = 0; + const byte alive = 2; + expectedData.Write(ref pos, (byte)0x2C); // Packet ID + expectedData.Write(ref pos, isDead ? dead : alive); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0, true)] + [InlineData(0, false)] + [InlineData(100, true)] + [InlineData(1000, false)] + public void TestSpecialAbility(int abilityId, bool active) + { + Span data = new ToggleSpecialAbility(abilityId, active).Compile(); + + Span expectedData = stackalloc byte[8]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)0x8); // Length + expectedData.Write(ref pos, (ushort)0x25); // Sub-packet + expectedData.Write(ref pos, (ushort)abilityId); + expectedData.Write(ref pos, active); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData("This is a header", "This is a body", "This is a footer")] + [InlineData(null, null, null)] + public void TestDisplayProfile(string header, string body, string footer) + { + Serial m = 0x1000; + + Span data = new DisplayProfile(m, header, body, footer).Compile(); + + header ??= ""; + body ??= ""; + footer ??= ""; + + int length = 12 + header.Length + footer.Length * 2 + body.Length * 2; + + Span expectedData = stackalloc byte[length]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xB8); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, m); // Mobile Serial or Serial.Zero + expectedData.WriteAsciiNull(ref pos, header); + expectedData.WriteBigUniNull(ref pos, footer); + expectedData.WriteBigUniNull(ref pos, body); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(LRReason.CannotLift)] + [InlineData(LRReason.TryToSteal)] + public void TestLiftRej(LRReason reason) + { + Span data = new LiftRej(reason).Compile(); + + Span expectedData = stackalloc byte[2]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x27); // Packet ID + expectedData.Write(ref pos, (byte)reason); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestLogoutAck() + { + Span data = new LogoutAck().Compile(); + + Span expectedData = stackalloc byte[2]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xD1); // Packet ID + expectedData.Write(ref pos, (byte)0x1); // 1 - Ack + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(1, 2, 3)] + [InlineData(4, 5, 6)] + public void TestWeather(int type, int density, int temp) + { + Span data = new Weather(type, density, temp).Compile(); + + Span expectedData = stackalloc byte[4]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x65); // Packet ID + expectedData.Write(ref pos, (byte)type); + expectedData.Write(ref pos, (byte)density); + expectedData.Write(ref pos, (byte)temp); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestRemoveEntity() + { + Serial e = 0x1000; + Span data = new RemoveEntity(e).Compile(); + + Span expectedData = stackalloc byte[5]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x1D); // Packet ID + expectedData.Write(ref pos, e); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestServerChange() + { + Point3D p = new Point3D(100, 1000, 1); + Map map = Map.Felucca; + Span data = new ServerChange(p, map).Compile(); + + Span expectedData = stackalloc byte[16]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x76); // Packet ID + expectedData.Write(ref pos, (ushort)p.X); + expectedData.Write(ref pos, (ushort)p.Y); + expectedData.Write(ref pos, (short)p.Z); +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); // Unknown + expectedData.Write(ref pos, 0); // Server X, Server Y +#else + pos += 5; +#endif + expectedData.Write(ref pos, (ushort)map.Width); // Server Width + expectedData.Write(ref pos, (ushort)map.Height); // Server Height + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestSkillUpdate() + { + Mobile m = new Mobile(0x1); + m.DefaultMobileInit(); + + Skills skills = m.Skills; + m.Skills[SkillName.Alchemy].BaseFixedPoint = 1000; // GM Alchemy + + Span data = new SkillUpdate(skills).Compile(); + + int length = 6 + skills.Length * 9; + Span expectedData = stackalloc byte[length]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x3A); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, (byte)0x02); // type: absolute, capped + + for (int i = 0; i < skills.Length; i++) + { + var s = skills[i]; + + var v = s.NonRacialValue; + var uv = Utility.Coerce((int)(v * 10), 0, 0xFFFF); + + expectedData.Write(ref pos, (ushort)(s.Info.SkillID + 1)); + expectedData.Write(ref pos, (ushort)uv); + expectedData.Write(ref pos, (ushort)s.BaseFixedPoint); + expectedData.Write(ref pos, (byte)s.Lock); + expectedData.Write(ref pos, (ushort)s.CapFixedPoint); + } + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0)] + [InlineData(10)] + [InlineData(255)] + public void TestSequence(byte num) + { + Span data = new Sequence(num).Compile(); + + Span expectedData = stackalloc byte[2]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x7B); // Packet ID + expectedData.Write(ref pos, num); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(SkillName.Alchemy, 0, 1)] + [InlineData(SkillName.Archery, 10, 1000)] + [InlineData(SkillName.Begging, 100000, 1000)] + public void TestSkillChange(SkillName skillName, int baseFixedPoint, int capFixedPoint) + { + // TODO: Eliminate all of this and just create a Skill directly + Mobile m = new Mobile(0x1); + m.DefaultMobileInit(); + + Skill skill = m.Skills[skillName]; + skill.BaseFixedPoint = baseFixedPoint; + skill.CapFixedPoint = capFixedPoint; + + Span data = new SkillChange(skill).Compile(); + + Span expectedData = stackalloc byte[13]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x3A); // Packet ID + expectedData.Write(ref pos, (ushort)13); // Length + expectedData.Write(ref pos, (byte)0xDF); // type: delta, capped + + var v = skill.NonRacialValue; + var uv = Utility.Coerce((int)(v * 10), 0, 0xFFFF); + + expectedData.Write(ref pos, (ushort)skill.Info.SkillID); + expectedData.Write(ref pos, (ushort)uv); + expectedData.Write(ref pos, (ushort)skill.BaseFixedPoint); + expectedData.Write(ref pos, (byte)skill.Lock); + expectedData.Write(ref pos, (ushort)skill.CapFixedPoint); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData("This is a URL, I promise")] + public void TestLaunchBrowser(string url) + { + Span data = new LaunchBrowser(url).Compile(); + + url ??= ""; + + int length = 4 + url.Length; + Span expectedData = stackalloc byte[length]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xA5); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.WriteAsciiNull(ref pos, url); // Note: use punycode for unicode URLs + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestDragEffect() + { + Entity src = new Entity(0x1, new Point3D(1000, 100, 10), Map.Felucca); + Entity targ = new Entity(0x2, new Point3D(1125, 125, 5), Map.Felucca); + var itemID = 0x384; + var hue = 1024; + var amount = 25; + + Span data = new DragEffect(src, targ, itemID, hue, amount).Compile(); + + Span expectedData = stackalloc byte[26]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x23); // Packet ID + expectedData.Write(ref pos, (ushort)itemID); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (byte)0); +#else + pos++; +#endif + + expectedData.Write(ref pos, (ushort)hue); + expectedData.Write(ref pos, (ushort)amount); + expectedData.Write(ref pos, src.Serial); + expectedData.Write(ref pos, src.Location); + expectedData.Write(ref pos, targ.Serial); + expectedData.Write(ref pos, targ.Location); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(1, false)] + [InlineData(2, true)] + public void TestSeasonChange(int season, bool playSound) + { + Span data = new SeasonChange(season, playSound).Compile(); + + Span expectedData = stackalloc byte[3]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xBC); // Packet ID + expectedData.Write(ref pos, (byte)season); + expectedData.Write(ref pos, playSound); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0x1024, "Test Title", true, true)] + [InlineData(0x1024, "Test Title", false, true)] + [InlineData(0x1024, "Test Title", true, false)] + public void TestDisplayPaperdoll(uint m, string title, bool warmode, bool canLift) + { + Span data = new DisplayPaperdoll(m, title, warmode, canLift).Compile(); + + Span expectedData = stackalloc byte[66]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x88); // Packet ID + expectedData.Write(ref pos, m); + expectedData.WriteAsciiFixed(ref pos, title, 60); + byte flags = 0x00; + if (warmode) + flags |= 0x01; + if (canLift) + flags |= 0x02; + + expectedData.Write(ref pos, flags); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(10, 1000, 10, 5)] + public void TestPlaySound(ushort soundID, int x, int y, int z) + { + Point3D p = new Point3D(x, y, z); + + Span data = new PlaySound(soundID, p).Compile(); + + Span expectedData = stackalloc byte[12]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x54); // Packet ID + expectedData.Write(ref pos, (byte)1); // Flags + expectedData.Write(ref pos, soundID); + +#if NO_LOCAL_INIT + expectedData.Write(ref pos, (ushort)0); // Volume +#else + pos += 2; +#endif + + expectedData.Write(ref pos, (ushort)p.X); + expectedData.Write(ref pos, (ushort)p.Y); + expectedData.Write(ref pos, (short)p.Z); + + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(MusicName.Approach)] + [InlineData(MusicName.Combat1)] + [InlineData(MusicName.ValoriaShips)] + public void TestPlayMusic(MusicName music) + { + Span data = new PlayMusic(music).Compile(); + + Span expectedData = stackalloc byte[3]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x6D); // Packet ID + expectedData.Write(ref pos, (ushort)music); // Flags + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(10, 1, "Some text")] + [InlineData(100, 10, "Some more text")] + public void TestScrollMessage(int type, int tip, string text) + { + Span data = new ScrollMessage(type, tip, text).Compile(); + + text ??= ""; + int length = 10 + text.Length; + Span expectedData = stackalloc byte[length]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xA6); // Packet ID + expectedData.Write(ref pos, (ushort)length); // Length + expectedData.Write(ref pos, (byte)type); + expectedData.Write(ref pos, tip); + expectedData.Write(ref pos, (ushort)text.Length); + expectedData.WriteAscii(ref pos, text); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestCurrentTime() + { + DateTime date = DateTime.Parse("2020-01-01 14:10:05"); + + Span data = new CurrentTime(date).Compile(); + + Span expectedData = stackalloc byte[4]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x5B); // Packet ID + expectedData.Write(ref pos, (byte)date.Hour); + expectedData.Write(ref pos, (byte)date.Minute); + expectedData.Write(ref pos, (byte)date.Second); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestPathfindMessage() + { + var p = new Point3D(1000, 10, 1); + Span data = new PathfindMessage(p).Compile(); + + Span expectedData = stackalloc byte[7]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x38); // Packet ID + expectedData.Write(ref pos, (ushort)p.X); + expectedData.Write(ref pos, (ushort)p.Y); + expectedData.Write(ref pos, (short)p.Z); + + AssertThat.Equal(data, expectedData); + } + + [Theory] + [InlineData(0)] + [InlineData(10)] + [InlineData(100)] + public void TestPingAck(byte ping) + { + Span data = new PingAck(ping).Compile(); + + Span expectedData = stackalloc byte[2]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0x73); // Packet ID + expectedData.Write(ref pos, ping); + + AssertThat.Equal(data, expectedData); + } + + [Fact] + public void TestClearAbility() + { + Span data = new ClearWeaponAbility().Compile(); + + Span expectedData = stackalloc byte[5]; + int pos = 0; + + expectedData.Write(ref pos, (byte)0xBF); // Packet ID + expectedData.Write(ref pos, (ushort)5); // Length + expectedData.Write(ref pos, (ushort)0x21); // Sub-packet + + AssertThat.Equal(data, expectedData); + } + } +} diff --git a/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs b/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs index ddb5f4713..005db4744 100644 --- a/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs +++ b/Projects/Server.Tests/Network/Packets/PacketTestUtilities.cs @@ -1,7 +1,5 @@ using System; -using System.Buffers.Binary; using System.Runtime.CompilerServices; -using System.Text; using Server.Network; namespace Server.Tests.Network.Packets diff --git a/Projects/Server/Buffers/SpanExtensions.cs b/Projects/Server/Buffers/SpanExtensions.cs index 67f56de98..52fa6a7f9 100644 --- a/Projects/Server/Buffers/SpanExtensions.cs +++ b/Projects/Server/Buffers/SpanExtensions.cs @@ -136,7 +136,10 @@ namespace System.Buffers { int length = value.Length; pos += Encoding.ASCII.GetBytes(value.AsSpan(0, length), span.Slice(pos, length)); - span[pos++] = 0; // Null terminator +#if NO_LOCAL_INIT + span[pos] = 0; // Null terminator +#endif + pos++; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -145,7 +148,10 @@ namespace System.Buffers 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 +#if NO_LOCAL_INIT + span[pos] = 0; // Null terminator +#endif + pos++; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -164,22 +170,6 @@ namespace System.Buffers pos += amount; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteAsciiFixedNull(this Span 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 span, ref int pos, string value) { @@ -191,5 +181,34 @@ namespace System.Buffers { pos += Encoding.Unicode.GetBytes(value, span.Slice(pos)); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteBigUniNull(this Span span, ref int pos, string value) + { + pos += Encoding.BigEndianUnicode.GetBytes(value, span.Slice(pos)); +#if NO_LOCAL_INIT + BinaryPrimitives.WriteUInt16BigEndian(span.Slice(pos, 2), 0); // Null terminator +#endif + pos += 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteLittleUniNull(this Span span, ref int pos, string value) + { + pos += Encoding.Unicode.GetBytes(value, span.Slice(pos)); +#if NO_LOCAL_INIT + BinaryPrimitives.WriteUInt16BigEndian(span.Slice(pos, 2), 0); // Null terminator +#endif + pos += 2; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void Write(this Span span, ref int pos, Point3D p) + { + BinaryPrimitives.WriteUInt16BigEndian(span.Slice(pos, 2), (ushort)p.X); + BinaryPrimitives.WriteUInt16BigEndian(span.Slice(pos + 2, 2), (ushort)p.Y); + span[pos + 4] = (byte)p.Z; + pos += 5; + } } } diff --git a/Projects/Server/Mobile.cs b/Projects/Server/Mobile.cs index e1e5a4fb9..c6eead6a5 100644 --- a/Projects/Server/Mobile.cs +++ b/Projects/Server/Mobile.cs @@ -1040,7 +1040,7 @@ namespace Server public static bool FwdEnabled { get; set; } = true; - public static bool FwdUOTDOverride { get; set; } = false; + public static bool FwdUOTDOverride { get; set; } public static int FwdMaxSteps { get; set; } = 4; @@ -2079,7 +2079,7 @@ namespace Server if (ns != null) { if (m_Map != null) - ns.Send(new ServerChange(this, m_Map)); + ns.Send(new ServerChange(m_Location, m_Map)); ns.Sequence = 0; ClearFastwalkStack(); @@ -2210,7 +2210,7 @@ namespace Server if (ns != null) { if (m_Map != null) - Send(new ServerChange(this, m_Map)); + Send(new ServerChange(m_Location, m_Map)); ns.Sequence = 0; ClearFastwalkStack(); diff --git a/Projects/Server/Network/Packets/Old Packets/PlayerPackets.cs b/Projects/Server/Network/Packets/Old Packets/PlayerPackets.cs index 709f93aba..a9931b6bf 100644 --- a/Projects/Server/Network/Packets/Old Packets/PlayerPackets.cs +++ b/Projects/Server/Network/Packets/Old Packets/PlayerPackets.cs @@ -101,7 +101,7 @@ namespace Server.Network public sealed class DisplayProfile : Packet { - public DisplayProfile(bool realSerial, Mobile m, string header, string body, string footer) : base(0xB8) + public DisplayProfile(Serial m, string header, string body, string footer) : base(0xB8) { header ??= ""; body ??= ""; @@ -109,7 +109,7 @@ namespace Server.Network EnsureCapacity(12 + header.Length + footer.Length * 2 + body.Length * 2); - Stream.Write(realSerial ? m.Serial : Serial.Zero); + Stream.Write(m); Stream.WriteAsciiNull(header); Stream.WriteBigUniNull(footer); Stream.WriteBigUniNull(body); @@ -144,19 +144,19 @@ namespace Server.Network public sealed class RemoveEntity : Packet { - public RemoveEntity(IEntity entity) : base(0x1D, 5) + public RemoveEntity(Serial entity) : base(0x1D, 5) { - Stream.Write(entity.Serial); + Stream.Write(entity); } } public sealed class ServerChange : Packet { - public ServerChange(Mobile m, Map map) : base(0x76, 16) + public ServerChange(Point3D p, Map map) : base(0x76, 16) { - Stream.Write((short)m.X); - Stream.Write((short)m.Y); - Stream.Write((short)m.Z); + Stream.Write((short)p.X); + Stream.Write((short)p.Y); + Stream.Write((short)p.Z); Stream.Write((byte)0); Stream.Write((short)0); Stream.Write((short)0); @@ -289,18 +289,18 @@ namespace Server.Network public sealed class DisplayPaperdoll : Packet { - public DisplayPaperdoll(Mobile m, string text, bool canLift) : base(0x88, 66) + public DisplayPaperdoll(Serial m, string title, bool warmode, bool canLift) : base(0x88, 66) { byte flags = 0x00; - if (m.Warmode) + if (warmode) flags |= 0x01; if (canLift) flags |= 0x02; - Stream.Write(m.Serial); - Stream.WriteAsciiFixed(text, 60); + Stream.Write(m); + Stream.WriteAsciiFixed(title, 60); Stream.Write(flags); } } @@ -370,19 +370,21 @@ namespace Server.Network public sealed class CurrentTime : Packet { - public CurrentTime() : base(0x5B, 4) + public CurrentTime() : this(DateTime.Now) { - var now = DateTime.UtcNow; + } - Stream.Write((byte)now.Hour); - Stream.Write((byte)now.Minute); - Stream.Write((byte)now.Second); + public CurrentTime(DateTime date) : base(0x5B, 4) + { + Stream.Write((byte)date.Hour); + Stream.Write((byte)date.Minute); + Stream.Write((byte)date.Second); } } public sealed class PathfindMessage : Packet { - public PathfindMessage(IPoint3D p) : base(0x38, 7) + public PathfindMessage(Point3D p) : base(0x38, 7) { Stream.Write((short)p.X); Stream.Write((short)p.Y); diff --git a/Projects/Server/Network/StaticPacketHandlers.cs b/Projects/Server/Network/StaticPacketHandlers.cs index cf3175e3f..7d36a8cef 100644 --- a/Projects/Server/Network/StaticPacketHandlers.cs +++ b/Projects/Server/Network/StaticPacketHandlers.cs @@ -62,7 +62,7 @@ namespace Server.Network { return RemoveEntityPackets.GetOrAdd(entity, value => { - var packet = new RemoveEntity(value); + var packet = new RemoveEntity(value.Serial); packet.SetStatic(); return packet; }); diff --git a/Projects/UOContent/Misc/Paperdoll.cs b/Projects/UOContent/Misc/Paperdoll.cs index ac914ebe9..1e68a3cfc 100644 --- a/Projects/UOContent/Misc/Paperdoll.cs +++ b/Projects/UOContent/Misc/Paperdoll.cs @@ -12,8 +12,8 @@ namespace Server.Misc public static void EventSink_PaperdollRequest(Mobile beholder, Mobile beheld) { - beholder.Send(new DisplayPaperdoll(beheld, Titles.ComputeTitle(beholder, beheld), - beheld.AllowEquipFrom(beholder))); + beholder.Send(new DisplayPaperdoll(beheld.Serial, Titles.ComputeTitle(beholder, beheld), + beheld.Warmode, beheld.AllowEquipFrom(beholder))); if (ObjectPropertyList.Enabled) { diff --git a/Projects/UOContent/Misc/Profile.cs b/Projects/UOContent/Misc/Profile.cs index a8d2c612a..b10f45957 100644 --- a/Projects/UOContent/Misc/Profile.cs +++ b/Projects/UOContent/Misc/Profile.cs @@ -44,8 +44,9 @@ namespace Server.Misc footer = GetAccountDuration(beheld); string body = beheld.Profile ?? ""; + Serial serial = beholder != beheld || !beheld.ProfileLocked ? beheld.Serial : Serial.Zero; - beholder.Send(new DisplayProfile(beholder != beheld || !beheld.ProfileLocked, beheld, header, body, footer)); + beholder.Send(new DisplayProfile(serial, header, body, footer)); } private static string GetAccountDuration(Mobile m) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9da563633..486cbbfd8 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -15,7 +15,7 @@ jobs: steps: - task: NuGetAuthenticate@0 - - script: dotnet restore --force-evaluate + - script: dotnet restore --force-evaluate --source https://api.nuget.org/v3/index.json displayName: 'Restore NuGet Packages' - script: dotnet build -c $(buildConfiguration) --no-restore Projects/Server/Server.csproj displayName: 'Build Server' @@ -43,7 +43,7 @@ jobs: steps: - task: NuGetAuthenticate@0 - - script: dotnet restore --force-evaluate + - script: dotnet restore --force-evaluate --source https://api.nuget.org/v3/index.json displayName: 'Restore NuGet Packages' - script: dotnet build -c $(buildConfiguration) --no-restore Projects/Server/Server.csproj displayName: 'Build Server'