fix: Stops creating blocked packets entirely (#944)

Optimizes larger servers where users are logging in and packets are being created for no reason.
This commit is contained in:
Kamron Batman 2022-02-27 00:13:49 -08:00 committed by GitHub
parent 5db8b1354c
commit 941452de4a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
58 changed files with 5510 additions and 5537 deletions

View file

@ -17,338 +17,337 @@ using System;
using System.Buffers;
using System.Runtime.CompilerServices;
namespace Server.Network
namespace Server.Network;
public enum LRReason : byte
{
public enum LRReason : byte
CannotLift,
OutOfRange,
OutOfSight,
TryToSteal,
AreHolding,
Inspecific
}
public static class OutgoingPlayerPackets
{
public const int DragEffectPacketLength = 26;
public static void SendStatLockInfo(this NetState ns, Mobile m)
{
CannotLift,
OutOfRange,
OutOfSight,
TryToSteal,
AreHolding,
Inspecific
if (ns.CannotSendPackets())
{
return;
}
var writer = new SpanWriter(stackalloc byte[12]);
writer.Write((byte)0xBF); // Packet ID
writer.Write((ushort)12);
writer.Write((short)0x19);
writer.Write((byte)2);
writer.Write(m.Serial);
writer.Write((byte)0);
var lockBits = ((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock;
writer.Write((byte)lockBits);
ns.Send(writer.Span);
}
public static class OutgoingPlayerPackets
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendChangeUpdateRange(this NetState ns, byte range) =>
ns?.Send(stackalloc byte[] { 0xC8, range });
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendDeathStatus(this NetState ns, bool dead) =>
ns?.Send(stackalloc byte[] { 0x2C, dead ? (byte)0 : (byte)2 });
public static void SendDisplayProfile(this NetState ns, Serial m, string header, string body, string footer)
{
public const int DragEffectPacketLength = 26;
public static void SendStatLockInfo(this NetState ns, Mobile m)
if (ns.CannotSendPackets())
{
if (ns == null)
{
return;
}
var writer = new SpanWriter(stackalloc byte[12]);
writer.Write((byte)0xBF); // Packet ID
writer.Write((ushort)12);
writer.Write((short)0x19);
writer.Write((byte)2);
writer.Write(m.Serial);
writer.Write((byte)0);
var lockBits = ((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock;
writer.Write((byte)lockBits);
ns.Send(writer.Span);
return;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendChangeUpdateRange(this NetState ns, byte range) =>
ns?.Send(stackalloc byte[] { 0xC8, range });
header ??= "";
body ??= "";
footer ??= "";
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendDeathStatus(this NetState ns, bool dead) =>
ns?.Send(stackalloc byte[] { 0x2C, dead ? (byte)0 : (byte)2 });
var length = 12 + header.Length + footer.Length * 2 + body.Length * 2;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xB8); // Packet ID
writer.Write((ushort)length);
writer.Write(m);
writer.WriteAsciiNull(header);
writer.WriteBigUniNull(footer);
writer.WriteBigUniNull(body);
public static void SendDisplayProfile(this NetState ns, Serial m, string header, string body, string footer)
ns.Send(writer.Span);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendLiftReject(this NetState ns, LRReason reason) =>
ns?.Send(stackalloc byte[] { 0x27, (byte)reason });
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendLogoutAck(this NetState ns) => ns?.Send(stackalloc byte[] { 0xD1, 0x01 });
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendWeather(this NetState ns, byte type, byte density, byte temp) =>
ns?.Send(stackalloc byte[] { 0x65, type, density, temp });
public static void SendServerChange(this NetState ns, Point3D p, Map map)
{
if (ns.CannotSendPackets())
{
if (ns == null)
{
return;
}
header ??= "";
body ??= "";
footer ??= "";
var length = 12 + header.Length + footer.Length * 2 + body.Length * 2;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xB8); // Packet ID
writer.Write((ushort)length);
writer.Write(m);
writer.WriteAsciiNull(header);
writer.WriteBigUniNull(footer);
writer.WriteBigUniNull(body);
ns.Send(writer.Span);
return;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendLiftReject(this NetState ns, LRReason reason) =>
ns?.Send(stackalloc byte[] { 0x27, (byte)reason });
var writer = new SpanWriter(stackalloc byte[16]);
writer.Write((byte)0x76); // Packet ID
writer.Write((short)p.X);
writer.Write((short)p.Y);
writer.Write((short)p.Z);
writer.Write((byte)0);
writer.Write((short)0);
writer.Write((short)0);
writer.Write((short)map.Width);
writer.Write((short)map.Height);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendLogoutAck(this NetState ns) => ns?.Send(stackalloc byte[] { 0xD1, 0x01 });
ns.Send(writer.Span);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendWeather(this NetState ns, byte type, byte density, byte temp) =>
ns?.Send(stackalloc byte[] { 0x65, type, density, temp });
public static void SendServerChange(this NetState ns, Point3D p, Map map)
public static void SendSkillsUpdate(this NetState ns, Skills skills)
{
if (ns.CannotSendPackets())
{
if (ns == null)
{
return;
}
var writer = new SpanWriter(stackalloc byte[16]);
writer.Write((byte)0x76); // Packet ID
writer.Write((short)p.X);
writer.Write((short)p.Y);
writer.Write((short)p.Z);
writer.Write((byte)0);
writer.Write((short)0);
writer.Write((short)0);
writer.Write((short)map.Width);
writer.Write((short)map.Height);
ns.Send(writer.Span);
return;
}
public static void SendSkillsUpdate(this NetState ns, Skills skills)
var length = 6 + 9 * skills.Length;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0x3A); // Packet ID
writer.Write((ushort)length);
writer.Write((byte)0x02); // type: absolute, capped
for (var i = 0; i < skills.Length; ++i)
{
if (ns == null)
{
return;
}
var s = skills[i];
var length = 6 + 9 * skills.Length;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0x3A); // Packet ID
writer.Write((ushort)length);
writer.Write((byte)0x02); // type: absolute, capped
for (var i = 0; i < skills.Length; ++i)
{
var s = skills[i];
var v = s.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
writer.Write((ushort)(s.Info.SkillID + 1));
writer.Write((ushort)uv);
writer.Write((ushort)s.BaseFixedPoint);
writer.Write((byte)s.Lock);
writer.Write((ushort)s.CapFixedPoint);
}
writer.Write((short)0); // terminate
ns.Send(writer.Span);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendSequence(this NetState ns, byte sequence) => ns?.Send(stackalloc byte[] { 0x7B, sequence });
public static void SendSkillChange(this NetState ns, Skill skill)
{
if (ns == null)
{
return;
}
var writer = new SpanWriter(stackalloc byte[13]);
writer.Write((byte)0x3A); // Packet ID
writer.Write((ushort)13);
var v = skill.NonRacialValue;
var v = s.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
writer.Write((byte)0xDF); // type: delta, capped
writer.Write((ushort)skill.Info.SkillID);
writer.Write((ushort)(s.Info.SkillID + 1));
writer.Write((ushort)uv);
writer.Write((ushort)skill.BaseFixedPoint);
writer.Write((byte)skill.Lock);
writer.Write((ushort)skill.CapFixedPoint);
ns.Send(writer.Span);
writer.Write((ushort)s.BaseFixedPoint);
writer.Write((byte)s.Lock);
writer.Write((ushort)s.CapFixedPoint);
}
public static void SendLaunchBrowser(this NetState ns, string uri)
writer.Write((short)0); // terminate
ns.Send(writer.Span);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendSequence(this NetState ns, byte sequence) => ns?.Send(stackalloc byte[] { 0x7B, sequence });
public static void SendSkillChange(this NetState ns, Skill skill)
{
if (ns.CannotSendPackets())
{
if (ns == null)
{
return;
}
uri ??= "";
var length = 4 + uri.Length;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xA5); // Packet ID
writer.Write((ushort)length);
writer.WriteAsciiNull(uri);
ns.Send(writer.Span);
return;
}
public static void CreateDragEffect(
Span<byte> buffer,
Serial srcSerial, Point3D srcLocation,
Serial trgSerial, Point3D trgLocation,
int itemID, int hue, int amount
)
var writer = new SpanWriter(stackalloc byte[13]);
writer.Write((byte)0x3A); // Packet ID
writer.Write((ushort)13);
var v = skill.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
writer.Write((byte)0xDF); // type: delta, capped
writer.Write((ushort)skill.Info.SkillID);
writer.Write((ushort)uv);
writer.Write((ushort)skill.BaseFixedPoint);
writer.Write((byte)skill.Lock);
writer.Write((ushort)skill.CapFixedPoint);
ns.Send(writer.Span);
}
public static void SendLaunchBrowser(this NetState ns, string uri)
{
if (ns.CannotSendPackets())
{
if (buffer[0] != 0)
{
return;
}
var writer = new SpanWriter(buffer);
writer.Write((byte)0x23); // Packet ID
writer.Write((short)itemID);
writer.Write((byte)0);
writer.Write((short)hue);
writer.Write((short)amount);
writer.Write(srcSerial);
writer.Write((short)srcLocation.X);
writer.Write((short)srcLocation.Y);
writer.Write((sbyte)srcLocation.Z);
writer.Write(trgSerial);
writer.Write((short)trgLocation.X);
writer.Write((short)trgLocation.Y);
writer.Write((sbyte)trgLocation.Z);
return;
}
public static void SendDragEffect(
this NetState ns,
Serial srcSerial, Point3D srcLocation,
Serial trgSerial, Point3D trgLocation,
int itemID, int hue, int amount
)
uri ??= "";
var length = 4 + uri.Length;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xA5); // Packet ID
writer.Write((ushort)length);
writer.WriteAsciiNull(uri);
ns.Send(writer.Span);
}
public static void CreateDragEffect(
Span<byte> buffer,
Serial srcSerial, Point3D srcLocation,
Serial trgSerial, Point3D trgLocation,
int itemID, int hue, int amount
)
{
if (buffer[0] != 0)
{
if (ns == null)
{
return;
}
Span<byte> buffer = stackalloc byte[DragEffectPacketLength].InitializePacket();
CreateDragEffect(buffer, srcSerial, srcLocation, trgSerial, trgLocation, itemID, hue, amount);
ns.Send(buffer);
return;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void SendSeasonChange(this NetState ns, byte season, bool playSound) =>
ns?.Send(stackalloc byte[]{ 0xBC, season, *(byte*)&playSound });
var writer = new SpanWriter(buffer);
writer.Write((byte)0x23); // Packet ID
writer.Write((short)itemID);
writer.Write((byte)0);
writer.Write((short)hue);
writer.Write((short)amount);
writer.Write(srcSerial);
writer.Write((short)srcLocation.X);
writer.Write((short)srcLocation.Y);
writer.Write((sbyte)srcLocation.Z);
writer.Write(trgSerial);
writer.Write((short)trgLocation.X);
writer.Write((short)trgLocation.Y);
writer.Write((sbyte)trgLocation.Z);
}
public static void SendDisplayPaperdoll(this NetState ns, Serial m, string title, bool warmode, bool canLift)
public static void SendDragEffect(
this NetState ns,
Serial srcSerial, Point3D srcLocation,
Serial trgSerial, Point3D trgLocation,
int itemID, int hue, int amount
)
{
if (ns.CannotSendPackets())
{
if (ns == null)
{
return;
}
byte flags = 0x00;
if (warmode)
{
flags |= 0x01;
}
if (canLift)
{
flags |= 0x02;
}
var writer = new SpanWriter(stackalloc byte[66]);
writer.Write((byte)0x88); // Packet ID
writer.Write(m);
writer.WriteAscii(title, 60);
writer.Write(flags);
ns.Send(writer.Span);
return;
}
public static void SendPlayMusic(this NetState ns, MusicName music)
Span<byte> buffer = stackalloc byte[DragEffectPacketLength].InitializePacket();
CreateDragEffect(buffer, srcSerial, srcLocation, trgSerial, trgLocation, itemID, hue, amount);
ns.Send(buffer);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void SendSeasonChange(this NetState ns, byte season, bool playSound) =>
ns?.Send(stackalloc byte[]{ 0xBC, season, *(byte*)&playSound });
public static void SendDisplayPaperdoll(this NetState ns, Serial m, string title, bool warmode, bool canLift)
{
if (ns.CannotSendPackets())
{
if (ns == null)
{
return;
}
var writer = new SpanWriter(stackalloc byte[3]);
writer.Write((byte)0x6D); // Packet ID
writer.Write((short)music);
ns.Send(writer.Span);
return;
}
public static void SendStopMusic(this NetState ns) => ns?.Send(stackalloc byte[] { 0x6D, 0x1F, 0xFF });
byte flags = 0x00;
public static void SendScrollMessage(this NetState ns, int type, int tip, string text)
if (warmode)
{
if (ns == null)
{
return;
}
text ??= "";
var length = 10 + text.Length;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xA6); // Packet ID
writer.Write((ushort)length);
writer.Write((byte)type);
writer.Write(tip);
writer.Write((ushort)text.Length);
writer.WriteAscii(text);
ns.Send(writer.Span);
flags |= 0x01;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendCurrentTime(this NetState ns) => ns.SendCurrentTime(Core.Now);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendCurrentTime(this NetState ns, DateTime date) =>
ns?.Send(stackalloc byte[] { 0x5B, (byte)date.Hour, (byte)date.Minute, (byte)date.Second });
public static void SendPathfindMessage(this NetState ns, Point3D p)
if (canLift)
{
if (ns == null)
{
return;
}
var writer = new SpanWriter(stackalloc byte[7]);
writer.Write((byte)0x38); // Packet ID
writer.Write((short)p.X);
writer.Write((short)p.Y);
writer.Write((short)p.Z);
ns.Send(writer.Span);
flags |= 0x02;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendPingAck(this NetState ns, byte ping) => ns?.Send(stackalloc byte[] { 0x73, ping });
var writer = new SpanWriter(stackalloc byte[66]);
writer.Write((byte)0x88); // Packet ID
writer.Write(m);
writer.WriteAscii(title, 60);
writer.Write(flags);
public static void SendDisplayHuePicker(this NetState ns, Serial huePickerSerial, int huePickerItemID)
ns.Send(writer.Span);
}
public static void SendPlayMusic(this NetState ns, MusicName music)
{
if (ns.CannotSendPackets())
{
if (ns == null)
{
return;
}
var writer = new SpanWriter(stackalloc byte[9]);
writer.Write((byte)0x95); // Packet ID
writer.Write(huePickerSerial);
writer.Write((short)0);
writer.Write((short)huePickerItemID);
ns.Send(writer.Span);
return;
}
var writer = new SpanWriter(stackalloc byte[3]);
writer.Write((byte)0x6D); // Packet ID
writer.Write((short)music);
ns.Send(writer.Span);
}
public static void SendStopMusic(this NetState ns) => ns?.Send(stackalloc byte[] { 0x6D, 0x1F, 0xFF });
public static void SendScrollMessage(this NetState ns, int type, int tip, string text)
{
if (ns.CannotSendPackets())
{
return;
}
text ??= "";
var length = 10 + text.Length;
var writer = new SpanWriter(stackalloc byte[length]);
writer.Write((byte)0xA6); // Packet ID
writer.Write((ushort)length);
writer.Write((byte)type);
writer.Write(tip);
writer.Write((ushort)text.Length);
writer.WriteAscii(text);
ns.Send(writer.Span);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendCurrentTime(this NetState ns) => ns.SendCurrentTime(Core.Now);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendCurrentTime(this NetState ns, DateTime date) =>
ns?.Send(stackalloc byte[] { 0x5B, (byte)date.Hour, (byte)date.Minute, (byte)date.Second });
public static void SendPathfindMessage(this NetState ns, Point3D p)
{
if (ns.CannotSendPackets())
{
return;
}
var writer = new SpanWriter(stackalloc byte[7]);
writer.Write((byte)0x38); // Packet ID
writer.Write((short)p.X);
writer.Write((short)p.Y);
writer.Write((short)p.Z);
ns.Send(writer.Span);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void SendPingAck(this NetState ns, byte ping) => ns?.Send(stackalloc byte[] { 0x73, ping });
public static void SendDisplayHuePicker(this NetState ns, Serial huePickerSerial, int huePickerItemID)
{
if (ns.CannotSendPackets())
{
return;
}
var writer = new SpanWriter(stackalloc byte[9]);
writer.Write((byte)0x95); // Packet ID
writer.Write(huePickerSerial);
writer.Write((short)0);
writer.Write((short)huePickerItemID);
ns.Send(writer.Span);
}
}