diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/AttributeNormalizerTests.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/AttributeNormalizerTests.cs deleted file mode 100644 index 220b8a212..000000000 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/AttributeNormalizerTests.cs +++ /dev/null @@ -1,93 +0,0 @@ -using System; -using System.Buffers; -using Server.Network; -using Xunit; - -namespace Server.Tests.Network -{ - [Collection("Sequential Tests")] - public class AttributeNormalizerTests - { - [Fact] - public void TestAttributeNormalizerEnabled() - { - AttributeNormalizer.Enabled = true; - AttributeNormalizer.Maximum = 25; - - var stream = new PacketWriter(4); - - const ushort cur = 50; - const ushort max = 100; - - AttributeNormalizer.Write(stream, cur, max); - - Span expectedData = stackalloc byte[4]; - var pos = 0; - expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum); - expectedData.Write(ref pos, (ushort)(cur * 25 / max)); - - AssertThat.Equal(stream.ToArray(), expectedData); - } - - [Fact] - public void TestAttributeNormalizerReversedEnabled() - { - AttributeNormalizer.Enabled = true; - AttributeNormalizer.Maximum = 25; - - var stream = new PacketWriter(4); - - const ushort cur = 50; - const ushort max = 100; - - AttributeNormalizer.WriteReverse(stream, cur, max); - - Span expectedData = stackalloc byte[4]; - var pos = 0; - expectedData.Write(ref pos, (ushort)(cur * 25 / max)); - expectedData.Write(ref pos, (ushort)AttributeNormalizer.Maximum); - - AssertThat.Equal(stream.ToArray(), expectedData); - } - - [Fact] - public void TestAttributeNormalizerDisabled() - { - AttributeNormalizer.Enabled = false; - - var stream = new PacketWriter(4); - - const ushort cur = 50; - const ushort max = 100; - - AttributeNormalizer.Write(stream, cur, max); - - Span expectedData = stackalloc byte[4]; - var pos = 0; - expectedData.Write(ref pos, max); - expectedData.Write(ref pos, cur); - - AssertThat.Equal(stream.ToArray(), expectedData); - } - - [Fact] - public void TestAttributeNormalizerReversedDisabled() - { - AttributeNormalizer.Enabled = false; - - var stream = new PacketWriter(4); - - const ushort cur = 50; - const ushort max = 100; - - AttributeNormalizer.WriteReverse(stream, cur, max); - - Span expectedData = stackalloc byte[4]; - var pos = 0; - expectedData.Write(ref pos, cur); - expectedData.Write(ref pos, max); - - AssertThat.Equal(stream.ToArray(), expectedData); - } - } -} diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs index d14b4e604..265a0c701 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePacketTests.cs @@ -625,17 +625,16 @@ namespace Server.Tests.Network { var m = new Mobile(0x1); m.DefaultMobileInit(); + m.Str = 100; + m.Hits = 100; - var data = new MobileHits(m).Compile(); + var expected = new MobileHits(m).Compile(); - Span expectedData = stackalloc byte[9]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileHits(m); - expectedData.Write(ref pos, (byte)0xA1); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -643,17 +642,16 @@ namespace Server.Tests.Network { var m = new Mobile(0x1); m.DefaultMobileInit(); + m.Str = 100; + m.Hits = 100; - var data = new MobileHitsN(m).Compile(); + var expected = new MobileHitsN(m).Compile(); - Span expectedData = stackalloc byte[9]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileHits(m, true); - expectedData.Write(ref pos, (byte)0xA1); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -661,17 +659,16 @@ namespace Server.Tests.Network { var m = new Mobile(0x1); m.DefaultMobileInit(); + m.Int = 75; + m.Mana = 100; - var data = new MobileMana(m).Compile(); + var expected = new MobileMana(m).Compile(); - Span expectedData = stackalloc byte[9]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileMana(m); - expectedData.Write(ref pos, (byte)0xA2); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -679,17 +676,16 @@ namespace Server.Tests.Network { var m = new Mobile(0x1); m.DefaultMobileInit(); + m.Int = 75; + m.Mana = 100; - var data = new MobileManaN(m).Compile(); + var expected = new MobileManaN(m).Compile(); - Span expectedData = stackalloc byte[9]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileMana(m, true); - expectedData.Write(ref pos, (byte)0xA2); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -697,17 +693,16 @@ namespace Server.Tests.Network { var m = new Mobile(0x1); m.DefaultMobileInit(); + m.Dex = 75; + m.Stam = 100; - var data = new MobileStam(m).Compile(); + var expected = new MobileStam(m).Compile(); - Span expectedData = stackalloc byte[9]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileStam(m); - expectedData.Write(ref pos, (byte)0xA3); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -715,17 +710,16 @@ namespace Server.Tests.Network { var m = new Mobile(0x1); m.DefaultMobileInit(); + m.Dex = 75; + m.Stam = 100; - var data = new MobileStamN(m).Compile(); + var expected = new MobileStamN(m).Compile(); - Span expectedData = stackalloc byte[9]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileStam(m, true); - expectedData.Write(ref pos, (byte)0xA3); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -733,19 +727,20 @@ namespace Server.Tests.Network { var m = new Mobile(0x1); m.DefaultMobileInit(); + m.Str = 50; + m.Hits = 100; + m.Int = 75; + m.Mana = 100; + m.Dex = 25; + m.Stam = 100; - var data = new MobileAttributes(m).Compile(); + var expected = new MobileAttributes(m).Compile(); - Span expectedData = stackalloc byte[17]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileAttributes(m); - expectedData.Write(ref pos, (byte)0x2D); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, false); - expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, false); - expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, false); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } [Fact] @@ -753,19 +748,20 @@ namespace Server.Tests.Network { var m = new Mobile(0x1); m.DefaultMobileInit(); + m.Str = 50; + m.Hits = 100; + m.Int = 75; + m.Mana = 100; + m.Dex = 25; + m.Stam = 100; - var data = new MobileAttributesN(m).Compile(); + var expected = new MobileAttributesN(m).Compile(); - Span expectedData = stackalloc byte[17]; - var pos = 0; + using var ns = PacketTestUtilities.CreateTestNetState(); + ns.SendMobileAttributes(m, true); - expectedData.Write(ref pos, (byte)0x2D); // Packet ID - expectedData.Write(ref pos, m.Serial); - expectedData.WriteAttribute(ref pos, m.Hits, m.HitsMax, true); - expectedData.WriteAttribute(ref pos, m.Mana, m.ManaMax, true); - expectedData.WriteAttribute(ref pos, m.Stam, m.StamMax, true); - - AssertThat.Equal(data, expectedData); + var result = ns.SendPipe.Reader.TryRead(); + AssertThat.Equal(result.Buffer[0].AsSpan(0), expected); } } } diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs index 6f14a62d8..11ef7c0e1 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/MobilePackets.cs @@ -49,4 +49,90 @@ namespace Server.Tests.Network Stream.Write((byte)noto); } } + + public sealed class MobileHits : Packet + { + public MobileHits(Mobile m) : base(0xA1, 9) + { + Stream.Write(m.Serial); + Stream.Write((short)m.HitsMax); + Stream.Write((short)m.Hits); + } + } + + public sealed class MobileHitsN : Packet + { + public MobileHitsN(Mobile m) : base(0xA1, 9) + { + Stream.Write(m.Serial); + AttributeNormalizer.Write(Stream, m.Hits, m.HitsMax); + } + } + + public sealed class MobileMana : Packet + { + public MobileMana(Mobile m) : base(0xA2, 9) + { + Stream.Write(m.Serial); + Stream.Write((short)m.ManaMax); + Stream.Write((short)m.Mana); + } + } + + public sealed class MobileManaN : Packet + { + public MobileManaN(Mobile m) : base(0xA2, 9) + { + Stream.Write(m.Serial); + AttributeNormalizer.Write(Stream, m.Mana, m.ManaMax); + } + } + + public sealed class MobileStam : Packet + { + public MobileStam(Mobile m) : base(0xA3, 9) + { + Stream.Write(m.Serial); + Stream.Write((short)m.StamMax); + Stream.Write((short)m.Stam); + } + } + + public sealed class MobileStamN : Packet + { + public MobileStamN(Mobile m) : base(0xA3, 9) + { + Stream.Write(m.Serial); + AttributeNormalizer.Write(Stream, m.Stam, m.StamMax); + } + } + + public sealed class MobileAttributes : Packet + { + public MobileAttributes(Mobile m) : base(0x2D, 17) + { + Stream.Write(m.Serial); + + Stream.Write((short)m.HitsMax); + Stream.Write((short)m.Hits); + + Stream.Write((short)m.ManaMax); + Stream.Write((short)m.Mana); + + Stream.Write((short)m.StamMax); + Stream.Write((short)m.Stam); + } + } + + public sealed class MobileAttributesN : Packet + { + public MobileAttributesN(Mobile m) : base(0x2D, 17) + { + Stream.Write(m.Serial); + + AttributeNormalizer.Write(Stream, m.Hits, m.HitsMax); + AttributeNormalizer.Write(Stream, m.Mana, m.ManaMax); + AttributeNormalizer.Write(Stream, m.Stam, m.StamMax); + } + } } diff --git a/Projects/Server/Mobiles/Mobile.cs b/Projects/Server/Mobiles/Mobile.cs index 0a62f29cc..b1f944c36 100644 --- a/Projects/Server/Mobiles/Mobile.cs +++ b/Projects/Server/Mobiles/Mobile.cs @@ -622,7 +622,7 @@ namespace Server [CommandProperty(AccessLevel.GameMaster)] public Race Race { - get => m_Race ?? (m_Race = Race.DefaultRace); + get => m_Race ??= Race.DefaultRace; set { var oldRace = Race; @@ -1322,15 +1322,7 @@ namespace Server [Hue, CommandProperty(AccessLevel.GameMaster)] public virtual int Hue { - get - { - if (m_HueMod != -1) - { - return m_HueMod; - } - - return m_Hue; - } + get => m_HueMod != -1 ? m_HueMod : m_Hue; set { var oldHue = m_Hue; @@ -2100,7 +2092,6 @@ namespace Server if (Hits < HitsMax) { m_HitsTimer ??= new HitsTimer(this); - m_HitsTimer.Start(); } else if (Hits > HitsMax) @@ -2290,7 +2281,6 @@ namespace Server if (CanRegenHits) { m_HitsTimer ??= new HitsTimer(this); - m_HitsTimer.Start(); } else @@ -2850,7 +2840,7 @@ namespace Server ns.Send(new MobileIncoming(ns, this, this)); ns.SendSupportedFeature(); ns.Send(new MobileUpdate(this, ns.StygianAbyss)); - ns.Send(new MobileAttributes(this)); + ns.SendMobileAttributes(this); } OnMapChange(oldMap); @@ -3091,23 +3081,23 @@ namespace Server } else if (sendAll) { - ourState.Send(new MobileAttributes(m)); + ourState.SendMobileAttributes(m); } else if (sendAny) { if (sendHits) { - ourState.Send(new MobileHits(m)); - } - - if (sendStam) - { - ourState.Send(new MobileStam(m)); + ourState.SendMobileHits(m); } if (sendMana) { - ourState.Send(new MobileMana(m)); + ourState.SendMobileMana(m); + } + + if (sendStam) + { + ourState.SendMobileStam(m); } } @@ -3115,15 +3105,15 @@ namespace Server { if (Party is IParty ip) { - if (sendStam) - { - ip.OnStamChanged(this); - } - if (sendMana) { ip.OnManaChanged(this); } + + if (sendStam) + { + ip.OnStamChanged(this); + } } } @@ -3165,9 +3155,6 @@ namespace Server sendOPLUpdate || sendHair || sendFacialHair || sendHealthbarPoison || sendHealthbarYellow)) { - Mobile beholder; - - Packet hitsPacket = null; Packet statPacketTrue = null; Packet statPacketFalse = null; Packet hairPacket = null; @@ -3183,104 +3170,111 @@ namespace Server Span removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; removeEntity.InitializePacket(); + Span hitsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength]; + hitsPacket.InitializePacket(); + foreach (var state in eable) { - beholder = state.Mobile; + var beholder = state.Mobile; - if (beholder != m && beholder.CanSee(m)) + if (beholder == m || !beholder.CanSee(m)) { - if (sendRemove) - { - if (removeEntity[0] == 0) - { - OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial); - } - - state.Send(removeEntity); - } - - if (sendIncoming) - { - state.Send(new MobileIncoming(state, beholder, m)); - - if (m.IsDeadBondedPet) - { - if (deadBuffer[0] == 0) - { - OutgoingMobilePackets.CreateBondedStatus(deadBuffer, m.Serial, true); - } - - state.Send(deadBuffer); - } - } - - if (sendMoving || !state.StygianAbyss && (sendHealthbarPoison || sendHealthbarYellow)) - { - state.SendMobileMovingUsingCache(mobileMovingPackets, beholder, m); - } - - if (state.StygianAbyss) - { - if (sendHealthbarPoison) - { - hbpPacket ??= Packet.Acquire(new HealthbarPoison(m)); - - state.Send(hbpPacket); - } - - if (sendHealthbarYellow) - { - hbyPacket ??= Packet.Acquire(new HealthbarYellow(m)); - - state.Send(hbyPacket); - } - } - - if (sendPublicStats) - { - if (m.CanBeRenamedBy(beholder)) - { - statPacketTrue ??= Packet.Acquire(new MobileStatusCompact(true, m)); - - state.Send(statPacketTrue); - } - else - { - statPacketFalse ??= Packet.Acquire(new MobileStatusCompact(false, m)); - - state.Send(statPacketFalse); - } - } - else if (sendHits) - { - hitsPacket ??= Packet.Acquire(new MobileHitsN(m)); - - state.Send(hitsPacket); - } - - if (sendHair) - { - hairPacket ??= removeHair - ? Packet.Acquire(new RemoveHair(m)) - : Packet.Acquire(new HairEquipUpdate(m)); - - state.Send(hairPacket); - } - - if (sendFacialHair) - { - facialhairPacket ??= removeFacialHair - ? Packet.Acquire(new RemoveFacialHair(m)) - : Packet.Acquire(new FacialHairEquipUpdate(m)); - - state.Send(facialhairPacket); - } - - SendOPLPacketTo(state); + continue; } + + if (sendRemove) + { + if (removeEntity[0] == 0) + { + OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial); + } + + state.Send(removeEntity); + } + + if (sendIncoming) + { + state.Send(new MobileIncoming(state, beholder, m)); + + if (m.IsDeadBondedPet) + { + if (deadBuffer[0] == 0) + { + OutgoingMobilePackets.CreateBondedStatus(deadBuffer, m.Serial, true); + } + + state.Send(deadBuffer); + } + } + + if (sendMoving || !state.StygianAbyss && (sendHealthbarPoison || sendHealthbarYellow)) + { + state.SendMobileMovingUsingCache(mobileMovingPackets, beholder, m); + } + + if (state.StygianAbyss) + { + if (sendHealthbarPoison) + { + hbpPacket ??= Packet.Acquire(new HealthbarPoison(m)); + + state.Send(hbpPacket); + } + + if (sendHealthbarYellow) + { + hbyPacket ??= Packet.Acquire(new HealthbarYellow(m)); + + state.Send(hbyPacket); + } + } + + if (sendPublicStats) + { + if (m.CanBeRenamedBy(beholder)) + { + statPacketTrue ??= Packet.Acquire(new MobileStatusCompact(true, m)); + + state.Send(statPacketTrue); + } + else + { + statPacketFalse ??= Packet.Acquire(new MobileStatusCompact(false, m)); + + state.Send(statPacketFalse); + } + } + else if (sendHits) + { + if (hitsPacket[0] == 0) + { + OutgoingMobilePackets.CreateMobileHits(ref hitsPacket, m, true); + } + + state.Send(hitsPacket); + } + + if (sendHair) + { + hairPacket ??= removeHair + ? Packet.Acquire(new RemoveHair(m)) + : Packet.Acquire(new HairEquipUpdate(m)); + + state.Send(hairPacket); + } + + if (sendFacialHair) + { + facialhairPacket ??= removeFacialHair + ? Packet.Acquire(new RemoveFacialHair(m)) + : Packet.Acquire(new FacialHairEquipUpdate(m)); + + state.Send(facialhairPacket); + } + + SendOPLPacketTo(state); } - Packet.Release(hitsPacket); Packet.Release(statPacketTrue); Packet.Release(statPacketFalse); Packet.Release(hairPacket); @@ -6652,7 +6646,6 @@ namespace Server if (CanRegenHits) { m_HitsTimer ??= new HitsTimer(this); - m_HitsTimer.Start(); } else diff --git a/Projects/Server/Network/Packets/AttributeNormalizer.cs b/Projects/Server/Network/Packets/AttributeNormalizer.cs index 47cc6dea2..a1fd4bef6 100644 --- a/Projects/Server/Network/Packets/AttributeNormalizer.cs +++ b/Projects/Server/Network/Packets/AttributeNormalizer.cs @@ -1,23 +1,8 @@ -/************************************************************************* - * ModernUO * - * Copyright 2019-2020 - ModernUO Development Team * - * Email: hi@modernuo.com * - * File: AttributeNormalizer.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 . * - *************************************************************************/ - namespace Server.Network { public static class AttributeNormalizer { - public static int Maximum { get; set; } = 25; + public static int Maximum { get; set; } = 100; public static bool Enabled { get; set; } = true; diff --git a/Projects/Server/Network/Packets/MobilePackets.cs b/Projects/Server/Network/Packets/MobilePackets.cs index 4f6a5e107..bac1b8e0d 100644 --- a/Projects/Server/Network/Packets/MobilePackets.cs +++ b/Projects/Server/Network/Packets/MobilePackets.cs @@ -17,92 +17,6 @@ using System.Threading; namespace Server.Network { - public sealed class MobileHits : Packet - { - public MobileHits(Mobile m) : base(0xA1, 9) - { - Stream.Write(m.Serial); - Stream.Write((short)m.HitsMax); - Stream.Write((short)m.Hits); - } - } - - public sealed class MobileHitsN : Packet - { - public MobileHitsN(Mobile m) : base(0xA1, 9) - { - Stream.Write(m.Serial); - AttributeNormalizer.Write(Stream, m.Hits, m.HitsMax); - } - } - - public sealed class MobileMana : Packet - { - public MobileMana(Mobile m) : base(0xA2, 9) - { - Stream.Write(m.Serial); - Stream.Write((short)m.ManaMax); - Stream.Write((short)m.Mana); - } - } - - public sealed class MobileManaN : Packet - { - public MobileManaN(Mobile m) : base(0xA2, 9) - { - Stream.Write(m.Serial); - AttributeNormalizer.Write(Stream, m.Mana, m.ManaMax); - } - } - - public sealed class MobileStam : Packet - { - public MobileStam(Mobile m) : base(0xA3, 9) - { - Stream.Write(m.Serial); - Stream.Write((short)m.StamMax); - Stream.Write((short)m.Stam); - } - } - - public sealed class MobileStamN : Packet - { - public MobileStamN(Mobile m) : base(0xA3, 9) - { - Stream.Write(m.Serial); - AttributeNormalizer.Write(Stream, m.Stam, m.StamMax); - } - } - - public sealed class MobileAttributes : Packet - { - public MobileAttributes(Mobile m) : base(0x2D, 17) - { - Stream.Write(m.Serial); - - Stream.Write((short)m.HitsMax); - Stream.Write((short)m.Hits); - - Stream.Write((short)m.ManaMax); - Stream.Write((short)m.Mana); - - Stream.Write((short)m.StamMax); - Stream.Write((short)m.Stam); - } - } - - public sealed class MobileAttributesN : Packet - { - public MobileAttributesN(Mobile m) : base(0x2D, 17) - { - Stream.Write(m.Serial); - - AttributeNormalizer.Write(Stream, m.Hits, m.HitsMax); - AttributeNormalizer.Write(Stream, m.Mana, m.ManaMax); - AttributeNormalizer.Write(Stream, m.Stam, m.StamMax); - } - } - public sealed class MobileName : Packet { public MobileName(Mobile m) : base(0x98) diff --git a/Projects/Server/Network/Packets/OutgoingMobilePackets.cs b/Projects/Server/Network/Packets/OutgoingMobilePackets.cs index 1706cadea..ddd004f5b 100644 --- a/Projects/Server/Network/Packets/OutgoingMobilePackets.cs +++ b/Projects/Server/Network/Packets/OutgoingMobilePackets.cs @@ -25,6 +25,9 @@ namespace Server.Network public const int DeathAnimationPacketLength = 13; public const int MobileMovingPacketLength = 17; public const int MobileMovingPacketCacheLength = MobileMovingPacketLength * 8 * 2; // 8 notoriety, 2 client versions + public const int AttributeMaximum = 100; + public const int MobileAttributePacketLength = 9; + public const int MobileAttributesPacketLength = 17; public static void CreateBondedStatus(Span buffer, Serial serial, bool bonded) { @@ -135,5 +138,119 @@ namespace Server.Network ns.Send(buffer); } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WriteAttribute(this ref SpanWriter writer, int max, int cur, bool normalize = false, bool reverse = false) + { + if (normalize && max != 0) + { + if (reverse) + { + writer.Write((short)(cur * AttributeMaximum / max)); + writer.Write((short)AttributeMaximum); + } + else + { + writer.Write((short)AttributeMaximum); + writer.Write((short)(cur * AttributeMaximum / max)); + } + } + else + { + if (reverse) + { + writer.Write((short)cur); + writer.Write((short)max); + } + else + { + writer.Write((short)max); + writer.Write((short)cur); + } + } + } + + public static void SendMobileHits(this NetState ns, Mobile m, bool normalize = false) + { + if (ns == null) + { + return; + } + + Span span = stackalloc byte[MobileAttributePacketLength]; + CreateMobileHits(ref span, m, normalize); + ns.Send(span); + } + + public static void CreateMobileHits(ref Span buffer, Mobile m, bool normalize = false) + { + var writer = new SpanWriter(buffer); + writer.Write((byte)0xA1); // Packet ID + writer.Write(m.Serial); + writer.WriteAttribute(m.HitsMax, m.Hits, normalize); + } + + public static void SendMobileMana(this NetState ns, Mobile m, bool normalize = false) + { + if (ns == null) + { + return; + } + + Span span = stackalloc byte[MobileAttributePacketLength]; + CreateMobileMana(ref span, m, normalize); + ns.Send(span); + } + + public static void CreateMobileMana(ref Span buffer, Mobile m, bool normalize = false) + { + var writer = new SpanWriter(buffer); + writer.Write((byte)0xA2); // Packet ID + writer.Write(m.Serial); + writer.WriteAttribute(m.ManaMax, m.Mana, normalize); + } + + public static void SendMobileStam(this NetState ns, Mobile m, bool normalize = false) + { + if (ns == null) + { + return; + } + + Span span = stackalloc byte[MobileAttributePacketLength]; + CreateMobileStam(ref span, m, normalize); + ns.Send(span); + } + + public static void CreateMobileStam(ref Span buffer, Mobile m, bool normalize = false) + { + var writer = new SpanWriter(buffer); + writer.Write((byte)0xA3); // Packet ID + writer.Write(m.Serial); + writer.WriteAttribute(m.StamMax, m.Stam, normalize); + } + + public static void SendMobileAttributes(this NetState ns, Mobile m, bool normalize = false) + { + if (ns == null) + { + return; + } + + Span span = stackalloc byte[MobileAttributesPacketLength]; + CreateMobileAttributes(ref span, m, normalize); + ns.Send(span); + } + + public static void CreateMobileAttributes(ref Span buffer, Mobile m, bool normalize = false) + { + var writer = new SpanWriter(buffer); + writer.Write((byte)0x2D); // Packet ID + writer.Write(m.Serial); + + writer.WriteAttribute(m.HitsMax, m.Hits, normalize); + writer.WriteAttribute(m.ManaMax, m.Mana, normalize); + writer.WriteAttribute(m.StamMax, m.Stam, normalize); + } } } diff --git a/Projects/UOContent/Engines/Party/Party.cs b/Projects/UOContent/Engines/Party/Party.cs index f2bb158c7..7ae14cb3b 100644 --- a/Projects/UOContent/Engines/Party/Party.cs +++ b/Projects/UOContent/Engines/Party/Party.cs @@ -50,46 +50,36 @@ namespace Server.Engines.PartySystem public void OnStamChanged(Mobile m) { - Packet p = null; + Span p = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength]; + OutgoingMobilePackets.CreateMobileStam(ref p, m, true); for (var i = 0; i < Members.Count; ++i) { var c = Members[i].Mobile; + var ns = c.NetState; - if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m)) + if (c != m && ns != null && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m)) { - if (p == null) - { - p = Packet.Acquire(new MobileStamN(m)); - } - - c.Send(p); + ns.Send(p); } } - - Packet.Release(p); } public void OnManaChanged(Mobile m) { - Packet p = null; + Span p = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength]; + OutgoingMobilePackets.CreateMobileMana(ref p, m, true); for (var i = 0; i < Members.Count; ++i) { var c = Members[i].Mobile; + var ns = c.NetState; - if (c != m && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m)) + if (c != m && ns != null && m.Map == c.Map && Utility.InUpdateRange(c, m) && c.CanSee(m)) { - if (p == null) - { - p = Packet.Acquire(new MobileManaN(m)); - } - - c.Send(p); + ns.Send(p); } } - - Packet.Release(p); } public void OnStatsQuery(Mobile beholder, Mobile beheld) @@ -102,7 +92,7 @@ namespace Server.Engines.PartySystem beholder.Send(new MobileStatusCompact(beheld.CanBeRenamedBy(beholder), beheld)); } - beholder.Send(new MobileAttributesN(beheld)); + beholder.NetState.SendMobileAttributes(beheld, true); } } @@ -198,11 +188,13 @@ namespace Server.Engines.PartySystem if (mi == null) { + var ns = m.NetState; Members.Add(new PartyMemberInfo(m)); m.Party = this; var memberList = Packet.Acquire(new PartyMemberList(this)); - var attrs = Packet.Acquire(new MobileAttributesN(m)); + Span attrsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributesPacketLength]; + OutgoingMobilePackets.CreateMobileAttributes(ref attrsPacket, m, true); for (var i = 0; i < Members.Count; ++i) { @@ -213,14 +205,13 @@ namespace Server.Engines.PartySystem if (f != m) { f.Send(new MobileStatusCompact(m.CanBeRenamedBy(f), m)); - f.Send(attrs); + f.NetState?.Send(attrsPacket); m.Send(new MobileStatusCompact(f.CanBeRenamedBy(m), f)); - m.Send(new MobileAttributesN(f)); + ns.SendMobileAttributes(f, true); } } Packet.Release(memberList); - Packet.Release(attrs); } } @@ -516,7 +507,10 @@ namespace Server.Engines.PartySystem Span buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(m_Mobile.Name, "")]; buffer.InitializePacket(); - var attrs = Packet.Acquire(new MobileAttributesN(m_Mobile)); + Span attrsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributesPacketLength]; + OutgoingMobilePackets.CreateMobileAttributes(ref attrsPacket, m_Mobile, true); + + var ns = m_Mobile.NetState; foreach (var mi in p.Members) { @@ -544,13 +538,11 @@ namespace Server.Engines.PartySystem m.NetState?.Send(buffer); m.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile)); - m.Send(attrs); + m.NetState?.Send(attrsPacket); m_Mobile.Send(new MobileStatusCompact(m.CanBeRenamedBy(m_Mobile), m)); - m_Mobile.Send(new MobileAttributesN(m)); + ns.SendMobileAttributes(m, true); } } - - Packet.Release(attrs); } } } diff --git a/Projects/UOContent/Misc/RegenRates.cs b/Projects/UOContent/Misc/RegenRates.cs index 674d2d444..36d695b80 100644 --- a/Projects/UOContent/Misc/RegenRates.cs +++ b/Projects/UOContent/Misc/RegenRates.cs @@ -61,9 +61,14 @@ namespace Server.Misc points += 40; } - if (Core.ML && from.Race == Race.Human) // Is this affected by the cap? + if (Core.ML && from is PlayerMobile) // does racial bonus go before/after? { - points += 2; + if (from.Race == Race.Human) + { + points += 2; + } + + points = Math.Min(points, 18); } if (points < 0) @@ -71,11 +76,6 @@ namespace Server.Misc points = 0; } - if (Core.ML && from is PlayerMobile) // does racial bonus go before/after? - { - points = Math.Min(points, 18); - } - if (CheckTransform(from, typeof(HorrificBeastSpell))) { points += 20; @@ -86,7 +86,7 @@ namespace Server.Misc points += from.Skills.Ninjitsu.Fixed / 30; } - return TimeSpan.FromSeconds(1.0 / (0.1 * (1 + points))); + return TimeSpan.FromSeconds(10.0 / (1 + points)); } private static TimeSpan Mobile_StamRegenRate(Mobile from) diff --git a/Projects/UOContent/Mobiles/BaseCreature.cs b/Projects/UOContent/Mobiles/BaseCreature.cs index d71f08165..414af3bdc 100644 --- a/Projects/UOContent/Mobiles/BaseCreature.cs +++ b/Projects/UOContent/Mobiles/BaseCreature.cs @@ -913,7 +913,7 @@ namespace Server.Mobiles public virtual TimeSpan BondingDelay => TimeSpan.FromDays(7.0); public virtual TimeSpan BondingAbandonDelay => TimeSpan.FromDays(1.0); - public override bool CanRegenHits => !IsDeadPet && base.CanRegenHits; + public override bool CanRegenHits => !IsDeadPet && !Summoned && base.CanRegenHits; public override bool CanRegenStam => !IsParagon && !IsDeadPet && base.CanRegenStam; public override bool CanRegenMana => !IsDeadPet && base.CanRegenMana;