using System.Text.Json.Serialization; namespace SVSim.BattleNode.Protocol.Bodies; /// Opponent-facing PlayActions frame the node synthesizes from the active player's /// send. KnownList reveals the played card's identity (null = token reveal deferred, see /// the deterministic-turn slice). OppoTargetList is the renamed targetList /// (independent of KnownList — a targeted hand play carries both). Both omitted when null via the /// envelope's WhenWritingNull policy. public sealed record PlayActionsBroadcastBody( [property: JsonPropertyName("playIdx")] int PlayIdx, [property: JsonPropertyName("type")] int Type, [property: JsonPropertyName("knownList")] IReadOnlyList? KnownList, [property: JsonPropertyName("oppoTargetList")] IReadOnlyList? OppoTargetList) : IMsgBody; /// One revealed card in a knownList. Vanilla slice fills cardId from the sender's /// deck map and leaves spellboost 0 / attachTarget "" (cost/clan/tribe deferred to the card-master /// port — the receiver re-derives them from cardId). public sealed record KnownCardEntry( [property: JsonPropertyName("idx")] int Idx, [property: JsonPropertyName("cardId")] long CardId, [property: JsonPropertyName("to")] int To, [property: JsonPropertyName("spellboost")] int Spellboost, [property: JsonPropertyName("attachTarget")] string AttachTarget); /// Renamed targetList entry. isSelf is actor-relative and passes through /// verbatim — no perspective flip (bullet-3 audit F2). public sealed record OppoTargetEntry( [property: JsonPropertyName("targetIdx")] int TargetIdx, [property: JsonPropertyName("isSelf")] int IsSelf);