engine cleanup passes 4-7 + multi-instancing ambient rip

Squashes 146 commits from battle-engine-extraction. Net: 2,045 files changed,
+11,896 / -158,687 lines. Ships engine passes 4-7 (dead-code cull, view-layer
stub, receive-path shrink) plus the Phase-5 AsyncLocal ambient deletion that
turns concurrent battles into a type-system property rather than a scope
contract.

## What landed

**Passes 4-7 (chunks 1-34):** Extended the Phase-4 const-false collapse into a
cascading cull across the skill graph, view layer, and receive-path periphery.
Six mode flags (IsWatchBattle/IsReplayBattle/IsAdmin/IsAdminWatch/IsPuzzleQuest/
IsAINetwork) became `const false`, every guarded block deleted. Field*.cs
subclass ctors + BackGroundBase + ObjectChecker culled to no-ops. Mulligan
family reworked to take a mgr param through IMulliganMgr.InitMulligan.
Emotion/Recovery/Resource clusters null-stubbed. Prediction/OperationSimulator/
skill filters converted from static ambient reads to per-mgr reads via
SkillPrm.ownerCard.SelfBattlePlayer.BattleMgr / ins.BattleMgr / this.BattleMgr.

**Phase-5 ambient rip (chunks 35-47):** Deleted BattleAmbient / BattleAmbient-
Context / TestBattleScope in full. Every per-battle mutable slot now lives on
the mgr instance itself:
  mgr.InstanceIsForecast / InstanceIsRandomDraw / InstanceRecoveryInfo /
  InstanceViewerId / InstanceNetworkAgent / GameMgr
BattleManagerBase.GetIns() returns null unconditionally; the residual static
flags + 3 façades (Certification.ViewerId, Data.BattleRecoveryInfo,
ToolboxGame.RealTimeNetworkAgent) are null-tolerant defaults kept for the
handful of engine-internal readers that still reference their types. Zero
BattleAmbient references anywhere in engine + node + tests.

Added pre-seeded GameMgr ctor overload threaded through the mgr chain
(BattleManagerBase → SingleBattleMgr / NetworkBattleManagerBase → NetworkStandard-
BattleMgr → HeadlessBattleMgr / HeadlessNetworkBattleMgr). Fixtures build a
GameMgr, seed it via HeadlessEngineEnv.SeedCharaIds/SeedNetUser, and pass it
to the mgr's ctor — no ambient reach.

Node side (SVSim.BattleNode/SessionBattleEngine): _ctx replaced with a plain
GameMgr field; 34 `using var _ambient = BattleAmbient.Enter(_ctx)` scope wraps
ripped from every accessor and mutator; EngineGlobalInit.WirePerSessionGameMgr
takes GameMgr as a param and runs from SessionBattleEngine.SetupInternal
BEFORE mgr construction.

Test side: TestBattleScope deleted; 18 fixture [SetUp]s migrated to
`HeadlessEngineEnv.EnsureProcessGlobals()`; MultiInstanceEngineTests rewritten
around per-mgr construction (GetIns() → null is the pinned invariant).

## Regression fixes

- **chunk-48** (MulliganCtrl): chunk-35's `= null` stubs on card lookups broke
  the live receive-driven Deal path (BattlePlayerBase.DrawCard NRE'd downstream
  of NetworkPlayerMulliganCtrl.StartMulliganVfx). Restored the three lookups
  via `_battlePlayer.BattleMgr.GetBattleCardIdx`. Engine tests were satisfied
  by the WireMulliganPhase seam; unit tests exposed the live-path gap.

## Ship state

- SVSim.BattleEngine.Tests: 56/56 pass, 2 skip
- SVSim.UnitTests: 1554/1554 pass (was 1523/31-fail before chunk 48)
- Solution build: 0 source warnings (40 pre-existing NU1902 MessagePack CVEs
  in SVSim.EmulatedEntrypoint, unrelated)
- Sequential PVP smoke: verified live (two back-to-back battles, no regression
  on cleanup/spinup)
- Concurrent PVP smoke: verified live

Adds tools/engine-port/ClosureAnalyzer/ — the Roslyn transitive-type-closure
analyzer needed to make future cascade cleanup safe (per feedback memory
"Engine cleanup needs closure tool" from the 2026-06-28 pass-3 failure).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-07-03 19:18:54 -04:00
parent 5c1db83967
commit 2d9a6eea4b
2045 changed files with 11704 additions and 158495 deletions

View File

@@ -16,10 +16,7 @@ public partial class UIManager
public enum ViewScene
{
None,
Splash,
Title,
MyPage,
CommonBackGround,
Battle,
Room,
RankMatch,
@@ -28,156 +25,45 @@ public partial class UIManager
StorySelectionWorld,
AreaSelect,
StoryChapterSelectionFlowChart,
Scenario,
Scenario2,
Prologue,
Ending,
QuestSelectionPage,
PracticePuzzle,
DeckList,
DeckCardEdit,
CardAllList,
CardDestruct,
TwoPick,
Sealed,
SealedCardPackOpen,
SealedDeckEdit,
Convention,
Colosseum,
Gacha,
BuildDeckPurchasePage,
CardSleevePurchasePage,
ClassSkinPurchasePage,
Profile,
Ranking,
Mission,
Mail,
BattlePass,
Tutorial1,
Tutorial2,
Tutorial3,
StoryTutorialElf,
StoryTutorialRoyal,
StoryTutorialWitch,
StoryTutorialDragon,
StoryTutorialNecromancer,
StoryTutorialVampire,
StoryTutorialBishop,
StoryTutorialNemesis,
Guild,
Friend,
LoginBonus,
LotteryPage,
BeginnerMission,
FreePackCampaign,
Gathering,
Competition2Pick,
CompetitionLobby,
BossRushLobby,
RedEtherCampaignLobby,
Bingo,
CrossoverPortal,
NeutralPopularityVote,
LeaderPopularityVote,
Max
}
public const int FLICK_LOWER_LIMIT_X = 50;
private Footer prefabFooter;
private Footer m_Footer;
private UIAtlasManager _atlasManager;
private GameObject m_myPageUICameraObj;
private DialogBase dialogOriginalClose;
private NguiObjs dialogInputOriginalClose;
private DrumrollDialog _dialogDrumrollOriginal;
private GameObject roomIdInputObj;
private GameObject frontLayer;
private GameObject SystemLayer;
private Camera frontCamera;
private LoadingBase LoadingInDownLoad;
private LoadingInScene lodingInScene;
private LoadingInScene lodingInSceneCenter;
private LoadingInScene lodingInSceneMatching;
private LoadingInScene lodingInSceneBattle;
private LoadingInScene notNetwork;
private GameObject LoadingLayer;
private GameObject NotTouchOriginal;
private GameObject NotTouch;
private FadeManager feadOriginal;
private FadeManager nowFadeObj;
private GameObject MyPageLayer;
LeaderPopularityVote }
public UIRoot UIManagerRoot;
public Transform UIRootLoadingTransform;
public Camera UIRootLoadingCamera;
private UIRoot _UIRootSystem;
private GameObject _support;
private DialogReportToManagement _reportToManagementDialogParts;
private RewardBase _rewardBase;
public GameObject _lotteryApplyPrefab;
private RankWinnerReward _rankWinnerReward;
private GameObject _preventTouchCollider;
public UpdateSocialAccountTask _updateSocialAccountTask;
private UIBase_CardManager uiCardManager;
private NguiObjs OriginalTopBar;
public IList<UILabel> m_CrystalLabelList;
public IList<UILabel> m_RupyLabelList;
public Dictionary<ViewScene, UIBase> BackSceneDict;
public Dictionary<ViewScene, ChangeViewSceneParam> TopBarBackParameterDict;
private GameObject FirstTipsPrefab;
private GameObject FirstTipsObject;
private GameObject VideoHostingSettingRootPrefab;
private GameObject VideoHostingHUDPrefab;
private VideoHostingHUD VideoHostingHUDObject;
private GameObject _homeDialogPrefab;
private GameObject _legendCrystalBuyDialogPrefab;
private WindowResize _windowResize;
private GameObject[] RootObjects;
private Transform creatSceneUIPoint;
private IDictionary<ViewScene, UIBase> UIBaseList;
private ViewScene nowScene;
public DeckCreateMenuUI _deckCreateMenuOriginal;
private SwitchLanguage _switchLanguageOriginal;
private SettingBase settingBaseOriginal;
private SettingBase _optionSettingPrefab;
private SettingFirstBattle _firstSettingOriginal;
private BuyCrystal buyCrystalOriginal;
private AccountBase accountBaseOriginal;
private FriendBase friendBaseOriginal;
private GameObject replayDialogPrefab;
private int m_LockCountOnChangeView;
private Action m_OnFinishChangeView;
private List<UnityEngine.Object[]> assetBundleDatas;
public bool isErrorProc;
public bool isRetryProc;
public bool isNoAvailMemory;
private bool _isCreateAssetFileErrorDialog;
private bool _isAssetErrorDialogUse;
public const string YELLOW_COLOR = "[ffca45]";
public const string WHITE_COLOR = "[ffffff]";
public const int CHARALIMIT_INPUT_USERNAME = 24;
public const int CHARALIMIT_INPUT_DECKNAME = 30;
public const int CHARALIMIT_INPUT_TRANSITIONCODE = 16;
public const int CHARALIMIT_INPUT_ACCOUNT = 0;
public const int CHARALIMIT_INPUT_DECKCODE = 16;
public const int CHARALIMIT_FIX_USERNAME = 12;
public const int CHARALIMIT_FIX_DECKNAME = 24;
public const int CHARALIMIT_FIX_TRANSITIONCODE = 16;
public const int CHARALIMIT_FIX_ACCOUNT = 0;
public const int CHARALIMIT_FIX_DECKCODE = 16;
public const UIInput.KeyboardType KEYBOARD_USERNAME = UIInput.KeyboardType.Default;
public const UIInput.KeyboardType KEYBOARD_DECKNAME = UIInput.KeyboardType.Default;
public const UIInput.KeyboardType KEYBOARD_DECKCODE = UIInput.KeyboardType.EmailAddress;
public const UIInput.KeyboardType KEYBOARD_TRANSITIONCODE = UIInput.KeyboardType.EmailAddress;
public const UIInput.KeyboardType KEYBOARD_ACCOUNT = UIInput.KeyboardType.EmailAddress;
private const float FLICK_THRESHOLD = 50f;
private const float TOUCH_INVALID_TIME = 1f;
private const int URL_DIALOG_DEPTH = 3000;
private const float CHANGEVIEWSCENE_WAITTIME = 0.5f;
private Dictionary<ViewScene, object> _sceneParam;
public Footer _Footer { get; set; }
public DialogManager DialogManager { get; set; }
public ApplicationFinishManager ApplicationFinishManager { get; set; }
public GameObject MyPageUICameraObj { get; set; }
public DialogBase DialogPrefab { get; set; }
public NguiObjs TextInputDialogPrefab { get; set; }
public DrumrollDialog DrumrollDialogPrefab { get; set; }
public DialogBase NowOpenDialog { get; set; }
@@ -185,66 +71,20 @@ public partial class UIManager
public Camera FrontCamera { get; set; }
public int FrontCameraPixelWidth { get; set; }
public int FrontCameraPixelHeight { get; set; }
public GameObject FrontLayerObject { get; set; }
public GameObject SystemLayerObject { get; set; }
public GameObject LoadingLayerObject { get; set; }
public LoadingBase LoadingInDownLoadPrefab { get; set; }
public LoadingInScene LoadingInScenePrefab { get; set; }
public LoadingInScene LoadingInSceneCenterPrefab { get; set; }
public LoadingInScene LoadingInSceneMatchingPrefab { get; set; }
public LoadingInScene LoadingInSceneBattlePrefab { get; set; }
public LoadingInScene LoadingForNetworkOfflinePrefab { get; set; }
public UIRoot UIRootSystem { get; set; }
public GameObject SupportDialogPrefab { get; set; }
public DialogReportToManagement DialogReportToManagement { get; set; }
public GameObject HomeDialogPrefab { get; set; }
public GameObject LegendCrystalBuyDialogPrefab { get; set; }
public bool IsCrystalDialogExe { get; set; }
public bool ApplicationHasFocus { get; set; }
public bool isBattleRecovery { get; set; }
public bool IsRoomRecovery { get; set; }
public WebViewHelper WebViewHelper { get; set; }
public LoadingViewManager LoadingViewManager { get; set; }
public bool IsTouchable { get; set; }
public AccountTransferHelper AccountTransferHelper { get; set; }
public SwitchLanguage SwitchLanguagePrefab { get; set; }
public SettingBase SettingPrefab { get; set; }
public SettingBase OptionSettingPrefab { get; set; }
public SettingFirstBattle SettingFirstBattle { get; set; }
public BuyCrystal BuyCrystalPrefab { get; set; }
public AccountBase AccountBasePrefab { get; set; }
public GameObject ReplayDialogPrefab { get; set; }
public bool IsAutoCacheClearAfter { get; set; }
public bool IsFadeIn { get; set; }
public void DisposeFooterMenu() { }
public bool IsNowOpenActiveDialog() => default!;
public static void ApplicationQuit() { }
private void Update() { }
private void Awake() { }
private void Start() { }
private void OnDestroy() { }
public Camera getCamera() => default!;
private IEnumerator WaitUntilLoadComplete() => default!;
public bool IsLocked() => default!;
public void AssetBundleLoad(Action callback = null) { }
public string GetSceneAssetPath(UIAtlasManager.AssetBundleNames assetname, string singlebundlename = "", bool isload = false) => default!;
public void AssetBundleLeaveRemove(ViewScene inLeaveScene) { }
public void AddResidentAtlas(UIAtlasManager.AssetBundleNames atlasName) { }
public void RemoveResidentAtlas(UIAtlasManager.AssetBundleNames atlasName) { }
private ViewScene GetFileResidentInMenu() => default!;
public List<UIAtlas> GetAtlasList() => default!;
public bool getAssetBundleEnd() => default!;
public void setAssetBundleEnd(bool flag) { }
private UIBase ViewOpen(ViewScene openScene, Action<GameObject> beforeOpening = null) => default!;
private UIBase CreateView(ViewScene scene, Action<GameObject> beforeOpening = null) => default!;
public void DestroyView(ViewScene scene) { }
private void DestroyView(List<ViewScene> sceneList) { }
public void DestroyViewAll() { }
public bool isViewOpen(ViewScene scene) => default!;
public void OffView(ViewScene scene) { }
private void OffView(List<ViewScene> sceneList) { }
public void OffViewAll() { }
public void OffViewAllOutside(ViewScene scene) { }
public UIBase GetUIBase(ViewScene scene) => default!;
public T GetCurrentSceneParam<T>() where T : class => default!;
public void OverrideSceneParam(ViewScene scene, object sceneParam) { }
@@ -254,26 +94,17 @@ public partial class UIManager
public void OnReadyViewScene(bool isFadein, Action onFinishChangeView = null, Action onFinishFadeIn = null) { }
public void Force_Increment_LockCountChangeView() { }
public void Force_Decrement_LockCountChangeView() { }
public void Increment_LockCountChangeView() { }
public void Decrement_LockCountChangeView() { }
private IEnumerator ChangeViewScene_Main(ViewScene nextScene, ChangeViewSceneParam param) => default!;
private IEnumerator ChangeViewScene_OnFinishWait(ViewScene nextScene, ChangeViewSceneParam param) => default!;
public void UpdateFooterMenuTexture(ViewScene scene) { }
public ViewScene GetCurrentScene() => default!;
private void SetCurrentScene(ViewScene scene) { }
public bool IsCurrentScene(ViewScene scene) => default!;
public UIBase GetUiBaseOfCurrentScene() => default!;
public void OpenNotTouch() { }
public void offNotTouch() { }
private void creatNotTouch() { }
public DialogBase CreateDialogClose(bool isSystem = false, bool dontChangeLabelColor = false) => default!;
public DialogBase CreateConfirmationDialog(string message) => default!;
public void dialogAllClear() { }
public void ActiveChangeDialogAll(bool active) { }
public void CloseNotLatestDialogAll() { }
public bool CloseLatestDialog() => default!;
public bool isOpenDialog() => default!;
public bool isOpenLoading() => default!;
public void createInSceneLoading(bool notBlack = false, bool notCollider = false, bool force = true, int playIndex = -1) { }
public void closeInSceneLoading(bool force = true) { }
public VfxBase CreateNowLoadingVfx(VfxBase loadResourcesVfx) => global::Wizard.Battle.View.Vfx.NullVfx.GetInstance();
@@ -281,23 +112,14 @@ public partial class UIManager
public void closeInSceneCenterLoading(bool force = true, bool disableCollider = false) { }
public LoadingInScene createInSceneLoadingMatching(bool notBlack = false, bool notCollider = false) => default!;
public LoadingInScene CloseInSceneLoadingMatching() => default!;
public LoadingInScene createInSceneLoadingBattle(bool notBlack = false, bool notCollider = false) => default!;
public LoadingInScene CloseInSceneLoadingBattle() => default!;
public void createInSceneNotNetwork() { }
public void closeInSceneNotNetwork() { }
public void CreatFadeOpen(Action onFinishCallback = null) { }
public void CreatFadeClose(Action onFinishCallback = null) { }
public void CreatFadeBlack() { }
public void CreatFadeObj() { }
public bool isFading() => default!;
public bool IsWizardSetupFinish() => default!;
public IEnumerator CardLoadResident() => default!;
public bool MyPageHomeCardLoadDeck(GameObject returnObj, DeckData deckData, int layer) => default!;
public void CardLoadSelect(GameObject returnObj, IList<int> CardNums, int layer, bool is2D, Action onFinish = null, bool isDefaultSleeve = false, CardMaster.CardMasterId cardMasterId = CardMaster.CardMasterId.Default) { }
public void CardLoadGachaPack(GameObject returnObj, IList<int> CardNums, int layer, bool is2D, int sleeveId = 3000011) { }
public bool isCardCreatEnd() => default!;
public List<UIBase_CardManager.CardObjData> getCardListObjs() => default!;
public List<UIBase_CardManager.CardObjData> getSelectCardListObjs() => default!;
public List<UIBase_CardManager.CardObjData> getCardList2DObjs() => default!;
// Shim fix (M5): return a non-null, field-wired no-op so the copied cosmetic helpers it
// exposes (UIBase_CardManager.SetNumberLabelStyle/SetNameLabelStyle, read by
@@ -306,40 +128,21 @@ public partial class UIManager
public UIBase_CardManager getUIBase_CardManager() => UnityEngine.ShimView.Create<UIBase_CardManager>();
public void setBackScene(GameObject obj, ViewScene backScene) { }
public TopBar CreateTopBar(GameObject obj, string titleMsg, ViewScene backScene = ViewScene.None, bool MoneyDraw = true, ChangeViewSceneParam Param = null, bool isWideMode = false) => default!;
public void SetBackButtonParameter(ChangeViewSceneParam in_Param) { }
public void RemoveNowSceneBackButtonParameter() { }
public void UpDateCrystalNum() { }
public void UpDateRupyNum() { }
public void UpdateLastRupyNum(int num) { }
public RankWinnerReward createRankWinnerReward() => default!;
public void ShowFooterMenu(bool isShow) { }
private bool IsShowMyPageSubOther() => default!;
public static void SetObjectToGrey(GameObject o, bool b, Color? enableTextColor = null, Dictionary<Color32, AllLabelColorChanger.ColorSet> changeColorDict = null) { }
public void CommonRetry() { }
public void CommonResetGame() { }
public FirstTips CheckFirstTips(FirstTips.TipsType TipsType, Action onFinish = null, int startPage = 0) => default!;
public FirstTips StartFirstTips(FirstTips.TipsType TipsType, Action onFinish = null, int startPage = 0, int seasonId = 0) => default!;
public FirstTips StartFirstTips(IEnumerable<FirstTips.TipsType> tipsTypes, Action onFinish = null, int startPage = 0, int seasonId = 0) => default!;
public bool IsActiveFirstTips() => default!;
public IEnumerator FirstTipsStart(int startPage = 0) => default!;
public void CreateVideoHostingHUD(VideoHostingHUD.HUDMode mode) { }
public void DestroyVideoHostingHUD() { }
public VideoHostingHUD GetVideoHostingHUD() => default!;
public DialogBase CreateVideoHostingSettingRoot() => default!;
public void SetLayerRecursive(Transform parentObj, int layer) { }
public void SetDeviceOrientation() { }
private IEnumerator SetDeviceOrientationFromBackGround() => default!;
private void OnApplicationPause(bool pauseStatus) { }
private void OnApplicationFocus(bool focus) { }
public void AttachAtlas(GameObject obj, bool isTargetChildren = true) { }
public void AttachAtlas(List<GameObject> obj_list, bool isTargetChildren = true) { }
private bool WantsToQuit() => default!;
public bool IsQuitDialog() => default!;
public static void ShowDialogUrl(string title, string url, Action<DialogBase> onDialogOpening = null) { }
public void CreateAssetFileErrorDialog() { }
public void SetIsAssetErrorDialogUse(bool inValue) { }
private bool IsAssetFileErrorDialogDispScene() => default!;
public RewardBase GetRewardDialogPrefab() => default!;
public void DelayExecute(float delayTime, Action func) { }
private IEnumerator DelayExecuteCoroutine(float delayTime, Action func) => default!;
}