using System.Buffers.Binary; using AcDream.Core.Net.Messages; using Xunit; namespace AcDream.Core.Net.Tests.Messages; /// /// Campaign FA slice FA1 (2026-08-11), D6: completes Core.Net's typed /// representation of the shared confirmation triple /// (0x0274/0x0275/0x0276). Grepping the tree before /// this slice showed 0x0274 () /// and 0x0276 () /// already had typed record + parser pairs; 0x0275 — the CLIENT→ /// SERVER leg — already had a byte-correct builder /// (ClientCommandRequests.BuildConfirmationResponse, lane C §3.3) /// but no typed record, no /// enum, and no parser. This file pins the completed triple: the new /// enum (1 = SwearAllegiance, /// 4 = Fellowship — D6), and /// round-tripping against the EXISTING builder byte-for-byte. /// public sealed class ConfirmationTripleTests { [Fact] public void ConfirmationType_SwearAllegianceIsOne_FellowshipIsFour() { // Handle_Character__ConfirmationRequest @0x005640A0 switch vs ACE // ConfirmationType.cs:5-12 — identical (lane B §3.15). Assert.Equal(1u, (uint)GameEvents.ConfirmationType.SwearAllegiance); Assert.Equal(4u, (uint)GameEvents.ConfirmationType.Fellowship); } [Fact] public void ParseConfirmationResponse_RoundTripsAgainstExistingBuilder() { byte[] wire = ClientCommandRequests.BuildConfirmationResponse( sequence: 5, confirmationType: (uint)GameEvents.ConfirmationType.Fellowship, contextId: 0x1234u, accepted: true); // Strip the 12-byte envelope/seq/opcode header the same way every // other GameEvents.Parse* function receives its payload (header // already stripped by the dispatcher) — here we strip the GameACTION // header by hand since BuildConfirmationResponse is a C→S builder. var response = GameEvents.ParseConfirmationResponse(wire.AsSpan(12)); Assert.NotNull(response); Assert.Equal(GameEvents.ConfirmationType.Fellowship, response.Value.Type); Assert.Equal(0x1234u, response.Value.ContextId); Assert.True(response.Value.Accepted); } [Fact] public void ParseConfirmationResponse_GoldenByteVector_SwearAllegianceDeclined() { // Hand-computed from CM_Character::Event_ConfirmationResponse // @0x006A1210 (lane B §3.15 / lane C §3.3): // [u32 confirmType][u32 context][u32 accepted]. byte[] payload = [ 0x01, 0x00, 0x00, 0x00, // confirmType = 1 (SwearAllegiance) 0x99, 0x00, 0x00, 0x00, // context = 0x99 0x00, 0x00, 0x00, 0x00, // accepted = 0 (declined) ]; var response = GameEvents.ParseConfirmationResponse(payload); Assert.NotNull(response); Assert.Equal(GameEvents.ConfirmationType.SwearAllegiance, response.Value.Type); Assert.Equal(0x99u, response.Value.ContextId); Assert.False(response.Value.Accepted); } [Fact] public void ParseConfirmationResponse_TruncatedPayload_ReturnsNull() { Assert.Null(GameEvents.ParseConfirmationResponse(new byte[8])); } }