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>
59 lines
3.0 KiB
C#
59 lines
3.0 KiB
C#
// AUTHORED SHIM (not copied). Input / Random / Resources statics + the full KeyCode
|
|
// enum. Referenced almost entirely by non-battle UI/input files swept into the closure;
|
|
// headless we never pump input and never load resources, so all of this is inert.
|
|
using System;
|
|
|
|
namespace UnityEngine
|
|
{
|
|
public static partial class Input
|
|
{
|
|
public static Vector3 mousePosition => Vector3.zero;
|
|
public static Vector2 mouseScrollDelta => Vector2.zero;
|
|
public static int touchCount => 0;
|
|
public static bool GetMouseButton(int b) => false;
|
|
public static bool GetMouseButtonDown(int b) => false;
|
|
public static bool GetMouseButtonUp(int b) => false;
|
|
public static bool GetKey(KeyCode k) => false;
|
|
public static bool GetKeyDown(KeyCode k) => false;
|
|
public static bool GetKeyUp(KeyCode k) => false;
|
|
public static string inputString => "";
|
|
public static bool multiTouchEnabled { get; set; }
|
|
}
|
|
|
|
public static class Random
|
|
{
|
|
public static float value => 0f;
|
|
public static int Range(int minInclusive, int maxExclusive) => minInclusive;
|
|
public static float Range(float min, float max) => min;
|
|
public static Quaternion rotation => Quaternion.identity;
|
|
public static int seed { get; set; }
|
|
}
|
|
|
|
public static partial class Resources
|
|
{
|
|
public static T Load<T>(string path) where T : Object => null;
|
|
public static T Load<T>(string path, Type t) where T : Object => null;
|
|
// Headless: the non-generic Load is used by the copied PrefabMgr to back a prefab
|
|
// dictionary that the resolution-path ctor then Instantiate()s + GetComponent()s
|
|
// (e.g. Prefab/Game/UnityEventAgent). Return a cached no-op GameObject per path so that
|
|
// chain yields a non-null object. Typed asset loads go through the generic Load<T> (null).
|
|
// ConcurrentDictionary + GetOrAdd so concurrent battle setups don't race on first-miss.
|
|
private static readonly System.Collections.Concurrent.ConcurrentDictionary<string, GameObject> _loaded
|
|
= new System.Collections.Concurrent.ConcurrentDictionary<string, GameObject>();
|
|
public static Object Load(string path)
|
|
{
|
|
if (string.IsNullOrEmpty(path)) return null;
|
|
return _loaded.GetOrAdd(path, static p => new GameObject(p));
|
|
}
|
|
public static Object Load(string path, Type t) => Load(path);
|
|
public static ResourceRequest LoadAsync(string path) => null;
|
|
public static AsyncOperation UnloadUnusedAssets() => null;
|
|
}
|
|
|
|
public class ResourceRequest : AsyncOperation { public Object asset => null; }
|
|
|
|
public enum KeyCode
|
|
{
|
|
None = 0, Tab = 9, Return = 13, Escape = 27, Alpha0 = 48, A = 97, B, D, E, F, N, P, S, X, RightArrow = 275, LeftArrow = 276, RightShift = 303, LeftShift = 304, RightControl = 305, LeftControl = 306, Mouse0 = 323, JoystickButton0 = 330, JoystickButton1 }
|
|
}
|