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

View file

@ -40,7 +40,7 @@ namespace Benchmarks
}
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
)
{
@ -116,8 +116,7 @@ namespace Benchmarks
Span<byte> buffer = result.Buffer[0];
var length = CreateUnicodeMessage(
ref buffer,
Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
buffer, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
);
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.";
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = CreateUnicodeMessage(
ref buffer,
Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
buffer, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
);
buffer = buffer.Slice(0, length);
@ -151,8 +149,7 @@ namespace Benchmarks
{
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = CreateUnicodeMessage(
ref buffer,
Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
buffer, Serial.MinusOne, -1, MessageType.Regular, 0x3B2, 3, "ENU", "System", text
);
buffer = buffer.Slice(0, length);

View file

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

View file

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

View file

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

View file

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

View file

@ -40,9 +40,20 @@ namespace Server.Network
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)]
public static void InitializePackets(this Span<byte> buffer, int chunkLength)
{
#if NO_LOCAL_INIT
var index = 0;
while (index < buffer.Length)
@ -50,6 +61,7 @@ namespace Server.Network
buffer[index] = 0;
index += chunkLength;
}
#endif
}
}
}

View file

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

View file

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

View file

@ -23,7 +23,7 @@ namespace Server.Network
{
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 hasAmount = item.Amount != 0;
@ -87,13 +87,13 @@ namespace Server.Network
Span<byte> buffer = stackalloc byte[MaxWorldItemPacketLength];
var length = ns.StygianAbyss ?
CreateWorldItemNew(ref buffer, item, ns.HighSeas) :
CreateWorldItem(ref buffer, item);
CreateWorldItemNew(buffer, item, ns.HighSeas) :
CreateWorldItem(buffer, item);
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);
writer.Write((byte)0xF3); // Packet ID

View file

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

View file

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

View file

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

View file

@ -154,8 +154,7 @@ namespace Server
Span<byte> buffer = stackalloc byte[length];
length = OutgoingMessagePackets.CreateMessage(
ref buffer,
Serial.MinusOne, -1, MessageType.Regular, hue, 3, ascii, "ENU", "System", text
buffer, Serial.MinusOne, -1, MessageType.Regular, hue, 3, ascii, "ENU", "System", text
);
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];
OutgoingEffectPackets.CreateSoundEffect(ref buffer, index, m);
buffer.InitializePacket();
foreach (var state in m.GetClientsInRange(12))
{
if (toAll || state.Mobile.CanSee(m))
{
if (buffer[0] == 0)
{
OutgoingEffectPackets.CreateSoundEffect(buffer, index, m);
}
state.Send(buffer);
}
}

View file

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

View file

@ -504,26 +504,30 @@ namespace Server.Engines.Doom
public static void POHMessage(Mobile from, int index)
{
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(Msgs[index])];
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
buffer.InitializePacket();
var eable = from.Map.GetClientsInRange(from.Location);
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);
}

View file

@ -96,7 +96,7 @@ namespace Server.Engines.MLQuests.Mobiles
}
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedLength("")];
var packetCreated = false;
buffer.InitializePacket();
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 (!packetCreated)
if (buffer[0] == 0)
{
// Double Click On Me For Help!
var length = OutgoingMessagePackets.CreateMessageLocalized(
ref buffer,
Serial, Body, MessageType.Regular, 946, 3, 1078099, Name
buffer, Serial, Body, MessageType.Regular, 946, 3, 1078099, Name
);
packetCreated = true;
buffer = buffer.Slice(0, length);
}
state.Send(buffer);

View file

@ -241,7 +241,7 @@ namespace Server.Engines.PartySystem
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(from.Name, "")];
var length = OutgoingMessagePackets.CreateMessageLocalizedAffix(
ref buffer,
buffer,
Serial.MinusOne,
-1,
MessageType.Label,
@ -253,10 +253,8 @@ namespace Server.Engines.PartySystem
from.Name
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
// : joined the party.
SendToAll(ref buffer, true);
SendToAll(buffer.Slice(0, length), true);
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)];
var length = OutgoingMessagePackets.CreateMessageLocalized(
ref buffer,
buffer,
Serial.MinusOne, -1, MessageType.Regular, hue, 3, number, "System", args
);
buffer = buffer.Slice(0, length); // Adjust to the actual size
SendToAll(ref buffer, true);
SendToAll(buffer.Slice(0, length), true);
}
public void SendPublicMessage(Mobile from, string text)
@ -429,19 +425,7 @@ namespace Server.Engines.PartySystem
private void SendToStaffMessage(Mobile from, string text)
{
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = OutgoingMessagePackets.CreateMessage(
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
buffer.InitializePacket();
foreach (var ns in from.GetClientsInRange(8))
{
@ -450,6 +434,24 @@ namespace Server.Engines.PartySystem
if (mob?.AccessLevel >= AccessLevel.GameMaster && mob.AccessLevel > from.AccessLevel &&
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);
}
}
@ -472,7 +474,7 @@ namespace Server.Engines.PartySystem
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)
{
@ -512,20 +514,7 @@ namespace Server.Engines.PartySystem
m_Mobile.Send(new PartyMemberList(p));
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLocalizedAffixLength(m_Mobile.Name, "")];
var length = OutgoingMessagePackets.CreateMessageLocalizedAffix(
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
buffer.InitializePacket();
var attrs = Packet.Acquire(new MobileAttributesN(m_Mobile));
@ -535,6 +524,24 @@ namespace Server.Engines.PartySystem
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.Send(new MobileStatusCompact(m_Mobile.CanBeRenamedBy(m), m_Mobile));
m.Send(attrs);

View file

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

View file

@ -50,12 +50,12 @@ namespace Server.Items
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);
}
else
{
length = OutgoingItemPackets.CreateWorldItem(ref buffer, this);
length = OutgoingItemPackets.CreateWorldItem(buffer, this);
BinaryPrimitives.WriteUInt16BigEndian(buffer.Slice(7, 2), GMItemId);
}

View file

@ -56,12 +56,12 @@ namespace Server.Items
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);
}
else
{
length = OutgoingItemPackets.CreateWorldItem(ref buffer, this);
length = OutgoingItemPackets.CreateWorldItem(buffer, this);
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)
{
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = OutgoingMessagePackets.CreateMessage(
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
buffer.InitializePacket();
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++)
{
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);
}
}
@ -1266,7 +1271,7 @@ namespace Server.Guilds
}
else
{
m_AllianceLeader = reader.ReadEntity<Guild>();;
m_AllianceLeader = reader.ReadEntity<Guild>();
}
goto case 4;
@ -1516,15 +1521,20 @@ namespace Server.Guilds
public void GuildChat(Mobile from, int hue, string text)
{
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = OutgoingMessagePackets.CreateMessage(
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
buffer.InitializePacket();
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);
}
}

View file

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

View file

@ -2827,20 +2827,7 @@ namespace Server.Mobiles
private static void SendToStaffMessage(Mobile from, string text)
{
Span<byte> buffer = stackalloc byte[OutgoingMessagePackets.GetMaxMessageLength(text)];
var length = OutgoingMessagePackets.CreateMessage(
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
buffer.InitializePacket();
foreach (var ns in from.GetClientsInRange(8))
{
@ -2848,6 +2835,24 @@ namespace Server.Mobiles
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);
}
}