using System.Buffers.Binary; namespace AcDream.Core.Net.Messages; /// /// Inbound retail PrivateUpdatePropertyInt64 (0x02CF): one signed /// 64-bit quality update for the local player. Total Experience (quality 1) /// and Available Experience (quality 2) use this message. /// /// /// Retail: CM_Qualities::DispatchUI_PrivateUpdateInt64 @ 0x006AEAD0 /// reads the sequence byte at +4, property at +5, and value at +9, then calls /// ClientObjMaintSystem::Handle_Qualities__PrivateUpdateInt64 @ 0x00559000. /// ACE GameMessagePrivateUpdatePropertyInt64 and holtburger's /// PrivateUpdatePropertyInt64Data confirm the same field order. /// public static class PrivateUpdatePropertyInt64 { public const uint Opcode = 0x02CFu; public const int BodySize = 17; // opcode(4) + sequence(1) + property(4) + value(8) public readonly record struct Parsed(uint Property, long Value); /// Parse a complete 0x02CF body, or return null on mismatch/truncation. public static Parsed? TryParse(ReadOnlySpan body) { if (body.Length < BodySize) return null; if (BinaryPrimitives.ReadUInt32LittleEndian(body) != Opcode) return null; const int propertyOffset = 5; // opcode + one-byte quality sequence uint property = BinaryPrimitives.ReadUInt32LittleEndian(body[propertyOffset..]); long value = BinaryPrimitives.ReadInt64LittleEndian(body[(propertyOffset + 4)..]); return new Parsed(property, value); } }