using System.Buffers.Binary;
namespace AcDream.Core.Net.Messages;
///
/// Inbound ObjectDelete GameMessage (opcode 0xF747).
///
///
/// Retail dispatch path:
/// CM_Physics::DispatchSB_DeleteObject 0x006AC6A0 reads guid from
/// buf+4 and instance sequence from buf+8, then calls
/// SmartBox::HandleDeleteObject 0x00451EA0. ACE emits the same
/// layout from GameMessageDeleteObject.
///
///
public static class DeleteObject
{
public const uint Opcode = 0xF747u;
///
/// when this delete was sourced from a
/// PickupEvent (0xF74A) — the object left the 3-D world view but
/// the weenie record still exists (it is moving into a container).
/// (default) when sourced from DeleteObject
/// (0xF747) — the weenie was destroyed and must be evicted from
/// .
/// Retail two-table model: PickupEvent removes from object_table;
/// DeleteObject removes from weenie_object_table.
///
public readonly record struct Parsed(uint Guid, ushort InstanceSequence, bool FromPickup = false);
///
/// Parse a 0xF747 body. must start with the
/// 4-byte opcode, matching every other parser in this namespace.
/// The returned is always
/// — this parser handles true destroys only.
///
public static Parsed? TryParse(ReadOnlySpan body)
{
if (body.Length < 10)
return null;
uint opcode = BinaryPrimitives.ReadUInt32LittleEndian(body.Slice(0, 4));
if (opcode != Opcode)
return null;
uint guid = BinaryPrimitives.ReadUInt32LittleEndian(body.Slice(4, 4));
ushort instanceSequence = BinaryPrimitives.ReadUInt16LittleEndian(body.Slice(8, 2));
return new Parsed(guid, instanceSequence, FromPickup: false);
}
}