fix: Fixes NPE in BuffTable and standardizes BuffIcon packets (#1785)

This commit is contained in:
Mink80 2024-05-21 23:43:55 +02:00 committed by GitHub
parent 50d3779d9b
commit 6747168db0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 97 additions and 86 deletions

View file

@ -20,7 +20,7 @@ namespace UOContent.Tests
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
BuffInfo.SendAddBuffPacket(ns, (Serial)mob, iconID, titleCliloc, secondaryCliloc, args, (int)timeSpan.TotalMilliseconds);
ns.SendAddBuffPacket((Serial)mob, iconID, titleCliloc, secondaryCliloc, args, (int)timeSpan.TotalMilliseconds);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
@ -34,7 +34,7 @@ namespace UOContent.Tests
var expected = new RemoveBuffPacket(m, buffIcon).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
BuffInfo.SendRemoveBuffPacket(ns, m, buffIcon);
ns.SendRemoveBuffPacket(m, buffIcon);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);

View file

@ -1,5 +1,4 @@
using System;
using System.Buffers;
using Server.Mobiles;
using Server.Network;
@ -137,84 +136,6 @@ namespace Server
{
(m as PlayerMobile)?.RemoveBuff(b);
}
public void SendAddBuffPacket(NetState ns, Serial m) => SendAddBuffPacket(
ns,
m,
ID,
TitleCliloc,
SecondaryCliloc,
Args,
TimeStart == 0 ? 0 : Math.Max(TimeStart + (long)TimeLength.TotalMilliseconds - Core.TickCount, 0)
);
public static void SendAddBuffPacket(
NetState ns, Serial mob, BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args,
long ticks
)
{
if (ns.CannotSendPackets())
{
return;
}
var hasArgs = args != null;
var length = hasArgs ? args.ToString()!.Length * 2 + 52 : 46;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xDF); // Packet ID
writer.Write((ushort)length);
writer.Write(mob);
writer.Write((short)iconID);
writer.Write((short)0x1); // command (0 = remove, 1 = add, 2 = data)
writer.Write(0);
writer.Write((short)iconID);
writer.Write((short)0x1); // command (0 = remove, 1 = add, 2 = data)
writer.Write(0);
// Truncate to whole seconds - The packet should be delayed by the partial seconds and then sent "on the second"
writer.Write((short)(ticks / 1000));
writer.Clear(3);
writer.Write(titleCliloc);
writer.Write(secondaryCliloc);
if (hasArgs)
{
writer.Write(0);
writer.Write((short)0x1);
writer.Write((ushort)0);
writer.WriteLE('\t');
writer.WriteLittleUniNull(args);
writer.Write((short)0x1);
writer.Write((ushort)0);
}
else
{
writer.Clear(10);
}
ns.Send(writer.Span);
}
public void SendRemoveBuffPacket(NetState ns, Serial mob) => SendRemoveBuffPacket(ns, mob, ID);
public static void SendRemoveBuffPacket(NetState ns, Serial mob, BuffIcon iconID)
{
if (ns.CannotSendPackets())
{
return;
}
var writer = new SpanWriter(stackalloc byte[15]);
writer.Write((byte)0xDF); // Packet ID
writer.Write((ushort)15);
writer.Write(mob);
writer.Write((short)iconID);
writer.Write((short)0x0); // command (0 = remove, 1 = add, 2 = data)
writer.Write(0);
ns.Send(writer.Span);
}
}
public enum BuffIcon : short

View file

@ -4492,13 +4492,32 @@ namespace Server.Mobiles
public void ResetRecipes() => _acquiredRecipes = null;
public void SendAddBuffPacket(BuffInfo buffInfo)
{
if (buffInfo == null)
{
return;
}
NetState.SendAddBuffPacket(
Serial,
buffInfo.ID,
buffInfo.TitleCliloc,
buffInfo.SecondaryCliloc,
buffInfo.Args,
buffInfo.TimeStart == 0
? 0
: Math.Max(buffInfo.TimeStart + (long)buffInfo.TimeLength.TotalMilliseconds - Core.TickCount, 0)
);
}
public void ResendBuffs()
{
if (BuffInfo.Enabled && m_BuffTable != null && NetState?.BuffIcon == true)
{
foreach (var info in m_BuffTable.Values)
{
info.SendAddBuffPacket(NetState, Serial);
SendAddBuffPacket(info);
}
}
}
@ -4525,15 +4544,15 @@ namespace Server.Mobiles
Timer.DelayCall(TimeSpan.FromMilliseconds(msecs), (buffInfo, pm) =>
{
// They are still online, we still have the buff icon in the table, and it is the same buff icon
if (pm.NetState != null && pm.m_BuffTable.TryGetValue(buffInfo.ID, out var checkBuff) && checkBuff == buffInfo)
if (pm.NetState != null && pm.m_BuffTable?.GetValueOrDefault(buffInfo.ID) == buffInfo)
{
buffInfo.SendAddBuffPacket(pm.NetState, pm.Serial);
pm.SendAddBuffPacket(buffInfo);
}
}, b, this);
}
else
{
b.SendAddBuffPacket(NetState, Serial);
SendAddBuffPacket(b);
}
}
}
@ -4557,7 +4576,7 @@ namespace Server.Mobiles
if (NetState?.BuffIcon == true)
{
BuffInfo.SendRemoveBuffPacket(NetState, Serial, b);
NetState.SendRemoveBuffPacket(Serial, b);
}
if (m_BuffTable.Count <= 0)

View file

@ -0,0 +1,71 @@
using System.Buffers;
namespace Server.Network;
public static class BuffIconPackets
{
public static void SendAddBuffPacket(
this NetState ns, Serial mob, BuffIcon iconID, int titleCliloc, int secondaryCliloc, TextDefinition args, long ticks
)
{
if (ns.CannotSendPackets())
{
return;
}
var hasArgs = args != null;
var length = hasArgs ? args.ToString()!.Length * 2 + 52 : 46;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xDF); // Packet ID
writer.Write((ushort)length);
writer.Write(mob);
writer.Write((short)iconID);
writer.Write((short)0x1); // command (0 = remove, 1 = add, 2 = data)
writer.Write(0);
writer.Write((short)iconID);
writer.Write((short)0x1); // command (0 = remove, 1 = add, 2 = data)
writer.Write(0);
// Truncate to whole seconds - The packet should be delayed by the partial seconds and then sent "on the second"
writer.Write((short)(ticks / 1000));
writer.Clear(3);
writer.Write(titleCliloc);
writer.Write(secondaryCliloc);
if (hasArgs)
{
writer.Write(0);
writer.Write((short)0x1);
writer.Write((ushort)0);
writer.WriteLE('\t');
writer.WriteLittleUniNull(args);
writer.Write((short)0x1);
writer.Write((ushort)0);
}
else
{
writer.Clear(10);
}
ns.Send(writer.Span);
}
public static void SendRemoveBuffPacket(this NetState ns, Serial mob, BuffIcon iconID)
{
if (ns.CannotSendPackets())
{
return;
}
var writer = new SpanWriter(stackalloc byte[15]);
writer.Write((byte)0xDF); // Packet ID
writer.Write((ushort)15);
writer.Write(mob);
writer.Write((short)iconID);
writer.Write((short)0x0); // command (0 = remove, 1 = add, 2 = data)
writer.Write(0);
ns.Send(writer.Span);
}
}