From 5631c1da6d94de2f9371c8c0a038a9f6b279ff6a Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Tue, 12 Jan 2021 19:25:45 -0800 Subject: [PATCH] fix(core): Converts map item packets (#404) - [X] Converts map item packets --- .../Tests/Items/Maps/Packets.cs | 68 +++++++++++++++ .../Tests/Items/Maps/TestMapItemPackets.cs | 49 +++++++++++ Projects/UOContent/Items/Maps/MapItem.cs | 84 ++----------------- .../UOContent/Items/Maps/MapItemPackets.cs | 74 ++++++++++++++++ 4 files changed, 197 insertions(+), 78 deletions(-) create mode 100644 Projects/UOContent.Tests/Tests/Items/Maps/Packets.cs create mode 100644 Projects/UOContent.Tests/Tests/Items/Maps/TestMapItemPackets.cs create mode 100644 Projects/UOContent/Items/Maps/MapItemPackets.cs diff --git a/Projects/UOContent.Tests/Tests/Items/Maps/Packets.cs b/Projects/UOContent.Tests/Tests/Items/Maps/Packets.cs new file mode 100644 index 000000000..ae5a9fb63 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/Items/Maps/Packets.cs @@ -0,0 +1,68 @@ +using Server.Network; + +namespace Server.Items +{ + public sealed class MapDetails : Packet + { + public MapDetails(MapItem map) : base(0x90, 19) + { + Stream.Write(map.Serial); + Stream.Write((short)0x139D); + Stream.Write((short)map.Bounds.Start.X); + Stream.Write((short)map.Bounds.Start.Y); + Stream.Write((short)map.Bounds.End.X); + Stream.Write((short)map.Bounds.End.Y); + Stream.Write((short)map.Width); + Stream.Write((short)map.Height); + } + } + + public sealed class MapDetailsNew : Packet + { + public MapDetailsNew(MapItem map) : base(0xF5, 21) + { + Stream.Write(map.Serial); + Stream.Write((short)0x139D); + Stream.Write((short)map.Bounds.Start.X); + Stream.Write((short)map.Bounds.Start.Y); + Stream.Write((short)map.Bounds.End.X); + Stream.Write((short)map.Bounds.End.Y); + Stream.Write((short)map.Width); + Stream.Write((short)map.Height); + Stream.Write((short)(map.Facet?.MapID ?? 0)); + } + } + + public class MapCommand : Packet + { + public MapCommand(MapItem map, int command, int number, int x, int y) : base(0x56, 11) + { + Stream.Write(map.Serial); + Stream.Write((byte)command); + Stream.Write((byte)number); + Stream.Write((short)x); + Stream.Write((short)y); + } + } + + public sealed class MapDisplay : MapCommand + { + public MapDisplay(MapItem map) : base(map, 5, 0, 0, 0) + { + } + } + + public sealed class MapAddPin : MapCommand + { + public MapAddPin(MapItem map, Point2D point) : base(map, 1, 0, point.X, point.Y) + { + } + } + + public sealed class MapSetEditable : MapCommand + { + public MapSetEditable(MapItem map, bool editable) : base(map, 7, editable ? 1 : 0, 0, 0) + { + } + } +} diff --git a/Projects/UOContent.Tests/Tests/Items/Maps/TestMapItemPackets.cs b/Projects/UOContent.Tests/Tests/Items/Maps/TestMapItemPackets.cs new file mode 100644 index 000000000..f99e5a607 --- /dev/null +++ b/Projects/UOContent.Tests/Tests/Items/Maps/TestMapItemPackets.cs @@ -0,0 +1,49 @@ +using System; +using Server; +using Server.Items; +using Server.Network; +using Server.Tests; +using Server.Tests.Network; +using Xunit; + +namespace UOContent.Tests +{ + public class TestMapItemPackets : IClassFixture + { + [Theory] + [InlineData(ProtocolChanges.NewCharacterList)] + [InlineData(ProtocolChanges.None)] + public void TestSendMapDetails(ProtocolChanges changes) + { + var mapItem = new MapItem(Map.Trammel); + + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.ProtocolChanges = changes; + + var expected = (ns.NewCharacterList ? + (Packet)new MapDetailsNew(mapItem) : new MapDetails(mapItem)).Compile(); + ns.SendMapDetails(mapItem); + + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); + } + + [Theory] + [InlineData(5, 0, 0, 0)] + [InlineData(1, 0, 100, 200)] + [InlineData(7, 1, 0, 0)] + [InlineData(7, 0, 0, 0)] + public void TestSendMapCommand(int command, int number, int x, int y) + { + var mapItem = new MapItem(Map.Trammel); + + var expected = new MapCommand(mapItem, command, number, x, y).Compile(); + + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMapCommand(mapItem, command, x, y, number > 0); + + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); + } + } +} diff --git a/Projects/UOContent/Items/Maps/MapItem.cs b/Projects/UOContent/Items/Maps/MapItem.cs index 8898e6161..c5e1a26f0 100644 --- a/Projects/UOContent/Items/Maps/MapItem.cs +++ b/Projects/UOContent/Items/Maps/MapItem.cs @@ -99,29 +99,21 @@ namespace Server.Items { var ns = from.NetState; - if (ns.NewCharacterList) // 7.0.13.0+ supports maps on all facets - { - from.Send(new MapDetailsNew(this)); - } - else if (Facet != null && Facet != Map.Felucca && Facet != Map.Trammel - ) // Is it Felucca and Trammel, or just Felucca? + if (!ns.NewCharacterList && Facet != null && Facet != Map.Felucca && Facet != Map.Trammel) { from.SendMessage("You must have client 7.0.13.0 or higher to display this map."); return; } - else - { - from.Send(new MapDetails(this)); - } - from.Send(new MapDisplay(this)); + ns.SendMapDetails(this); + ns.SendMapDisplay(this); for (var i = 0; i < Pins.Count; ++i) { - from.Send(new MapAddPin(this, Pins[i])); + ns.SendMapAddPin(this, Pins[i]); } - from.Send(new MapSetEditable(this, ValidateEdit(from))); + ns.SendMapSetEditable(this, ValidateEdit(from)); } public virtual void OnAddPin(Mobile from, int x, int y) @@ -194,7 +186,7 @@ namespace Server.Items m_Editable = !m_Editable; } - from.Send(new MapSetEditable(this, Validate(from) && m_Editable)); + from.NetState.SendMapSetEditable(this, m_Editable && Validate(from)); } public virtual void Validate(ref int x, ref int y) @@ -371,69 +363,5 @@ namespace Server.Items break; } } - - private sealed class MapDetails : Packet - { - public MapDetails(MapItem map) : base(0x90, 19) - { - Stream.Write(map.Serial); - Stream.Write((short)0x139D); - Stream.Write((short)map.Bounds.Start.X); - Stream.Write((short)map.Bounds.Start.Y); - Stream.Write((short)map.Bounds.End.X); - Stream.Write((short)map.Bounds.End.Y); - Stream.Write((short)map.Width); - Stream.Write((short)map.Height); - } - } - - private sealed class MapDetailsNew : Packet - { - public MapDetailsNew(MapItem map) : base(0xF5, 21) - { - Stream.Write(map.Serial); - Stream.Write((short)0x139D); - Stream.Write((short)map.Bounds.Start.X); - Stream.Write((short)map.Bounds.Start.Y); - Stream.Write((short)map.Bounds.End.X); - Stream.Write((short)map.Bounds.End.Y); - Stream.Write((short)map.Width); - Stream.Write((short)map.Height); - Stream.Write((short)(map.Facet?.MapID ?? 0)); - } - } - - private abstract class MapCommand : Packet - { - public MapCommand(MapItem map, int command, int number, int x, int y) : base(0x56, 11) - { - Stream.Write(map.Serial); - Stream.Write((byte)command); - Stream.Write((byte)number); - Stream.Write((short)x); - Stream.Write((short)y); - } - } - - private sealed class MapDisplay : MapCommand - { - public MapDisplay(MapItem map) : base(map, 5, 0, 0, 0) - { - } - } - - private sealed class MapAddPin : MapCommand - { - public MapAddPin(MapItem map, Point2D point) : base(map, 1, 0, point.X, point.Y) - { - } - } - - private sealed class MapSetEditable : MapCommand - { - public MapSetEditable(MapItem map, bool editable) : base(map, 7, editable ? 1 : 0, 0, 0) - { - } - } } } diff --git a/Projects/UOContent/Items/Maps/MapItemPackets.cs b/Projects/UOContent/Items/Maps/MapItemPackets.cs new file mode 100644 index 000000000..305f6ccbe --- /dev/null +++ b/Projects/UOContent/Items/Maps/MapItemPackets.cs @@ -0,0 +1,74 @@ +/************************************************************************* + * ModernUO * + * Copyright (C) 2019-2021 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: MapItemPackets.cs * + * * + * 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. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System.Buffers; +using Server.Items; + +namespace Server.Network +{ + public static class MapItemPackets + { + public static void SendMapDetails(this NetState ns, MapItem map) + { + if (ns == null) + { + return; + } + + var writer = new SpanWriter(stackalloc byte[ns.NewCharacterList ? 21 : 19]); + writer.Write((byte)(ns.NewCharacterList ? 0xF5 : 0x90)); // Packet ID + writer.Write(map.Serial); + writer.Write((short)0x139D); + + var bounds = map.Bounds; + writer.Write((short)bounds.Start.X); + writer.Write((short)bounds.Start.Y); + writer.Write((short)bounds.End.X); + writer.Write((short)bounds.End.Y); + writer.Write((short)map.Width); + writer.Write((short)map.Height); + + if (ns.NewCharacterList) + { + writer.Write((short)(map.Facet?.MapID ?? 0)); + } + + ns.Send(writer.Span); + } + + public static void SendMapCommand(this NetState ns, MapItem map, int command, int x = 0, int y = 0, bool editable = false) + { + if (ns == null) + { + return; + } + + var writer = new SpanWriter(stackalloc byte[11]); + writer.Write((byte)0x56); // Packet ID + writer.Write(map.Serial); + writer.Write((byte)command); + writer.Write(editable); + writer.Write((short)x); + writer.Write((short)y); + + ns.Send(writer.Span); + } + + public static void SendMapDisplay(this NetState ns, MapItem map) => ns.SendMapCommand(map, 5); + public static void SendMapAddPin(this NetState ns, MapItem map, Point2D p) => ns.SendMapCommand(map, 1, p.X, p.Y); + public static void SendMapSetEditable(this NetState ns, MapItem map, bool editable) => + ns.SendMapCommand(map, 7, 0, 0, true); + } +}