using System.Buffers.Binary; using AcDream.Core.Net.Messages; using AcDream.Core.Net.Packets; namespace AcDream.Core.Net.Tests.Messages; public class CharacterListTests { [Fact] public void Parse_SingleCharacter_ExtractsGuidAndName() { // Hand-assemble a CharacterList body matching ACE's writer format: // u32 opcode, u32 0, u32 count=1, // u32 guid, String16L name, u32 deleteDelta, // u32 0, u32 slotCount, String16L accountName, // u32 useTurbineChat, u32 hasToD var w = new PacketWriter(128); w.WriteUInt32(CharacterList.Opcode); w.WriteUInt32(0); w.WriteUInt32(1); // count w.WriteUInt32(0x50000001u); w.WriteString16L("+Acdream"); w.WriteUInt32(0); // deleteDelta w.WriteUInt32(0); w.WriteUInt32(11); // slotCount w.WriteString16L("testaccount"); w.WriteUInt32(1); // useTurbineChat w.WriteUInt32(1); // hasToD var parsed = CharacterList.Parse(w.ToArray()); Assert.Single(parsed.Characters); Assert.Equal(0x50000001u, parsed.Characters[0].Id); Assert.Equal("+Acdream", parsed.Characters[0].Name); Assert.Equal(0u, parsed.Characters[0].DeleteTimeDelta); Assert.Equal(11u, parsed.SlotCount); Assert.Equal("testaccount", parsed.AccountName); Assert.True(parsed.UseTurbineChat); Assert.True(parsed.HasThroneOfDestiny); } [Fact] public void Parse_MultipleCharacters_PreservesOrder() { var w = new PacketWriter(128); w.WriteUInt32(CharacterList.Opcode); w.WriteUInt32(0); w.WriteUInt32(3); // count w.WriteUInt32(0x50000001u); w.WriteString16L("Alice"); w.WriteUInt32(0); w.WriteUInt32(0x50000002u); w.WriteString16L("Bob"); w.WriteUInt32(0); w.WriteUInt32(0x50000003u); w.WriteString16L("Carol"); w.WriteUInt32(0); w.WriteUInt32(0); w.WriteUInt32(11); w.WriteString16L("acct"); w.WriteUInt32(0); w.WriteUInt32(1); var parsed = CharacterList.Parse(w.ToArray()); Assert.Equal(3, parsed.Characters.Count); Assert.Equal("Alice", parsed.Characters[0].Name); Assert.Equal("Bob", parsed.Characters[1].Name); Assert.Equal("Carol", parsed.Characters[2].Name); } [Fact] public void Parse_WrongOpcode_Throws() { byte[] bytes = new byte[4]; BinaryPrimitives.WriteUInt32LittleEndian(bytes, 0xDEADBEEFu); Assert.Throws(() => CharacterList.Parse(bytes)); } [Fact] public void Parse_Truncated_Throws() { byte[] bytes = new byte[8]; // just opcode + first zero, missing count BinaryPrimitives.WriteUInt32LittleEndian(bytes, CharacterList.Opcode); Assert.Throws(() => CharacterList.Parse(bytes)); } }