using System.Buffers.Binary; using AcDream.Core.Net.Packets; namespace AcDream.Core.Net.Messages; /// /// Retail character-logoff request and server confirmation (opcode /// 0xF653). /// /// /// Retail Proto_UI::LogOffCharacter at 0x00546A20 sends the /// opcode followed by the active character id. The server confirmation uses /// the same opcode with no trailing payload. CPlayerSystem::RequestLogOff /// at 0x00562DD0 waits for that confirmation; its inbound dispatch calls /// CPlayerSystem::ExecuteLogOff at 0x0055D780, which only then /// disconnects the world connection. /// public static class CharacterLogOff { public const uint Opcode = 0xF653u; /// Builds retail's eight-byte client request. public static byte[] BuildRequestBody(uint characterId) { var writer = new PacketWriter(8); writer.WriteUInt32(Opcode); writer.WriteUInt32(characterId); return writer.ToArray(); } /// /// Returns whether a complete game-message body is the server's logoff /// confirmation. ACE emits the canonical four-byte opcode-only form. /// public static bool IsConfirmation(ReadOnlySpan body) => body.Length == sizeof(uint) && BinaryPrimitives.ReadUInt32LittleEndian(body) == Opcode; }