From 4e756a6c46f03620471fb8beecb11dcfc556d30a Mon Sep 17 00:00:00 2001 From: gamer147 Date: Sun, 7 Jun 2026 21:23:27 -0400 Subject: [PATCH] refactor(engine-ambient): BattleManagerBase.GetIns reads ambient first, static fallback Step 3 of multi-instancing migration. The dominant per-battle singleton now resolves through BattleAmbient.Current.Mgr when a scope is active. The legacy 'main' field is renamed _mainFallback and retained for unwrapped callers (tests, anything not yet scope-wrapped). GetIns() still returns null when neither is set, preserving the '?.Foo ?? default' patterns in engine code. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../BattleAmbientTests.cs | 19 +++++++++ SVSim.BattleEngine/COPIED.manifest.tsv | 2 +- .../Engine/BattleManagerBase.cs | 8 ++-- ...attleManagerBase.ambient-main-getins.patch | 40 +++++++++++++++++++ 4 files changed, 64 insertions(+), 5 deletions(-) create mode 100644 SVSim.BattleEngine/Patches/BattleManagerBase.ambient-main-getins.patch diff --git a/SVSim.BattleEngine.Tests/BattleAmbientTests.cs b/SVSim.BattleEngine.Tests/BattleAmbientTests.cs index efd0f30..77cc0ec 100644 --- a/SVSim.BattleEngine.Tests/BattleAmbientTests.cs +++ b/SVSim.BattleEngine.Tests/BattleAmbientTests.cs @@ -1,6 +1,7 @@ #nullable enable using SVSim.BattleEngine.Ambient; using NUnit.Framework; +using System.Runtime.Serialization; using System.Threading.Tasks; namespace SVSim.BattleEngine.Tests; @@ -129,4 +130,22 @@ public class BattleAmbientTests BattleManagerBase.IsRandomDraw = false; } + + [Test] + public void GetIns_ReadsAmbient_WhenScopeActive() + { + var fakeMgr = (BattleManagerBase)System.Runtime.Serialization + .FormatterServices.GetUninitializedObject(typeof(BattleManagerBase)); + var ctx = new BattleAmbientContext { Mgr = fakeMgr }; + using var _ = BattleAmbient.Enter(ctx); + Assert.That(BattleManagerBase.GetIns(), Is.SameAs(fakeMgr)); + } + + [Test] + public void GetIns_OutsideScope_FallsBackToStatic() + { + Assert.That(BattleAmbient.Current, Is.Null); + var v = BattleManagerBase.GetIns(); + Assert.Pass($"GetIns()={(v is null ? "null" : v.GetType().Name)}"); + } } diff --git a/SVSim.BattleEngine/COPIED.manifest.tsv b/SVSim.BattleEngine/COPIED.manifest.tsv index 8dbc488..9040327 100644 --- a/SVSim.BattleEngine/COPIED.manifest.tsv +++ b/SVSim.BattleEngine/COPIED.manifest.tsv @@ -62,7 +62,7 @@ BattleFinishToOpponentDisConnectChecker.cs BattleFinishToOpponentDisConnectCheck BattleKeywordInfoListMgr.cs BattleKeywordInfoListMgr.cs a014170d0b3f5499635bcc2e29755dc2f3125d5a5a28b1741a4abc74b4abcf86 0 BattleLifeTimeSharedObject.cs BattleLifeTimeSharedObject.cs ab8bc3703d268752a1de56ab5d3e9ebd276980c20076eb0ca300838b3db13d5f 0 BattleLogTextBuilderAttachSkill.cs BattleLogTextBuilderAttachSkill.cs 11c585ae931fa3dc734bb231d6da61df3b51b803516ca2c5d88a0c78bc7c0104 0 -BattleManagerBase.cs BattleManagerBase.cs 6e537b57a66d16c056f62ed3d00c1727d08adab098e90b4f1373c987a2da8a35 1 +BattleManagerBase.cs BattleManagerBase.cs d12aed345f596e068bfb130a247e280457cf5160a76f8bfef4a1dda1c561d196 1 BattleMenuMgr.cs BattleMenuMgr.cs 7418699063e01641d0df1ed16773a9ac9418f418cc047fc18c5892eb7971d361 0 BattlePlayer.cs BattlePlayer.cs 001409844b46ddaf0a5edbce4e015749ece61053adf725a978987d7063a02632 0 BattlePlayerBase.cs BattlePlayerBase.cs 9d3a665158706460a52900008dcfcdf575dbe08cb6d3cc05e63e718b2885b51b 0 diff --git a/SVSim.BattleEngine/Engine/BattleManagerBase.cs b/SVSim.BattleEngine/Engine/BattleManagerBase.cs index 0a100df..be34674 100644 --- a/SVSim.BattleEngine/Engine/BattleManagerBase.cs +++ b/SVSim.BattleEngine/Engine/BattleManagerBase.cs @@ -410,7 +410,7 @@ public class BattleManagerBase private NetworkTouchControl _networkTouchControl; - private static BattleManagerBase main; + private static BattleManagerBase _mainFallback; private static bool _isRandomDrawFallback = false; public static bool IsRandomDraw { @@ -724,12 +724,12 @@ public class BattleManagerBase public static BattleManagerBase GetIns() { - return main; + return SVSim.BattleEngine.Ambient.BattleAmbient.Current?.Mgr ?? _mainFallback; } protected BattleManagerBase(IBattleMgrContentsCreator contentsCreator) { - main = this; + _mainFallback = this; BattleLifeTimeSharedObject = new BattleLifeTimeSharedObject(); PublishedSkillList = new List(); _contentsCreator = contentsCreator; @@ -1488,7 +1488,7 @@ public class BattleManagerBase GameMgr.GetIns().GetPrefabMgr().DisposeAllClonedObject(); GameMgr.GetIns().GetGameObjMgr().DisposeUIGameObj(); GameMgr.GetIns().GetPrefabMgr().AllUnLoad(); - main = null; + _mainFallback = null; } private void DisposeBattleGameObj_DestroyImmediate(GameObject obj) diff --git a/SVSim.BattleEngine/Patches/BattleManagerBase.ambient-main-getins.patch b/SVSim.BattleEngine/Patches/BattleManagerBase.ambient-main-getins.patch new file mode 100644 index 0000000..e683f9a --- /dev/null +++ b/SVSim.BattleEngine/Patches/BattleManagerBase.ambient-main-getins.patch @@ -0,0 +1,40 @@ +Multi-instancing migration (Step 3): convert the dominant per-battle singleton seam — the +static `main` backing field and the `GetIns()` accessor — to read through BattleAmbient.Current +first, falling back to a renamed `_mainFallback` static when no scope is active. The legacy +field is kept (renamed) so unwrapped callers (SingleBattleMgr today, in-process tests that +don't yet wrap in BattleAmbient.Enter) keep working with zero behavioral change; scoped +callers get per-AsyncLocal isolation so sibling battles in the same process don't clobber +each other's "current manager" (design 2026-06-07-engine-multi-instancing, Task 3). + +GetIns() is the canonical accessor used by ~hundreds of engine call sites; routing it through +ambient is what makes the rest of the migration value-adding. Direct cross-file reads of +`BattleManagerBase.main` were already absent (the field was private; only an in-comment +reference in Shim/BattleAmbientContext.cs exists), so no external callers needed updating. + +In-file references (4 total) handled as follows: + - line 413 declaration → renamed to `_mainFallback` + - line 725 GetIns body → ambient-first via Current?.Mgr ?? _mainFallback + - line 730 ctor `main = this` → `_mainFallback = this` + - line 1491 dispose `main=null` → `_mainFallback = null` + +--- Engine/BattleManagerBase.cs (~line 413) +- private static BattleManagerBase main; ++ private static BattleManagerBase _mainFallback; + +--- Engine/BattleManagerBase.cs (~line 725) + public static BattleManagerBase GetIns() + { +- return main; ++ return SVSim.BattleEngine.Ambient.BattleAmbient.Current?.Mgr ?? _mainFallback; + } + +--- Engine/BattleManagerBase.cs (~line 730) + protected BattleManagerBase(IBattleMgrContentsCreator contentsCreator) + { +- main = this; ++ _mainFallback = this; + +--- Engine/BattleManagerBase.cs (~line 1491) +- main = null; ++ _mainFallback = null; + }