Files
SVSimServer/SVSim.BattleEngine/Patches/Certification.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

74 lines
3.2 KiB
Diff

Multi-instancing migration (Step 8 — forcing function): delete the static viewer-id fallback the
earlier .ambient-viewerid patch added as a coexistence shim. ViewerId is now strictly per-session
ambient (BattleAmbient.Require().ViewerId). Supersedes the intermediate .ambient-viewerid patch
(kept for the audit trail).
Semantics:
- get : BattleAmbient.Require().ViewerId — strict (throws when no scope is active)
- set : NO-OP. The historical caller (SavedataManager.SetInt + Save) is the client process's
persistent-storage path; in the headless multi-instance world the viewer id flows from the
session ctx (BattleAmbientContext.ViewerId, init-only at scope entry — see
SessionBattleEngine's field initializer, which seeds it from EngineGlobalInit.ThisViewerId).
Making the setter strict (Require()) would also work but degrades to a write that can't land
(init-only) — a comment-documented no-op is clearer about why the setter went dead.
Related (SVSim.BattleNode/Sessions/Engine/EngineGlobalInit.cs): the reflection write that seeded
`Certification._viewerIdFallback` is now dead — the static is deleted. Replaced with a comment-
only marker so the design intent (ThisViewerId defines the engine's "player" perspective for the
IsRecovery target parse) stays discoverable from the global init path.
InitializeFileds(): the now-dead `_viewerIdFallback = 0;` line is also deleted (the line above and
below — SavedataManager.SetInt("VIEWER_ID", 0) — stay).
In-file edits:
- line ~19 declaration `private static int _viewerIdFallback;` DELETED
- lines ~41-65 the ambient+fallback get/set body REPLACED with strict get + no-op set
- line ~155 `_viewerIdFallback = 0;` inside InitializeFileds DELETED
--- Engine/Cute/Certification.cs (~line 19)
private static string udid;
-
- private static int _viewerIdFallback;
-
private static int short_udid;
--- Engine/Cute/Certification.cs (~lines 41-65)
public static int ViewerId
{
- get
- {
- var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
- if (c != null) return c.ViewerId;
- if (_viewerIdFallback == 0)
- {
- _viewerIdFallback = Toolbox.SavedataManager.GetInt("VIEWER_ID");
- }
- return _viewerIdFallback;
- }
- set
- {
- var c = SVSim.BattleEngine.Ambient.BattleAmbient.Current;
- if (c != null)
- {
- // Inside a scope, ViewerId is fixed at scope entry — swallow the write.
- return;
- }
- Toolbox.SavedataManager.SetInt("VIEWER_ID", value);
- Toolbox.SavedataManager.Save();
- _viewerIdFallback = value;
- }
+ // Post-Task-8: strictly ambient. The historical SavedataManager-backed lazy decode was the
+ // client process's single-viewer-id source; in the headless multi-instance world the viewer
+ // id MUST come from the per-session ambient context. Setter is a no-op (BattleAmbientContext
+ // .ViewerId is `init`-only — fixed at scope entry per design — and the historical caller
+ // (SavedataManager.SetInt + Save) is dead in the server world).
+ get => SVSim.BattleEngine.Ambient.BattleAmbient.Require().ViewerId;
+ set { /* ambient ViewerId is init-only; SavedataManager path is dead headless */ }
}
--- Engine/Cute/Certification.cs (~line 155)
sessionId = null;
udid = null;
- _viewerIdFallback = 0;
short_udid = 0;