Commit Graph

5 Commits

Author SHA1 Message Date
gamer147
7d4da69f22 refactor(battlenode): low-churn §B/§D/§E/§F quality cleanups
Behavior-preserving; 231 BattleNode tests green.

- §D: MsgEnvelope.Try -> RetryAttempt (drops keyword-escape; wire key stays "try");
  SocketIoFrame.AckResponse arg -> pubSeqEcho.
- §B: Gungnir.EmitInterval -> BattleNodeOptions.AliveEmitInterval (unused literal
  moved to its config home); deck-idx 4L -> InitialHand.Length + 1.
- §E: shared Wire.WireJsonOptions.CamelCase replaces the duplicated camelCase
  JsonSerializerOptions in EngineIoHandshake and MsgEnvelope.
- §F: do-NOT-consistency-fix polarity notes on TurnEndFinalHandler (From wins)
  and RetireKillHandler (From loses).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 23:06:44 -04:00
gamer147
99129c786c fix(battle-node): harden SIO parse + narrow Matched OppoId/Seed to int
#3: SocketIoFrame.Parse now range-checks the packet type char (was
unchecked cast — any char outside 0-6 produced an undefined enum
value) and uses int.TryParse for ack-id (was int.Parse — a >10-digit
ack-id threw OverflowException, tearing down the WS mid-game). Both
now throw ArgumentException consistently. The read loop in
RealParticipant wraps both EIO and SIO parse calls with try-catch so
a malformed frame is logged and skipped instead of killing the battle.

#4: MatchedSelfInfo/MatchedOppoInfo OppoId and Seed narrowed from
long to int. The client reads both with Convert.ToInt32 inside a
swallowing try/catch — any value > int.MaxValue silently dropped the
Matched event, preventing the battle from starting. Seed was already
int-range (BattleSeeds.Stable returns int); OppoId (viewer ID) is
~847M in captures, well under int.MaxValue. The narrowing cast now
happens explicitly in ServerBattleFrames.BuildMatched at the wire
boundary.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-06-04 21:57:29 -04:00
gamer147
24180d5b4b refactor(battle-node): de-magic wire flags and scattered constants
Quality pass from the 2026-06-04 BattleNode review (audit in the outer
repo). All changes are behavior-preserving — identical wire bytes,
verified by the full 1008-test suite staying green.

- Name scattered magic numbers: crypto key/IV lengths, outbound-sequencer
  base, WS receive buffer / EIO ping / SID length, polite-close timeout,
  upgrade-credential keys, battle-id digit math, deterministic-turn spin.
- resultCode = 1 -> (int)ReceiveNodeResultCode.Success across body records.
- Pong "3" -> EngineIoPacketType.Pong; remove dead NoOpBotParticipant.Touch
  (replace with #pragma warning disable CS0067).
- Wire-flag enums, serialized as numbers via JsonNumberEnumConverter:
  turnState -> TurnState{First,Second}, isSelf -> CardOwner{Opponent,Self},
  open -> ChoiceVisibility{Hidden,Open}.
- isOfficial / isInvoke -> bool / bool? via new NumericBoolJsonConverter
  (reads/writes 0/1; TDD'd). Scoped to the BattleNode wire boundary only;
  MatchContext and the HTTP/AI-start path stay int (AI-start uses -1 as a
  sentinel, so it is not boolean).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 20:46:09 -04:00
gamer147
3f5d97cb2f feat(battle-node): derive Matched.seed + Ready.idxChangeSeed from master seed
InitBattle now emits Stable(master) as the shared effect seed and the master-
shuffled deck as selfDeck; Swap emits each recipient's per-side IdxChange seed.
BattleSession exposes + logs the master seed per battle for future replay.
Updated lifecycle/dispatch/integration tests (deck assertions now permutation-
based since selfDeck is shuffled).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 18:20:51 -04:00
gamer147
ba18790156 refactor(battle-node): rename ScriptedLifecycle->ServerBattleFrames, ScriptedProfiles->BattleFrameDefaults
Pure rename. These hold the shared server-authored frame builders used by every
battle mode's handshake/mulligan dispatch — the 'Scripted' name was a historical
accident that hid the PvP/Bot crossover. No behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-03 20:36:32 -04:00