From 97b9b6fe42322b455c8f917ba3a5e0147c2977cd Mon Sep 17 00:00:00 2001 From: gamer147 Date: Mon, 1 Jun 2026 10:34:44 -0400 Subject: [PATCH] feat(battle-node): typed Deal/Swap/Ready bodies + PosIdx --- SVSim.BattleNode/Protocol/Bodies/DealBody.cs | 8 +++ SVSim.BattleNode/Protocol/Bodies/PosIdx.cs | 7 +++ SVSim.BattleNode/Protocol/Bodies/ReadyBody.cs | 10 ++++ .../Protocol/Bodies/SwapResponseBody.cs | 7 +++ .../Protocol/Bodies/HandBodiesTests.cs | 55 +++++++++++++++++++ 5 files changed, 87 insertions(+) create mode 100644 SVSim.BattleNode/Protocol/Bodies/DealBody.cs create mode 100644 SVSim.BattleNode/Protocol/Bodies/PosIdx.cs create mode 100644 SVSim.BattleNode/Protocol/Bodies/ReadyBody.cs create mode 100644 SVSim.BattleNode/Protocol/Bodies/SwapResponseBody.cs create mode 100644 SVSim.UnitTests/BattleNode/Protocol/Bodies/HandBodiesTests.cs diff --git a/SVSim.BattleNode/Protocol/Bodies/DealBody.cs b/SVSim.BattleNode/Protocol/Bodies/DealBody.cs new file mode 100644 index 0000000..2c23aa2 --- /dev/null +++ b/SVSim.BattleNode/Protocol/Bodies/DealBody.cs @@ -0,0 +1,8 @@ +using System.Text.Json.Serialization; + +namespace SVSim.BattleNode.Protocol.Bodies; + +public sealed record DealBody( + [property: JsonPropertyName("self")] IReadOnlyList Self, + [property: JsonPropertyName("oppo")] IReadOnlyList Oppo, + [property: JsonPropertyName("resultCode")] int ResultCode = 1) : IMsgBody; diff --git a/SVSim.BattleNode/Protocol/Bodies/PosIdx.cs b/SVSim.BattleNode/Protocol/Bodies/PosIdx.cs new file mode 100644 index 0000000..934a60c --- /dev/null +++ b/SVSim.BattleNode/Protocol/Bodies/PosIdx.cs @@ -0,0 +1,7 @@ +using System.Text.Json.Serialization; + +namespace SVSim.BattleNode.Protocol.Bodies; + +public sealed record PosIdx( + [property: JsonPropertyName("pos")] int Pos, + [property: JsonPropertyName("idx")] int Idx); diff --git a/SVSim.BattleNode/Protocol/Bodies/ReadyBody.cs b/SVSim.BattleNode/Protocol/Bodies/ReadyBody.cs new file mode 100644 index 0000000..21b5736 --- /dev/null +++ b/SVSim.BattleNode/Protocol/Bodies/ReadyBody.cs @@ -0,0 +1,10 @@ +using System.Text.Json.Serialization; + +namespace SVSim.BattleNode.Protocol.Bodies; + +public sealed record ReadyBody( + [property: JsonPropertyName("self")] IReadOnlyList Self, + [property: JsonPropertyName("oppo")] IReadOnlyList Oppo, + [property: JsonPropertyName("idxChangeSeed")] int IdxChangeSeed, + [property: JsonPropertyName("spin")] int Spin, + [property: JsonPropertyName("resultCode")] int ResultCode = 1) : IMsgBody; diff --git a/SVSim.BattleNode/Protocol/Bodies/SwapResponseBody.cs b/SVSim.BattleNode/Protocol/Bodies/SwapResponseBody.cs new file mode 100644 index 0000000..673aca7 --- /dev/null +++ b/SVSim.BattleNode/Protocol/Bodies/SwapResponseBody.cs @@ -0,0 +1,7 @@ +using System.Text.Json.Serialization; + +namespace SVSim.BattleNode.Protocol.Bodies; + +public sealed record SwapResponseBody( + [property: JsonPropertyName("self")] IReadOnlyList Self, + [property: JsonPropertyName("resultCode")] int ResultCode = 1) : IMsgBody; diff --git a/SVSim.UnitTests/BattleNode/Protocol/Bodies/HandBodiesTests.cs b/SVSim.UnitTests/BattleNode/Protocol/Bodies/HandBodiesTests.cs new file mode 100644 index 0000000..54bdc2f --- /dev/null +++ b/SVSim.UnitTests/BattleNode/Protocol/Bodies/HandBodiesTests.cs @@ -0,0 +1,55 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using NUnit.Framework; +using SVSim.BattleNode.Protocol.Bodies; + +namespace SVSim.UnitTests.BattleNode.Protocol.Bodies; + +[TestFixture] +public class HandBodiesTests +{ + [Test] + public void DealBody_SerializesSelfAndOppoArrays_WithPosIdxKeys() + { + var body = new DealBody( + Self: new[] { new PosIdx(0, 1), new PosIdx(1, 2), new PosIdx(2, 3) }, + Oppo: new[] { new PosIdx(0, 1), new PosIdx(1, 2), new PosIdx(2, 3) }); + + var node = (JsonObject)JsonSerializer.SerializeToNode(body)!; + var self = (JsonArray)node["self"]!; + + Assert.That(self.Count, Is.EqualTo(3)); + Assert.That(((JsonObject)self[0]!)["pos"]!.GetValue(), Is.EqualTo(0)); + Assert.That(((JsonObject)self[0]!)["idx"]!.GetValue(), Is.EqualTo(1)); + Assert.That(node["resultCode"]!.GetValue(), Is.EqualTo(1)); // default + } + + [Test] + public void SwapResponseBody_OnlyContainsSelf_NotOppo() + { + var body = new SwapResponseBody( + Self: new[] { new PosIdx(0, 1), new PosIdx(1, 4), new PosIdx(2, 3) }); + + var node = (JsonObject)JsonSerializer.SerializeToNode(body)!; + + Assert.That(node.ContainsKey("self"), Is.True); + Assert.That(node.ContainsKey("oppo"), Is.False); + Assert.That(((JsonObject)((JsonArray)node["self"]!)[1]!)["idx"]!.GetValue(), Is.EqualTo(4)); + } + + [Test] + public void ReadyBody_SerializesAllFields_IncludingIdxChangeSeedAndSpin() + { + var body = new ReadyBody( + Self: new[] { new PosIdx(0, 1) }, + Oppo: new[] { new PosIdx(0, 1) }, + IdxChangeSeed: 771_335_280, + Spin: 243); + + var node = (JsonObject)JsonSerializer.SerializeToNode(body)!; + + Assert.That(node["idxChangeSeed"]!.GetValue(), Is.EqualTo(771_335_280)); + Assert.That(node["spin"]!.GetValue(), Is.EqualTo(243)); + Assert.That(node["resultCode"]!.GetValue(), Is.EqualTo(1)); + } +}