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;