diff --git a/SVSim.BattleNode/Lifecycle/ScriptedLifecycle.cs b/SVSim.BattleNode/Lifecycle/ScriptedLifecycle.cs index 47ec22c..164a348 100644 --- a/SVSim.BattleNode/Lifecycle/ScriptedLifecycle.cs +++ b/SVSim.BattleNode/Lifecycle/ScriptedLifecycle.cs @@ -149,8 +149,14 @@ public static class ScriptedLifecycle return deck; } - private static MsgEnvelope EnvelopeForPush(NetworkBattleUri uri, Dictionary body, string? bid = null) => - new(uri, + private static MsgEnvelope EnvelopeForPush(NetworkBattleUri uri, Dictionary body, string? bid = null) + { + // Synchronize-push routing in the client's OnReceived drops any frame whose + // resultCode != Success (1). Absent counts as 0 (None) and is also dropped — so we + // MUST include it on every scripted push, not just InitNetwork ack / BattleFinish. + // See server-to-client.md §"Routing in OnReceived" and the matching prod captures. + body["resultCode"] = (int)ReceiveNodeResultCode.Success; + return new MsgEnvelope(uri, ViewerId: FakeOpponentViewerId, Uuid: "node-stub", Bid: bid, @@ -159,4 +165,5 @@ public static class ScriptedLifecycle PubSeq: null, PlaySeq: null, // OutboundSequencer.AssignAndArchive stamps this Body: body); + } }