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

@@ -10,21 +10,6 @@ public static class NGUIMath
return from * (1f - factor) + to * factor;
}
[DebuggerHidden]
[DebuggerStepThrough]
public static int ClampIndex(int val, int max)
{
if (val >= 0)
{
if (val >= max)
{
return max - 1;
}
return val;
}
return 0;
}
[DebuggerHidden]
[DebuggerStepThrough]
public static int RepeatIndex(int val, int max)
@@ -44,28 +29,6 @@ public static class NGUIMath
return val;
}
[DebuggerHidden]
[DebuggerStepThrough]
public static float WrapAngle(float angle)
{
while (angle > 180f)
{
angle -= 360f;
}
while (angle < -180f)
{
angle += 360f;
}
return angle;
}
[DebuggerHidden]
[DebuggerStepThrough]
public static float Wrap01(float val)
{
return val - (float)Mathf.FloorToInt(val);
}
[DebuggerHidden]
[DebuggerStepThrough]
public static int HexToDecimal(char ch)
@@ -115,29 +78,6 @@ public static class NGUIMath
}
}
[DebuggerHidden]
[DebuggerStepThrough]
public static char DecimalToHexChar(int num)
{
if (num > 15)
{
return 'F';
}
if (num < 10)
{
return (char)(48 + num);
}
return (char)(65 + num - 10);
}
[DebuggerHidden]
[DebuggerStepThrough]
public static string DecimalToHex8(int num)
{
num &= 0xFF;
return num.ToString("X2");
}
[DebuggerHidden]
[DebuggerStepThrough]
public static string DecimalToHex24(int num)
@@ -160,43 +100,6 @@ public static class NGUIMath
return 0 | (Mathf.RoundToInt(c.r * 255f) << 24) | (Mathf.RoundToInt(c.g * 255f) << 16) | (Mathf.RoundToInt(c.b * 255f) << 8) | Mathf.RoundToInt(c.a * 255f);
}
[DebuggerHidden]
[DebuggerStepThrough]
public static Color IntToColor(int val)
{
float num = 0.003921569f;
Color black = Color.black;
black.r = num * (float)((val >> 24) & 0xFF);
black.g = num * (float)((val >> 16) & 0xFF);
black.b = num * (float)((val >> 8) & 0xFF);
black.a = num * (float)(val & 0xFF);
return black;
}
[DebuggerHidden]
[DebuggerStepThrough]
public static string IntToBinary(int val, int bits)
{
string text = "";
int num = bits;
while (num > 0)
{
if (num == 8 || num == 16 || num == 24)
{
text += " ";
}
text += (((val & (1 << --num)) != 0) ? '1' : '0');
}
return text;
}
[DebuggerHidden]
[DebuggerStepThrough]
public static Color HexToColor(uint val)
{
return IntToColor((int)val);
}
public static Rect ConvertToTexCoords(Rect rect, int width, int height)
{
Rect result = rect;
@@ -230,25 +133,6 @@ public static class NGUIMath
return result;
}
public static Rect MakePixelPerfect(Rect rect)
{
rect.xMin = Mathf.RoundToInt(rect.xMin);
rect.yMin = Mathf.RoundToInt(rect.yMin);
rect.xMax = Mathf.RoundToInt(rect.xMax);
rect.yMax = Mathf.RoundToInt(rect.yMax);
return rect;
}
public static Rect MakePixelPerfect(Rect rect, int width, int height)
{
rect = ConvertToPixels(rect, width, height, round: true);
rect.xMin = Mathf.RoundToInt(rect.xMin);
rect.yMin = Mathf.RoundToInt(rect.yMin);
rect.xMax = Mathf.RoundToInt(rect.xMax);
rect.yMax = Mathf.RoundToInt(rect.yMax);
return ConvertToTexCoords(rect, width, height);
}
public static Vector2 ConstrainRect(Vector2 minRect, Vector2 maxRect, Vector2 minArea, Vector2 maxArea)
{
Vector2 zero = Vector2.zero;
@@ -483,138 +367,6 @@ public static class NGUIMath
return vector * 0.06f;
}
public static Vector2 SpringDampen(ref Vector2 velocity, float strength, float deltaTime)
{
if (deltaTime > 1f)
{
deltaTime = 1f;
}
float f = 1f - strength * 0.001f;
int num = Mathf.RoundToInt(deltaTime * 1000f);
float num2 = Mathf.Pow(f, num);
Vector2 vector = velocity * ((num2 - 1f) / Mathf.Log(f));
velocity *= num2;
return vector * 0.06f;
}
public static float SpringLerp(float strength, float deltaTime)
{
if (deltaTime > 1f)
{
deltaTime = 1f;
}
int num = Mathf.RoundToInt(deltaTime * 1000f);
deltaTime = 0.001f * strength;
float num2 = 0f;
for (int i = 0; i < num; i++)
{
num2 = Mathf.Lerp(num2, 1f, deltaTime);
}
return num2;
}
public static float SpringLerp(float from, float to, float strength, float deltaTime)
{
if (deltaTime > 1f)
{
deltaTime = 1f;
}
int num = Mathf.RoundToInt(deltaTime * 1000f);
deltaTime = 0.001f * strength;
for (int i = 0; i < num; i++)
{
from = Mathf.Lerp(from, to, deltaTime);
}
return from;
}
public static Vector2 SpringLerp(Vector2 from, Vector2 to, float strength, float deltaTime)
{
return Vector2.Lerp(from, to, SpringLerp(strength, deltaTime));
}
public static Vector3 SpringLerp(Vector3 from, Vector3 to, float strength, float deltaTime)
{
return Vector3.Lerp(from, to, SpringLerp(strength, deltaTime));
}
public static Quaternion SpringLerp(Quaternion from, Quaternion to, float strength, float deltaTime)
{
return Quaternion.Slerp(from, to, SpringLerp(strength, deltaTime));
}
public static float RotateTowards(float from, float to, float maxAngle)
{
float num = WrapAngle(to - from);
if (Mathf.Abs(num) > maxAngle)
{
num = maxAngle * Mathf.Sign(num);
}
return from + num;
}
private static float DistancePointToLineSegment(Vector2 point, Vector2 a, Vector2 b)
{
float sqrMagnitude = (b - a).sqrMagnitude;
if (sqrMagnitude == 0f)
{
return (point - a).magnitude;
}
float num = Vector2.Dot(point - a, b - a) / sqrMagnitude;
if (num < 0f)
{
return (point - a).magnitude;
}
if (num > 1f)
{
return (point - b).magnitude;
}
Vector2 vector = a + num * (b - a);
return (point - vector).magnitude;
}
public static float DistanceToRectangle(Vector2[] screenPoints, Vector2 mousePos)
{
bool flag = false;
int val = 4;
for (int i = 0; i < 5; i++)
{
Vector3 vector = screenPoints[RepeatIndex(i, 4)];
Vector3 vector2 = screenPoints[RepeatIndex(val, 4)];
if (vector.y > mousePos.y != vector2.y > mousePos.y && mousePos.x < (vector2.x - vector.x) * (mousePos.y - vector.y) / (vector2.y - vector.y) + vector.x)
{
flag = !flag;
}
val = i;
}
if (!flag)
{
float num = -1f;
for (int j = 0; j < 4; j++)
{
Vector3 vector3 = screenPoints[j];
Vector3 vector4 = screenPoints[RepeatIndex(j + 1, 4)];
float num2 = DistancePointToLineSegment(mousePos, vector3, vector4);
if (num2 < num || num < 0f)
{
num = num2;
}
}
return num;
}
return 0f;
}
public static float DistanceToRectangle(Vector3[] worldPoints, Vector2 mousePos, Camera cam)
{
Vector2[] array = new Vector2[4];
for (int i = 0; i < 4; i++)
{
array[i] = cam.WorldToScreenPoint(worldPoints[i]);
}
return DistanceToRectangle(array, mousePos);
}
public static Vector2 GetPivotOffset(UIWidget.Pivot pv)
{
Vector2 zero = Vector2.zero;
@@ -690,11 +442,6 @@ public static class NGUIMath
return UIWidget.Pivot.Center;
}
public static void MoveWidget(UIRect w, float x, float y)
{
MoveRect(w, x, y);
}
public static void MoveRect(UIRect rect, float x, float y)
{
int num = Mathf.FloorToInt(x + 0.5f);
@@ -727,70 +474,11 @@ public static class NGUIMath
}
}
public static void ResizeWidget(UIWidget w, UIWidget.Pivot pivot, float x, float y, int minWidth, int minHeight)
{
ResizeWidget(w, pivot, x, y, 2, 2, 100000, 100000);
}
public static void ResizeWidget(UIWidget w, UIWidget.Pivot pivot, float x, float y, int minWidth, int minHeight, int maxWidth, int maxHeight)
{
if (pivot == UIWidget.Pivot.Center)
{
int num = Mathf.RoundToInt(x - (float)w.width);
int num2 = Mathf.RoundToInt(y - (float)w.height);
num -= num & 1;
num2 -= num2 & 1;
if ((num | num2) != 0)
{
num >>= 1;
num2 >>= 1;
AdjustWidget(w, -num, -num2, num, num2, minWidth, minHeight);
}
return;
}
Vector3 vector = new Vector3(x, y);
vector = Quaternion.Inverse(w.cachedTransform.localRotation) * vector;
switch (pivot)
{
case UIWidget.Pivot.BottomLeft:
AdjustWidget(w, vector.x, vector.y, 0f, 0f, minWidth, minHeight, maxWidth, maxHeight);
break;
case UIWidget.Pivot.Left:
AdjustWidget(w, vector.x, 0f, 0f, 0f, minWidth, minHeight, maxWidth, maxHeight);
break;
case UIWidget.Pivot.TopLeft:
AdjustWidget(w, vector.x, 0f, 0f, vector.y, minWidth, minHeight, maxWidth, maxHeight);
break;
case UIWidget.Pivot.Top:
AdjustWidget(w, 0f, 0f, 0f, vector.y, minWidth, minHeight, maxWidth, maxHeight);
break;
case UIWidget.Pivot.TopRight:
AdjustWidget(w, 0f, 0f, vector.x, vector.y, minWidth, minHeight, maxWidth, maxHeight);
break;
case UIWidget.Pivot.Right:
AdjustWidget(w, 0f, 0f, vector.x, 0f, minWidth, minHeight, maxWidth, maxHeight);
break;
case UIWidget.Pivot.BottomRight:
AdjustWidget(w, 0f, vector.y, vector.x, 0f, minWidth, minHeight, maxWidth, maxHeight);
break;
case UIWidget.Pivot.Bottom:
AdjustWidget(w, 0f, vector.y, 0f, 0f, minWidth, minHeight, maxWidth, maxHeight);
break;
case UIWidget.Pivot.Center:
break;
}
}
public static void AdjustWidget(UIWidget w, float left, float bottom, float right, float top)
{
AdjustWidget(w, left, bottom, right, top, 2, 2, 100000, 100000);
}
public static void AdjustWidget(UIWidget w, float left, float bottom, float right, float top, int minWidth, int minHeight)
{
AdjustWidget(w, left, bottom, right, top, minWidth, minHeight, 100000, 100000);
}
public static void AdjustWidget(UIWidget w, float left, float bottom, float right, float top, int minWidth, int minHeight, int maxWidth, int maxHeight)
{
Vector2 pivotOffset = w.pivotOffset;
@@ -960,74 +648,4 @@ public static class NGUIMath
}
return num2;
}
public static Vector2 ScreenToPixels(Vector2 pos, Transform relativeTo)
{
Camera camera = NGUITools.FindCameraForLayer(relativeTo.gameObject.layer);
if (camera == null)
{
return pos;
}
Vector3 position = camera.ScreenToWorldPoint(pos);
return relativeTo.InverseTransformPoint(position);
}
public static Vector2 ScreenToParentPixels(Vector2 pos, Transform relativeTo)
{
int layer = relativeTo.gameObject.layer;
if (relativeTo.parent != null)
{
relativeTo = relativeTo.parent;
}
Camera camera = NGUITools.FindCameraForLayer(layer);
if (camera == null)
{
return pos;
}
Vector3 vector = camera.ScreenToWorldPoint(pos);
return (relativeTo != null) ? relativeTo.InverseTransformPoint(vector) : vector;
}
public static Vector3 WorldToLocalPoint(Vector3 worldPos, Camera worldCam, Camera uiCam, Transform relativeTo)
{
worldPos = worldCam.WorldToViewportPoint(worldPos);
worldPos = uiCam.ViewportToWorldPoint(worldPos);
if (relativeTo == null)
{
return worldPos;
}
relativeTo = relativeTo.parent;
if (relativeTo == null)
{
return worldPos;
}
return relativeTo.InverseTransformPoint(worldPos);
}
public static void OverlayPosition(this Transform trans, Vector3 worldPos, Camera worldCam, Camera myCam)
{
worldPos = worldCam.WorldToViewportPoint(worldPos);
worldPos = myCam.ViewportToWorldPoint(worldPos);
Transform parent = trans.parent;
trans.localPosition = ((parent != null) ? parent.InverseTransformPoint(worldPos) : worldPos);
}
public static void OverlayPosition(this Transform trans, Vector3 worldPos, Camera worldCam)
{
Camera camera = NGUITools.FindCameraForLayer(trans.gameObject.layer);
if (camera != null)
{
trans.OverlayPosition(worldPos, worldCam, camera);
}
}
public static void OverlayPosition(this Transform trans, Transform target)
{
Camera camera = NGUITools.FindCameraForLayer(trans.gameObject.layer);
Camera camera2 = NGUITools.FindCameraForLayer(target.gameObject.layer);
if (camera != null && camera2 != null)
{
trans.OverlayPosition(target.position, camera2, camera);
}
}
}