docs(battle-node): project README + docstrings on hosting/lifecycle
Add a per-project README in SVSim.BattleNode/ that covers: - Architecture (the six concern folders) - The connect-handshake sequence verified end-to-end at smoke - A wire-format-gotchas table for the spec divergences caught during v1 (headers vs query for credentials, schemeless node URL with /socket.io/ path, required card_master_id, required resultCode=1, Matched in response to InitBattle not InitNetwork, EIO3 0x04 prefix on binary frames, FromJson conditional-expression number-boxing) - What the v1 scripted opponent does and what is hardcoded - A "where to extend" table for v2 work - The full test layout and cross-references to specs/plans Fill in XML docs on the public surface that previously had none: - BattleNodeExtensions.AddBattleNode / UseBattleNode (DI + middleware wiring, including the pipeline-order note that auth runs before UseWebSockets) - BattleNodeWebSocketHandler class + HandleAsync (the validation chain) - BattleSession.ComputeResponses (the lifecycle state machine, with the NoStock flag's meaning) - ScriptedLifecycle class (v1 scope, resultCode injection rule, pointer to the "where to extend" section) - MatchingBridge class (mint-id + register flow) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -3,15 +3,38 @@ using SVSim.BattleNode.Protocol;
|
||||
namespace SVSim.BattleNode.Lifecycle;
|
||||
|
||||
/// <summary>
|
||||
/// v1 Path-A scripted opponent. Hand-rolled static frames good enough to land the client on
|
||||
/// the mulligan screen and let them play turn 1. Templates derived from
|
||||
/// data_dumps/captures/battle-traffic_tk2_regular.ndjson.
|
||||
/// v1 hand-rolled scripted opponent. Static frame builders for the five lifecycle uris
|
||||
/// (Matched / BattleStart / Deal / Swap response / Ready) plus a trivial opponent TurnStart
|
||||
/// the dispatch pushes after the player's TurnEnd. The values are templated from the TK2
|
||||
/// captures at <c>data_dumps/captures/battle-traffic_tk2_regular.ndjson</c> — anything
|
||||
/// hardcoded here came from a real prod frame.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>"Scripted" means the opponent never reacts to your plays. We push enough to land
|
||||
/// you on the mulligan screen, run a real mulligan exchange, give you turn 1, transition
|
||||
/// to "Opponent's turn…" after your <c>TurnEnd</c>, and then sit there indefinitely. This
|
||||
/// is the documented v1 stopping point.</para>
|
||||
/// <para>
|
||||
/// All builders go through <see cref="EnvelopeForPush"/>, which injects
|
||||
/// <c>resultCode = 1</c> into every body. The client's <c>OnReceived</c> drops any
|
||||
/// synchronize push whose <c>resultCode != Success</c> (absent counts as None=0); leaving
|
||||
/// it off silently breaks the state machine without surfacing an error.
|
||||
/// </para>
|
||||
/// <para>To make this less scripted: see the project README §"Where to extend".</para>
|
||||
/// </remarks>
|
||||
public static class ScriptedLifecycle
|
||||
{
|
||||
/// <summary>30 dummy cardIds — repeats of a stable neutral card.</summary>
|
||||
/// <summary>
|
||||
/// CardId used for all 30 entries in the dummy deck. A stable neutral card that exists in
|
||||
/// every card-master version we care about, so the client can render it without
|
||||
/// triggering a card-master-mismatch error.
|
||||
/// </summary>
|
||||
public static readonly long DummyCardId = 100011010;
|
||||
|
||||
/// <summary>
|
||||
/// Viewer id we present as the opponent on every scripted push. Out-of-range vs. real
|
||||
/// viewer ids so it can't collide with a real account in the auth pipeline.
|
||||
/// </summary>
|
||||
public const long FakeOpponentViewerId = 999_999_999L;
|
||||
|
||||
public static MsgEnvelope BuildMatched(long playerViewerId, long opponentViewerId, string battleId)
|
||||
|
||||
Reference in New Issue
Block a user