fix(core): Converts mobile moving packet (#357)
- [X] Converts mobile moving packet
This commit is contained in:
parent
c2143584bc
commit
10a6e17640
9 changed files with 147 additions and 170 deletions
|
|
@ -17,6 +17,7 @@
|
|||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
<WarningsAsErrors />
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<!-- <SkipLocalsInitAttribute>true</SkipLocalsInitAttribute>-->
|
||||
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows>
|
||||
<IsOSX Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::OSX)))' == 'true'">true</IsOSX>
|
||||
<IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>
|
||||
|
|
@ -24,6 +25,7 @@
|
|||
<DefineConstants Condition="'$(IsOSX)'=='true'">OSX</DefineConstants>
|
||||
<DefineConstants Condition="'$(IsLinux)'=='true'">LINUX</DefineConstants>
|
||||
<DefineConstants Condition="'$(IsOSX)'=='true' OR '$(IsLinux)'=='true'">UNIX</DefineConstants>
|
||||
<DefineConstants Condition="'$(SkipLocalsInitAttribute)'=='true'">NO_LOCAL_INIT</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'==''">
|
||||
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
||||
|
|
|
|||
|
|
@ -26,52 +26,35 @@ namespace Server.Tests.Network
|
|||
public void TestBondStatus()
|
||||
{
|
||||
Serial petSerial = 0x1;
|
||||
var bonded = true;
|
||||
const bool bonded = true;
|
||||
|
||||
var data = new BondedStatus(petSerial, bonded).Compile();
|
||||
var expected = new BondedStatus(petSerial, bonded).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[11];
|
||||
var pos = 0;
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendBondedStatus(petSerial, bonded);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0xBF); // Packet ID
|
||||
expectedData.Write(ref pos, (ushort)0x0B); // Length
|
||||
expectedData.Write(ref pos, (ushort)0x19); // Sub-packet
|
||||
|
||||
#if NO_LOCAL_INIT
|
||||
expectedData.Write(ref pos, (byte)0); // Command
|
||||
#else
|
||||
pos++;
|
||||
#endif
|
||||
|
||||
expectedData.Write(ref pos, petSerial);
|
||||
expectedData.Write(ref pos, bonded);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestMobileMoving()
|
||||
[Theory]
|
||||
[InlineData(ProtocolChanges.StygianAbyss)]
|
||||
[InlineData(ProtocolChanges.None)]
|
||||
public void TestMobileMoving(ProtocolChanges protocolChanges)
|
||||
{
|
||||
var m = new Mobile(0x1);
|
||||
m.DefaultMobileInit();
|
||||
|
||||
var noto = 10;
|
||||
|
||||
var data = new MobileMoving(m, noto, true).Compile();
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.ProtocolChanges = protocolChanges;
|
||||
var expected = new MobileMoving(m, noto, ns.StygianAbyss).Compile();
|
||||
|
||||
Span<byte> expectedData = stackalloc byte[17];
|
||||
var pos = 0;
|
||||
ns.SendMobileMoving(m, noto);
|
||||
|
||||
expectedData.Write(ref pos, (byte)0x77); // Packet ID
|
||||
expectedData.Write(ref pos, m.Serial);
|
||||
expectedData.Write(ref pos, (ushort)m.Body);
|
||||
expectedData.Write(ref pos, m.Location);
|
||||
expectedData.Write(ref pos, (byte)m.Direction);
|
||||
expectedData.Write(ref pos, (ushort)m.Hue);
|
||||
expectedData.Write(ref pos, (byte)m.GetPacketFlags(true));
|
||||
expectedData.Write(ref pos, (byte)noto);
|
||||
|
||||
AssertThat.Equal(data, expectedData);
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
|
|
|||
|
|
@ -14,4 +14,39 @@ namespace Server.Tests.Network
|
|||
Stream.Write((byte)(bonded ? 1 : 0));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DeathAnimation : Packet
|
||||
{
|
||||
public DeathAnimation(Serial killed, Serial corpse) : base(0xAF, 13)
|
||||
{
|
||||
Stream.Write(killed);
|
||||
Stream.Write(corpse);
|
||||
Stream.Write(0);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileMoving : Packet
|
||||
{
|
||||
public MobileMoving(Mobile m, int noto, bool stygianAbyss) : base(0x77, 17)
|
||||
{
|
||||
var loc = m.Location;
|
||||
|
||||
var hue = m.Hue;
|
||||
|
||||
if (m.SolidHueOverride >= 0)
|
||||
{
|
||||
hue = m.SolidHueOverride;
|
||||
}
|
||||
|
||||
Stream.Write(m.Serial);
|
||||
Stream.Write((short)m.Body);
|
||||
Stream.Write((short)loc.X);
|
||||
Stream.Write((short)loc.Y);
|
||||
Stream.Write((sbyte)loc.Z);
|
||||
Stream.Write((byte)m.Direction);
|
||||
Stream.Write((short)hue);
|
||||
Stream.Write((byte)m.GetPacketFlags(stygianAbyss));
|
||||
Stream.Write((byte)noto);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -435,12 +435,6 @@ namespace Server
|
|||
private static readonly TimeSpan ExpireCombatantDelay = TimeSpan.FromMinutes(1.0);
|
||||
private static readonly TimeSpan ExpireAggressorsDelay = TimeSpan.FromSeconds(5.0);
|
||||
|
||||
private static readonly Packet[][] m_MovingPacketCache =
|
||||
{
|
||||
new Packet[8],
|
||||
new Packet[8]
|
||||
};
|
||||
|
||||
private static readonly List<IEntity> m_MoveList = new();
|
||||
private static readonly List<Mobile> m_MoveClientList = new();
|
||||
|
||||
|
|
@ -3055,7 +3049,8 @@ namespace Server
|
|||
sendFacialHair = true;
|
||||
}
|
||||
|
||||
var cache = new[] { new Packet[8], new Packet[8] };
|
||||
Span<byte> mobileMovingPackets = stackalloc byte[OutgoingMobilePackets.MobileMovingPacketCacheLength];
|
||||
mobileMovingPackets.InitializePackets(OutgoingMobilePackets.MobileMovingPacketLength);
|
||||
|
||||
var ourState = m.m_NetState;
|
||||
|
||||
|
|
@ -3072,14 +3067,13 @@ namespace Server
|
|||
ourState.Send(new MobileIncoming(ourState, m, m));
|
||||
}
|
||||
|
||||
if (sendMoving || !ourState.StygianAbyss && (sendHealthbarPoison || sendHealthbarYellow))
|
||||
{
|
||||
ourState.SendMobileMovingUsingCache(mobileMovingPackets, m, m);
|
||||
}
|
||||
|
||||
if (ourState.StygianAbyss)
|
||||
{
|
||||
if (sendMoving)
|
||||
{
|
||||
var noto = Notoriety.Compute(m, m);
|
||||
ourState.Send(cache[0][noto] = Packet.Acquire(new MobileMoving(m, noto, true)));
|
||||
}
|
||||
|
||||
if (sendHealthbarPoison)
|
||||
{
|
||||
ourState.Send(new HealthbarPoison(m));
|
||||
|
|
@ -3090,14 +3084,6 @@ namespace Server
|
|||
ourState.Send(new HealthbarYellow(m));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sendMoving || sendHealthbarPoison || sendHealthbarYellow)
|
||||
{
|
||||
var noto = Notoriety.Compute(m, m);
|
||||
ourState.Send(cache[1][noto] = Packet.Acquire(new MobileMoving(m, noto, false)));
|
||||
}
|
||||
}
|
||||
|
||||
if (sendPublicStats || sendPrivateStats)
|
||||
{
|
||||
|
|
@ -3218,22 +3204,13 @@ namespace Server
|
|||
}
|
||||
}
|
||||
|
||||
if (sendMoving || !state.StygianAbyss && (sendHealthbarPoison || sendHealthbarYellow))
|
||||
{
|
||||
state.SendMobileMovingUsingCache(mobileMovingPackets, beholder, m);
|
||||
}
|
||||
|
||||
if (state.StygianAbyss)
|
||||
{
|
||||
if (sendMoving)
|
||||
{
|
||||
var noto = Notoriety.Compute(beholder, m);
|
||||
|
||||
var p = cache[0][noto];
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
cache[0][noto] = p = Packet.Acquire(new MobileMoving(m, noto, true));
|
||||
}
|
||||
|
||||
state.Send(p);
|
||||
}
|
||||
|
||||
if (sendHealthbarPoison)
|
||||
{
|
||||
hbpPacket ??= Packet.Acquire(new HealthbarPoison(m));
|
||||
|
|
@ -3248,22 +3225,6 @@ namespace Server
|
|||
state.Send(hbyPacket);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (sendMoving || sendHealthbarPoison || sendHealthbarYellow)
|
||||
{
|
||||
var noto = Notoriety.Compute(beholder, m);
|
||||
|
||||
var p = cache[1][noto];
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
cache[1][noto] = p = Packet.Acquire(new MobileMoving(m, noto, false));
|
||||
}
|
||||
|
||||
state.Send(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (sendPublicStats)
|
||||
{
|
||||
|
|
@ -3319,17 +3280,6 @@ namespace Server
|
|||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
if (sendMoving || sendNonlocalMoving || sendHealthbarPoison || sendHealthbarYellow)
|
||||
{
|
||||
for (var i = 0; i < cache.Length; ++i)
|
||||
{
|
||||
for (var j = 0; j < cache[i].Length; ++j)
|
||||
{
|
||||
Packet.Release(ref cache[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ISpawner Spawner { get; set; }
|
||||
|
|
@ -4580,11 +4530,8 @@ namespace Server
|
|||
|
||||
eable.Free();
|
||||
|
||||
var cache = m_MovingPacketCache;
|
||||
|
||||
/*for( int i = 0; i < cache.Length; ++i )
|
||||
for( int j = 0; j < cache[i].Length; ++j )
|
||||
Packet.Release( ref cache[i][j] );*/
|
||||
Span<byte> mobileMovingPackets = stackalloc byte[OutgoingMobilePackets.MobileMovingPacketCacheLength];
|
||||
mobileMovingPackets.InitializePackets(OutgoingMobilePackets.MobileMovingPacketLength);
|
||||
|
||||
foreach (var m in m_MoveClientList)
|
||||
{
|
||||
|
|
@ -4592,38 +4539,7 @@ namespace Server
|
|||
|
||||
if (ns != null && Utility.InUpdateRange(m_Location, m.m_Location) && m.CanSee(this))
|
||||
{
|
||||
if (ns.StygianAbyss)
|
||||
{
|
||||
var noto = Notoriety.Compute(m, this);
|
||||
var p = cache[0][noto];
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
cache[0][noto] = p = Packet.Acquire(new MobileMoving(this, noto, true));
|
||||
}
|
||||
|
||||
ns.Send(p);
|
||||
}
|
||||
else
|
||||
{
|
||||
var noto = Notoriety.Compute(m, this);
|
||||
var p = cache[1][noto];
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
cache[1][noto] = p = Packet.Acquire(new MobileMoving(this, noto, false));
|
||||
}
|
||||
|
||||
ns.Send(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < cache.Length; ++i)
|
||||
{
|
||||
for (var j = 0; j < cache[i].Length; ++j)
|
||||
{
|
||||
Packet.Release(ref cache[i][j]);
|
||||
ns.SendMobileMovingUsingCache(mobileMovingPackets, m, this);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
|
@ -38,5 +39,17 @@ namespace Server.Network
|
|||
writer.Write((ushort)length);
|
||||
writer.Seek(length, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void InitializePackets(this Span<byte> buffer, int chunkLength)
|
||||
{
|
||||
var index = 0;
|
||||
|
||||
while (index < buffer.Length)
|
||||
{
|
||||
buffer[index] = 0;
|
||||
index += chunkLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,41 +17,6 @@ using System.Threading;
|
|||
|
||||
namespace Server.Network
|
||||
{
|
||||
public sealed class DeathAnimation : Packet
|
||||
{
|
||||
public DeathAnimation(Serial killed, Serial corpse) : base(0xAF, 13)
|
||||
{
|
||||
Stream.Write(killed);
|
||||
Stream.Write(corpse);
|
||||
Stream.Write(0);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileMoving : Packet
|
||||
{
|
||||
public MobileMoving(Mobile m, int noto, bool stygianAbyss) : base(0x77, 17)
|
||||
{
|
||||
var loc = m.Location;
|
||||
|
||||
var hue = m.Hue;
|
||||
|
||||
if (m.SolidHueOverride >= 0)
|
||||
{
|
||||
hue = m.SolidHueOverride;
|
||||
}
|
||||
|
||||
Stream.Write(m.Serial);
|
||||
Stream.Write((short)m.Body);
|
||||
Stream.Write((short)loc.m_X);
|
||||
Stream.Write((short)loc.m_Y);
|
||||
Stream.Write((sbyte)loc.m_Z);
|
||||
Stream.Write((byte)m.Direction);
|
||||
Stream.Write((short)hue);
|
||||
Stream.Write((byte)m.GetPacketFlags(stygianAbyss));
|
||||
Stream.Write((byte)noto);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class MobileHits : Packet
|
||||
{
|
||||
public MobileHits(Mobile m) : base(0xA1, 9)
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
|
|
@ -22,6 +23,8 @@ namespace Server.Network
|
|||
{
|
||||
public const int BondedStatusPacketLength = 11;
|
||||
public const int DeathAnimationPacketLength = 13;
|
||||
public const int MobileMovingPacketLength = 17;
|
||||
public const int MobileMovingPacketCacheLength = MobileMovingPacketLength * 8 * 2; // 8 notoriety, 2 client versions
|
||||
|
||||
public static void CreateBondedStatus(ref Span<byte> buffer, Serial serial, bool bonded)
|
||||
{
|
||||
|
|
@ -72,5 +75,65 @@ namespace Server.Network
|
|||
CreateDeathAnimation(ref span, killed, corpse);
|
||||
ns.Send(span);
|
||||
}
|
||||
|
||||
public static void CreateMobileMoving(ref Span<byte> buffer, Mobile m, int noto, bool stygianAbyss)
|
||||
{
|
||||
var loc = m.Location;
|
||||
var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue;
|
||||
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Write((byte)0x77); // Packet ID
|
||||
writer.Write(m.Serial);
|
||||
writer.Write((short)m.Body);
|
||||
writer.Write((short)loc.m_X);
|
||||
writer.Write((short)loc.m_Y);
|
||||
writer.Write((sbyte)loc.m_Z);
|
||||
writer.Write((byte)m.Direction);
|
||||
writer.Write((short)hue);
|
||||
writer.Write((byte)m.GetPacketFlags(stygianAbyss));
|
||||
writer.Write((byte)noto);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SendMobileMoving(this NetState ns, Mobile source, Mobile target) =>
|
||||
ns.SendMobileMoving(target, Notoriety.Compute(source, target));
|
||||
|
||||
public static void SendMobileMoving(this NetState ns, Mobile target, int noto)
|
||||
{
|
||||
if (ns == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Span<byte> span = stackalloc byte[MobileMovingPacketLength];
|
||||
CreateMobileMoving(ref span, target, noto, ns.StygianAbyss);
|
||||
ns.Send(span);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SendMobileMovingUsingCache(this NetState ns, Span<byte> cache, Mobile source, Mobile target) =>
|
||||
ns.SendMobileMovingUsingCache(cache, target, Notoriety.Compute(source, target));
|
||||
|
||||
// Requires a buffer of 16 packets, 17bytes per packet (272 bytes).
|
||||
// Requires cache to have the first byte of each packet zeroed.
|
||||
public static void SendMobileMovingUsingCache(this NetState ns, Span<byte> cache, Mobile target, int noto)
|
||||
{
|
||||
if (ns == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var stygianAbyss = ns.StygianAbyss;
|
||||
var startIndex = (noto * 2 + (stygianAbyss ? 1 : 0)) * MobileMovingPacketLength;
|
||||
var buffer = cache.Slice(startIndex, MobileMovingPacketLength);
|
||||
|
||||
// Packet not created yet
|
||||
if (buffer[0] == 0)
|
||||
{
|
||||
CreateMobileMoving(ref buffer, target, noto, stygianAbyss);
|
||||
}
|
||||
|
||||
ns.Send(buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1438,6 +1438,7 @@ namespace Server
|
|||
return string.Join(lineSeparator, parts);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Tidy<T>(this List<T> list) where T : ISerializable
|
||||
{
|
||||
for (int i = list.Count - 1; i >= 0; i--)
|
||||
|
|
@ -1452,6 +1453,7 @@ namespace Server
|
|||
list.TrimExcess();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void Tidy<T>(this HashSet<T> set) where T : ISerializable
|
||||
{
|
||||
set.RemoveWhere(entry => entry?.Deleted != false);
|
||||
|
|
|
|||
|
|
@ -4276,9 +4276,7 @@ namespace Server.Mobiles
|
|||
|
||||
if (t == oldType || t == newType)
|
||||
{
|
||||
var ns = NetState;
|
||||
|
||||
ns?.Send(new MobileMoving(m, Notoriety.Compute(this, m), ns.StygianAbyss));
|
||||
m.NetState.SendMobileMoving(this, m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue