ace/Source/ACE.Server/Network/MessageFragment.cs
Mag-nus c2ed2eab9a
Performance improvements with the help of Claude (#4472)
* Network performance improvements, limit boxing

* Polygon comment out redundant test code

* Transition remove duplicate Init()

* Creature_BodyPart and Monster_Melee comment out unused var
2026-08-03 11:48:37 +00:00

107 lines
3.9 KiB
C#

using System;
using System.IO;
using ACE.Server.Network.GameMessages;
using log4net;
namespace ACE.Server.Network
{
internal class MessageFragment
{
private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private static readonly ILog packetLog = LogManager.GetLogger(System.Reflection.Assembly.GetEntryAssembly(), "Packets");
public GameMessage Message { get; private set; }
public uint Sequence { get; set; }
public ushort Index { get; set; }
public ushort Count { get; set; }
public int DataLength => (int)Message.Data.Length;
public int DataRemaining { get; private set; }
public int NextSize
{
get
{
var dataSize = DataRemaining;
if (dataSize > PacketFragment.MaxFragmentDataSize)
dataSize = PacketFragment.MaxFragmentDataSize;
return PacketFragmentHeader.HeaderSize + dataSize;
}
}
public int TailSize => PacketFragmentHeader.HeaderSize + (DataLength % PacketFragment.MaxFragmentDataSize);
public bool TailSent { get; private set; }
public MessageFragment(GameMessage message, uint sequence)
{
Message = message;
DataRemaining = DataLength;
Sequence = sequence;
Count = (ushort)(Math.Ceiling((double)DataLength / PacketFragment.MaxFragmentDataSize));
Index = 0;
if (Count == 1)
TailSent = true;
if (packetLog.IsDebugEnabled)
packetLog.DebugFormat("Sequence {0}, count {1}, DataRemaining {2}", sequence, Count, DataRemaining);
}
public ServerPacketFragment GetTailFragment()
{
var index = (ushort)(Count - 1);
TailSent = true;
return CreateServerFragment(index);
}
public ServerPacketFragment GetNextFragment()
{
return CreateServerFragment(Index++);
}
private ServerPacketFragment CreateServerFragment(ushort index)
{
if (packetLog.IsDebugEnabled)
packetLog.DebugFormat("Creating ServerFragment for index {0}", index);
if (index >= Count)
throw new ArgumentOutOfRangeException("index", index, "Passed index is greater then computed count");
var position = index * PacketFragment.MaxFragmentDataSize;
if (position > DataLength)
throw new ArgumentOutOfRangeException("index", index, "Passed index computes to invalid position size");
if (DataRemaining <= 0)
throw new InvalidOperationException("There is no data remaining");
var dataToSend = DataLength - position;
if (dataToSend > PacketFragment.MaxFragmentDataSize)
dataToSend = PacketFragment.MaxFragmentDataSize;
if (DataRemaining < dataToSend)
throw new InvalidOperationException("More data to send then data remaining!");
// Read data starting at position reading dataToSend bytes
Message.Data.Seek(position, SeekOrigin.Begin);
byte[] data = new byte[dataToSend];
Message.Data.Read(data, 0, dataToSend);
// Build ServerPacketFragment structure
ServerPacketFragment fragment = new ServerPacketFragment(data);
fragment.Header.Sequence = Sequence;
fragment.Header.Id = 0x80000000;
fragment.Header.Count = Count;
fragment.Header.Index = index;
fragment.Header.Queue = (ushort)Message.Group;
DataRemaining -= dataToSend;
if (packetLog.IsDebugEnabled)
packetLog.DebugFormat("Done creating ServerFragment for index {0}. After reading {1} DataRemaining {2}", index, dataToSend, DataRemaining);
return fragment;
}
}
}