using System; using System.Buffers.Binary; namespace AcDream.Core.Net.Messages; /// /// Inbound 0x01E2 SoulEmote top-level GameMessage. /// Server-driven complex emote with optional animation pairing. /// Wire layout is identical to ; the difference /// is only how the client renders it (chat-only vs paired with a /// PlayScript on the same target). /// /// /// Wire layout (port from holtburger /// references/holtburger/.../messages/chat/types.rs::SoulEmoteData, /// see also opcodes.rs:158): /// /// u32 opcode // 0x01E2 /// u32 senderGuid /// string16L senderName /// string16L text /// /// /// public static class SoulEmote { public const uint Opcode = 0x01E2u; public readonly record struct Parsed( uint SenderGuid, string SenderName, string Text); public static Parsed? TryParse(byte[] body) { if (body is null || body.Length < 8) return null; uint opcode = BinaryPrimitives.ReadUInt32LittleEndian(body); if (opcode != Opcode) return null; try { int pos = 4; uint senderGuid = BinaryPrimitives.ReadUInt32LittleEndian(body.AsSpan(pos)); pos += 4; string senderName = StringReader.ReadString16L(body, ref pos); string text = StringReader.ReadString16L(body, ref pos); return new Parsed(senderGuid, senderName, text); } catch { return null; } } }