diff --git a/Directory.Build.props b/Directory.Build.props index 69268aa70..352e3d34c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -9,6 +9,7 @@ x64 9 true + true NU1603 win-x64;debian.10-x64;debian.9-x64;ubuntu.16.04-x64;ubuntu.18.04-x64;ubuntu.20.04-x64;centos.7-x64;centos.8-x64;osx-x64 Debug;Release;Analyze diff --git a/Projects/Benchmarks/Benchmarks.csproj b/Projects/Benchmarks/Benchmarks.csproj index afd521a92..1d9434d67 100644 --- a/Projects/Benchmarks/Benchmarks.csproj +++ b/Projects/Benchmarks/Benchmarks.csproj @@ -1,10 +1,15 @@ - - Exe - - - - - - + + Exe + net5.0 + x64 + x64 + 9 + true + + + + + + diff --git a/Projects/Benchmarks/Directory.Build.props b/Projects/Benchmarks/Directory.Build.props new file mode 100644 index 000000000..b9b7c8ad8 --- /dev/null +++ b/Projects/Benchmarks/Directory.Build.props @@ -0,0 +1,3 @@ + + + diff --git a/Projects/Benchmarks/Packets/BenchmarkPacketBroadcast.cs b/Projects/Benchmarks/Packets/BenchmarkPacketBroadcast.cs new file mode 100644 index 000000000..933206cf3 --- /dev/null +++ b/Projects/Benchmarks/Packets/BenchmarkPacketBroadcast.cs @@ -0,0 +1,183 @@ +using System; +using System.Buffers; +using System.Runtime.InteropServices; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; +using Server; +using Server.Network; + +namespace Benchmarks +{ + [SimpleJob(RuntimeMoniker.NetCoreApp50)] + public class BenchmarkPacketBroadcast + { + public static int SendUnicodeMessage( + ArraySegment[] buffer, + Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name, string text + ) + { + name = name?.Trim() ?? ""; + text = text?.Trim() ?? ""; + lang = lang?.Trim() ?? "ENU"; + + if (hue == 0) + { + hue = 0x3B2; + } + + var writer = new CircularBufferWriter(buffer); + writer.Write((byte)0xAE); + writer.Write((ushort)(50 + text.Length * 2)); + writer.Write(serial); + writer.Write((short)graphic); + writer.Write((byte)type); + writer.Write((short)hue); + writer.Write((short)font); + writer.WriteAscii(lang, 4); + writer.WriteAscii(name, 30); + writer.WriteBigUniNull(text); + + return writer.Position; + } + + public static int CreateUnicodeMessage( + ref Span buffer, + Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name, string text + ) + { + name = name?.Trim() ?? ""; + text = text?.Trim() ?? ""; + lang = lang?.Trim() ?? "ENU"; + + if (hue == 0) + { + hue = 0x3B2; + } + + var writer = new SpanWriter(buffer); + writer.Write((byte)0xAE); + writer.Write((ushort)(50 + text.Length * 2)); + writer.Write(serial); + writer.Write((short)graphic); + writer.Write((byte)type); + writer.Write((short)hue); + writer.Write((short)font); + writer.WriteAscii(lang, 4); + writer.WriteAscii(name, 30); + writer.WriteBigUniNull(text); + + return writer.Position; + } + + private Pipe[] _pipes = new Pipe[512]; + private IntPtr[] _pointers = new IntPtr[512]; + + [IterationSetup] + public void SetUp() + { + for (var i = 0; i < _pipes.Length; i++) + { + _pipes[i] = new Pipe(new byte[8192]); + _pointers[i] = Marshal.AllocHGlobal(8192); + } + } + + [IterationCleanup] + public void CleanUp() + { + for (var i = 0; i < _pipes.Length; i++) + { + _pipes[i] = null; + Marshal.FreeHGlobal(_pointers[i]); + } + } + + [Benchmark] + public int TestCircularBuffer() + { + var text = "This is some really long text that we want to handle. It should take a little bit to encode this."; + foreach (var pipe in _pipes) + { + var result = pipe.Writer.TryGetMemory(); + var length = SendUnicodeMessage( + result.Buffer, + Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text + ); + pipe.Writer.Advance((uint)length); + } + + return _pipes.Length; + } + + [Benchmark] + public int TestSpanWriterFromBuffer() + { + var text = "This is some really long text that we want to handle. It should take a little bit to encode this."; + foreach (var pipe in _pipes) + { + var result = pipe.Writer.TryGetMemory(); + + Span buffer = result.Buffer[0]; + + var length = CreateUnicodeMessage( + ref buffer, + Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text + ); + pipe.Writer.Advance((uint)length); + } + + return _pipes.Length; + } + + [Benchmark] + public int TestSpanWriter() + { + var text = "This is some really long text that we want to handle. It should take a little bit to encode this."; + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; + var length = CreateUnicodeMessage( + ref buffer, + Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text + ); + + buffer = buffer.Slice(0, length); + + foreach (var pipe in _pipes) + { + var result = pipe.Writer.TryGetMemory(); + result.CopyFrom(buffer); + pipe.Writer.Advance((uint)buffer.Length); + } + + return _pipes.Length; + } + + [Benchmark] + public int TestSpanWriterAllocH() + { + var text = "This is some really long text that we want to handle. It should take a little bit to encode this."; + + foreach (var pointer in _pointers) + { + Span buffer; + unsafe + { + buffer = new Span(pointer.ToPointer(), 8192); + } + + CreateUnicodeMessage( + ref buffer, + Serial.MinusOne, + -1, + MessageType.Regular, + 0x3B2, + 3, + "ENU", + "System", + text + ); + } + + return _pipes.Length; + } + } +} diff --git a/Projects/Benchmarks/Packets/BenchmarkPacketConstruction.cs b/Projects/Benchmarks/Packets/BenchmarkPacketConstruction.cs index 1a38d7631..3809ed9a0 100644 --- a/Projects/Benchmarks/Packets/BenchmarkPacketConstruction.cs +++ b/Projects/Benchmarks/Packets/BenchmarkPacketConstruction.cs @@ -1,4 +1,5 @@ using System; +using System.Buffers; using System.Buffers.Binary; using System.Collections.Generic; using BenchmarkDotNet.Attributes; @@ -8,7 +9,7 @@ using Server.Network; namespace Benchmarks { - [MemoryDiagnoser, SimpleJob(RuntimeMoniker.NetCoreApp31)] + [SimpleJob(RuntimeMoniker.NetCoreApp50)] public class BenchmarkPacketConstruction { public List m_States; @@ -150,7 +151,7 @@ namespace Benchmarks w.Write((ushort)buyState.Hue); } - return w.Pos; + return w.Position; } } } diff --git a/Projects/Benchmarks/Packets/SpanWriter.cs b/Projects/Benchmarks/Packets/SpanWriter.cs deleted file mode 100644 index 18cb03a1d..000000000 --- a/Projects/Benchmarks/Packets/SpanWriter.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System; -using System.Buffers.Binary; -using System.Runtime.CompilerServices; -using Server; - -namespace Benchmarks -{ - public ref struct SpanWriter - { - public Span Span; - public int Pos; - - public SpanWriter(Span span) - { - Span = span; - Pos = 0; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Write(Serial serial) - { - BinaryPrimitives.WriteUInt32BigEndian(Span.Slice(Pos), serial); - Pos += 4; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Write(ushort value) - { - BinaryPrimitives.WriteUInt16BigEndian(Span.Slice(Pos), value); - Pos += 2; - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public void Write(byte value) => Span[Pos++] = value; - } -} diff --git a/Projects/Benchmarks/Program.cs b/Projects/Benchmarks/Program.cs index c9b023050..a9bf8cccb 100644 --- a/Projects/Benchmarks/Program.cs +++ b/Projects/Benchmarks/Program.cs @@ -2,12 +2,13 @@ using BenchmarkDotNet.Running; namespace Benchmarks { - public class Program + public static class Program { - static void Main(string[] args) + private static void Main(string[] args) { - var featureFlags = BenchmarkRunner.Run(); - var packetConstruction = BenchmarkRunner.Run(); + // var featureFlags = BenchmarkRunner.Run(); + // var packetConstruction = BenchmarkRunner.Run(); + var broadcast = BenchmarkRunner.Run(); } } } diff --git a/Projects/Server/Network/Packets/MessagePackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MessagePackets.cs similarity index 54% rename from Projects/Server/Network/Packets/MessagePackets.cs rename to Projects/Server.Tests/Tests/Network/Packets/Outgoing/MessagePackets.cs index ab896f8ae..dd7cd8c5d 100644 --- a/Projects/Server/Network/Packets/MessagePackets.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MessagePackets.cs @@ -1,36 +1,7 @@ -/************************************************************************* - * ModernUO * - * Copyright 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: MessagePackets.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; - namespace Server.Network { - [Flags] - public enum AffixType : byte - { - Append = 0x00, - Prepend = 0x01, - System = 0x02 - } - public sealed class MessageLocalized : Packet { - private static readonly MessageLocalized[] m_Cache_IntLoc = new MessageLocalized[15000]; - private static readonly MessageLocalized[] m_Cache_CliLoc = new MessageLocalized[100000]; - private static readonly MessageLocalized[] m_Cache_CliLocCmp = new MessageLocalized[5000]; - public MessageLocalized( Serial serial, int graphic, MessageType type, int hue, int font, int number, string name, string args ) : base(0xC1) @@ -54,56 +25,6 @@ namespace Server.Network Stream.WriteAsciiFixed(name, 30); Stream.WriteLittleUniNull(args); } - - public static MessageLocalized InstantiateGeneric(int number) - { - MessageLocalized[] cache = null; - var index = 0; - - if (number >= 3000000) - { - cache = m_Cache_IntLoc; - index = number - 3000000; - } - else if (number >= 1000000) - { - cache = m_Cache_CliLoc; - index = number - 1000000; - } - else if (number >= 500000) - { - cache = m_Cache_CliLocCmp; - index = number - 500000; - } - - MessageLocalized p; - - if (cache != null && index < cache.Length) - { - p = cache[index]; - - if (p == null) - { - cache[index] = p = new MessageLocalized( - Serial.MinusOne, - -1, - MessageType.Regular, - 0x3B2, - 3, - number, - "System", - "" - ); - p.SetStatic(); - } - } - else - { - p = new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, number, "System", ""); - } - - return p; - } } public sealed class MessageLocalizedAffix : Packet diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MessageTests.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MessageTests.cs index cb1cafa74..190a4aa53 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MessageTests.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MessageTests.cs @@ -19,7 +19,7 @@ namespace Server.Tests.Network var name = "Stuff"; var args = "Arguments"; - var data = new MessageLocalized( + var expected = new MessageLocalized( serial, graphic, messageType, @@ -30,21 +30,20 @@ namespace Server.Tests.Network args ).Compile(); - Span expectedData = stackalloc byte[50 + args.Length * 2]; - var pos = 0; - expectedData.Write(ref pos, (byte)0xC1); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMessageLocalized( + serial, + graphic, + messageType, + hue, + font, + number, + name, + args + ); - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)graphic); - expectedData.Write(ref pos, (byte)messageType); - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)font); - expectedData.Write(ref pos, number); - expectedData.WriteAsciiFixed(ref pos, name, 30); - expectedData.WriteLittleUniNull(ref pos, args); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -61,7 +60,7 @@ namespace Server.Tests.Network var affixType = AffixType.System; var affix = "Affix"; - var data = new MessageLocalizedAffix( + var expected = new MessageLocalizedAffix( serial, graphic, messageType, @@ -74,23 +73,22 @@ namespace Server.Tests.Network args ).Compile(); - Span expectedData = stackalloc byte[52 + affix.Length + args.Length * 2]; - var pos = 0; - expectedData.Write(ref pos, (byte)0xCC); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMessageLocalizedAffix( + serial, + graphic, + messageType, + hue, + font, + number, + name, + affixType, + affix, + args + ); - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)graphic); - expectedData.Write(ref pos, (byte)messageType); - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)font); - expectedData.Write(ref pos, number); - expectedData.Write(ref pos, (byte)affixType); - expectedData.WriteAsciiFixed(ref pos, name, 30); - expectedData.WriteAsciiNull(ref pos, affix); - expectedData.WriteBigUniNull(ref pos, args); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -104,7 +102,7 @@ namespace Server.Tests.Network var name = "Stuff"; var text = "Some Text"; - var data = new AsciiMessage( + var expected = new AsciiMessage( serial, graphic, messageType, @@ -114,20 +112,21 @@ namespace Server.Tests.Network text ).Compile(); - Span expectedData = stackalloc byte[45 + text.Length]; - var pos = 0; - expectedData.Write(ref pos, (byte)0x1C); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMessage( + serial, + graphic, + messageType, + hue, + font, + true, + null, + name, + text + ); - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)graphic); - expectedData.Write(ref pos, (byte)messageType); - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)font); - expectedData.WriteAsciiFixed(ref pos, name, 30); - expectedData.WriteAsciiNull(ref pos, text); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -142,7 +141,7 @@ namespace Server.Tests.Network var name = "Stuff"; var text = "Some Text"; - var data = new UnicodeMessage( + var expected = new UnicodeMessage( serial, graphic, messageType, @@ -153,21 +152,21 @@ namespace Server.Tests.Network text ).Compile(); - Span expectedData = stackalloc byte[50 + text.Length * 2]; - var pos = 0; - expectedData.Write(ref pos, (byte)0xAE); // Packet ID - expectedData.Write(ref pos, (ushort)expectedData.Length); // Length + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMessage( + serial, + graphic, + messageType, + hue, + font, + false, + lang, + name, + text + ); - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, (ushort)graphic); - expectedData.Write(ref pos, (byte)messageType); - expectedData.Write(ref pos, (ushort)hue); - expectedData.Write(ref pos, (ushort)font); - expectedData.WriteAsciiFixed(ref pos, lang, 4); - expectedData.WriteAsciiFixed(ref pos, name, 30); - expectedData.WriteBigUniNull(ref pos, text); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -176,16 +175,13 @@ namespace Server.Tests.Network Serial serial = 0x1; Serial serial2 = 0x2; - var data = new FollowMessage(serial, serial2).Compile(); + var expected = new FollowMessage(serial, serial2).Compile(); - Span expectedData = stackalloc byte[9]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendFollowMessage(serial, serial2); - expectedData.Write(ref pos, (byte)0x15); // Packet ID - expectedData.Write(ref pos, serial); - expectedData.Write(ref pos, serial2); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } } } diff --git a/Projects/Server/Items/Item.cs b/Projects/Server/Items/Item.cs index 950bfdf58..66f02ca66 100644 --- a/Projects/Server/Items/Item.cs +++ b/Projects/Server/Items/Item.cs @@ -2332,19 +2332,14 @@ namespace Server MoveToWorld(location, m_Map); } - public void LabelTo(Mobile to, int number) + public void LabelTo(Mobile to, int number, string args = "") { - to.Send(new MessageLocalized(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", "")); - } - - public void LabelTo(Mobile to, int number, string args) - { - to.Send(new MessageLocalized(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", args)); + to.NetState.SendMessageLocalized(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", args); } public void LabelTo(Mobile to, string text) { - to.Send(new UnicodeMessage(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, "ENU", "", text)); + to.NetState.SendMessage(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, false, "ENU", "", text); } public void LabelTo(Mobile to, string format, params object[] args) @@ -2352,14 +2347,9 @@ namespace Server LabelTo(to, string.Format(format, args)); } - public void LabelToAffix(Mobile to, int number, AffixType type, string affix) + public void LabelToAffix(Mobile to, int number, AffixType type, string affix, string args = "") { - to.Send(new MessageLocalizedAffix(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", type, affix, "")); - } - - public void LabelToAffix(Mobile to, int number, AffixType type, string affix, string args) - { - to.Send(new MessageLocalizedAffix(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", type, affix, args)); + to.NetState.SendMessageLocalizedAffix(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, number, "", type, affix, args); } public virtual void LabelLootTypeTo(Mobile to) @@ -3433,71 +3423,61 @@ namespace Server return; } - Packet p = null; var worldLoc = GetWorldLocation(); - var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); + var length = OutgoingMessagePackets.GetMaxMessageLength(text); + + Span buffer = stackalloc byte[length]; + length = OutgoingMessagePackets.CreateMessage( + ref buffer, + Serial, m_ItemID, type, hue, 3, ascii, "ENU", Name, text + ); + + buffer = buffer.Slice(0, length); // Adjust to the actual size + foreach (var state in eable) { var m = state.Mobile; if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) { - if (p == null) - { - if (ascii) - { - p = new AsciiMessage(Serial, m_ItemID, type, hue, 3, Name, text); - } - else - { - p = new UnicodeMessage(Serial, m_ItemID, type, hue, 3, "ENU", Name, text); - } - - p.Acquire(); - } - - state.Send(p); + state.Send(buffer); } } - Packet.Release(p); - eable.Free(); } - public void PublicOverheadMessage(MessageType type, int hue, int number) - { - PublicOverheadMessage(type, hue, number, ""); - } - - public void PublicOverheadMessage(MessageType type, int hue, int number, string args) + public void PublicOverheadMessage(MessageType type, int hue, int number, string args = "") { if (m_Map == null) { return; } - Packet p = null; var worldLoc = GetWorldLocation(); - var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)]; + + var length = OutgoingMessagePackets.CreateMessageLocalized( + ref buffer, + Serial, m_ItemID, type, hue, 3, number, Name, args + ); + + buffer = buffer.Slice(0, length); // Adjust to the actual size + foreach (var state in eable) { var m = state.Mobile; if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) { - p ??= Packet.Acquire(new MessageLocalized(Serial, m_ItemID, type, hue, 3, number, Name, args)); - - state.Send(p); + state.Send(buffer); } } - Packet.Release(p); - eable.Free(); } @@ -3994,24 +3974,14 @@ namespace Server public Point3D GetWorldTop() => RootParent?.Location ?? new Point3D(m_Location.m_X, m_Location.m_Y, m_Location.m_Z + ItemData.CalcHeight); - public void SendLocalizedMessageTo(Mobile to, int number) + public void SendLocalizedMessageTo(Mobile to, int number, string args = "") { if (Deleted || !to.CanSee(this)) { return; } - to.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", "")); - } - - public void SendLocalizedMessageTo(Mobile to, int number, string args) - { - if (Deleted || !to.CanSee(this)) - { - return; - } - - to.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", args)); + to.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", args); } public void SendLocalizedMessageTo(Mobile to, int number, AffixType affixType, string affix, string args) @@ -4021,19 +3991,17 @@ namespace Server return; } - to.Send( - new MessageLocalizedAffix( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - number, - "", - affixType, - affix, - args - ) + to.NetState.SendMessageLocalizedAffix( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + number, + "", + affixType, + affix, + args ); } @@ -4254,17 +4222,15 @@ namespace Server if (opl.Header > 0) { - from.Send( - new MessageLocalized( - Serial, - m_ItemID, - MessageType.Label, - 0x3B2, - 3, - opl.Header, - Name, - opl.HeaderArgs - ) + from.NetState.SendMessageLocalized( + Serial, + m_ItemID, + MessageType.Label, + 0x3B2, + 3, + opl.Header, + Name, + opl.HeaderArgs ); } } @@ -4292,39 +4258,35 @@ namespace Server { if (m_Amount <= 1) { - ns.Send(new MessageLocalized(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, LabelNumber, "", "")); + ns.SendMessageLocalized(Serial, m_ItemID, MessageType.Label, 0x3B2, 3, LabelNumber); } else { - ns.Send( - new MessageLocalizedAffix( - Serial, - m_ItemID, - MessageType.Label, - 0x3B2, - 3, - LabelNumber, - "", - AffixType.Append, - $" : {m_Amount}", - "" - ) - ); - } - } - else - { - ns.Send( - new UnicodeMessage( + ns.SendMessageLocalizedAffix( Serial, m_ItemID, MessageType.Label, 0x3B2, 3, - "ENU", + LabelNumber, "", - Name + (m_Amount > 1 ? $" : {m_Amount}" : "") - ) + AffixType.Append, + $" : {m_Amount}" + ); + } + } + else + { + ns.SendMessage( + Serial, + m_ItemID, + MessageType.Label, + 0x3B2, + 3, + false, + "ENU", + "", + $"{Name}{(m_Amount > 1 ? $" : {m_Amount}" : "")}" ); } } diff --git a/Projects/Server/Mobiles/Mobile.cs b/Projects/Server/Mobiles/Mobile.cs index 51f453389..0116bf67e 100644 --- a/Projects/Server/Mobiles/Mobile.cs +++ b/Projects/Server/Mobiles/Mobile.cs @@ -1434,7 +1434,7 @@ namespace Server m_Warmode = value; Delta(MobileDelta.Flags); - m_NetState?.SendSetWarMode(value); + m_NetState.SendSetWarMode(value); if (!m_Warmode) { @@ -3718,7 +3718,7 @@ namespace Server hue = Notoriety.GetHue(Notoriety.Compute(from, this)); } - from.Send(new MessageLocalized(Serial, Body, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs)); + from.NetState.SendMessageLocalized(Serial, Body, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs); } } @@ -6114,11 +6114,22 @@ namespace Server ProcessDelta(); - Packet regp = null; - Packet mutp = null; + Span regBuffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; + Span mutBuffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(mutatedText)]; + + var length = OutgoingMessagePackets.CreateMessage( + ref regBuffer, + Serial, Body, type, hue, 3, false, m_Language, Name, text + ); + regBuffer = regBuffer.Slice(0, length); // Adjust to the actual size + + length = OutgoingMessagePackets.CreateMessage( + ref mutBuffer, + Serial, Body, type, hue, 3, false, m_Language, Name, mutatedText + ); + mutBuffer = mutBuffer.Slice(0, length); // Adjust to the actual size // TODO: Should this be sorted like onSpeech is below? - for (var i = 0; i < hears.Count; ++i) { var heard = hears[i]; @@ -6126,36 +6137,15 @@ namespace Server if (mutatedArgs == null || !CheckHearsMutatedSpeech(heard, mutateContext)) { heard.OnSpeech(regArgs); - - var ns = heard.NetState; - - if (ns != null) - { - regp ??= Packet.Acquire(new UnicodeMessage(Serial, Body, type, hue, 3, m_Language, Name, text)); - - ns.Send(regp); - } + heard.NetState?.Send(regBuffer); } else { heard.OnSpeech(mutatedArgs); - - var ns = heard.NetState; - - if (ns != null) - { - mutp ??= Packet.Acquire( - new UnicodeMessage(Serial, Body, type, hue, 3, m_Language, Name, mutatedText) - ); - - ns.Send(mutp); - } + heard.NetState?.Send(mutBuffer); } } - Packet.Release(regp); - Packet.Release(mutp); - if (onSpeech.Count > 1) { onSpeech.Sort(LocationComparer.GetInstance(this)); @@ -6459,7 +6449,7 @@ namespace Server if (amount > 0) { - ourState?.SendDamage(Serial, amount); + ourState.SendDamage(Serial, amount); if (theirState != null && theirState != ourState) { @@ -6534,7 +6524,7 @@ namespace Server { if (damaged.CanSeeVisibleDamage) { - ourState?.SendDamage(Serial, amount); + ourState.SendDamage(Serial, amount); } if (theirState != null && theirState != ourState && damager.CanSeeVisibleDamage) @@ -6569,19 +6559,16 @@ namespace Server if (message && amount > 0) { - m_NetState?.Send( - new MessageLocalizedAffix( - Serial.MinusOne, - -1, - MessageType.Label, - 0x3B2, - 3, - 1008158, - "", - AffixType.Append | AffixType.System, - amount.ToString(), - "" - ) + m_NetState.SendMessageLocalizedAffix( + Serial.MinusOne, + -1, + MessageType.Label, + 0x3B2, + 3, + 1008158, + "", + AffixType.Append | AffixType.System, + amount.ToString() ); } } @@ -7291,13 +7278,13 @@ namespace Server [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SendSound(int soundID) { - m_NetState?.SendSoundEffect(soundID, this); + m_NetState.SendSoundEffect(soundID, this); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void SendSound(int soundID, IPoint3D p) { - m_NetState?.SendSoundEffect(soundID, p); + m_NetState.SendSoundEffect(soundID, p); } /** @@ -8769,11 +8756,8 @@ namespace Server public void SayTo(Mobile to, bool ascii, string format, params object[] args) => SayTo(to, ascii, string.Format(format, args)); - public void SayTo(Mobile to, int number) => - to.Send(new MessageLocalized(Serial, Body, MessageType.Regular, SpeechHue, 3, number, Name, "")); - - public void SayTo(Mobile to, int number, string args) => - to.Send(new MessageLocalized(Serial, Body, MessageType.Regular, SpeechHue, 3, number, Name, args)); + public void SayTo(Mobile to, int number, string args = "") => + to.NetState.SendMessageLocalized(Serial, Body, MessageType.Regular, SpeechHue, 3, number, Name, args); public void Say(bool ascii, string text) => PublicOverheadMessage(MessageType.Regular, SpeechHue, ascii, text); @@ -9578,15 +9562,7 @@ namespace Server public Direction GetDirectionTo(Point2D p) => GetDirectionTo(p.m_X, p.m_Y); public Direction GetDirectionTo(Point3D p) => GetDirectionTo(p.m_X, p.m_Y); - public Direction GetDirectionTo(IPoint2D p) - { - if (p == null) - { - return Direction.North; - } - - return GetDirectionTo(p.X, p.Y); - } + public Direction GetDirectionTo(IPoint2D p) => p == null ? Direction.North : GetDirectionTo(p.X, p.Y); public void PublicOverheadMessage(MessageType type, int hue, bool ascii, string text, bool noLineOfSight = true) { @@ -9595,11 +9571,15 @@ namespace Server return; } - var p = ascii - ? (Packet)new AsciiMessage(Serial, Body, type, hue, 3, Name, text) - : new UnicodeMessage(Serial, Body, type, hue, 3, m_Language, Name, text); + var length = OutgoingMessagePackets.GetMaxMessageLength(text); - p.Acquire(); + Span buffer = stackalloc byte[length]; + length = OutgoingMessagePackets.CreateMessage( + ref buffer, + Serial, Body, type, hue, 3, ascii, Language, Name, text + ); + + buffer = buffer.Slice(0, length); // Adjust to the actual size var eable = m_Map.GetClientsInRange(m_Location); @@ -9607,12 +9587,10 @@ namespace Server { if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this))) { - state.Send(p); + state.Send(buffer); } } - Packet.Release(p); - eable.Free(); } @@ -9623,7 +9601,13 @@ namespace Server return; } - var p = Packet.Acquire(new MessageLocalized(Serial, Body, type, hue, 3, number, Name, args)); + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)]; + + var length = OutgoingMessagePackets.CreateMessageLocalized( + ref buffer, + Serial, Body, type, hue, 3, number, Name, args + ); + buffer = buffer.Slice(0, length); // Adjust to the actual size var eable = m_Map.GetClientsInRange(m_Location); @@ -9631,12 +9615,10 @@ namespace Server { if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this))) { - state.Send(p); + state.Send(buffer); } } - Packet.Release(p); - eable.Free(); } @@ -9650,20 +9632,13 @@ namespace Server return; } - var p = Packet.Acquire( - new MessageLocalizedAffix( - Serial, - Body, - type, - hue, - 3, - number, - Name, - affixType, - affix, - args - ) + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(affix, args)]; + + var length = OutgoingMessagePackets.CreateMessageLocalizedAffix( + ref buffer, + Serial, Body, type, hue, 3, number, Name, affixType, affix, args ); + buffer = buffer.Slice(0, length); // Adjust to the actual size var eable = m_Map.GetClientsInRange(m_Location); @@ -9671,59 +9646,29 @@ namespace Server { if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this))) { - state.Send(p); + state.Send(buffer); } } - Packet.Release(p); - eable.Free(); } public void PrivateOverheadMessage(MessageType type, int hue, bool ascii, string text, NetState state) { - if (state == null) - { - return; - } - - if (ascii) - { - state.Send(new AsciiMessage(Serial, Body, type, hue, 3, Name, text)); - } - else - { - state.Send(new UnicodeMessage(Serial, Body, type, hue, 3, m_Language, Name, text)); - } + state.SendMessage(Serial, Body, type, hue, 3, ascii, m_Language, Name, text); } public void PrivateOverheadMessage(MessageType type, int hue, int number, NetState state) => PrivateOverheadMessage(type, hue, number, "", state); public void PrivateOverheadMessage(MessageType type, int hue, int number, string args, NetState state) => - state?.Send(new MessageLocalized(Serial, Body, type, hue, 3, number, Name, args)); + state.SendMessageLocalized(Serial, Body, type, hue, 3, number, Name, args); - public void LocalOverheadMessage(MessageType type, int hue, bool ascii, string text) - { - var ns = m_NetState; - - if (ns == null) - { - return; - } - - if (ascii) - { - ns.Send(new AsciiMessage(Serial, Body, type, hue, 3, Name, text)); - } - else - { - ns.Send(new UnicodeMessage(Serial, Body, type, hue, 3, m_Language, Name, text)); - } - } + public void LocalOverheadMessage(MessageType type, int hue, bool ascii, string text) => + m_NetState.SendMessage(Serial, Body, type, hue, 3, ascii, m_Language, Name, text); public void LocalOverheadMessage(MessageType type, int hue, int number, string args = "") => - m_NetState?.Send(new MessageLocalized(Serial, Body, type, hue, 3, number, Name, args)); + m_NetState.SendMessageLocalized(Serial, Body, type, hue, 3, number, Name, args); public void NonlocalOverheadMessage(MessageType type, int hue, int number, string args = "") { @@ -9732,7 +9677,13 @@ namespace Server return; } - var p = Packet.Acquire(new MessageLocalized(Serial, Body, type, hue, 3, number, Name, args)); + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)]; + + var length = OutgoingMessagePackets.CreateMessageLocalized( + ref buffer, + Serial, Body, type, hue, 3, number, Name, args + ); + buffer = buffer.Slice(0, length); // Adjust to the actual size var eable = m_Map.GetClientsInRange(m_Location); @@ -9740,12 +9691,10 @@ namespace Server { if (state != m_NetState && state.Mobile.CanSee(this)) { - state.Send(p); + state.Send(buffer); } } - Packet.Release(p); - eable.Free(); } @@ -9756,11 +9705,15 @@ namespace Server return; } - var p = ascii - ? (Packet)new AsciiMessage(Serial, Body, type, hue, 3, Name, text) - : new UnicodeMessage(Serial, Body, type, hue, 3, Language, Name, text); + var length = OutgoingMessagePackets.GetMaxMessageLength(text); - p.Acquire(); + Span buffer = stackalloc byte[length]; + length = OutgoingMessagePackets.CreateMessage( + ref buffer, + Serial, Body, type, hue, 3, ascii, Language, Name, text + ); + + buffer = buffer.Slice(0, length); // Adjust to the actual size var eable = m_Map.GetClientsInRange(m_Location); @@ -9768,45 +9721,28 @@ namespace Server { if (state != m_NetState && state.Mobile.CanSee(this)) { - state.Send(p); + state.Send(buffer); } } - Packet.Release(p); - eable.Free(); } - public void SendLocalizedMessage(int number) => m_NetState?.Send(MessageLocalized.InstantiateGeneric(number)); - - public void SendLocalizedMessage(int number, string args, int hue = 0x3B2) - { - if (hue == 0x3B2 && string.IsNullOrEmpty(args)) - { - m_NetState?.Send(MessageLocalized.InstantiateGeneric(number)); - } - else - { - m_NetState?.Send( - new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args) - ); - } - } + public void SendLocalizedMessage(int number, string args = "", int hue = 0x3B2) => + m_NetState.SendMessageLocalized(Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args); public void SendLocalizedMessage(int number, bool append, string affix, string args = "", int hue = 0x3B2) => - m_NetState?.Send( - new MessageLocalizedAffix( - Serial.MinusOne, - -1, - MessageType.Regular, - hue, - 3, - number, - "System", - (append ? AffixType.Append : AffixType.Prepend) | AffixType.System, - affix, - args - ) + m_NetState.SendMessageLocalizedAffix( + Serial.MinusOne, + -1, + MessageType.Regular, + hue, + 3, + number, + "System", + (append ? AffixType.Append : AffixType.Prepend) | AffixType.System, + affix, + args ); public void SendMessage(string text) => SendMessage(0x3B2, text); @@ -9815,7 +9751,7 @@ namespace Server SendMessage(0x3B2, string.Format(format, args)); public void SendMessage(int hue, string text) => - m_NetState?.Send(new UnicodeMessage(Serial.MinusOne, -1, MessageType.Regular, hue, 3, "ENU", "System", text)); + m_NetState.SendMessage(Serial.MinusOne, -1, MessageType.Regular, hue, 3, false, "ENU", "System", text); public void SendMessage(int hue, string format, params object[] args) => SendMessage(hue, string.Format(format, args)); @@ -9826,7 +9762,7 @@ namespace Server SendAsciiMessage(0x3B2, string.Format(format, args)); public void SendAsciiMessage(int hue, string text) => - m_NetState?.Send(new AsciiMessage(Serial.MinusOne, -1, MessageType.Regular, hue, 3, "System", text)); + m_NetState.SendMessage(Serial.MinusOne, -1, MessageType.Regular, hue, 3, true, null, "System", text); public void SendAsciiMessage(int hue, string format, params object[] args) => SendAsciiMessage(hue, string.Format(format, args)); diff --git a/Projects/Server/Network/NetState/NetState.cs b/Projects/Server/Network/NetState/NetState.cs index 0fefc26e1..7684de8c8 100644 --- a/Projects/Server/Network/NetState/NetState.cs +++ b/Projects/Server/Network/NetState/NetState.cs @@ -353,7 +353,7 @@ namespace Server.Network public void LaunchBrowser(string url) { - Send(new MessageLocalized(Serial.MinusOne, -1, MessageType.Label, 0x35, 3, 501231, "", "")); + this.SendMessageLocalized(Serial.MinusOne, -1, MessageType.Label, 0x35, 3, 501231); Send(new LaunchBrowser(url)); } diff --git a/Projects/Server/Network/PacketUtilities.cs b/Projects/Server/Network/PacketUtilities.cs index 0fda88dce..65d3e4301 100644 --- a/Projects/Server/Network/PacketUtilities.cs +++ b/Projects/Server/Network/PacketUtilities.cs @@ -15,11 +15,13 @@ using System.Buffers; using System.IO; +using System.Runtime.CompilerServices; namespace Server.Network { public static class PacketUtilities { + [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void WritePacketLength(this CircularBufferWriter writer) { var length = writer.Position; @@ -27,5 +29,14 @@ namespace Server.Network writer.Write((ushort)length); writer.Seek(length, SeekOrigin.Begin); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WritePacketLength(this SpanWriter writer) + { + var length = writer.Position; + writer.Seek(1, SeekOrigin.Begin); + writer.Write((ushort)length); + writer.Seek(length, SeekOrigin.Begin); + } } } diff --git a/Projects/Server/Network/Packets/OutgoingEffectPackets.cs b/Projects/Server/Network/Packets/OutgoingEffectPackets.cs index e54554b78..4765e3d9b 100644 --- a/Projects/Server/Network/Packets/OutgoingEffectPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingEffectPackets.cs @@ -25,6 +25,19 @@ namespace Server.Network public const int HuedEffectLength = 36; public const int BoltEffectLength = 36; + public static void SendSoundEffect(this NetState ns, int soundID, IPoint3D target) + { + if (ns == null) + { + return; + } + + Span buffer = stackalloc byte[SoundPacketLength]; + CreateSoundEffect(ref buffer, soundID, target); + + ns.Send(buffer); + } + public static void CreateSoundEffect(ref Span buffer, int soundID, IPoint3D target) { var writer = new SpanWriter(buffer); @@ -37,25 +50,6 @@ namespace Server.Network writer.Write((short)target.Z); } - public static void SendSoundEffect(this NetState ns, int soundID, IPoint3D target) - { - if (ns == null || !ns.GetSendBuffer(out var buffer)) - { - return; - } - - var writer = new CircularBufferWriter(buffer); - writer.Write((byte)0x54); // Packet ID - writer.Write((byte)1); // flags - writer.Write((short)soundID); - writer.Write((short)0); // volume - writer.Write((short)target.X); - writer.Write((short)target.Y); - writer.Write((short)target.Z); - - ns.Send(ref buffer, writer.Position); - } - public static void CreateParticleEffect( ref Span buffer, EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint, diff --git a/Projects/Server/Network/Packets/OutgoingEquipmentPackets.cs b/Projects/Server/Network/Packets/OutgoingEquipmentPackets.cs index 0a73bd30c..119cd4b43 100644 --- a/Projects/Server/Network/Packets/OutgoingEquipmentPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingEquipmentPackets.cs @@ -36,11 +36,7 @@ namespace Server.Network { public static void SendDisplayEquipmentInfo( this NetState ns, - Serial serial, - int number, - string crafterName, - bool unidentified, - List attrs + Serial serial, int number, string crafterName, bool unidentified, List attrs ) { if (ns == null || !ns.GetSendBuffer(out var buffer)) diff --git a/Projects/Server/Network/Packets/OutgoingMenuPackets.cs b/Projects/Server/Network/Packets/OutgoingMenuPackets.cs index 0b02f44c8..2f5969c63 100644 --- a/Projects/Server/Network/Packets/OutgoingMenuPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingMenuPackets.cs @@ -72,11 +72,9 @@ namespace Server.Network } } - var length = writer.Position; - writer.Seek(1, SeekOrigin.Begin); - writer.Write((ushort)length); + writer.WritePacketLength(); - ns.Send(ref buffer, length); + ns.Send(ref buffer, writer.Position); } public static void SendDisplayQuestionMenu(this NetState ns, QuestionMenu menu) @@ -129,11 +127,9 @@ namespace Server.Network } } - var length = writer.Position; - writer.Seek(1, SeekOrigin.Begin); - writer.Write((ushort)length); + writer.WritePacketLength(); - ns.Send(ref buffer, length); + ns.Send(ref buffer, writer.Position); } public static void SendDisplayContextMenu(this NetState ns, ContextMenu menu) @@ -209,11 +205,9 @@ namespace Server.Network } } - var length = writer.Position; - writer.Seek(1, SeekOrigin.Begin); - writer.Write((ushort)length); + writer.WritePacketLength(); - ns.Send(ref buffer, length); + ns.Send(ref buffer, writer.Position); } } } diff --git a/Projects/Server/Network/Packets/OutgoingMessagePackets.cs b/Projects/Server/Network/Packets/OutgoingMessagePackets.cs new file mode 100644 index 000000000..692cc0578 --- /dev/null +++ b/Projects/Server/Network/Packets/OutgoingMessagePackets.cs @@ -0,0 +1,235 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2020 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: OutgoingMessagePackets.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; +using System.Buffers; +using System.IO; +using System.Linq; +using System.Runtime.CompilerServices; + +namespace Server.Network +{ + [Flags] + public enum AffixType : byte + { + Append = 0x00, + Prepend = 0x01, + System = 0x02 + } + + public static class OutgoingMessagePackets + { + public static void SendMessageLocalized( + this NetState ns, + Serial serial, int graphic, MessageType type, int hue, int font, int number, string name = "", string args = "" + ) + { + if (ns == null) + { + return; + } + + Span buffer = stackalloc byte[GetMaxMessageLocalizedLength(args)]; + var length = CreateMessageLocalized( + ref buffer, + serial, graphic, type, hue, font, number, name, args + ); + + ns.Send(buffer.Slice(0, length)); + } + + public static int GetMaxMessageLocalizedLength(string args) => 50 + (args?.Length ?? 0) * 2; + + public static int CreateMessageLocalized( + ref Span buffer, + Serial serial, int graphic, MessageType type, int hue, int font, int number, string name = "", string args = "" + ) + { + name = name?.Trim() ?? ""; + args = args?.Trim() ?? ""; + + if (hue == 0) + { + hue = 0x3B2; + } + + var writer = new SpanWriter(buffer); + writer.Write((byte)0xC1); + writer.Seek(2, SeekOrigin.Current); + writer.Write(serial); + writer.Write((short)graphic); + writer.Write((byte)type); + writer.Write((short)hue); + writer.Write((short)font); + writer.Write(number); + writer.WriteAscii(name, 30); + writer.WriteLittleUniNull(args); + + writer.WritePacketLength(); + + return writer.Position; + } + + public static void SendMessageLocalizedAffix( + this NetState ns, + Serial serial, int graphic, MessageType type, int hue, int font, int number, string name, + AffixType affixType, string affix = "", string args = "" + ) + { + if (ns == null) + { + return; + } + + Span buffer = stackalloc byte[GetMaxMessageLocalizedAffixLength(affix, args)]; + var length = CreateMessageLocalizedAffix( + ref buffer, + serial, graphic, type, hue, font, number, name, affixType, affix, args + ); + + ns.Send(buffer.Slice(0, length)); + } + + public static int GetMaxMessageLocalizedAffixLength(string affix, string args) => + 52 + (affix?.Length ?? 0) + (args?.Length ?? 0) * 2; + + public static int CreateMessageLocalizedAffix( + ref Span buffer, + Serial serial, int graphic, MessageType type, int hue, int font, int number, string name, + AffixType affixType, string affix = "", string args = "" + ) + { + name = name?.Trim() ?? ""; + affix = affix?.Trim() ?? ""; + args = args?.Trim() ?? ""; + + if (hue == 0) + { + hue = 0x3B2; + } + + var writer = new SpanWriter(buffer); + writer.Write((byte)0xCC); + writer.Seek(2, SeekOrigin.Current); + writer.Write(serial); + writer.Write((short)graphic); + writer.Write((byte)type); + writer.Write((short)hue); + writer.Write((short)font); + writer.Write(number); + writer.Write((byte)affixType); + writer.WriteAscii(name, 30); + writer.WriteAsciiNull(affix); + writer.WriteBigUniNull(args); + + writer.WritePacketLength(); + + return writer.Position; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void SendMessage( + this NetState ns, + Serial serial, int graphic, MessageType type, int hue, int font, bool ascii, string lang, string name, string text + ) + { + if (ns == null) + { + return; + } + + Span buffer = stackalloc byte[GetMaxMessageLength(text)]; + var length = CreateMessage( + ref buffer, + serial, + graphic, + type, + hue, + font, + ascii, + lang, + name, + text + ); + + ns.Send(buffer.Slice(0, length)); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetMaxMessageLength(string text) => 50 + (text?.Length ?? 0) * 2; + + public static int CreateMessage( + ref Span buffer, + Serial serial, + int graphic, + MessageType type, + int hue, + int font, + bool ascii, + string lang, + string name, + string text + ) + { + name = name?.Trim() ?? ""; + text = text?.Trim() ?? ""; + lang = lang?.Trim() ?? "ENU"; + + if (hue == 0) + { + hue = 0x3B2; + } + + var writer = new SpanWriter(buffer); + writer.Write((byte)(ascii ? 0x1C : 0xAE)); // Packet ID + writer.Seek(2, SeekOrigin.Current); + writer.Write(serial); + writer.Write((short)graphic); + writer.Write((byte)type); + writer.Write((short)hue); + writer.Write((short)font); + if (ascii) + { + writer.WriteAscii(name, 30); + writer.WriteAsciiNull(text); + } + else + { + writer.WriteAscii(lang, 4); + writer.WriteAscii(name, 30); + writer.WriteBigUniNull(text); + } + + writer.WritePacketLength(); + + return writer.Position; + } + + public static void SendFollowMessage(this NetState ns, Serial s1, Serial s2) + { + if (ns == null || !ns.GetSendBuffer(out var buffer)) + { + return; + } + + var writer = new CircularBufferWriter(buffer); + writer.Write((byte)0x15); // Packet ID + writer.Write(s1); + writer.Write(s2); + + ns.Send(ref buffer, 9); + } + } +} diff --git a/Projects/Server/World/World.cs b/Projects/Server/World/World.cs index f7b3012ed..708b8fc5a 100644 --- a/Projects/Server/World/World.cs +++ b/Projects/Server/World/World.cs @@ -152,28 +152,23 @@ namespace Server public static void Broadcast(int hue, bool ascii, string text) { - Packet p; + var length = OutgoingMessagePackets.GetMaxMessageLength(text); - if (ascii) - { - p = new AsciiMessage(Serial.MinusOne, -1, MessageType.Regular, hue, 3, "System", text); - } - else - { - p = new UnicodeMessage(Serial.MinusOne, -1, MessageType.Regular, hue, 3, "ENU", "System", text); - } + Span buffer = stackalloc byte[length]; + length = OutgoingMessagePackets.CreateMessage( + ref buffer, + Serial.MinusOne, -1, MessageType.Regular, hue, 3, ascii, "ENU", "System", text + ); - p.Acquire(); + buffer = buffer.Slice(0, length); // Adjust to the actual size foreach (var ns in TcpServer.Instances) { if (ns.Mobile != null) { - ns.Send(p); + ns.Send(buffer); } } - - p.Release(); } public static void Broadcast(int hue, bool ascii, string format, params object[] args) diff --git a/Projects/UOContent/Engines/ConPVP/Games/CTF.cs b/Projects/UOContent/Engines/ConPVP/Games/CTF.cs index 49a78f60a..e9410a79e 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/CTF.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/CTF.cs @@ -291,17 +291,16 @@ namespace Server.Engines.ConPVP { if (Location == m_TeamInfo.Origin && Map == m_TeamInfo.Game.Facet) { - from.Send( - new UnicodeMessage( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - "ENU", - Name, - "Touch me not for I am chaste." - ) + from.NetState.SendMessage( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + false, + "ENU", + Name, + "Touch me not for I am chaste." ); } else diff --git a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs index b3f2fa69c..6f6de1a20 100644 --- a/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs +++ b/Projects/UOContent/Engines/Doom/LeverPuzzle/LeverPuzzleController.cs @@ -487,38 +487,47 @@ namespace Server.Engines.Doom public static void PlayerSendASCII(Mobile player, int index) { - player.Send( - new AsciiMessage( - Serial.MinusOne, - 0xFFFF, - MessageType.Label, - MsgParams[index][0], - MsgParams[index][1], - null, - Msgs[index] - ) + player.NetState.SendMessage( + Serial.MinusOne, + 0xFFFF, + MessageType.Label, + MsgParams[index][0], + MsgParams[index][1], + true, + null, + null, + Msgs[index] ); } /* I cant find any better way to send "speech" using fonts other than default */ public static void POHMessage(Mobile from, int index) { - Packet p = new AsciiMessage( + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(Msgs[index])]; + + var length = OutgoingMessagePackets.CreateMessage( + ref buffer, from.Serial, from.Body, MessageType.Regular, MsgParams[index][0], MsgParams[index][1], + true, + null, from.Name, Msgs[index] ); - p.Acquire(); - foreach (var state in from.Map.GetClientsInRange(from.Location)) + + buffer = buffer.Slice(0, length); // Adjust to the actual size + + var eable = from.Map.GetClientsInRange(from.Location); + + foreach (var state in eable) { - state.Send(p); + state.Send(buffer); } - Packet.Release(p); + eable.Free(); } public override void Serialize(IGenericWriter writer) diff --git a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs index 7d2ff0f9e..0d4b2c107 100644 --- a/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs +++ b/Projects/UOContent/Engines/Factions/Items/Traps/BaseFactionTrap.cs @@ -192,9 +192,7 @@ namespace Server.Factions public void PrivateOverheadLocalizedMessage(Mobile to, int number, int hue, string name, string args) { - var ns = to?.NetState; - - ns?.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, name, args)); + to?.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, name, args); } public virtual bool CheckDecay() diff --git a/Projects/UOContent/Engines/MLQuests/Mobiles/SirHelper.cs b/Projects/UOContent/Engines/MLQuests/Mobiles/SirHelper.cs index 518f5a71a..08b164330 100644 --- a/Projects/UOContent/Engines/MLQuests/Mobiles/SirHelper.cs +++ b/Projects/UOContent/Engines/MLQuests/Mobiles/SirHelper.cs @@ -90,37 +90,35 @@ namespace Server.Engines.MLQuests.Mobiles { base.OnThink(); - if (m_NextShout <= DateTime.UtcNow) + if (m_NextShout > DateTime.UtcNow) { - Packet shoutPacket = null; - - foreach (var state in GetClientsInRange(12)) - { - var m = state.Mobile; - - if (m.CanSee(this) && m.InLOS(this) && m.CanBeginAction(this)) - { - shoutPacket ??= Packet.Acquire( - new MessageLocalized( - Serial, - Body, - MessageType.Regular, - 946, - 3, - 1078099, - Name, - "" - ) - ); // Double Click On Me For Help! - - state.Send(shoutPacket); - } - } - - Packet.Release(shoutPacket); - - m_NextShout = DateTime.UtcNow + m_ShoutDelay; + return; } + + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength("")]; + var packetCreated = false; + + foreach (var state in GetClientsInRange(12)) + { + var m = state.Mobile; + + if (m.CanSee(this) && m.InLOS(this) && m.CanBeginAction(this)) + { + if (!packetCreated) + { + // Double Click On Me For Help! + var length = OutgoingMessagePackets.CreateMessageLocalized( + ref buffer, + Serial, Body, MessageType.Regular, 946, 3, 1078099, Name + ); + packetCreated = true; + } + + state.Send(buffer); + } + } + + m_NextShout = DateTime.UtcNow + m_ShoutDelay; } private void EndLock(Mobile m) diff --git a/Projects/UOContent/Engines/Party/Party.cs b/Projects/UOContent/Engines/Party/Party.cs index 861d37847..45efc269e 100644 --- a/Projects/UOContent/Engines/Party/Party.cs +++ b/Projects/UOContent/Engines/Party/Party.cs @@ -239,22 +239,25 @@ namespace Server.Engines.PartySystem return; } - // : joined the party. - SendToAll( - new MessageLocalizedAffix( - Serial.MinusOne, - -1, - MessageType.Label, - 0x3B2, - 3, - 1008094, - "", - AffixType.Prepend | AffixType.System, - from.Name, - "" - ) + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(from.Name, "")]; + var length = OutgoingMessagePackets.CreateMessageLocalizedAffix( + ref buffer, + Serial.MinusOne, + -1, + MessageType.Label, + 0x3B2, + 3, + 1008094, + "", + AffixType.Prepend | AffixType.System, + from.Name ); + buffer = buffer.Slice(0, length); // Adjust to the actual size + + // : joined the party. + SendToAll(ref buffer, true); + from.SendLocalizedMessage(1005445); // You have been added to the party. Candidates.Remove(from); @@ -288,32 +291,31 @@ namespace Server.Engines.PartySystem if (m == Leader) { Disband(); + return; } - else + + for (var i = 0; i < Members.Count; ++i) { - for (var i = 0; i < Members.Count; ++i) + if (Members[i].Mobile == m) { - if (Members[i].Mobile == m) - { - Members.RemoveAt(i); + Members.RemoveAt(i); - m.Party = null; - m.Send(new PartyEmptyList(m)); + m.Party = null; + m.Send(new PartyEmptyList(m)); - m.SendLocalizedMessage(1005451); // You have been removed from the party. + m.SendLocalizedMessage(1005451); // You have been removed from the party. - SendToAll(new PartyRemoveMember(m, this)); - SendToAll(1005452); // A player has been removed from your party. + SendToAll(new PartyRemoveMember(m, this)); + SendToAll(1005452); // A player has been removed from your party. - break; - } + break; } + } - if (Members.Count == 1) - { - SendToAll(1005450); // The last person has left the party... - Disband(); - } + if (Members.Count == 1) + { + SendToAll(1005450); // The last person has left the party... + Disband(); } } @@ -357,19 +359,16 @@ namespace Server.Engines.PartySystem } // : You are invited to join the party. Type /accept to join or /decline to decline the offer. - target.Send( - new MessageLocalizedAffix( - Serial.MinusOne, - -1, - MessageType.Label, - 0x3B2, - 3, - 1008089, - "", - AffixType.Prepend | AffixType.System, - from.Name, - "" - ) + target.NetState.SendMessageLocalizedAffix( + Serial.MinusOne, + -1, + MessageType.Label, + 0x3B2, + 3, + 1008089, + "", + AffixType.Prepend | AffixType.System, + from.Name ); from.SendLocalizedMessage(1008090); // You have invited them to join the party. @@ -380,19 +379,17 @@ namespace Server.Engines.PartySystem DeclineTimer.Start(target, from); } - public void SendToAll(int number) + public void SendToAll(int number, string args = "", int hue = 0x3B2) { - SendToAll(number, "", 0x3B2); - } + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)]; + var length = OutgoingMessagePackets.CreateMessageLocalized( + ref buffer, + Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args + ); - public void SendToAll(int number, string args) - { - SendToAll(number, args, 0x3B2); - } + buffer = buffer.Slice(0, length); // Adjust to the actual size - public void SendToAll(int number, string args, int hue) - { - SendToAll(new MessageLocalized(Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args)); + SendToAll(ref buffer, true); } public void SendPublicMessage(Mobile from, string text) @@ -431,7 +428,20 @@ namespace Server.Engines.PartySystem private void SendToStaffMessage(Mobile from, string text) { - Packet p = null; + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; + var length = OutgoingMessagePackets.CreateMessage( + ref buffer, + from.Serial, + from.Body, + MessageType.Regular, + from.SpeechHue, + 3, + false, + from.Language, + from.Name, + text + ); + buffer = buffer.Slice(0, length); // Adjust to the actual size foreach (var ns in from.GetClientsInRange(8)) { @@ -440,27 +450,9 @@ namespace Server.Engines.PartySystem if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel && mob.Party != this && !m_Listeners.Contains(mob)) { - if (p == null) - { - p = Packet.Acquire( - new UnicodeMessage( - from.Serial, - from.Body, - MessageType.Regular, - from.SpeechHue, - 3, - from.Language, - from.Name, - text - ) - ); - } - - ns.Send(p); + ns.Send(buffer); } } - - Packet.Release(p); } private void SendToStaffMessage(Mobile from, string format, params object[] args) @@ -477,7 +469,17 @@ namespace Server.Engines.PartySystem Members[i].Mobile.Send(p); } - if (p is MessageLocalized || p is MessageLocalizedAffix || p is UnicodeMessage || p is AsciiMessage) + p.Release(); + } + + public void SendToAll(ref Span span, bool isSpeech) + { + for (var i = 0; i < Members.Count; ++i) + { + Members[i].Mobile.NetState?.Send(span); + } + + if (isSpeech) { for (var i = 0; i < m_Listeners.Count; ++i) { @@ -485,12 +487,10 @@ namespace Server.Engines.PartySystem if (mob.Party != this) { - mob.Send(p); + mob.NetState?.Send(span); } } } - - p.Release(); } private class RejoinTimer : Timer @@ -511,20 +511,22 @@ namespace Server.Engines.PartySystem m_Mobile.SendLocalizedMessage(1005437); // You have rejoined the party. m_Mobile.Send(new PartyMemberList(p)); - var message = Packet.Acquire( - new MessageLocalizedAffix( - Serial.MinusOne, - -1, - MessageType.Label, - 0x3B2, - 3, - 1008087, - "", - AffixType.Prepend | AffixType.System, - m_Mobile.Name, - "" - ) + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(m_Mobile.Name, "")]; + var length = OutgoingMessagePackets.CreateMessageLocalizedAffix( + ref buffer, + Serial.MinusOne, + -1, + MessageType.Label, + 0x3B2, + 3, + 1008087, + "", + AffixType.Prepend | AffixType.System, + m_Mobile.Name ); + + buffer = buffer.Slice(0, length); // Adjust to the actual size + var attrs = Packet.Acquire(new MobileAttributesN(m_Mobile)); foreach (var mi in p.Members) @@ -533,7 +535,7 @@ namespace Server.Engines.PartySystem if (m != m_Mobile) { - m.Send(message); + m.NetState?.Send(buffer); m.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile)); m.Send(attrs); m_Mobile.Send(new MobileStatusCompact(m.CanBeRenamedBy(m_Mobile), m)); @@ -541,7 +543,6 @@ namespace Server.Engines.PartySystem } } - Packet.Release(message); Packet.Release(attrs); } } diff --git a/Projects/UOContent/Engines/Quests/Collector/Items/Obsidian.cs b/Projects/UOContent/Engines/Quests/Collector/Items/Obsidian.cs index 7e40799a8..c59401bf6 100644 --- a/Projects/UOContent/Engines/Quests/Collector/Items/Obsidian.cs +++ b/Projects/UOContent/Engines/Quests/Collector/Items/Obsidian.cs @@ -189,17 +189,13 @@ namespace Server.Engines.Quests.Collector { if (!IsChildOf(from.Backpack)) { - from.Send( - new MessageLocalized( - Serial, - ItemID, - MessageType.Regular, - 0x2C, - 3, - 500309, - "", - "" - ) + from.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Regular, + 0x2C, + 3, + 500309 ); // Nothing Happens. } else @@ -286,33 +282,30 @@ namespace Server.Engines.Quests.Collector targObsidian.StatueName = RandomName(from); } - from.Send( - new AsciiMessage( - targObsidian.Serial, - targObsidian.ItemID, - MessageType.Regular, - 0x59, - 3, - m_Obsidian.Name, - "Something Happened." - ) + from.NetState.SendMessage( + targObsidian.Serial, + targObsidian.ItemID, + MessageType.Regular, + 0x59, + 3, + true, + null, + m_Obsidian.Name, + "Something Happened." ); return; } } - from.Send( - new MessageLocalized( - m_Obsidian.Serial, - m_Obsidian.ItemID, - MessageType.Regular, - 0x2C, - 3, - 500309, - m_Obsidian.Name, - "" - ) + from.NetState.SendMessageLocalized( + m_Obsidian.Serial, + m_Obsidian.ItemID, + MessageType.Regular, + 0x2C, + 3, + 500309, + m_Obsidian.Name ); // Nothing Happens. } } diff --git a/Projects/UOContent/Engines/Quests/Core/Items/EnchantedSextant.cs b/Projects/UOContent/Engines/Quests/Core/Items/EnchantedSextant.cs index dfc9138da..139b18fcf 100644 --- a/Projects/UOContent/Engines/Quests/Core/Items/EnchantedSextant.cs +++ b/Projects/UOContent/Engines/Quests/Core/Items/EnchantedSextant.cs @@ -102,18 +102,15 @@ namespace Server.Items banks = m_IlshenarBanks; moongates = PMList.Ilshenar; #else - from.Send( - new MessageLocalized( - Serial, - ItemID, - MessageType.Label, - 0x482, - 3, - 1061684, - "", - "" - ) + from.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Label, + 0x482, + 3, + 1061684 ); // The magic of the sextant fails... + return; #endif } @@ -176,7 +173,7 @@ namespace Server.Items moonMsg = 1048018; // You are next to a Moongate at the moment. } - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x482, 3, moonMsg, "", "")); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Label, 0x482, 3, moonMsg); int bankMsg; if (bankDistance == double.MaxValue) @@ -196,7 +193,7 @@ namespace Server.Items bankMsg = 1048019; // You are next to a Bank at the moment. } - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, 0x5AA, 3, bankMsg, "", "")); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Label, 0x5AA, 3, bankMsg); } public override void Serialize(IGenericWriter writer) diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickApprenticeCorpse.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickApprenticeCorpse.cs index 50077499c..8dded19d2 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickApprenticeCorpse.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Items/SchmendrickApprenticeCorpse.cs @@ -89,32 +89,26 @@ namespace Server.Engines.Quests.Haven if (ItemID == 0x2006) // Corpse form { - from.Send( - new MessageLocalized( - Serial, - ItemID, - MessageType.Label, - hue, - 3, - 1049144, - "", - Name - ) + from.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Label, + hue, + 3, + 1049144, + "", + Name ); // the remains of ~1_NAME~ the apprentice } else { - from.Send( - new MessageLocalized( - Serial, - ItemID, - MessageType.Label, - hue, - 3, - 1049145, - "", - "" - ) + from.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Label, + hue, + 3, + 1049145 ); // the remains of a wizard's apprentice } } diff --git a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaFighter.cs b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaFighter.cs index 968530315..ee0a3795c 100644 --- a/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaFighter.cs +++ b/Projects/UOContent/Engines/Quests/Uzeraan Turmoil/Mobiles/MilitiaFighter.cs @@ -127,32 +127,26 @@ namespace Server.Engines.Quests.Haven if (ItemID == 0x2006) // Corpse form { - from.Send( - new MessageLocalized( - Serial, - ItemID, - MessageType.Label, - hue, - 3, - 1049318, - "", - Name - ) + from.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Label, + hue, + 3, + 1049318, + "", + Name ); // the remains of ~1_NAME~ the militia fighter } else { - from.Send( - new MessageLocalized( - Serial, - ItemID, - MessageType.Label, - hue, - 3, - 1049319, - "", - "" - ) + from.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Label, + hue, + 3, + 1049319 ); // the remains of a militia fighter } } diff --git a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagApprenticeCorpse.cs b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagApprenticeCorpse.cs index 0578ea900..9603bab33 100644 --- a/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagApprenticeCorpse.cs +++ b/Projects/UOContent/Engines/Quests/Witch Apprentice/Items/HagApprenticeCorpse.cs @@ -48,7 +48,7 @@ namespace Server.Engines.Quests.Hag { var hue = Notoriety.GetHue(NotorietyHandlers.CorpseNotoriety(from, this)); - from.Send(new AsciiMessage(Serial, ItemID, MessageType.Label, hue, 3, "", "a charred corpse")); + from.NetState.SendMessage(Serial, ItemID, MessageType.Label, hue, 3, true, null, "", "a charred corpse"); } public override void Open(Mobile from, bool checkSelfLoot) diff --git a/Projects/UOContent/Items/Armor/BaseArmor.cs b/Projects/UOContent/Items/Armor/BaseArmor.cs index 58752d49d..5229dbd50 100644 --- a/Projects/UOContent/Items/Armor/BaseArmor.cs +++ b/Projects/UOContent/Items/Armor/BaseArmor.cs @@ -2036,7 +2036,7 @@ namespace Server.Items return; } - from.NetState?.SendDisplayEquipmentInfo(Serial, number, m_Crafter?.RawName, false, attrs); + from.NetState.SendDisplayEquipmentInfo(Serial, number, m_Crafter?.RawName, false, attrs); } [Flags] diff --git a/Projects/UOContent/Items/Clothing/BaseClothing.cs b/Projects/UOContent/Items/Clothing/BaseClothing.cs index 8e7bdf614..17288493f 100644 --- a/Projects/UOContent/Items/Clothing/BaseClothing.cs +++ b/Projects/UOContent/Items/Clothing/BaseClothing.cs @@ -880,7 +880,7 @@ namespace Server.Items return; } - from.NetState?.SendDisplayEquipmentInfo(Serial, number, m_Crafter?.RawName, false, attrs); + from.NetState.SendDisplayEquipmentInfo(Serial, number, m_Crafter?.RawName, false, attrs); } public virtual void AddEquipInfoAttributes(Mobile from, List attrs) diff --git a/Projects/UOContent/Items/Containers/LockableContainer.cs b/Projects/UOContent/Items/Containers/LockableContainer.cs index 54d0e3d92..c541abaa2 100644 --- a/Projects/UOContent/Items/Containers/LockableContainer.cs +++ b/Projects/UOContent/Items/Containers/LockableContainer.cs @@ -279,7 +279,7 @@ namespace Server.Items inaccessible = true; } - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", "")); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number); } return inaccessible; diff --git a/Projects/UOContent/Items/Containers/TrappableContainer.cs b/Projects/UOContent/Items/Containers/TrappableContainer.cs index 05b97f8eb..ac9398ae9 100644 --- a/Projects/UOContent/Items/Containers/TrappableContainer.cs +++ b/Projects/UOContent/Items/Containers/TrappableContainer.cs @@ -51,7 +51,7 @@ namespace Server.Items return; } - to.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number, "", "")); + to.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, hue, 3, number); } private void SendMessageTo(Mobile to, string text, int hue) @@ -61,7 +61,7 @@ namespace Server.Items return; } - to.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, hue, 3, "ENU", "", text)); + to.NetState.SendMessage(Serial, ItemID, MessageType.Regular, hue, 3, false, "ENU", "", text); } public virtual bool ExecuteTrap(Mobile from) diff --git a/Projects/UOContent/Items/Guilds/Guildstone.cs b/Projects/UOContent/Items/Guilds/Guildstone.cs index a6578b217..458ca8c73 100644 --- a/Projects/UOContent/Items/Guilds/Guildstone.cs +++ b/Projects/UOContent/Items/Guilds/Guildstone.cs @@ -276,17 +276,13 @@ namespace Server.Items } else if (from.AccessLevel < AccessLevel.GameMaster && !Guild.IsMember(from)) { - from.Send( - new MessageLocalized( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - 501158, - "", - "" - ) + from.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + 501158 ); // You are not a member ... } else diff --git a/Projects/UOContent/Items/Maps/TreasureMap.cs b/Projects/UOContent/Items/Maps/TreasureMap.cs index dd7170e4e..b0c7587ea 100644 --- a/Projects/UOContent/Items/Maps/TreasureMap.cs +++ b/Projects/UOContent/Items/Maps/TreasureMap.cs @@ -519,7 +519,7 @@ namespace Server.Items if (m_Completed) { - list.Add(1041507, m_CompletedBy == null ? "someone" : m_CompletedBy.Name); // completed by ~1_val~ + list.Add(1041507, m_CompletedBy?.RawName ?? "someone"); // completed by ~1_val~ } } @@ -527,19 +527,16 @@ namespace Server.Items { if (m_Completed) { - from.Send( - new MessageLocalizedAffix( - Serial, - ItemID, - MessageType.Label, - 0x3B2, - 3, - 1048030, - "", - AffixType.Append, - $" completed by {(m_CompletedBy == null ? "someone" : m_CompletedBy.Name)}", - "" - ) + from.NetState.SendMessageLocalizedAffix( + Serial, + ItemID, + MessageType.Label, + 0x3B2, + 3, + 1048030, + "", + AffixType.Append, + $" completed by {m_CompletedBy?.RawName ?? "someone"}" ); } else if (m_Decoder != null) diff --git a/Projects/UOContent/Items/Misc/BankCheck.cs b/Projects/UOContent/Items/Misc/BankCheck.cs index 32c9535a1..5683d9d5f 100644 --- a/Projects/UOContent/Items/Misc/BankCheck.cs +++ b/Projects/UOContent/Items/Misc/BankCheck.cs @@ -153,19 +153,16 @@ namespace Server.Items public override void OnSingleClick(Mobile from) { - from.Send( - new MessageLocalizedAffix( - Serial, - ItemID, - MessageType.Label, - 0x3B2, - 3, - 1041361, - "", - AffixType.Append, - $" {m_Worth}", - "" - ) + from.NetState.SendMessageLocalizedAffix( + Serial, + ItemID, + MessageType.Label, + 0x3B2, + 3, + 1041361, + "", + AffixType.Append, + $" {m_Worth}" ); // A bank check: } diff --git a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs index c04c52b6e..fbac6fe2b 100644 --- a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs +++ b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs @@ -1168,7 +1168,7 @@ namespace Server.Items if (opl.Header > 0) { - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs)); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, opl.Header, Name, opl.HeaderArgs); } } @@ -1180,16 +1180,16 @@ namespace Server.Items { if (m_CorpseName != null) { - from.Send(new AsciiMessage(Serial, ItemID, MessageType.Label, hue, 3, "", m_CorpseName)); + from.NetState.SendMessage(Serial, ItemID, MessageType.Label, hue, 3, true, null, "", m_CorpseName); } else { - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name)); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name); } } else // Bone form { - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name)); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Label, hue, 3, 1046414, "", Name); } } diff --git a/Projects/UOContent/Items/Misc/Key.cs b/Projects/UOContent/Items/Misc/Key.cs index 2f33ebe5b..058f4f49d 100644 --- a/Projects/UOContent/Items/Misc/Key.cs +++ b/Projects/UOContent/Items/Misc/Key.cs @@ -249,14 +249,14 @@ namespace Server.Items { desc = "(blank)"; } - else if ((desc = m_Description) == null || (desc = desc.Trim()).Length <= 0) + else { - desc = ""; + desc = m_Description?.Trim() ?? ""; } if (desc.Length > 0) { - from.Send(new UnicodeMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, "ENU", "", desc)); + from.NetState.SendMessage(Serial, ItemID, MessageType.Regular, 0x3B2, 3, false, "ENU", "", desc); } } diff --git a/Projects/UOContent/Items/Misc/PowerGenerator.cs b/Projects/UOContent/Items/Misc/PowerGenerator.cs index 5d0710ef9..35d8899d8 100644 --- a/Projects/UOContent/Items/Misc/PowerGenerator.cs +++ b/Projects/UOContent/Items/Misc/PowerGenerator.cs @@ -216,18 +216,18 @@ namespace Server.Items public void DoDamage(Mobile to) { - to.Send( - new UnicodeMessage( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - "", - "", - "The generator shoots an arc of electricity at you!" - ) + to.NetState.SendMessage( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + false, + "ENU", + "", + "The generator shoots an arc of electricity at you!" ); + to.BoltEffect(0); to.LocalOverheadMessage(MessageType.Regular, 0xC9, true, "* Your body convulses from electric shock *"); to.NonlocalOverheadMessage(MessageType.Regular, 0xC9, true, $"* {to.Name} spasms from electric shock *"); diff --git a/Projects/UOContent/Items/Misc/Teleporter.cs b/Projects/UOContent/Items/Misc/Teleporter.cs index 31a905caa..16f53cfb0 100644 --- a/Projects/UOContent/Items/Misc/Teleporter.cs +++ b/Projects/UOContent/Items/Misc/Teleporter.cs @@ -429,32 +429,28 @@ namespace Server.Items { if (m_MessageString != null) { - m.Send( - new UnicodeMessage( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - "ENU", - null, - m_MessageString - ) + m.NetState.SendMessage( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + false, + "ENU", + null, + m_MessageString ); } else if (m_MessageNumber != 0) { - m.Send( - new MessageLocalized( - Serial, - ItemID, - MessageType.Regular, - 0x3B2, - 3, - m_MessageNumber, - null, - "" - ) + m.NetState.SendMessageLocalized( + Serial, + ItemID, + MessageType.Regular, + 0x3B2, + 3, + m_MessageNumber, + null ); } diff --git a/Projects/UOContent/Items/Resources/Tailor/BoltOfCloth.cs b/Projects/UOContent/Items/Resources/Tailor/BoltOfCloth.cs index c1450e397..3363c4741 100644 --- a/Projects/UOContent/Items/Resources/Tailor/BoltOfCloth.cs +++ b/Projects/UOContent/Items/Resources/Tailor/BoltOfCloth.cs @@ -61,10 +61,8 @@ namespace Server.Items public override void OnSingleClick(Mobile from) { var number = Amount == 1 ? 1049122 : 1049121; - - from.Send( - new MessageLocalized(Serial, ItemID, MessageType.Label, 0x3B2, 3, number, "", (Amount * 50).ToString()) - ); + var amount = (Amount * 50).ToString(); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Label, 0x3B2, 3, number, "", amount); } } } diff --git a/Projects/UOContent/Items/Resources/Tailor/Cloth.cs b/Projects/UOContent/Items/Resources/Tailor/Cloth.cs index b18f2b427..998c7d3fb 100644 --- a/Projects/UOContent/Items/Resources/Tailor/Cloth.cs +++ b/Projects/UOContent/Items/Resources/Tailor/Cloth.cs @@ -62,7 +62,7 @@ namespace Server.Items { var number = Amount == 1 ? 1049124 : 1049123; - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", Amount.ToString())); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", Amount.ToString()); } } } diff --git a/Projects/UOContent/Items/Resources/Tailor/UncutCloth.cs b/Projects/UOContent/Items/Resources/Tailor/UncutCloth.cs index 51aaffc55..78d97416b 100644 --- a/Projects/UOContent/Items/Resources/Tailor/UncutCloth.cs +++ b/Projects/UOContent/Items/Resources/Tailor/UncutCloth.cs @@ -62,7 +62,7 @@ namespace Server.Items { var number = Amount == 1 ? 1049124 : 1049123; - from.Send(new MessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", Amount.ToString())); + from.NetState.SendMessageLocalized(Serial, ItemID, MessageType.Regular, 0x3B2, 3, number, "", Amount.ToString()); } } } diff --git a/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs b/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs index bc415b404..9d4158dc7 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Spellbook.cs @@ -696,7 +696,7 @@ namespace Server.Items else if (Parent is Mobile) { // What will happen if the client doesn't know about our parent? - to.NetState?.SendEquipUpdate(this); + to.NetState.SendEquipUpdate(this); } if (ns.HighSeas) diff --git a/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs b/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs index 3b150ae58..98296973a 100644 --- a/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs +++ b/Projects/UOContent/Items/Skill Items/Musical Instruments/BaseInstrument.cs @@ -469,7 +469,7 @@ namespace Server.Items return; } - from.NetState?.SendDisplayEquipmentInfo(Serial, number, m_Crafter?.RawName, false, attrs); + from.NetState.SendDisplayEquipmentInfo(Serial, number, m_Crafter?.RawName, false, attrs); } public override void Serialize(IGenericWriter writer) diff --git a/Projects/UOContent/Items/Skill Items/Tinkering/Spyglass.cs b/Projects/UOContent/Items/Skill Items/Tinkering/Spyglass.cs index b313ee557..46b5004a5 100644 --- a/Projects/UOContent/Items/Skill Items/Tinkering/Spyglass.cs +++ b/Projects/UOContent/Items/Skill Items/Tinkering/Spyglass.cs @@ -22,33 +22,28 @@ namespace Server.Items 1008155 ); // You peer into the heavens, seeking the moons... - from.Send( - new MessageLocalizedAffix( - from.Serial, - from.Body, - MessageType.Regular, - 0x3B2, - 3, - 1008146 + (int)Clock.GetMoonPhase(Map.Trammel, from.X, from.Y), - "", - AffixType.Prepend, - "Trammel : ", - "" - ) + from.NetState.SendMessageLocalizedAffix( + from.Serial, + from.Body, + MessageType.Regular, + 0x3B2, + 3, + 1008146 + (int)Clock.GetMoonPhase(Map.Trammel, from.X, from.Y), + "", + AffixType.Prepend, + "Trammel : " ); - from.Send( - new MessageLocalizedAffix( - from.Serial, - from.Body, - MessageType.Regular, - 0x3B2, - 3, - 1008146 + (int)Clock.GetMoonPhase(Map.Felucca, from.X, from.Y), - "", - AffixType.Prepend, - "Felucca : ", - "" - ) + + from.NetState.SendMessageLocalizedAffix( + from.Serial, + from.Body, + MessageType.Regular, + 0x3B2, + 3, + 1008146 + (int)Clock.GetMoonPhase(Map.Felucca, from.X, from.Y), + "", + AffixType.Prepend, + "Felucca : " ); if (from is PlayerMobile player) diff --git a/Projects/UOContent/Items/Special/Solen Items/BagOfSending.cs b/Projects/UOContent/Items/Special/Solen Items/BagOfSending.cs index 142664a06..e4af5f581 100644 --- a/Projects/UOContent/Items/Special/Solen Items/BagOfSending.cs +++ b/Projects/UOContent/Items/Special/Solen Items/BagOfSending.cs @@ -260,16 +260,16 @@ namespace Server.Items } else if (item is BagOfSending || item is Container) { - from.Send( - new AsciiMessage( - m_Bag.Serial, - m_Bag.ItemID, - MessageType.Regular, - 0x3B2, - 3, - "", - "You cannot send a container through the bag of sending." - ) + from.NetState.SendMessage( + m_Bag.Serial, + m_Bag.ItemID, + MessageType.Regular, + 0x3B2, + 3, + true, + null, + "", + "You cannot send a container through the bag of sending." ); } else if (item.LootType == LootType.Cursed) diff --git a/Projects/UOContent/Items/Special/Solen Items/BallOfSummoning.cs b/Projects/UOContent/Items/Special/Solen Items/BallOfSummoning.cs index e6f638a6a..ed6b6971a 100644 --- a/Projects/UOContent/Items/Special/Solen Items/BallOfSummoning.cs +++ b/Projects/UOContent/Items/Special/Solen Items/BallOfSummoning.cs @@ -226,16 +226,16 @@ namespace Server.Items else if (from.Map == Map.Ilshenar || from.Region.IsPartOf() || from.Region.IsPartOf() || from.Region.IsPartOf()) { - from.Send( - new AsciiMessage( - Serial, - ItemID, - MessageType.Regular, - 0x22, - 3, - "", - "You cannot summon your pet to this location." - ) + from.NetState.SendMessage( + Serial, + ItemID, + MessageType.Regular, + 0x22, + 3, + true, + null, + "", + "You cannot summon your pet to this location." ); } else if (Core.ML && from is PlayerMobile mobile && DateTime.UtcNow < mobile.LastPetBallTime.AddSeconds(15.0)) diff --git a/Projects/UOContent/Items/Special/Solen Items/MessageHelper.cs b/Projects/UOContent/Items/Special/Solen Items/MessageHelper.cs index 441689886..21bb8170c 100644 --- a/Projects/UOContent/Items/Special/Solen Items/MessageHelper.cs +++ b/Projects/UOContent/Items/Special/Solen Items/MessageHelper.cs @@ -11,12 +11,12 @@ namespace Server public static void SendLocalizedMessageTo(Item from, Mobile to, int number, string args, int hue) { - to.Send(new MessageLocalized(from.Serial, from.ItemID, MessageType.Regular, hue, 3, number, "", args)); + to.NetState.SendMessageLocalized(from.Serial, from.ItemID, MessageType.Regular, hue, 3, number, "", args); } public static void SendMessageTo(Item from, Mobile to, string text, int hue) { - to.Send(new UnicodeMessage(from.Serial, from.ItemID, MessageType.Regular, hue, 3, "ENU", "", text)); + to.NetState.SendMessage(from.Serial, from.ItemID, MessageType.Regular, hue, 3, false, "ENU", "", text); } } } diff --git a/Projects/UOContent/Items/Wands/BaseWand.cs b/Projects/UOContent/Items/Wands/BaseWand.cs index 022282a72..305556d6d 100644 --- a/Projects/UOContent/Items/Wands/BaseWand.cs +++ b/Projects/UOContent/Items/Wands/BaseWand.cs @@ -268,7 +268,7 @@ namespace Server.Items return; } - from.NetState?.SendDisplayEquipmentInfo(Serial, number, Crafter?.RawName, false, attrs); + from.NetState.SendDisplayEquipmentInfo(Serial, number, Crafter?.RawName, false, attrs); } public void Cast(Spell spell) diff --git a/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs b/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs index ce47d2c01..bec5b60df 100644 --- a/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs +++ b/Projects/UOContent/Items/Weapons/Ranged/BaseRanged.cs @@ -83,7 +83,7 @@ namespace Server.Items if (canSwing && attacker.HarmfulCheck(defender)) { attacker.DisruptiveAction(); - attacker.NetState?.SendSwing(attacker.Serial, defender.Serial); + attacker.NetState.SendSwing(attacker.Serial, defender.Serial); if (OnFired(attacker, defender)) { diff --git a/Projects/UOContent/Misc/Guild.cs b/Projects/UOContent/Misc/Guild.cs index 09e9d26bd..c7e5c0aca 100644 --- a/Projects/UOContent/Misc/Guild.cs +++ b/Projects/UOContent/Misc/Guild.cs @@ -343,38 +343,31 @@ namespace Server.Guilds public void AllianceChat(Mobile from, int hue, string text) { - Packet p = null; + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; + var length = OutgoingMessagePackets.CreateMessage( + ref buffer, + from.Serial, + from.Body, + MessageType.Alliance, + hue, + 3, + false, + from.Language, + from.Name, + text + ); + + buffer = buffer.Slice(0, length); // Adjust to the actual size + for (var i = 0; i < m_Members.Count; i++) { var g = m_Members[i]; for (var j = 0; j < g.Members.Count; j++) { - var m = g.Members[j]; - - var state = m.NetState; - - if (state != null) - { - p ??= Packet.Acquire( - new UnicodeMessage( - from.Serial, - from.Body, - MessageType.Alliance, - hue, - 3, - from.Language, - from.Name, - text - ) - ); - - state.Send(p); - } + g.Members[j].NetState?.Send(buffer); } } - - Packet.Release(p); } public void AllianceChat(Mobile from, string text) @@ -1512,24 +1505,18 @@ namespace Server.Guilds public void GuildChat(Mobile from, int hue, string text) { - Packet p = null; + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; + var length = OutgoingMessagePackets.CreateMessage( + ref buffer, + from.Serial, from.Body, MessageType.Guild, hue, 3, false, from.Language, from.Name, text + ); + + buffer = buffer.Slice(0, length); // Adjust to the actual size + for (var i = 0; i < Members.Count; i++) { - var m = Members[i]; - - var state = m.NetState; - - if (state != null) - { - p ??= Packet.Acquire( - new UnicodeMessage(from.Serial, from.Body, MessageType.Guild, hue, 3, from.Language, from.Name, text) - ); - - state.Send(p); - } + Members[i].NetState?.Send(buffer); } - - Packet.Release(p); } public void GuildChat(Mobile from, string text) diff --git a/Projects/UOContent/Mobiles/PlayerMobile.cs b/Projects/UOContent/Mobiles/PlayerMobile.cs index 931f9a57c..f78ce3e40 100644 --- a/Projects/UOContent/Mobiles/PlayerMobile.cs +++ b/Projects/UOContent/Mobiles/PlayerMobile.cs @@ -2851,7 +2851,21 @@ namespace Server.Mobiles private static void SendToStaffMessage(Mobile from, string text) { - Packet p = null; + Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; + var length = OutgoingMessagePackets.CreateMessage( + ref buffer, + from.Serial, + from.Body, + MessageType.Regular, + from.SpeechHue, + 3, + false, + from.Language, + from.Name, + text + ); + + buffer = buffer.Slice(0, length); // Adjust to the actual size foreach (var ns in from.GetClientsInRange(8)) { @@ -2859,24 +2873,9 @@ namespace Server.Mobiles if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel) { - p ??= Packet.Acquire( - new UnicodeMessage( - from.Serial, - from.Body, - MessageType.Regular, - from.SpeechHue, - 3, - from.Language, - from.Name, - text - ) - ); - - ns.Send(p); + ns.Send(buffer); } } - - Packet.Release(p); } private static void SendToStaffMessage(Mobile from, string format, params object[] args) diff --git a/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs b/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs index fa0533f85..ea4e117f9 100644 --- a/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs +++ b/Projects/UOContent/Mobiles/Vendors/BaseVendor.cs @@ -1021,13 +1021,13 @@ namespace Server.Mobiles AddItem(pack); } - from.NetState?.SendEquipUpdate(pack); + from.NetState.SendEquipUpdate(pack); pack = FindItemOnLayer(Layer.ShopSell); if (pack != null) { - from.NetState?.SendEquipUpdate(pack); + from.NetState.SendEquipUpdate(pack); } pack = FindItemOnLayer(Layer.ShopResale); @@ -1038,7 +1038,7 @@ namespace Server.Mobiles AddItem(pack); } - from.NetState?.SendEquipUpdate(pack); + from.NetState.SendEquipUpdate(pack); } public virtual void VendorSell(Mobile from) diff --git a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BaseGuildmaster.cs b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BaseGuildmaster.cs index 23b68e00a..731f1bbbb 100644 --- a/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BaseGuildmaster.cs +++ b/Projects/UOContent/Mobiles/Vendors/NPC/Guildmasters/BaseGuildmaster.cs @@ -48,19 +48,16 @@ namespace Server.Mobiles public virtual void SayPriceTo(Mobile m) { - m.Send( - new MessageLocalizedAffix( - Serial, - Body, - MessageType.Regular, - SpeechHue, - 3, - 1008052, - Name, - AffixType.Append, - JoinCost.ToString(), - "" - ) + m.NetState.SendMessageLocalizedAffix( + Serial, + Body, + MessageType.Regular, + SpeechHue, + 3, + 1008052, + Name, + AffixType.Append, + JoinCost.ToString() ); } diff --git a/Projects/UOContent/Multis/HouseFoundation.cs b/Projects/UOContent/Multis/HouseFoundation.cs index 5be269f0a..cd45eca4a 100644 --- a/Projects/UOContent/Multis/HouseFoundation.cs +++ b/Projects/UOContent/Multis/HouseFoundation.cs @@ -1980,7 +1980,7 @@ namespace Server.Multis public void SendGeneralInfoTo(NetState state) { - state?.Send(new DesignStateGeneral(Foundation, this)); + state.Send(new DesignStateGeneral(Foundation, this)); } public void SendDetailedInfoTo(NetState state) diff --git a/Projects/UOContent/Skills/Tracking/QuestArrow.cs b/Projects/UOContent/Skills/Tracking/QuestArrow.cs index c41bd37d3..8267dd22a 100644 --- a/Projects/UOContent/Skills/Tracking/QuestArrow.cs +++ b/Projects/UOContent/Skills/Tracking/QuestArrow.cs @@ -35,7 +35,7 @@ namespace Server return; } - Mobile.NetState?.SendSetArrow(x, y, Target.Serial); + Mobile.NetState.SendSetArrow(x, y, Target.Serial); } public void Stop() @@ -51,7 +51,7 @@ namespace Server } Mobile.ClearQuestArrow(); - Mobile.NetState?.SendCancelArrow(x, y, Target.Serial); + Mobile.NetState.SendCancelArrow(x, y, Target.Serial); Running = false; OnStop(); diff --git a/Projects/UOContent/SpecialSystems/Engines/TestCenter.cs b/Projects/UOContent/SpecialSystems/Engines/TestCenter.cs index ba2c444e0..355a2f4bb 100644 --- a/Projects/UOContent/SpecialSystems/Engines/TestCenter.cs +++ b/Projects/UOContent/SpecialSystems/Engines/TestCenter.cs @@ -226,17 +226,18 @@ namespace Server.Misc if (sb.Length + 1 + v.Length >= 256) { - sender.Send( - new AsciiMessage( - Server.Serial.MinusOne, - -1, - MessageType.Label, - 0x35, - 3, - "System", - sb.ToString() - ) + sender.SendMessage( + Server.Serial.MinusOne, + -1, + MessageType.Label, + 0x35, + 3, + true, + null, + "System", + sb.ToString() ); + sb = new StringBuilder(); sb.Append(v); } @@ -249,16 +250,16 @@ namespace Server.Misc if (sb.Length > 0) { - sender.Send( - new AsciiMessage( - Server.Serial.MinusOne, - -1, - MessageType.Label, - 0x35, - 3, - "System", - sb.ToString() - ) + sender.SendMessage( + Server.Serial.MinusOne, + -1, + MessageType.Label, + 0x35, + 3, + true, + null, + "System", + sb.ToString() ); } diff --git a/Projects/UOContent/Spells/Sixth/Mark.cs b/Projects/UOContent/Spells/Sixth/Mark.cs index c36a205f2..aa1c4a7a9 100644 --- a/Projects/UOContent/Spells/Sixth/Mark.cs +++ b/Projects/UOContent/Spells/Sixth/Mark.cs @@ -26,17 +26,14 @@ namespace Server.Spells.Sixth { if (!(item is RecallRune rune)) { - Caster.Send( - new MessageLocalized( - Caster.Serial, - Caster.Body, - MessageType.Regular, - 0x3B2, - 3, - 501797, - Caster.Name, - "" - ) + Caster.NetState.SendMessageLocalized( + Caster.Serial, + Caster.Body, + MessageType.Regular, + 0x3B2, + 3, + 501797, + Caster.Name ); // I cannot mark that object. } else if (!Caster.CanSee(rune)) diff --git a/Projects/UOContent/Spells/Targeting/RecallSpellTarget.cs b/Projects/UOContent/Spells/Targeting/RecallSpellTarget.cs index aead21c64..2a43e6ea4 100644 --- a/Projects/UOContent/Spells/Targeting/RecallSpellTarget.cs +++ b/Projects/UOContent/Spells/Targeting/RecallSpellTarget.cs @@ -51,17 +51,14 @@ namespace Server.Spells } else { - from.Send( - new MessageLocalized( - from.Serial, - from.Body, - MessageType.Regular, - 0x3B2, - 3, - 502357, - from.Name, - "" - ) + from.NetState.SendMessageLocalized( + from.Serial, + from.Body, + MessageType.Regular, + 0x3B2, + 3, + 502357, + from.Name ); // I can not recall from that object. } } @@ -71,17 +68,14 @@ namespace Server.Spells } else { - from.Send( - new MessageLocalized( - from.Serial, - from.Body, - MessageType.Regular, - 0x3B2, - 3, - 502357, - from.Name, - "" - ) + from.NetState.SendMessageLocalized( + from.Serial, + from.Body, + MessageType.Regular, + 0x3B2, + 3, + 502357, + from.Name ); // I can not recall from that object. } }