Files
SVSimServer/SVSim.BattleEngine/Patches/ToolboxGame.ambient-fallback-deletion.patch
gamer147 c789d836f1 feat(engine-ambient): delete static fallbacks; add MultiInstanceEngineTests
Step 8 (final) of multi-instancing migration. All per-battle statics now
require a BattleAmbient scope — unwrapped writes throw InvalidOperationException
(fail-fast forcing function). MultiInstanceEngineTests proves correctness:
two parallel battles resolve independently, N=4/8/16 stress matches sequential
baseline, GameMgr.GetIns throws without scope.

Migration complete. EngineSessionGate gone. Suite fully green.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-06-07 23:19:37 -04:00

58 lines
2.8 KiB
Diff

Multi-instancing migration (Step 8 — forcing function): delete the static RealTimeNetworkAgent
fallback the earlier .ambient-rtna patch added as a coexistence shim. RealTimeNetworkAgent is now
strictly per-session ambient. Supersedes the intermediate .ambient-rtna patch (kept for the audit
trail).
Semantics:
- RealTimeNetworkAgent (getter) : Current?.NetworkAgent — soft (null when no scope).
Engine code reads this via `ToolboxGame.RealTimeNetworkAgent?.Foo`-style patterns (network
send paths gated on a non-null agent), so a null on the unwrapped path is the correct
degrade — not a throw.
- SetRealTimeNetworkBattle : BattleAmbient.Require().NetworkAgent = agent — strict (writes must
land on the per-session ctx; forcing function).
- DestroyNetworkAgent : reads Current, destroys, nulls the ambient NetworkAgent in-place.
Outside a scope is a no-op (nothing to destroy in the ambient world).
In-file edits:
- line ~28 declaration `private static RealTimeNetworkAgent _realTimeNetworkAgentFallback;` DELETED
- lines ~29-32 getter body no fallback chain
- lines ~61-66 Set body Require() (strict)
- lines ~68-78 Destroy body Current-based; no fallback branch
--- Engine/Wizard/ToolboxGame.cs (~lines 28-32)
- private static RealTimeNetworkAgent _realTimeNetworkAgentFallback;
public static RealTimeNetworkAgent RealTimeNetworkAgent
{
- get => SVSim.BattleEngine.Ambient.BattleAmbient.Current?.NetworkAgent ?? _realTimeNetworkAgentFallback;
+ // Soft read: returns null when no scope is active, mirroring GetIns. Engine code reads
+ // this via `ToolboxGame.RealTimeNetworkAgent?.Foo`-style patterns (network-send paths
+ // gated on a non-null agent), so a null on the unwrapped path is the correct degrade —
+ // not a throw.
+ get => SVSim.BattleEngine.Ambient.BattleAmbient.Current?.NetworkAgent;
}
--- Engine/Wizard/ToolboxGame.cs (~lines 61-78)
public static void SetRealTimeNetworkBattle(RealTimeNetworkAgent agent)
{
- var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
- if (c != null) c.NetworkAgent = agent;
- else _realTimeNetworkAgentFallback = agent;
+ // Strict: must be inside a scope to set the per-session agent. Forcing-function — any
+ // historical unwrapped caller (no production callsite remains) now fails fast.
+ SVSim.BattleEngine.Ambient.BattleAmbient.Require().NetworkAgent = agent;
}
public static void DestroyNetworkAgent()
{
var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
- var current = c?.NetworkAgent ?? _realTimeNetworkAgentFallback;
+ var current = c?.NetworkAgent;
if (current != null)
{
Object.DestroyImmediate(current.gameObject);
- if (c != null) c.NetworkAgent = null;
- else _realTimeNetworkAgentFallback = null;
+ c.NetworkAgent = null;
}
}