fix(core): Converts virtual hair packets (#388)
- [X] Converts virtual hair packets
This commit is contained in:
parent
30ef0761cb
commit
0912876f7c
11 changed files with 214 additions and 86 deletions
|
|
@ -1,7 +1,4 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
|
||||
|
|
|
|||
|
|
@ -590,7 +590,7 @@ namespace Server.Tests.Network
|
|||
itemID |= 0x8000;
|
||||
}
|
||||
|
||||
Stream.Write(HairInfo.FakeSerial(beheld));
|
||||
Stream.Write(HairInfo.FakeSerial(beheld.Serial));
|
||||
Stream.Write((ushort)itemID);
|
||||
Stream.Write((byte)Layer.Hair);
|
||||
|
||||
|
|
@ -621,7 +621,7 @@ namespace Server.Tests.Network
|
|||
itemID |= 0x8000;
|
||||
}
|
||||
|
||||
Stream.Write(FacialHairInfo.FakeSerial(beheld));
|
||||
Stream.Write(FacialHairInfo.FakeSerial(beheld.Serial));
|
||||
Stream.Write((ushort)itemID);
|
||||
Stream.Write((byte)Layer.FacialHair);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using Server.HuePickers;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Server.Network;
|
||||
using Xunit;
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
using System;
|
||||
using Server.Network;
|
||||
using Server.Tests.Network;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests
|
||||
{
|
||||
public class VirtualHairPacketTests: IClassFixture<ServerFixture>
|
||||
{
|
||||
[Fact]
|
||||
public void TestSendVirtualHairUpdate()
|
||||
{
|
||||
var m = new Mobile(0x1024u);
|
||||
m.DefaultMobileInit();
|
||||
|
||||
var expected = new HairEquipUpdate(m).Compile();
|
||||
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendHairEquipUpdatePacket(m, HairInfo.FakeSerial(m.Serial), Layer.Hair);
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestSendRemoveVirtualHair()
|
||||
{
|
||||
var m = new Mobile(0x1024u);
|
||||
m.DefaultMobileInit();
|
||||
|
||||
var expected = new RemoveHair(m).Compile();
|
||||
|
||||
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||
ns.SendRemoveHairPacket(HairInfo.FakeSerial(m.Serial));
|
||||
|
||||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
namespace Server.Network
|
||||
{
|
||||
public sealed class HairEquipUpdate : Packet
|
||||
{
|
||||
public HairEquipUpdate(Mobile parent)
|
||||
: base(0x2E, 15)
|
||||
{
|
||||
var hue = parent.SolidHueOverride >= 0 ? parent.SolidHueOverride : parent.HairHue;
|
||||
|
||||
Stream.Write(HairInfo.FakeSerial(parent.Serial));
|
||||
Stream.Write((short)parent.HairItemID);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)Layer.Hair);
|
||||
Stream.Write(parent.Serial);
|
||||
Stream.Write((short)hue);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FacialHairEquipUpdate : Packet
|
||||
{
|
||||
public FacialHairEquipUpdate(Mobile parent)
|
||||
: base(0x2E, 15)
|
||||
{
|
||||
var hue = parent.SolidHueOverride >= 0 ? parent.SolidHueOverride : parent.FacialHairHue;
|
||||
|
||||
Stream.Write(FacialHairInfo.FakeSerial(parent.Serial));
|
||||
Stream.Write((short)parent.FacialHairItemID);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)Layer.FacialHair);
|
||||
Stream.Write(parent.Serial);
|
||||
Stream.Write((short)hue);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RemoveHair : Packet
|
||||
{
|
||||
public RemoveHair(Mobile parent)
|
||||
: base(0x1D, 5)
|
||||
{
|
||||
Stream.Write(HairInfo.FakeSerial(parent.Serial));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RemoveFacialHair : Packet
|
||||
{
|
||||
public RemoveFacialHair(Mobile parent)
|
||||
: base(0x1D, 5)
|
||||
{
|
||||
Stream.Write(FacialHairInfo.FakeSerial(parent.Serial));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,7 +1,62 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
public static class OutgoingVirtualHairPackets
|
||||
{
|
||||
public const int EquipUpdatePacketLength = 15;
|
||||
public const int RemovePacketLength = 5;
|
||||
|
||||
public static void SendHairEquipUpdatePacket(this NetState ns, Mobile m, Serial hairSerial, Layer layer)
|
||||
{
|
||||
if (ns == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Span<byte> buffer = stackalloc byte[EquipUpdatePacketLength];
|
||||
CreateHairEquipUpdatePacket(buffer, m, hairSerial, layer);
|
||||
ns.Send(buffer);
|
||||
}
|
||||
|
||||
public static void CreateHairEquipUpdatePacket(Span<byte> buffer, Mobile m, Serial hairSerial, Layer layer)
|
||||
{
|
||||
var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.HairHue;
|
||||
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Write((byte)0x2E); // Packet ID
|
||||
|
||||
writer.Write(hairSerial);
|
||||
writer.Write((short)m.HairItemID);
|
||||
writer.Write((byte)0);
|
||||
writer.Write((byte)layer);
|
||||
writer.Write(m.Serial);
|
||||
writer.Write((short)hue);
|
||||
}
|
||||
|
||||
public static void SendRemoveHairPacket(this NetState ns, Serial hairSerial)
|
||||
{
|
||||
if (ns == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Span<byte> buffer = stackalloc byte[RemovePacketLength];
|
||||
CreateRemoveHairPacket(buffer, hairSerial);
|
||||
ns.Send(buffer);
|
||||
}
|
||||
|
||||
public static void CreateRemoveHairPacket(Span<byte> buffer, Serial hairSerial)
|
||||
{
|
||||
var writer = new SpanWriter(buffer);
|
||||
writer.Write((byte)0x1D); // Packet ID
|
||||
writer.Write(hairSerial);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class BaseHairInfo
|
||||
{
|
||||
protected BaseHairInfo(int itemid, int hue = 0)
|
||||
|
|
@ -57,7 +112,8 @@ namespace Server
|
|||
}
|
||||
|
||||
// TODO: Can we make this higher for newer clients?
|
||||
public static uint FakeSerial(Mobile parent) => 0x7FFFFFFF - 0x400 - parent.Serial * 4;
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static uint FakeSerial(Serial m) => 0x7FFFFFFF - 0x400 - m * 4;
|
||||
}
|
||||
|
||||
public class FacialHairInfo : BaseHairInfo
|
||||
|
|
@ -77,57 +133,8 @@ namespace Server
|
|||
{
|
||||
}
|
||||
|
||||
// TOOD: Can we make this higher for newer clients?
|
||||
public static uint FakeSerial(Mobile parent) => 0x7FFFFFFF - 0x400 - 1 - parent.Serial * 4;
|
||||
}
|
||||
|
||||
public sealed class HairEquipUpdate : Packet
|
||||
{
|
||||
public HairEquipUpdate(Mobile parent)
|
||||
: base(0x2E, 15)
|
||||
{
|
||||
var hue = parent.SolidHueOverride >= 0 ? parent.SolidHueOverride : parent.HairHue;
|
||||
|
||||
Stream.Write(HairInfo.FakeSerial(parent));
|
||||
Stream.Write((short)parent.HairItemID);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)Layer.Hair);
|
||||
Stream.Write(parent.Serial);
|
||||
Stream.Write((short)hue);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class FacialHairEquipUpdate : Packet
|
||||
{
|
||||
public FacialHairEquipUpdate(Mobile parent)
|
||||
: base(0x2E, 15)
|
||||
{
|
||||
var hue = parent.SolidHueOverride >= 0 ? parent.SolidHueOverride : parent.FacialHairHue;
|
||||
|
||||
Stream.Write(FacialHairInfo.FakeSerial(parent));
|
||||
Stream.Write((short)parent.FacialHairItemID);
|
||||
Stream.Write((byte)0);
|
||||
Stream.Write((byte)Layer.FacialHair);
|
||||
Stream.Write(parent.Serial);
|
||||
Stream.Write((short)hue);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RemoveHair : Packet
|
||||
{
|
||||
public RemoveHair(Mobile parent)
|
||||
: base(0x1D, 5)
|
||||
{
|
||||
Stream.Write(HairInfo.FakeSerial(parent));
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class RemoveFacialHair : Packet
|
||||
{
|
||||
public RemoveFacialHair(Mobile parent)
|
||||
: base(0x1D, 5)
|
||||
{
|
||||
Stream.Write(FacialHairInfo.FakeSerial(parent));
|
||||
}
|
||||
// TODO: Can we make this higher for newer clients?
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static uint FakeSerial(Serial m) => 0x7FFFFFFF - 0x400 - 1 - m * 4;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3101,11 +3101,11 @@ namespace Server
|
|||
{
|
||||
if (removeHair)
|
||||
{
|
||||
ourState.Send(new RemoveHair(this));
|
||||
ourState.SendRemoveHairPacket(HairInfo.FakeSerial(Serial));
|
||||
}
|
||||
else
|
||||
{
|
||||
ourState.Send(new HairEquipUpdate(this));
|
||||
ourState.SendHairEquipUpdatePacket(this, HairInfo.FakeSerial(Serial), Layer.Hair);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3113,11 +3113,11 @@ namespace Server
|
|||
{
|
||||
if (removeFacialHair)
|
||||
{
|
||||
ourState.Send(new RemoveFacialHair(this));
|
||||
ourState.SendRemoveHairPacket(FacialHairInfo.FakeSerial(Serial));
|
||||
}
|
||||
else
|
||||
{
|
||||
ourState.Send(new FacialHairEquipUpdate(this));
|
||||
ourState.SendHairEquipUpdatePacket(this, FacialHairInfo.FakeSerial(Serial), Layer.FacialHair);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3144,9 +3144,6 @@ namespace Server
|
|||
return;
|
||||
}
|
||||
|
||||
Packet hairPacket = null;
|
||||
Packet facialhairPacket = null;
|
||||
|
||||
var eable = Map.GetClientsInRange(m_Location);
|
||||
|
||||
Span<byte> statBufferTrue = stackalloc byte[OutgoingMobilePackets.MobileStatusCompactLength];
|
||||
|
|
@ -3170,6 +3167,20 @@ namespace Server
|
|||
Span<byte> hitsPacket = stackalloc byte[OutgoingMobilePackets.MobileAttributePacketLength];
|
||||
hitsPacket.InitializePacket();
|
||||
|
||||
var hairLength = removeHair
|
||||
? OutgoingVirtualHairPackets.RemovePacketLength
|
||||
: OutgoingVirtualHairPackets.EquipUpdatePacketLength;
|
||||
|
||||
Span<byte> hairPacket = stackalloc byte[hairLength];
|
||||
hairPacket.InitializePacket();
|
||||
|
||||
var facialHairLength = removeFacialHair
|
||||
? OutgoingVirtualHairPackets.RemovePacketLength
|
||||
: OutgoingVirtualHairPackets.EquipUpdatePacketLength;
|
||||
|
||||
Span<byte> facialhairPacket = stackalloc byte[facialHairLength];
|
||||
facialhairPacket.InitializePacket();
|
||||
|
||||
foreach (var state in eable)
|
||||
{
|
||||
var beholder = state.Mobile;
|
||||
|
|
@ -3265,18 +3276,46 @@ namespace Server
|
|||
|
||||
if (sendHair)
|
||||
{
|
||||
hairPacket ??= removeHair
|
||||
? Packet.Acquire(new RemoveHair(this))
|
||||
: Packet.Acquire(new HairEquipUpdate(this));
|
||||
if (hairPacket[0] == 0)
|
||||
{
|
||||
var hairSerial = HairInfo.FakeSerial(Serial);
|
||||
if (removeHair)
|
||||
{
|
||||
OutgoingVirtualHairPackets.CreateRemoveHairPacket(hairPacket, hairSerial);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutgoingVirtualHairPackets.CreateHairEquipUpdatePacket(
|
||||
hairPacket,
|
||||
this,
|
||||
hairSerial,
|
||||
Layer.Hair
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
state.Send(hairPacket);
|
||||
}
|
||||
|
||||
if (sendFacialHair)
|
||||
{
|
||||
facialhairPacket ??= removeFacialHair
|
||||
? Packet.Acquire(new RemoveFacialHair(this))
|
||||
: Packet.Acquire(new FacialHairEquipUpdate(this));
|
||||
if (facialhairPacket[0] == 0)
|
||||
{
|
||||
var hairSerial = HairInfo.FakeSerial(Serial);
|
||||
if (removeFacialHair)
|
||||
{
|
||||
OutgoingVirtualHairPackets.CreateRemoveHairPacket(facialhairPacket, hairSerial);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutgoingVirtualHairPackets.CreateHairEquipUpdatePacket(
|
||||
facialhairPacket,
|
||||
this,
|
||||
hairSerial,
|
||||
Layer.FacialHair
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
state.Send(facialhairPacket);
|
||||
}
|
||||
|
|
@ -3284,9 +3323,6 @@ namespace Server
|
|||
SendOPLPacketTo(state);
|
||||
}
|
||||
|
||||
Packet.Release(hairPacket);
|
||||
Packet.Release(facialhairPacket);
|
||||
|
||||
eable.Free();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -614,7 +614,7 @@ namespace Server.Network
|
|||
itemID |= 0x8000;
|
||||
}
|
||||
|
||||
writer.Write(HairInfo.FakeSerial(beheld));
|
||||
writer.Write(HairInfo.FakeSerial(beheld.Serial));
|
||||
writer.Write((ushort)itemID);
|
||||
writer.Write((byte)Layer.Hair);
|
||||
|
||||
|
|
@ -637,7 +637,7 @@ namespace Server.Network
|
|||
itemID |= 0x8000;
|
||||
}
|
||||
|
||||
writer.Write(FacialHairInfo.FakeSerial(beheld));
|
||||
writer.Write(FacialHairInfo.FakeSerial(beheld.Serial));
|
||||
writer.Write((ushort)itemID);
|
||||
writer.Write((byte)Layer.FacialHair);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,13 +38,13 @@ namespace Server.Network
|
|||
if (beheld.Hair?.ItemID > 0)
|
||||
{
|
||||
Stream.Write((byte)(Layer.Hair + 1));
|
||||
Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2);
|
||||
Stream.Write(HairInfo.FakeSerial(beheld.Owner.Serial) - 2);
|
||||
}
|
||||
|
||||
if (beheld.FacialHair?.ItemID > 0)
|
||||
{
|
||||
Stream.Write((byte)(Layer.FacialHair + 1));
|
||||
Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2);
|
||||
Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner.Serial) - 2);
|
||||
}
|
||||
|
||||
Stream.Write((byte)Layer.Invalid);
|
||||
|
|
@ -98,7 +98,7 @@ namespace Server.Network
|
|||
|
||||
if (beheld.Hair?.ItemID > 0)
|
||||
{
|
||||
Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2);
|
||||
Stream.Write(HairInfo.FakeSerial(beheld.Owner.Serial) - 2);
|
||||
Stream.Write((ushort)beheld.Hair.ItemID);
|
||||
Stream.Write((byte)0); // signed, itemID offset
|
||||
Stream.Write((ushort)1);
|
||||
|
|
@ -112,7 +112,7 @@ namespace Server.Network
|
|||
|
||||
if (beheld.FacialHair?.ItemID > 0)
|
||||
{
|
||||
Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2);
|
||||
Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner.Serial) - 2);
|
||||
Stream.Write((ushort)beheld.FacialHair.ItemID);
|
||||
Stream.Write((byte)0); // signed, itemID offset
|
||||
Stream.Write((ushort)1);
|
||||
|
|
@ -177,7 +177,7 @@ namespace Server.Network
|
|||
|
||||
if (beheld.Hair?.ItemID > 0)
|
||||
{
|
||||
Stream.Write(HairInfo.FakeSerial(beheld.Owner) - 2);
|
||||
Stream.Write(HairInfo.FakeSerial(beheld.Owner.Serial) - 2);
|
||||
Stream.Write((ushort)beheld.Hair.ItemID);
|
||||
Stream.Write((byte)0); // signed, itemID offset
|
||||
Stream.Write((ushort)1);
|
||||
|
|
@ -192,7 +192,7 @@ namespace Server.Network
|
|||
|
||||
if (beheld.FacialHair?.ItemID > 0)
|
||||
{
|
||||
Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner) - 2);
|
||||
Stream.Write(FacialHairInfo.FakeSerial(beheld.Owner.Serial) - 2);
|
||||
Stream.Write((ushort)beheld.FacialHair.ItemID);
|
||||
Stream.Write((byte)0); // signed, itemID offset
|
||||
Stream.Write((ushort)1);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue