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

@@ -8,394 +8,33 @@ namespace Wizard;
public class MyPageCustomBGControl : MonoBehaviour
{
private const string PARTICLE_SORT_LAYER = "Default";
private const int CHARACTER_BACK_EFFECT_SORT_ORDER = 15;
private const int RENDER_TEXTURE_DEPTH_BIT = 16;
private const float FADE_TIME = 0.3f;
private readonly Vector3 FADE_DESTROY_OFFSET = new Vector3(6000f, 0f, 0f);
private const float RENDER_TEXTURE_BASE_SIZE = 2048f;
private const float ASPECT_RATIO = 0.5625f;
private const float ASPECT_RATIO_2 = 0.46153846f;
private const float ASPECT_RATIO_REVERSE = 1.7777778f;
[SerializeField]
private UITexture _bg;
[SerializeField]
private UITexture _character;
[SerializeField]
private GameObject _effectRoot;
[SerializeField]
private GameObject _effectRootBG;
[SerializeField]
private GameObject _root;
[SerializeField]
private UITexture _customBGTexture;
[SerializeField]
private Camera _customBGCamera;
[SerializeField]
private GameObject _spineRoot;
[SerializeField]
private GameObject _spineCameraPrefab;
[SerializeField]
private GameObject _spineCameraParent;
[SerializeField]
private SpineDisplay _spineDiaplay;
[SerializeField]
private UITexture _spineTexture;
[SerializeField]
private Camera _myPageParticleCamera;
[SerializeField]
private GameObject _effectPositionDecideObject;
[SerializeField]
private UIPanel _panel;
private List<string> _loadFileList = new List<string>();
private GameObject _frontEffect;
private List<GameObject> _frontEffectChild = new List<GameObject>();
private List<Vector3> _frontEffectLocalPosition = new List<Vector3>();
private GameObject _backEffect;
private RenderTexture _renderTexture;
private Camera _spineCamera;
private float _characterAspectFixRate = 1f;
private Vector3 _characterAspectOffset = Vector3.zero;
private float _fadeOutTimer;
private bool _isFadeOut = true;
private bool _isFadeOutDestroy;
private int _saveScreenWidth;
private int _saveScreenHeight;
private bool _isFadeOutStandbyCalled;
private Shader _fadeoutShader;
private Shader _normalShader;
private Action _onFadeFinish;
private float _startShowTime;
public bool IsLoading { get; private set; }
public string Id { get; private set; } = string.Empty;
public bool IsLoadRequestEnd => Id != string.Empty;
private string GetBackGroundTexturePath(string id, bool isFetch)
{
return Toolbox.ResourcesManager.GetAssetTypePath(id, ResourcesManager.AssetLoadPathType.MyPageBackGround, isFetch);
}
private string GetBackGroundMaterialPath(string id, bool isFetch)
{
return Toolbox.ResourcesManager.GetAssetTypePath(id + "_M", ResourcesManager.AssetLoadPathType.MyPageBackGround, isFetch);
}
private string GetBackGroundMaskPath(string id, bool isFetch)
{
return Toolbox.ResourcesManager.GetAssetTypePath(id + "_mask", ResourcesManager.AssetLoadPathType.MyPageBackGround, isFetch);
}
private string GetCharacterPath(string id, bool isFetch)
{
return Toolbox.ResourcesManager.GetAssetTypePath(id, ResourcesManager.AssetLoadPathType.MyPageCharacter, isFetch);
}
private string GetCharacterMaskPath(string id, bool isFetch)
{
return Toolbox.ResourcesManager.GetAssetTypePath(id, ResourcesManager.AssetLoadPathType.MyPageCharacterMask, isFetch);
}
private string GetEffectPath(string id, string footer, bool isFetch)
{
return Toolbox.ResourcesManager.GetAssetTypePath("scn_bg_mypage_" + id + "_" + footer, ResourcesManager.AssetLoadPathType.Effect2D, isFetch);
}
private string GetSpineFileName(string id)
{
return "spine_mypage_" + id + "_body";
}
public void Load(string id, bool isDisplaySoon, Action onLoadFinish)
{
IsLoading = true;
Id = id;
_fadeoutShader = Shader.Find("Unlit/Transparent Colored MyPageFinal");
_normalShader = Shader.Find("Unlit/Texture");
_spineCamera = NGUITools.AddChild(_spineCameraParent, _spineCameraPrefab).GetComponent<Camera>();
_spineCamera.enabled = false;
_myPageParticleCamera.enabled = false;
_customBGTexture.alpha = 0f;
StartCoroutine(LoadResources(id, isDisplaySoon, onLoadFinish));
}
public void SetEnable(bool enable)
{
_root.SetActive(enable);
}
private IEnumerator LoadResources(string id, bool isDisplaySoon, Action onLoadFinish)
{
_loadFileList.Add(GetBackGroundTexturePath(id, isFetch: false));
_loadFileList.Add(GetCharacterPath(id, isFetch: false));
_loadFileList.Add(GetCharacterMaskPath(id, isFetch: false));
_loadFileList.Add(GetEffectPath(id, "1", isFetch: false));
_loadFileList.Add(GetEffectPath(id, "2", isFetch: false));
_loadFileList.AddRange(_spineDiaplay.GetLoadPath(GetSpineFileName(id), fetch: false));
if (Data.Master.MyPageCustomBGMaster[id].IsBGCardShader)
{
_loadFileList.Add(GetBackGroundMaterialPath(id, isFetch: false));
_loadFileList.Add(GetBackGroundMaskPath(id, isFetch: false));
}
yield return StartCoroutine(Toolbox.ResourcesManager.LoadAssetGroupAsync(_loadFileList, null));
InitializeBG(id);
_character.material = Toolbox.ResourcesManager.LoadObject(GetCharacterPath(id, isFetch: true)) as Material;
_character.onRender = SetCharacterMaterial;
_spineDiaplay.Initialize(GetSpineFileName(id), _spineTexture, _spineCamera);
_spineTexture.enabled = false;
_spineDiaplay.gameObject.SetActive(value: false);
_spineDiaplay.gameObject.SetActive(value: true);
_character.material.mainTexture = _spineTexture.mainTexture;
_character.material.SetTexture("_MaskTex", Toolbox.ResourcesManager.LoadObject(GetCharacterMaskPath(id, isFetch: true)) as Texture);
yield return InitializeEffect(id);
CreateRenderTexture();
SetMasterData(id);
if (isDisplaySoon)
{
Show();
}
else
{
SetEnable(enable: false);
}
_spineCamera.enabled = true;
_myPageParticleCamera.enabled = true;
_customBGTexture.onRender = SetRenderFinalTexture;
onLoadFinish.Call();
IsLoading = false;
}
private void InitializeBG(string id)
{
MyPageCustomBGMasterData myPageCustomBGMasterData = Data.Master.MyPageCustomBGMaster[id];
Texture mainTexture = Toolbox.ResourcesManager.LoadObject(GetBackGroundTexturePath(id, isFetch: true)) as Texture;
_bg.mainTexture = mainTexture;
if (myPageCustomBGMasterData.IsBGCardShader)
{
Material material = Toolbox.ResourcesManager.LoadObject(GetBackGroundMaterialPath(id, isFetch: true)) as Material;
Texture value = Toolbox.ResourcesManager.LoadObject(GetBackGroundMaskPath(id, isFetch: true)) as Texture;
material.SetTexture("_MainTex", _bg.mainTexture);
material.SetTexture("_MaskTex", value);
_bg.material = material;
}
}
private void CreateRenderTexture()
{
if (!(_renderTexture != null))
{
_renderTexture = new RenderTexture(2048, 1152, 16, RenderTextureFormat.ARGB32);
_renderTexture.name = "bgControl";
_customBGCamera.targetTexture = _renderTexture;
_customBGTexture.mainTexture = _renderTexture;
UpdateUITextureSize();
}
}
private void UpdateUITextureSize()
{
Camera frontCamera = UIManager.GetInstance().FrontCamera;
_saveScreenWidth = frontCamera.pixelWidth;
_saveScreenHeight = frontCamera.pixelHeight;
Vector3 position = new Vector3(0f, 1f, 0f);
Vector3 position2 = new Vector3(1f, 0f, 0f);
Vector3 position3 = frontCamera.ViewportToWorldPoint(position);
Vector3 position4 = frontCamera.ViewportToWorldPoint(position2);
Vector3 vector = _customBGTexture.transform.InverseTransformPoint(position3);
Vector3 vector2 = _customBGTexture.transform.InverseTransformPoint(position4);
float num = frontCamera.pixelHeight;
float num2 = frontCamera.pixelWidth;
float num3 = num / num2;
if (num3 < 0.5625f)
{
float num4 = vector2.x - vector.x;
float num5 = num4 * 0.5625f;
_customBGTexture.width = (int)Math.Ceiling(num4);
_customBGTexture.height = (int)Math.Ceiling(num5);
}
else
{
float num6 = vector.y - vector2.y;
float num7 = num6 * 1.7777778f;
_customBGTexture.width = (int)Math.Ceiling(num7);
_customBGTexture.height = (int)Math.Ceiling(num6);
}
if (!string.IsNullOrEmpty(Id))
{
MyPageCustomBGMasterData myPageCustomBGMasterData = Data.Master.MyPageCustomBGMaster[Id];
_characterAspectFixRate = myPageCustomBGMasterData.Scale;
_characterAspectOffset = myPageCustomBGMasterData.Position;
if (num3 < 0.5625f)
{
float num8 = (0.5625f - num3) / 0.100961536f;
float num9 = myPageCustomBGMasterData.Scale2 - myPageCustomBGMasterData.Scale;
_characterAspectFixRate = num9 * num8 + myPageCustomBGMasterData.Scale;
_characterAspectOffset = (myPageCustomBGMasterData.Position2 - myPageCustomBGMasterData.Position) * num8 + myPageCustomBGMasterData.Position;
}
if (myPageCustomBGMasterData.IsFrontEffectAttachCharacter)
{
FixEffectPosition();
}
}
if (!string.IsNullOrEmpty(Id))
{
SetMasterData(Id);
}
}
private void FixEffectPosition()
{
if (string.IsNullOrEmpty(Id))
{
return;
}
MyPageCustomBGMasterData myPageCustomBGMasterData = Data.Master.MyPageCustomBGMaster[Id];
float num = 1f + (_characterAspectFixRate - myPageCustomBGMasterData.Scale);
_effectRoot.transform.localScale = new Vector3(num, num, 1f);
if (myPageCustomBGMasterData.IsFrontEffectAttachCharacter)
{
for (int i = 0; i < _frontEffectChild.Count; i++)
{
_effectPositionDecideObject.transform.localPosition = _frontEffectLocalPosition[i];
_frontEffectChild[i].transform.localPosition = _frontEffect.transform.InverseTransformPoint(_effectPositionDecideObject.transform.position);
}
}
}
private IEnumerator InitializeEffect(string id)
{
MyPageCustomBGMasterData myPageCustomBGMasterData = Data.Master.MyPageCustomBGMaster[id];
GameObject effectCharacterFront = (_frontEffect = UnityEngine.Object.Instantiate(Toolbox.ResourcesManager.LoadObject(GetEffectPath(id, "1", isFetch: true))) as GameObject);
effectCharacterFront.transform.parent = (myPageCustomBGMasterData.IsFrontEffectAttachCharacter ? _effectRoot.transform : _effectRootBG.transform);
effectCharacterFront.SetLayer(28, isSetChildren: true);
effectCharacterFront.transform.localPosition = new Vector3(0f, 0f, -6f);
effectCharacterFront.transform.localScale = Vector3.one * 320f;
if (myPageCustomBGMasterData.IsFrontEffectAttachCharacter)
{
Vector3 localPosition = _character.transform.localPosition;
Vector3 localScale = _character.transform.localScale;
_character.transform.localPosition = myPageCustomBGMasterData.Position;
_character.transform.localScale = new Vector3(myPageCustomBGMasterData.Scale, myPageCustomBGMasterData.Scale, 1f);
for (int i = 0; i < effectCharacterFront.transform.childCount; i++)
{
Transform child = effectCharacterFront.transform.GetChild(i);
_effectPositionDecideObject.transform.position = child.position;
_frontEffectChild.Add(child.gameObject);
_frontEffectLocalPosition.Add(_effectPositionDecideObject.transform.localPosition);
}
_character.transform.localPosition = localPosition;
_character.transform.localScale = localScale;
}
GameObject effectCharacterBack = (_backEffect = UnityEngine.Object.Instantiate(Toolbox.ResourcesManager.LoadObject(GetEffectPath(id, "2", isFetch: true))) as GameObject);
effectCharacterBack.transform.parent = (myPageCustomBGMasterData.IsBackEffectAttachCharacter ? _effectRoot.transform : _effectRootBG.transform);
effectCharacterBack.SetLayer(28, isSetChildren: true);
effectCharacterBack.transform.localPosition = new Vector3(0f, 0f, 7f);
effectCharacterBack.transform.localScale = Vector3.one * 320f;
Renderer[] componentsInChildren = effectCharacterBack.GetComponentsInChildren<Renderer>();
foreach (Renderer obj in componentsInChildren)
{
obj.sortingLayerName = "Default";
obj.sortingOrder = 15;
}
bool isLoading = true;
bool isLoading2 = true;
_loadFileList.AddRange(GameMgr.GetIns().GetEffectMgr().SetUIParticleShader(effectCharacterBack, delegate
{
isLoading = false;
}));
_loadFileList.AddRange(GameMgr.GetIns().GetEffectMgr().SetUIParticleShader(effectCharacterFront, delegate
{
isLoading2 = false;
}));
while (isLoading || isLoading2)
{
yield return null;
}
effectCharacterFront.SetActive(value: true);
effectCharacterBack.SetActive(value: true);
}
private void OnDestroy()
{
Toolbox.ResourcesManager.RemoveAssetGroup(_loadFileList);
_loadFileList.Clear();
if (_renderTexture != null)
{
_renderTexture.Release();
UnityEngine.Object.Destroy(_renderTexture);
_renderTexture = null;
}
}
public void FadeOut()
{
_fadeOutTimer = 0.3f;
_isFadeOut = true;
}
public void FadeoutStandby()
{
_spineRoot.transform.localPosition += FADE_DESTROY_OFFSET;
_root.transform.localPosition += FADE_DESTROY_OFFSET;
_isFadeOutStandbyCalled = true;
_panel.Refresh();
}
public void FadeOutDestroy()
{
if (!_isFadeOutStandbyCalled)
{
FadeoutStandby();
}
_fadeOutTimer = 0.3f;
_isFadeOut = true;
_isFadeOutDestroy = true;
}
public void Show(Action onFadeFinish = null)
{
SetEnable(enable: true);
@@ -444,77 +83,4 @@ public class MyPageCustomBGControl : MonoBehaviour
{
return material.shader.name.Contains("VariantMypage");
}
private void SetMasterData(string id)
{
MyPageCustomBGMasterData myPageCustomBGMasterData = Data.Master.MyPageCustomBGMaster[id];
_character.transform.localPosition = _characterAspectOffset;
Vector3 localScale = new Vector3(_characterAspectFixRate, _characterAspectFixRate, 1f);
_character.transform.localScale = localScale;
_spineTexture.transform.localPosition = myPageCustomBGMasterData.Position;
_spineTexture.transform.localScale = new Vector3(myPageCustomBGMasterData.Scale, myPageCustomBGMasterData.Scale, 1f);
_spineCamera.orthographicSize = myPageCustomBGMasterData.SpineCameraSize;
FixEffectPosition();
}
private void SetCharacterMaterial(Material material)
{
material.SetFloat("_SleeveSrcFactor", 5f);
material.SetFloat("_SleeveDstFactor", 10f);
if (!string.IsNullOrEmpty(Id))
{
MyPageCustomBGMasterData myPageCustomBGMasterData = Data.Master.MyPageCustomBGMaster[Id];
material.SetFloat("_MypageBoundaryAlpha", myPageCustomBGMasterData.ShaderAlphaBorder);
material.SetFloat("_MypageDivisionValue", myPageCustomBGMasterData.ShaderAlphaDevide);
}
}
private void SetRenderFinalTexture(Material material)
{
material.shader = ((_fadeOutTimer > 0f) ? _fadeoutShader : _normalShader);
}
private void CheckScreenSizeChange()
{
if (UIManager.GetInstance().FrontCameraPixelWidth != _saveScreenWidth || UIManager.GetInstance().FrontCameraPixelHeight != _saveScreenHeight)
{
UpdateUITextureSize();
}
}
private void Update()
{
CheckScreenSizeChange();
if (_customBGTexture.alpha > 0.01f)
{
SetSpecialResetShaderParameter();
}
if (_fadeOutTimer <= 0f || IsLoading)
{
return;
}
_fadeOutTimer -= Time.deltaTime;
if (_fadeOutTimer <= 0f)
{
_fadeOutTimer = 0f;
_onFadeFinish.Call();
_onFadeFinish = null;
if (_isFadeOutDestroy)
{
UnityEngine.Object.Destroy(base.gameObject);
return;
}
}
float num = _fadeOutTimer / 0.3f;
float num2 = num;
if (!_isFadeOut)
{
num2 = 1f - num;
}
_customBGTexture.alpha = num2;
if ((num2 < 0.01f) & _isFadeOut)
{
_character.gameObject.SetActive(value: false);
}
}
}