fix(core): Adds SkipLocalsInitAttribute support, optimizes broadcasted packets (#363)

- [X] Adds support for `SkipLocalsInitAttribute`. SkipLocalsInitAttribute skips initializing stack variables including `stackalloc`. I don't think it is wired/working yet but should be implemented soon.
- [X] Optimizes broadcasted packets by checking if the first byte (packet ID) is non-zero. If it is already set, it reuses the buffer.
- [X] Removes unnecessary refs to Spans. I don't think the Span struct itself is mutable, so a ref is not helpful.
This commit is contained in:
Kamron Batman 2020-12-26 12:46:06 -08:00 • committed by GitHub
parent 9c9591b098
commit 03d0a4664e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 478 additions and 285 deletions

View file

@ -17,7 +17,7 @@
<TreatWarningsAsErrors>true</TreatWarningsAsErrors> <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<WarningsAsErrors /> <WarningsAsErrors />
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<!-- <SkipLocalsInitAttribute>true</SkipLocalsInitAttribute>--> <SkipLocalsInitAttribute>false</SkipLocalsInitAttribute>
<IsWindows Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Windows)))' == 'true'">true</IsWindows> <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> <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> <IsLinux Condition="'$([System.Runtime.InteropServices.RuntimeInformation]::IsOSPlatform($([System.Runtime.InteropServices.OSPlatform]::Linux)))' == 'true'">true</IsLinux>

View file

@ -40,7 +40,7 @@ namespace Benchmarks
} }
public static int CreateUnicodeMessage( public static int CreateUnicodeMessage(
ref Span<byte> buffer, Span<byte> buffer,
Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name, string text Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name, string text
) )
{ {
@ -116,8 +116,7 @@ namespace Benchmarks
Span<byte> buffer = result.Buffer[0]; Span<byte> buffer = result.Buffer[0];
var length = CreateUnicodeMessage( var length = CreateUnicodeMessage(
ref buffer, buffer, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
); );
pipe.Writer.Advance((uint)length); pipe.Writer.Advance((uint)length);
} }
@ -131,8 +130,7 @@ namespace Benchmarks
var text = "This is some really long text that we want to handle. It should take a little bit to encode this."; var text = "This is some really long text that we want to handle. It should take a little bit to encode this.";
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = CreateUnicodeMessage( var length = CreateUnicodeMessage(
ref buffer, buffer, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
); );
buffer = buffer.Slice(0, length); buffer = buffer.Slice(0, length);
@ -151,8 +149,7 @@ namespace Benchmarks
{ {
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = CreateUnicodeMessage( var length = CreateUnicodeMessage(
ref buffer, buffer, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
); );
buffer = buffer.Slice(0, length); buffer = buffer.Slice(0, length);

View file

@ -50,7 +50,7 @@ namespace Server.Tests.Network
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength]; Span<byte> actual = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateParticleEffect( OutgoingEffectPackets.CreateParticleEffect(
ref actual, actual,
effectType, from, to, itemId, fromPoint, toPoint, speed, duration, direction, effectType, from, to, itemId, fromPoint, toPoint, speed, duration, direction,
explode, hue, renderMode, effect, explodeEffect, explodeSound, serial, layer, explode, hue, renderMode, effect, explodeEffect, explodeSound, serial, layer,
unknown unknown
@ -82,7 +82,7 @@ namespace Server.Tests.Network
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.HuedEffectLength]; Span<byte> actual = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateHuedEffect( OutgoingEffectPackets.CreateHuedEffect(
ref actual, actual,
effectType, from, to, itemId, fromPoint, toPoint, speed, effectType, from, to, itemId, fromPoint, toPoint, speed,
duration, direction, explode, hue, renderMode duration, direction, explode, hue, renderMode
); );
@ -110,10 +110,7 @@ namespace Server.Tests.Network
var expected = new BoltEffect(entity, hue).Compile(); var expected = new BoltEffect(entity, hue).Compile();
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.BoltEffectLength]; Span<byte> actual = stackalloc byte[OutgoingEffectPackets.BoltEffectLength];
OutgoingEffectPackets.CreateBoltEffect( OutgoingEffectPackets.CreateBoltEffect(actual, entity, hue);
ref actual,
entity, hue
);
AssertThat.Equal(actual, expected); AssertThat.Equal(actual, expected);
} }

View file

@ -73,13 +73,19 @@ namespace Server
if (map != null) if (map != null)
{ {
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength]; Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, soundID, p); buffer.InitializePacket();
var eable = map.GetClientsInRange(new Point3D(p)); var eable = map.GetClientsInRange(new Point3D(p));
foreach (var state in eable) foreach (var state in eable)
{ {
state.Mobile.ProcessDelta(); state.Mobile.ProcessDelta();
if (buffer[0] == 0)
{
OutgoingEffectPackets.CreateSoundEffect(buffer, soundID, p);
}
state.Send(buffer); state.Send(buffer);
} }
@ -99,18 +105,14 @@ namespace Server
e.ProcessDelta(); e.ProcessDelta();
Span<byte> preEffect = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength]; Span<byte> preEffect = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateTargetParticleEffect( preEffect.InitializePacket();
ref preEffect,
e, 0, 10, 5, 0, 0, 5031, 3, 0
);
Span<byte> boltEffect = stackalloc byte[OutgoingEffectPackets.BoltEffectLength]; Span<byte> boltEffect = stackalloc byte[OutgoingEffectPackets.BoltEffectLength];
OutgoingEffectPackets.CreateBoltEffect(ref boltEffect, e, hue); boltEffect.InitializePacket();
Span<byte> soundEffect = sound ? stackalloc byte[OutgoingEffectPackets.SoundPacketLength] : null; Span<byte> soundEffect = sound ? stackalloc byte[OutgoingEffectPackets.SoundPacketLength] : null;
if (sound) if (sound)
{ {
OutgoingEffectPackets.CreateSoundEffect(ref soundEffect, 0x29, e); soundEffect.InitializePacket();
} }
var eable = map.GetClientsInRange(e.Location); var eable = map.GetClientsInRange(e.Location);
@ -121,13 +123,31 @@ namespace Server
{ {
if (SendParticlesTo(state)) if (SendParticlesTo(state))
{ {
if (preEffect[0] == 0)
{
OutgoingEffectPackets.CreateTargetParticleEffect(
preEffect,
e, 0, 10, 5, 0, 0, 5031, 3, 0
);
}
state.Send(preEffect); state.Send(preEffect);
} }
if (boltEffect[0] == 0)
{
OutgoingEffectPackets.CreateBoltEffect(boltEffect, e, hue);
}
state.Send(boltEffect); state.Send(boltEffect);
if (sound) if (sound)
{ {
if (soundEffect[0] == 0)
{
OutgoingEffectPackets.CreateSoundEffect(soundEffect, 0x29, e);
}
state.Send(soundEffect); state.Send(soundEffect);
} }
} }
@ -146,11 +166,11 @@ namespace Server
{ {
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength]; Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateLocationHuedEffect( OutgoingEffectPackets.CreateLocationHuedEffect(
ref effect, effect,
p, itemID, speed, duration, hue, renderMode p, itemID, speed, duration, hue, renderMode
); );
SendPacket(p, map, ref effect); SendPacket(p, map, effect);
} }
public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect) public static void SendLocationParticles(IEntity e, int itemID, int speed, int duration, int effect)
@ -175,18 +195,12 @@ namespace Server
} }
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength]; Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateLocationParticleEffect( particles.InitializePacket();
ref particles,
e, itemID, speed, duration, hue, renderMode, effect, unknown
);
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null; Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null;
if (itemID != 0) if (itemID != 0)
{ {
OutgoingEffectPackets.CreateLocationHuedEffect( regular.InitializePacket();
ref regular,
e.Location, itemID, speed, duration, hue, renderMode
);
} }
var eable = map.GetClientsInRange(e.Location); var eable = map.GetClientsInRange(e.Location);
@ -197,10 +211,26 @@ namespace Server
if (SendParticlesTo(state)) if (SendParticlesTo(state))
{ {
if (particles[0] == 0)
{
OutgoingEffectPackets.CreateLocationParticleEffect(
particles,
e, itemID, speed, duration, hue, renderMode, effect, unknown
);
}
state.Send(particles); state.Send(particles);
} }
else if (itemID != 0) else if (itemID != 0)
{ {
if (regular[0] == 0)
{
OutgoingEffectPackets.CreateLocationHuedEffect(
regular,
e.Location, itemID, speed, duration, hue, renderMode
);
}
state.Send(regular); state.Send(regular);
} }
} }
@ -214,11 +244,11 @@ namespace Server
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength]; Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateTargetHuedEffect( OutgoingEffectPackets.CreateTargetHuedEffect(
ref effect, effect,
target, itemID, speed, duration, hue, renderMode target, itemID, speed, duration, hue, renderMode
); );
SendPacket(target.Location, target.Map, ref effect); SendPacket(target.Location, target.Map, effect);
} }
public static void SendTargetParticles( public static void SendTargetParticles(
@ -244,15 +274,12 @@ namespace Server
} }
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength]; Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateTargetParticleEffect( particles.InitializePacket();
ref particles,
target, itemID, speed, duration, hue, renderMode, effect, (int)layer, unknown
);
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null; Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null;
if (itemID != 0) if (itemID != 0)
{ {
OutgoingEffectPackets.CreateTargetHuedEffect(ref regular, target, itemID, speed, duration, hue, renderMode); regular.InitializePacket();
} }
var eable = map.GetClientsInRange(target.Location); var eable = map.GetClientsInRange(target.Location);
@ -263,10 +290,23 @@ namespace Server
if (SendParticlesTo(state)) if (SendParticlesTo(state))
{ {
if (particles[0] == 0)
{
OutgoingEffectPackets.CreateTargetParticleEffect(
particles,
target, itemID, speed, duration, hue, renderMode, effect, (int)layer, unknown
);
}
state.Send(particles); state.Send(particles);
} }
else if (itemID != 0) else if (itemID != 0)
{ {
if (regular[0] == 0)
{
OutgoingEffectPackets.CreateTargetHuedEffect(regular, target, itemID, speed, duration, hue, renderMode);
}
state.Send(regular); state.Send(regular);
} }
} }
@ -393,12 +433,12 @@ namespace Server
{ {
Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength]; Span<byte> effect = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateMovingHuedEffect( OutgoingEffectPackets.CreateMovingHuedEffect(
ref effect, effect,
from, to, itemID, fromLocation, toLocation, speed, duration, fixedDirection, from, to, itemID, fromLocation, toLocation, speed, duration, fixedDirection,
explodes, hue, renderMode explodes, hue, renderMode
); );
SendPacket(origin, map, ref effect); SendPacket(origin, map, effect);
} }
public static void SendMovingParticles( public static void SendMovingParticles(
@ -464,19 +504,12 @@ namespace Server
} }
Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength]; Span<byte> particles = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateMovingParticleEffect( particles.InitializePacket();
ref particles,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode, effect,
explodeEffect, explodeSound, layer, unknown
);
Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null; Span<byte> regular = itemID != 0 ? stackalloc byte[OutgoingEffectPackets.HuedEffectLength] : null;
if (itemID != 0) if (itemID != 0)
{ {
OutgoingEffectPackets.CreateMovingHuedEffect( regular.InitializePacket();
ref regular,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode
);
} }
var eable = map.GetClientsInRange(from.Location); var eable = map.GetClientsInRange(from.Location);
@ -487,10 +520,27 @@ namespace Server
if (SendParticlesTo(state)) if (SendParticlesTo(state))
{ {
if (particles[0] == 0)
{
OutgoingEffectPackets.CreateMovingParticleEffect(
particles,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode, effect,
explodeEffect, explodeSound, layer, unknown
);
}
state.Send(particles); state.Send(particles);
} }
else if (itemID > 1) else if (itemID > 1)
{ {
if (regular[0] == 0)
{
OutgoingEffectPackets.CreateMovingHuedEffect(
regular,
from, to, itemID, speed, duration, fixedDirection, explodes, hue, renderMode
);
}
state.Send(regular); state.Send(regular);
} }
} }
@ -498,7 +548,7 @@ namespace Server
eable.Free(); eable.Free();
} }
public static void SendPacket(Point3D origin, Map map, ref Span<byte> effectBuffer) public static void SendPacket(Point3D origin, Map map, Span<byte> effectBuffer)
{ {
if (map == null) if (map == null)
{ {

View file

@ -370,7 +370,7 @@ namespace Server
var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange());
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var state in eable) foreach (var state in eable)
{ {
@ -378,6 +378,11 @@ namespace Server
if (!m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) if (!m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m)))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
state.Send(removeEntity); state.Send(removeEntity);
} }
} }
@ -1136,21 +1141,18 @@ namespace Server
if (m_Map != null) if (m_Map != null)
{ {
Span<byte> oldWorldItem = stackalloc byte[OutgoingItemPackets.MaxWorldItemPacketLength]; Span<byte> oldWorldItem = stackalloc byte[OutgoingItemPackets.MaxWorldItemPacketLength];
var length = OutgoingItemPackets.CreateWorldItem(ref oldWorldItem, this); oldWorldItem.InitializePacket();
oldWorldItem = oldWorldItem.Slice(0, length);
Span<byte> saWorldItem = stackalloc byte[OutgoingItemPackets.MaxWorldItemPacketLength]; Span<byte> saWorldItem = stackalloc byte[OutgoingItemPackets.MaxWorldItemPacketLength];
length = OutgoingItemPackets.CreateWorldItemNew(ref saWorldItem, this, false); saWorldItem.InitializePacket();
saWorldItem = saWorldItem.Slice(0, length);
Span<byte> hsWorldItem = stackalloc byte[OutgoingItemPackets.MaxWorldItemPacketLength]; Span<byte> hsWorldItem = stackalloc byte[OutgoingItemPackets.MaxWorldItemPacketLength];
length = OutgoingItemPackets.CreateWorldItemNew(ref hsWorldItem, this, true); hsWorldItem.InitializePacket();
hsWorldItem = hsWorldItem.Slice(0, length);
Span<byte> opl = ObjectPropertyList.Enabled ? stackalloc byte[OutgoingEntityPackets.OPLPacketLength] : null; Span<byte> opl = ObjectPropertyList.Enabled ? stackalloc byte[OutgoingEntityPackets.OPLPacketLength] : null;
if (opl != null) if (opl != null)
{ {
OutgoingEntityPackets.CreateOPLInfo(ref opl, this); OutgoingEntityPackets.CreateOPLInfo(opl, this);
} }
var eable = m_Map.GetClientsInRange(m_Location, GetMaxUpdateRange()); var eable = m_Map.GetClientsInRange(m_Location, GetMaxUpdateRange());
@ -1163,14 +1165,32 @@ namespace Server
{ {
if (state.HighSeas) if (state.HighSeas)
{ {
if (hsWorldItem[0] == 0)
{
var length = OutgoingItemPackets.CreateWorldItemNew(hsWorldItem, this, true);
hsWorldItem = hsWorldItem.Slice(0, length);
}
SendInfoTo(state, hsWorldItem, opl); SendInfoTo(state, hsWorldItem, opl);
} }
else if (state.StygianAbyss) else if (state.StygianAbyss)
{ {
if (saWorldItem[0] == 0)
{
var length = OutgoingItemPackets.CreateWorldItemNew(saWorldItem, this, false);
saWorldItem = saWorldItem.Slice(0, length);
}
SendInfoTo(state, saWorldItem, opl); SendInfoTo(state, saWorldItem, opl);
} }
else else
{ {
if (oldWorldItem[0] == 0)
{
var length = OutgoingItemPackets.CreateWorldItem(oldWorldItem, this);
oldWorldItem = oldWorldItem.Slice(0, length);
}
SendInfoTo(state, oldWorldItem, opl); SendInfoTo(state, oldWorldItem, opl);
} }
} }
@ -1195,7 +1215,7 @@ namespace Server
eable = m_Map.GetClientsInRange(oldLocation, GetMaxUpdateRange()); eable = m_Map.GetClientsInRange(oldLocation, GetMaxUpdateRange());
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var state in eable) foreach (var state in eable)
{ {
@ -1203,6 +1223,10 @@ namespace Server
if (!m.InRange(location, GetUpdateRange(m))) if (!m.InRange(location, GetUpdateRange(m)))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
state.Send(removeEntity); state.Send(removeEntity);
} }
} }
@ -1536,7 +1560,7 @@ namespace Server
eable = m_Map.GetClientsInRange(oldLocation, GetMaxUpdateRange()); eable = m_Map.GetClientsInRange(oldLocation, GetMaxUpdateRange());
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var state in eable) foreach (var state in eable)
{ {
@ -1544,6 +1568,11 @@ namespace Server
if (!m.InRange(value, GetUpdateRange(m))) if (!m.InRange(value, GetUpdateRange(m)))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
state.Send(removeEntity); state.Send(removeEntity);
} }
} }
@ -3323,15 +3352,8 @@ namespace Server
var worldLoc = GetWorldLocation(); var worldLoc = GetWorldLocation();
var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange());
var length = OutgoingMessagePackets.GetMaxMessageLength(text); Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
buffer.InitializePacket();
Span<byte> buffer = stackalloc byte[length];
length = OutgoingMessagePackets.CreateMessage(
ref buffer,
Serial, m_ItemID, type, hue, 3, ascii, "ENU", Name, text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
foreach (var state in eable) foreach (var state in eable)
{ {
@ -3339,6 +3361,15 @@ namespace Server
if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m)))
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
buffer, Serial, m_ItemID, type, hue, 3, ascii, "ENU", Name, text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
state.Send(buffer); state.Send(buffer);
} }
} }
@ -3357,13 +3388,7 @@ namespace Server
var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange());
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)];
buffer.InitializePacket();
var length = OutgoingMessagePackets.CreateMessageLocalized(
ref buffer,
Serial, m_ItemID, type, hue, 3, number, Name, args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
foreach (var state in eable) foreach (var state in eable)
{ {
@ -3371,6 +3396,15 @@ namespace Server
if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m))) if (m.CanSee(this) && m.InRange(worldLoc, GetUpdateRange(m)))
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessageLocalized(
buffer, Serial, m_ItemID, type, hue, 3, number, Name, args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
state.Send(buffer); state.Send(buffer);
} }
} }
@ -3821,7 +3855,7 @@ namespace Server
var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange()); var eable = m_Map.GetClientsInRange(worldLoc, GetMaxUpdateRange());
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var state in eable) foreach (var state in eable)
{ {
@ -3829,6 +3863,11 @@ namespace Server
if (m.InRange(worldLoc, GetUpdateRange(m))) if (m.InRange(worldLoc, GetUpdateRange(m)))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
state.Send(removeEntity); state.Send(removeEntity);
} }
} }

View file

@ -3175,13 +3175,13 @@ namespace Server
Packet hbpPacket = null; Packet hbpPacket = null;
Packet hbyPacket = null; Packet hbyPacket = null;
Span<byte> deadBuffer = stackalloc byte[OutgoingMobilePackets.BondedStatusPacketLength];
OutgoingMobilePackets.CreateBondedStatus(ref deadBuffer, m.Serial, true);
var eable = m.Map.GetClientsInRange(m.m_Location); var eable = m.Map.GetClientsInRange(m.m_Location);
Span<byte> deadBuffer = stackalloc byte[OutgoingMobilePackets.BondedStatusPacketLength];
deadBuffer.InitializePacket();
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var state in eable) foreach (var state in eable)
{ {
@ -3191,6 +3191,11 @@ namespace Server
{ {
if (sendRemove) if (sendRemove)
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
state.Send(removeEntity); state.Send(removeEntity);
} }
@ -3200,6 +3205,11 @@ namespace Server
if (m.IsDeadBondedPet) if (m.IsDeadBondedPet)
{ {
if (deadBuffer[0] == 0)
{
OutgoingMobilePackets.CreateBondedStatus(deadBuffer, m.Serial, true);
}
state.Send(deadBuffer); state.Send(deadBuffer);
} }
} }
@ -4988,18 +4998,29 @@ namespace Server
var corpseSerial = c?.Serial ?? Serial.Zero; var corpseSerial = c?.Serial ?? Serial.Zero;
Span<byte> deathAnimation = stackalloc byte[OutgoingMobilePackets.DeathAnimationPacketLength]; Span<byte> deathAnimation = stackalloc byte[OutgoingMobilePackets.DeathAnimationPacketLength];
OutgoingMobilePackets.CreateDeathAnimation(ref deathAnimation, Serial, corpseSerial); deathAnimation.InitializePacket();
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var state in eable) foreach (var state in eable)
{ {
if (state != m_NetState) if (state != m_NetState)
{ {
if (deathAnimation[0] == 0)
{
OutgoingMobilePackets.CreateDeathAnimation(deathAnimation, Serial, corpseSerial);
}
state.Send(deathAnimation); state.Send(deathAnimation);
if (!state.Mobile.CanSee(this)) if (!state.Mobile.CanSee(this))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
state.Send(removeEntity); state.Send(removeEntity);
} }
} }
@ -5782,19 +5803,9 @@ namespace Server
ProcessDelta(); ProcessDelta();
Span<byte> regBuffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; Span<byte> regBuffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
regBuffer.InitializePacket();
Span<byte> mutBuffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(mutatedText)]; Span<byte> mutBuffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(mutatedText)];
mutBuffer.InitializePacket();
var length = OutgoingMessagePackets.CreateMessage(
ref regBuffer,
Serial, Body, type, hue, 3, false, m_Language, Name, text
);
regBuffer = regBuffer.Slice(0, length); // Adjust to the actual size
length = OutgoingMessagePackets.CreateMessage(
ref mutBuffer,
Serial, Body, type, hue, 3, false, m_Language, Name, mutatedText
);
mutBuffer = mutBuffer.Slice(0, length); // Adjust to the actual size
// TODO: Should this be sorted like onSpeech is below? // TODO: Should this be sorted like onSpeech is below?
for (var i = 0; i < hears.Count; ++i) for (var i = 0; i < hears.Count; ++i)
@ -5803,11 +5814,27 @@ namespace Server
if (mutatedArgs == null || !CheckHearsMutatedSpeech(heard, mutateContext)) if (mutatedArgs == null || !CheckHearsMutatedSpeech(heard, mutateContext))
{ {
if (regBuffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
regBuffer, Serial, Body, type, hue, 3, false, m_Language, Name, text
);
regBuffer = regBuffer.Slice(0, length); // Adjust to the actual size
}
heard.OnSpeech(regArgs); heard.OnSpeech(regArgs);
heard.NetState?.Send(regBuffer); heard.NetState?.Send(regBuffer);
} }
else else
{ {
if (mutBuffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
mutBuffer, Serial, Body, type, hue, 3, false, m_Language, Name, mutatedText
);
mutBuffer = mutBuffer.Slice(0, length); // Adjust to the actual size
}
heard.OnSpeech(mutatedArgs); heard.OnSpeech(mutatedArgs);
heard.NetState?.Send(mutBuffer); heard.NetState?.Send(mutBuffer);
} }
@ -6934,7 +6961,7 @@ namespace Server
} }
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength]; Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, soundID, this); buffer.InitializePacket();
var eable = m_Map.GetClientsInRange(m_Location); var eable = m_Map.GetClientsInRange(m_Location);
@ -6942,6 +6969,11 @@ namespace Server
{ {
if (state.Mobile.CanSee(this)) if (state.Mobile.CanSee(this))
{ {
if (buffer[0] == 0)
{
OutgoingEffectPackets.CreateSoundEffect(buffer, soundID, this);
}
state.Send(buffer); state.Send(buffer);
} }
} }
@ -6997,12 +7029,17 @@ namespace Server
var eable = m_Map.GetClientsInRange(m_Location); var eable = m_Map.GetClientsInRange(m_Location);
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var state in eable) foreach (var state in eable)
{ {
if (state != m_NetState && (everyone || !state.Mobile.CanSee(this))) if (state != m_NetState && (everyone || !state.Mobile.CanSee(this)))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
state.Send(removeEntity); state.Send(removeEntity);
} }
} }
@ -7253,12 +7290,17 @@ namespace Server
var eable = m_Map.GetClientsInRange(m_Location); var eable = m_Map.GetClientsInRange(m_Location);
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var state in eable) foreach (var state in eable)
{ {
if (!state.Mobile.CanSee(this)) if (!state.Mobile.CanSee(this))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
state.Send(removeEntity); state.Send(removeEntity);
} }
else else
@ -7483,12 +7525,17 @@ namespace Server
var eable = map.GetClientsInRange(oldLocation); var eable = map.GetClientsInRange(oldLocation);
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, Serial); removeEntity.InitializePacket();
foreach (var ns in eable) foreach (var ns in eable)
{ {
if (ns != m_NetState && !Utility.InUpdateRange(newLocation, ns.Mobile.Location)) if (ns != m_NetState && !Utility.InUpdateRange(newLocation, ns.Mobile.Location))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, Serial);
}
ns.Send(removeEntity); ns.Send(removeEntity);
} }
} }
@ -9176,15 +9223,8 @@ namespace Server
return; return;
} }
var length = OutgoingMessagePackets.GetMaxMessageLength(text); Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
buffer.InitializePacket();
Span<byte> buffer = stackalloc byte[length];
length = OutgoingMessagePackets.CreateMessage(
ref buffer,
Serial, Body, type, hue, 3, ascii, Language, Name, text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
var eable = m_Map.GetClientsInRange(m_Location); var eable = m_Map.GetClientsInRange(m_Location);
@ -9192,6 +9232,15 @@ namespace Server
{ {
if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this))) if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this)))
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
buffer, Serial, Body, type, hue, 3, ascii, Language, Name, text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
state.Send(buffer); state.Send(buffer);
} }
} }
@ -9207,12 +9256,7 @@ namespace Server
} }
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)];
buffer.InitializePacket();
var length = OutgoingMessagePackets.CreateMessageLocalized(
ref buffer,
Serial, Body, type, hue, 3, number, Name, args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
var eable = m_Map.GetClientsInRange(m_Location); var eable = m_Map.GetClientsInRange(m_Location);
@ -9220,6 +9264,14 @@ namespace Server
{ {
if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this))) if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this)))
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessageLocalized(
buffer, Serial, Body, type, hue, 3, number, Name, args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
state.Send(buffer); state.Send(buffer);
} }
} }
@ -9238,12 +9290,7 @@ namespace Server
} }
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(affix, args)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(affix, args)];
buffer.InitializePacket();
var length = OutgoingMessagePackets.CreateMessageLocalizedAffix(
ref buffer,
Serial, Body, type, hue, 3, number, Name, affixType, affix, args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
var eable = m_Map.GetClientsInRange(m_Location); var eable = m_Map.GetClientsInRange(m_Location);
@ -9251,6 +9298,14 @@ namespace Server
{ {
if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this))) if (state.Mobile.CanSee(this) && (noLineOfSight || state.Mobile.InLOS(this)))
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessageLocalizedAffix(
buffer, Serial, Body, type, hue, 3, number, Name, affixType, affix, args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
state.Send(buffer); state.Send(buffer);
} }
} }
@ -9283,12 +9338,7 @@ namespace Server
} }
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)];
buffer.InitializePacket();
var length = OutgoingMessagePackets.CreateMessageLocalized(
ref buffer,
Serial, Body, type, hue, 3, number, Name, args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
var eable = m_Map.GetClientsInRange(m_Location); var eable = m_Map.GetClientsInRange(m_Location);
@ -9296,6 +9346,14 @@ namespace Server
{ {
if (state != m_NetState && state.Mobile.CanSee(this)) if (state != m_NetState && state.Mobile.CanSee(this))
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessageLocalized(
buffer, Serial, Body, type, hue, 3, number, Name, args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
state.Send(buffer); state.Send(buffer);
} }
} }
@ -9310,15 +9368,8 @@ namespace Server
return; return;
} }
var length = OutgoingMessagePackets.GetMaxMessageLength(text); Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
buffer.InitializePacket();
Span<byte> buffer = stackalloc byte[length];
length = OutgoingMessagePackets.CreateMessage(
ref buffer,
Serial, Body, type, hue, 3, ascii, Language, Name, text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
var eable = m_Map.GetClientsInRange(m_Location); var eable = m_Map.GetClientsInRange(m_Location);
@ -9326,6 +9377,15 @@ namespace Server
{ {
if (state != m_NetState && state.Mobile.CanSee(this)) if (state != m_NetState && state.Mobile.CanSee(this))
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
buffer, Serial, Body, type, hue, 3, ascii, Language, Name, text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
state.Send(buffer); state.Send(buffer);
} }
} }

View file

@ -40,9 +40,20 @@ namespace Server.Network
writer.Seek(length, SeekOrigin.Begin); writer.Seek(length, SeekOrigin.Begin);
} }
// If LOCAL INIT is off, then stack/heap allocations have garbage data
// Initializes the first byte (Packet ID) so it can be used as a flag.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InitializePacket(this Span<byte> buffer)
{
#if NO_LOCAL_INIT
buffer[0] = 0;
#endif
}
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void InitializePackets(this Span<byte> buffer, int chunkLength) public static void InitializePackets(this Span<byte> buffer, int chunkLength)
{ {
#if NO_LOCAL_INIT
var index = 0; var index = 0;
while (index < buffer.Length) while (index < buffer.Length)
@ -50,6 +61,7 @@ namespace Server.Network
buffer[index] = 0; buffer[index] = 0;
index += chunkLength; index += chunkLength;
} }
#endif
} }
} }
} }

View file

@ -33,12 +33,12 @@ namespace Server.Network
} }
Span<byte> buffer = stackalloc byte[SoundPacketLength]; Span<byte> buffer = stackalloc byte[SoundPacketLength];
CreateSoundEffect(ref buffer, soundID, target); CreateSoundEffect(buffer, soundID, target);
ns.Send(buffer); ns.Send(buffer);
} }
public static void CreateSoundEffect(ref Span<byte> buffer, int soundID, IPoint3D target) public static void CreateSoundEffect(Span<byte> buffer, int soundID, IPoint3D target)
{ {
var writer = new SpanWriter(buffer); var writer = new SpanWriter(buffer);
writer.Write((byte)0x54); // Packet ID writer.Write((byte)0x54); // Packet ID
@ -51,7 +51,7 @@ namespace Server.Network
} }
public static void CreateParticleEffect( public static void CreateParticleEffect(
ref Span<byte> buffer, Span<byte> buffer,
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint, EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect, int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown int explodeEffect, int explodeSound, Serial serial, int layer, int unknown
@ -86,10 +86,10 @@ namespace Server.Network
} }
public static void CreateTargetParticleEffect( public static void CreateTargetParticleEffect(
ref Span<byte> buffer, Span<byte> buffer,
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int layer, int unknown IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int layer, int unknown
) => CreateParticleEffect( ) => CreateParticleEffect(
ref buffer, buffer,
EffectType.FixedFrom, EffectType.FixedFrom,
e.Serial, e.Serial,
Serial.Zero, Serial.Zero,
@ -111,10 +111,10 @@ namespace Server.Network
); );
public static void CreateLocationParticleEffect( public static void CreateLocationParticleEffect(
ref Span<byte> buffer, Span<byte> buffer,
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int unknown IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect, int unknown
) => CreateParticleEffect( ) => CreateParticleEffect(
ref buffer, buffer,
EffectType.FixedXYZ, EffectType.FixedXYZ,
e.Serial, e.Serial,
Serial.Zero, Serial.Zero,
@ -136,12 +136,12 @@ namespace Server.Network
); );
public static void CreateMovingParticleEffect( public static void CreateMovingParticleEffect(
ref Span<byte> buffer, Span<byte> buffer,
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection, IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, EffectLayer layer, bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, EffectLayer layer,
int unknown int unknown
) => CreateParticleEffect( ) => CreateParticleEffect(
ref buffer, buffer,
EffectType.Moving, EffectType.Moving,
from.Serial, from.Serial,
to.Serial, to.Serial,
@ -163,7 +163,7 @@ namespace Server.Network
); );
public static void CreateHuedEffect( public static void CreateHuedEffect(
ref Span<byte> buffer, Span<byte> buffer,
EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint, EffectType type, Serial from, Serial to, int itemID, Point3D fromPoint, Point3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode
) )
@ -191,10 +191,10 @@ namespace Server.Network
} }
public static void CreateTargetHuedEffect( public static void CreateTargetHuedEffect(
ref Span<byte> buffer, Span<byte> buffer,
IEntity e, int itemID, int speed, int duration, int hue, int renderMode IEntity e, int itemID, int speed, int duration, int hue, int renderMode
) => CreateHuedEffect( ) => CreateHuedEffect(
ref buffer, buffer,
EffectType.FixedFrom, EffectType.FixedFrom,
e.Serial, e.Serial,
Serial.Zero, Serial.Zero,
@ -210,10 +210,10 @@ namespace Server.Network
); );
public static void CreateLocationHuedEffect( public static void CreateLocationHuedEffect(
ref Span<byte> buffer, Span<byte> buffer,
Point3D p, int itemID, int speed, int duration, int hue, int renderMode Point3D p, int itemID, int speed, int duration, int hue, int renderMode
) => CreateHuedEffect( ) => CreateHuedEffect(
ref buffer, buffer,
EffectType.FixedXYZ, EffectType.FixedXYZ,
Serial.Zero, Serial.Zero,
Serial.Zero, Serial.Zero,
@ -229,11 +229,11 @@ namespace Server.Network
); );
public static void CreateMovingHuedEffect( public static void CreateMovingHuedEffect(
ref Span<byte> buffer, Span<byte> buffer,
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection, IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode bool explodes, int hue, int renderMode
) => CreateHuedEffect( ) => CreateHuedEffect(
ref buffer, buffer,
EffectType.Moving, EffectType.Moving,
from.Serial, from.Serial,
to.Serial, to.Serial,
@ -249,11 +249,11 @@ namespace Server.Network
); );
public static void CreateMovingHuedEffect( public static void CreateMovingHuedEffect(
ref Span<byte> buffer, Span<byte> buffer,
int itemID, Point3D fromLocation, Point3D toLocation, int speed, int duration, int itemID, Point3D fromLocation, Point3D toLocation, int speed, int duration,
bool fixedDirection, bool explodes, int hue, int renderMode bool fixedDirection, bool explodes, int hue, int renderMode
) => CreateHuedEffect( ) => CreateHuedEffect(
ref buffer, buffer,
EffectType.Moving, EffectType.Moving,
Serial.Zero, Serial.Zero,
Serial.Zero, Serial.Zero,
@ -269,11 +269,11 @@ namespace Server.Network
); );
public static void CreateMovingHuedEffect( public static void CreateMovingHuedEffect(
ref Span<byte> buffer, Span<byte> buffer,
Serial from, Serial to, int itemID, Point3D fromLocation, Point3D toLocation, int speed, int duration, Serial from, Serial to, int itemID, Point3D fromLocation, Point3D toLocation, int speed, int duration,
bool fixedDirection, bool explodes, int hue, int renderMode bool fixedDirection, bool explodes, int hue, int renderMode
) => CreateHuedEffect( ) => CreateHuedEffect(
ref buffer, buffer,
EffectType.Moving, EffectType.Moving,
from, from,
to, to,
@ -288,8 +288,8 @@ namespace Server.Network
renderMode renderMode
); );
public static void CreateBoltEffect(ref Span<byte> buffer, IEntity target, int hue) => CreateHuedEffect( public static void CreateBoltEffect(Span<byte> buffer, IEntity target, int hue) => CreateHuedEffect(
ref buffer, buffer,
EffectType.Lightning, EffectType.Lightning,
target.Serial, target.Serial,
Serial.Zero, Serial.Zero,

View file

@ -23,10 +23,10 @@ namespace Server.Network
public const int OPLPacketLength = 9; public const int OPLPacketLength = 9;
public const int RemoveEntityLength = 5; public const int RemoveEntityLength = 5;
public static void CreateOPLInfo(ref Span<byte> buffer, Item item) => public static void CreateOPLInfo(Span<byte> buffer, Item item) =>
CreateOPLInfo(ref buffer, item.Serial, item.PropertyList.Hash); CreateOPLInfo(buffer, item.Serial, item.PropertyList.Hash);
public static void CreateOPLInfo(ref Span<byte> buffer, Serial serial, int hash) public static void CreateOPLInfo(Span<byte> buffer, Serial serial, int hash)
{ {
var writer = new SpanWriter(buffer); var writer = new SpanWriter(buffer);
writer.Write((byte)0xDC); // Packet ID writer.Write((byte)0xDC); // Packet ID
@ -45,12 +45,12 @@ namespace Server.Network
} }
Span<byte> buffer = stackalloc byte[OPLPacketLength]; Span<byte> buffer = stackalloc byte[OPLPacketLength];
CreateOPLInfo(ref buffer, serial, hash); CreateOPLInfo(buffer, serial, hash);
ns.Send(buffer); ns.Send(buffer);
} }
public static void CreateRemoveEntity(ref Span<byte> buffer, Serial serial) public static void CreateRemoveEntity(Span<byte> buffer, Serial serial)
{ {
var writer = new SpanWriter(buffer); var writer = new SpanWriter(buffer);
writer.Write((byte)0x1D); // Packet ID writer.Write((byte)0x1D); // Packet ID
@ -65,7 +65,7 @@ namespace Server.Network
} }
Span<byte> buffer = stackalloc byte[RemoveEntityLength]; Span<byte> buffer = stackalloc byte[RemoveEntityLength];
CreateRemoveEntity(ref buffer, serial); CreateRemoveEntity(buffer, serial);
ns.Send(buffer); ns.Send(buffer);
} }

View file

@ -23,7 +23,7 @@ namespace Server.Network
{ {
public const int MaxWorldItemPacketLength = 26; public const int MaxWorldItemPacketLength = 26;
public static int CreateWorldItem(ref Span<byte> buffer, Item item) public static int CreateWorldItem(Span<byte> buffer, Item item)
{ {
var itemID = item is BaseMulti ? item.ItemID | 0x4000 : item.ItemID & 0x3FFF; var itemID = item is BaseMulti ? item.ItemID | 0x4000 : item.ItemID & 0x3FFF;
var hasAmount = item.Amount != 0; var hasAmount = item.Amount != 0;
@ -87,13 +87,13 @@ namespace Server.Network
Span<byte> buffer = stackalloc byte[MaxWorldItemPacketLength]; Span<byte> buffer = stackalloc byte[MaxWorldItemPacketLength];
var length = ns.StygianAbyss ? var length = ns.StygianAbyss ?
CreateWorldItemNew(ref buffer, item, ns.HighSeas) : CreateWorldItemNew(buffer, item, ns.HighSeas) :
CreateWorldItem(ref buffer, item); CreateWorldItem(buffer, item);
ns.Send(buffer.Slice(0, length)); ns.Send(buffer.Slice(0, length));
} }
public static int CreateWorldItemNew(ref Span<byte> buffer, Item item, bool isHS) public static int CreateWorldItemNew(Span<byte> buffer, Item item, bool isHS)
{ {
var writer = new SpanWriter(buffer); var writer = new SpanWriter(buffer);
writer.Write((byte)0xF3); // Packet ID writer.Write((byte)0xF3); // Packet ID

View file

@ -43,8 +43,7 @@ namespace Server.Network
Span<byte> buffer = stackalloc byte[GetMaxMessageLocalizedLength(args)]; Span<byte> buffer = stackalloc byte[GetMaxMessageLocalizedLength(args)];
var length = CreateMessageLocalized( var length = CreateMessageLocalized(
ref buffer, buffer, serial, graphic, type, hue, font, number, name, args
serial, graphic, type, hue, font, number, name, args
); );
ns.Send(buffer.Slice(0, length)); ns.Send(buffer.Slice(0, length));
@ -53,7 +52,7 @@ namespace Server.Network
public static int GetMaxMessageLocalizedLength(string args) => 50 + (args?.Length ?? 0) * 2; public static int GetMaxMessageLocalizedLength(string args) => 50 + (args?.Length ?? 0) * 2;
public static int CreateMessageLocalized( public static int CreateMessageLocalized(
ref Span<byte> buffer, Span<byte> buffer,
Serial serial, int graphic, MessageType type, int hue, int font, int number, string name = "", string args = "" Serial serial, int graphic, MessageType type, int hue, int font, int number, string name = "", string args = ""
) )
{ {
@ -95,8 +94,7 @@ namespace Server.Network
Span<byte> buffer = stackalloc byte[GetMaxMessageLocalizedAffixLength(affix, args)]; Span<byte> buffer = stackalloc byte[GetMaxMessageLocalizedAffixLength(affix, args)];
var length = CreateMessageLocalizedAffix( var length = CreateMessageLocalizedAffix(
ref buffer, buffer, serial, graphic, type, hue, font, number, name, affixType, affix, args
serial, graphic, type, hue, font, number, name, affixType, affix, args
); );
ns.Send(buffer.Slice(0, length)); ns.Send(buffer.Slice(0, length));
@ -106,7 +104,7 @@ namespace Server.Network
52 + (affix?.Length ?? 0) + (args?.Length ?? 0) * 2; 52 + (affix?.Length ?? 0) + (args?.Length ?? 0) * 2;
public static int CreateMessageLocalizedAffix( public static int CreateMessageLocalizedAffix(
ref Span<byte> buffer, Span<byte> buffer,
Serial serial, int graphic, MessageType type, int hue, int font, int number, string name, Serial serial, int graphic, MessageType type, int hue, int font, int number, string name,
AffixType affixType, string affix = "", string args = "" AffixType affixType, string affix = "", string args = ""
) )
@ -152,7 +150,7 @@ namespace Server.Network
Span<byte> buffer = stackalloc byte[GetMaxMessageLength(text)]; Span<byte> buffer = stackalloc byte[GetMaxMessageLength(text)];
var length = CreateMessage( var length = CreateMessage(
ref buffer, buffer,
serial, serial,
graphic, graphic,
type, type,
@ -171,7 +169,7 @@ namespace Server.Network
public static int GetMaxMessageLength(string text) => 50 + (text?.Length ?? 0) * 2; public static int GetMaxMessageLength(string text) => 50 + (text?.Length ?? 0) * 2;
public static int CreateMessage( public static int CreateMessage(
ref Span<byte> buffer, Span<byte> buffer,
Serial serial, Serial serial,
int graphic, int graphic,
MessageType type, MessageType type,

View file

@ -26,7 +26,7 @@ namespace Server.Network
public const int MobileMovingPacketLength = 17; public const int MobileMovingPacketLength = 17;
public const int MobileMovingPacketCacheLength = MobileMovingPacketLength * 8 * 2; // 8 notoriety, 2 client versions public const int MobileMovingPacketCacheLength = MobileMovingPacketLength * 8 * 2; // 8 notoriety, 2 client versions
public static void CreateBondedStatus(ref Span<byte> buffer, Serial serial, bool bonded) public static void CreateBondedStatus(Span<byte> buffer, Serial serial, bool bonded)
{ {
var writer = new SpanWriter(buffer); var writer = new SpanWriter(buffer);
writer.Write((byte)0xBF); // Packet ID writer.Write((byte)0xBF); // Packet ID
@ -55,7 +55,7 @@ namespace Server.Network
ns.Send(ref buffer, writer.Position); ns.Send(ref buffer, writer.Position);
} }
public static void CreateDeathAnimation(ref Span<byte> buffer, Serial killed, Serial corpse) public static void CreateDeathAnimation(Span<byte> buffer, Serial killed, Serial corpse)
{ {
var writer = new SpanWriter(buffer); var writer = new SpanWriter(buffer);
writer.Write((byte)0xAF); // Packet ID writer.Write((byte)0xAF); // Packet ID
@ -72,11 +72,11 @@ namespace Server.Network
} }
Span<byte> span = stackalloc byte[DeathAnimationPacketLength]; Span<byte> span = stackalloc byte[DeathAnimationPacketLength];
CreateDeathAnimation(ref span, killed, corpse); CreateDeathAnimation(span, killed, corpse);
ns.Send(span); ns.Send(span);
} }
public static void CreateMobileMoving(ref Span<byte> buffer, Mobile m, int noto, bool stygianAbyss) public static void CreateMobileMoving(Span<byte> buffer, Mobile m, int noto, bool stygianAbyss)
{ {
var loc = m.Location; var loc = m.Location;
var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue; var hue = m.SolidHueOverride >= 0 ? m.SolidHueOverride : m.Hue;
@ -106,7 +106,7 @@ namespace Server.Network
} }
Span<byte> span = stackalloc byte[MobileMovingPacketLength]; Span<byte> span = stackalloc byte[MobileMovingPacketLength];
CreateMobileMoving(ref span, target, noto, ns.StygianAbyss); CreateMobileMoving(span, target, noto, ns.StygianAbyss);
ns.Send(span); ns.Send(span);
} }
@ -130,7 +130,7 @@ namespace Server.Network
// Packet not created yet // Packet not created yet
if (buffer[0] == 0) if (buffer[0] == 0)
{ {
CreateMobileMoving(ref buffer, target, noto, stygianAbyss); CreateMobileMoving(buffer, target, noto, stygianAbyss);
} }
ns.Send(buffer); ns.Send(buffer);

View file

@ -96,7 +96,7 @@ namespace Server
if (index >= 0) if (index >= 0)
{ {
list[index] = newValue; list![index] = newValue;
} }
else else
{ {

View file

@ -154,8 +154,7 @@ namespace Server
Span<byte> buffer = stackalloc byte[length]; Span<byte> buffer = stackalloc byte[length];
length = OutgoingMessagePackets.CreateMessage( length = OutgoingMessagePackets.CreateMessage(
ref buffer, buffer, Serial.MinusOne, -1, MessageType.Regular, hue, 3, ascii, "ENU", "System", text
Serial.MinusOne, -1, MessageType.Regular, hue, 3, ascii, "ENU", "System", text
); );
buffer = buffer.Slice(0, length); // Adjust to the actual size buffer = buffer.Slice(0, length); // Adjust to the actual size

View file

@ -417,12 +417,17 @@ namespace Server.Commands
); );
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength]; Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, index, m); buffer.InitializePacket();
foreach (var state in m.GetClientsInRange(12)) foreach (var state in m.GetClientsInRange(12))
{ {
if (toAll || state.Mobile.CanSee(m)) if (toAll || state.Mobile.CanSee(m))
{ {
if (buffer[0] == 0)
{
OutgoingEffectPackets.CreateSoundEffect(buffer, index, m);
}
state.Send(buffer); state.Send(buffer);
} }
} }

View file

@ -70,7 +70,7 @@ namespace Server.Commands
if (list.Count > 0) if (list.Count > 0)
{ {
Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength]; Span<byte> removeEntity = stackalloc byte[OutgoingEntityPackets.RemoveEntityLength];
OutgoingEntityPackets.CreateRemoveEntity(ref removeEntity, pm.Serial); removeEntity.InitializePacket();
for (var i = 0; i < list.Count; ++i) for (var i = 0; i < list.Count; ++i)
{ {
@ -78,6 +78,11 @@ namespace Server.Commands
if (!m.CanSee(pm) && Utility.InUpdateRange(m, pm)) if (!m.CanSee(pm) && Utility.InUpdateRange(m, pm))
{ {
if (removeEntity[0] == 0)
{
OutgoingEntityPackets.CreateRemoveEntity(removeEntity, pm.Serial);
}
m.NetState?.Send(removeEntity); m.NetState?.Send(removeEntity);
} }
} }

View file

@ -504,26 +504,30 @@ namespace Server.Engines.Doom
public static void POHMessage(Mobile from, int index) public static void POHMessage(Mobile from, int index)
{ {
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(Msgs[index])]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(Msgs[index])];
buffer.InitializePacket();
var length = OutgoingMessagePackets.CreateMessage(
ref buffer,
from.Serial,
from.Body,
MessageType.Regular,
MsgParams[index][0],
MsgParams[index][1],
true,
null,
from.Name,
Msgs[index]
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
var eable = from.Map.GetClientsInRange(from.Location); var eable = from.Map.GetClientsInRange(from.Location);
foreach (var state in eable) foreach (var state in eable)
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
buffer,
from.Serial,
from.Body,
MessageType.Regular,
MsgParams[index][0],
MsgParams[index][1],
true,
null,
from.Name,
Msgs[index]
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
state.Send(buffer); state.Send(buffer);
} }

View file

@ -96,7 +96,7 @@ namespace Server.Engines.MLQuests.Mobiles
} }
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength("")]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength("")];
var packetCreated = false; buffer.InitializePacket();
foreach (var state in GetClientsInRange(12)) foreach (var state in GetClientsInRange(12))
{ {
@ -104,14 +104,14 @@ namespace Server.Engines.MLQuests.Mobiles
if (m.CanSee(this) && m.InLOS(this) && m.CanBeginAction(this)) if (m.CanSee(this) && m.InLOS(this) && m.CanBeginAction(this))
{ {
if (!packetCreated) if (buffer[0] == 0)
{ {
// Double Click On Me For Help! // Double Click On Me For Help!
var length = OutgoingMessagePackets.CreateMessageLocalized( var length = OutgoingMessagePackets.CreateMessageLocalized(
ref buffer, buffer, Serial, Body, MessageType.Regular, 946, 3, 1078099, Name
Serial, Body, MessageType.Regular, 946, 3, 1078099, Name
); );
packetCreated = true;
buffer = buffer.Slice(0, length);
} }
state.Send(buffer); state.Send(buffer);

View file

@ -241,7 +241,7 @@ namespace Server.Engines.PartySystem
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(from.Name, "")]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(from.Name, "")];
var length = OutgoingMessagePackets.CreateMessageLocalizedAffix( var length = OutgoingMessagePackets.CreateMessageLocalizedAffix(
ref buffer, buffer,
Serial.MinusOne, Serial.MinusOne,
-1, -1,
MessageType.Label, MessageType.Label,
@ -253,10 +253,8 @@ namespace Server.Engines.PartySystem
from.Name from.Name
); );
buffer = buffer.Slice(0, length); // Adjust to the actual size
// : joined the party. // : joined the party.
SendToAll(ref buffer, true); SendToAll(buffer.Slice(0, length), true);
from.SendLocalizedMessage(1005445); // You have been added to the party. from.SendLocalizedMessage(1005445); // You have been added to the party.
@ -383,13 +381,11 @@ namespace Server.Engines.PartySystem
{ {
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength(args)];
var length = OutgoingMessagePackets.CreateMessageLocalized( var length = OutgoingMessagePackets.CreateMessageLocalized(
ref buffer, buffer,
Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args
); );
buffer = buffer.Slice(0, length); // Adjust to the actual size SendToAll(buffer.Slice(0, length), true);
SendToAll(ref buffer, true);
} }
public void SendPublicMessage(Mobile from, string text) public void SendPublicMessage(Mobile from, string text)
@ -429,19 +425,7 @@ namespace Server.Engines.PartySystem
private void SendToStaffMessage(Mobile from, string text) private void SendToStaffMessage(Mobile from, string text)
{ {
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = OutgoingMessagePackets.CreateMessage( buffer.InitializePacket();
ref buffer,
from.Serial,
from.Body,
MessageType.Regular,
from.SpeechHue,
3,
false,
from.Language,
from.Name,
text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
foreach (var ns in from.GetClientsInRange(8)) foreach (var ns in from.GetClientsInRange(8))
{ {
@ -450,6 +434,24 @@ namespace Server.Engines.PartySystem
if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel && if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel &&
mob.Party != this && !m_Listeners.Contains(mob)) mob.Party != this && !m_Listeners.Contains(mob))
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
buffer,
from.Serial,
from.Body,
MessageType.Regular,
from.SpeechHue,
3,
false,
from.Language,
from.Name,
text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
ns.Send(buffer); ns.Send(buffer);
} }
} }
@ -472,7 +474,7 @@ namespace Server.Engines.PartySystem
p.Release(); p.Release();
} }
public void SendToAll(ref Span<byte> span, bool isSpeech) public void SendToAll(Span<byte> span, bool isSpeech)
{ {
for (var i = 0; i < Members.Count; ++i) for (var i = 0; i < Members.Count; ++i)
{ {
@ -512,20 +514,7 @@ namespace Server.Engines.PartySystem
m_Mobile.Send(new PartyMemberList(p)); m_Mobile.Send(new PartyMemberList(p));
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(m_Mobile.Name, "")]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(m_Mobile.Name, "")];
var length = OutgoingMessagePackets.CreateMessageLocalizedAffix( buffer.InitializePacket();
ref buffer,
Serial.MinusOne,
-1,
MessageType.Label,
0x3B2,
3,
1008087,
"",
AffixType.Prepend | AffixType.System,
m_Mobile.Name
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
var attrs = Packet.Acquire(new MobileAttributesN(m_Mobile)); var attrs = Packet.Acquire(new MobileAttributesN(m_Mobile));
@ -535,6 +524,24 @@ namespace Server.Engines.PartySystem
if (m != m_Mobile) if (m != m_Mobile)
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessageLocalizedAffix(
buffer,
Serial.MinusOne,
-1,
MessageType.Label,
0x3B2,
3,
1008087,
"",
AffixType.Prepend | AffixType.System,
m_Mobile.Name
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
m.NetState?.Send(buffer); m.NetState?.Send(buffer);
m.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile)); m.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile));
m.Send(attrs); m.Send(attrs);

View file

@ -88,10 +88,15 @@ namespace Server.Items
else else
{ {
Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength]; Span<byte> buffer = stackalloc byte[OutgoingEffectPackets.SoundPacketLength];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, 0x127, GetWorldLocation()); buffer.InitializePacket();
foreach (var state in GetClientsInRange(2)) foreach (var state in GetClientsInRange(2))
{ {
if (buffer[0] == 0)
{
OutgoingEffectPackets.CreateSoundEffect(buffer, 0x127, GetWorldLocation());
}
state.Send(buffer); state.Send(buffer);
} }
} }

View file

@ -50,12 +50,12 @@ namespace Server.Items
if (ns.StygianAbyss) if (ns.StygianAbyss)
{ {
length = OutgoingItemPackets.CreateWorldItemNew(ref buffer, this, ns.HighSeas); length = OutgoingItemPackets.CreateWorldItemNew(buffer, this, ns.HighSeas);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(8, 2), GMItemId); BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(8, 2), GMItemId);
} }
else else
{ {
length = OutgoingItemPackets.CreateWorldItem(ref buffer, this); length = OutgoingItemPackets.CreateWorldItem(buffer, this);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(7, 2), GMItemId); BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(7, 2), GMItemId);
} }

View file

@ -56,12 +56,12 @@ namespace Server.Items
if (ns.StygianAbyss) if (ns.StygianAbyss)
{ {
length = OutgoingItemPackets.CreateWorldItemNew(ref buffer, this, ns.HighSeas); length = OutgoingItemPackets.CreateWorldItemNew(buffer, this, ns.HighSeas);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(8, 2), GMItemId); BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(8, 2), GMItemId);
} }
else else
{ {
length = OutgoingItemPackets.CreateWorldItem(ref buffer, this); length = OutgoingItemPackets.CreateWorldItem(buffer, this);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(7, 2), GMItemId); BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(7, 2), GMItemId);
} }

View file

@ -331,20 +331,7 @@ namespace Server.Guilds
public void AllianceChat(Mobile from, int hue, string text) public void AllianceChat(Mobile from, int hue, string text)
{ {
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = OutgoingMessagePackets.CreateMessage( buffer.InitializePacket();
ref buffer,
from.Serial,
from.Body,
MessageType.Alliance,
hue,
3,
false,
from.Language,
from.Name,
text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
for (var i = 0; i < m_Members.Count; i++) for (var i = 0; i < m_Members.Count; i++)
{ {
@ -352,6 +339,24 @@ namespace Server.Guilds
for (var j = 0; j < g.Members.Count; j++) for (var j = 0; j < g.Members.Count; j++)
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
buffer,
from.Serial,
from.Body,
MessageType.Alliance,
hue,
3,
false,
from.Language,
from.Name,
text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
g.Members[j].NetState?.Send(buffer); g.Members[j].NetState?.Send(buffer);
} }
} }
@ -1266,7 +1271,7 @@ namespace Server.Guilds
} }
else else
{ {
m_AllianceLeader = reader.ReadEntity<Guild>();; m_AllianceLeader = reader.ReadEntity<Guild>();
} }
goto case 4; goto case 4;
@ -1516,15 +1521,20 @@ namespace Server.Guilds
public void GuildChat(Mobile from, int hue, string text) public void GuildChat(Mobile from, int hue, string text)
{ {
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = OutgoingMessagePackets.CreateMessage( buffer.InitializePacket();
ref buffer,
from.Serial, from.Body, MessageType.Guild, hue, 3, false, from.Language, from.Name, text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
for (var i = 0; i < Members.Count; i++) for (var i = 0; i < Members.Count; i++)
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
buffer, from.Serial, from.Body, MessageType.Guild, hue, 3, false, from.Language,
from.Name, text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
Members[i].NetState?.Send(buffer); Members[i].NetState?.Send(buffer);
} }
} }

View file

@ -3844,8 +3844,8 @@ namespace Server.Mobiles
IsDeadPet = false; IsDeadPet = false;
Span<byte> buffer = stackalloc byte[OutgoingMobilePackets.BondedStatusPacketLength]; Span<byte> buffer = stackalloc byte[OutgoingMobilePackets.BondedStatusPacketLength];
OutgoingMobilePackets.CreateBondedStatus(ref buffer, Serial, false); OutgoingMobilePackets.CreateBondedStatus(buffer, Serial, false);
Effects.SendPacket(Location, Map, ref buffer); Effects.SendPacket(Location, Map, buffer);
SendIncomingPacket(); SendIncomingPacket();
SendIncomingPacket(); SendIncomingPacket();

View file

@ -2827,20 +2827,7 @@ namespace Server.Mobiles
private static void SendToStaffMessage(Mobile from, string text) private static void SendToStaffMessage(Mobile from, string text)
{ {
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)]; Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = OutgoingMessagePackets.CreateMessage( buffer.InitializePacket();
ref buffer,
from.Serial,
from.Body,
MessageType.Regular,
from.SpeechHue,
3,
false,
from.Language,
from.Name,
text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
foreach (var ns in from.GetClientsInRange(8)) foreach (var ns in from.GetClientsInRange(8))
{ {
@ -2848,6 +2835,24 @@ namespace Server.Mobiles
if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel) if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel)
{ {
if (buffer[0] == 0)
{
var length = OutgoingMessagePackets.CreateMessage(
buffer,
from.Serial,
from.Body,
MessageType.Regular,
from.SpeechHue,
3,
false,
from.Language,
from.Name,
text
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
}
ns.Send(buffer); ns.Send(buffer);
} }
} }