Files
SVSimServer/SVSim.BattleEngine/Engine/IDInput.cs
gamer147 2d9a6eea4b 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>
2026-07-03 19:18:54 -04:00

148 lines
3.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Text.RegularExpressions;
using UnityEngine;
using Wizard;
public class IDInput : MonoBehaviour
{
[Serializable]
public class LayoutSet
{
public GameObject _root;
public UILabel[] _label;
}
[SerializeField]
private UIButton[] m_InputBtns;
[SerializeField]
private UIButton m_InputClearBtn;
[SerializeField]
private LayoutSet[] _layoutSet;
private LayoutSet _currentLayout;
[SerializeField]
private UIButton _pasteButton;
private int InputIndex;
private int _maxIndex;
public DialogBase CurrentDialogBase;
[HideInInspector]
public string InputID { get; set; }
public static IDInput Create(GameObject parentObj)
{
return NGUITools.AddChild(parentObj, UIManager.GetInstance().IdInputPrefab).GetComponent<IDInput>();
}
public void InitInputID(int maxCount)
{
InputIndex = 0;
InputID = "";
_maxIndex = maxCount - 1;
for (int i = 0; i < m_InputBtns.Length; i++)
{
UIEventListener uIEventListener = UIEventListener.Get(m_InputBtns[i].gameObject);
uIEventListener.onClick = (UIEventListener.VoidDelegate)Delegate.Combine(uIEventListener.onClick, new UIEventListener.VoidDelegate(InputNum));
}
_pasteButton.onClick.Add(new EventDelegate(delegate
{
Paste();
}));
LayoutSet[] layoutSet = _layoutSet;
foreach (LayoutSet layoutSet2 in layoutSet)
{
if (layoutSet2._label.Length == maxCount)
{
layoutSet2._root.SetActive(value: true);
_currentLayout = layoutSet2;
}
else
{
layoutSet2._root.SetActive(value: false);
}
}
if (_currentLayout == null)
{
Debug.LogError("未知の桁数です");
}
for (int num2 = 0; num2 < _currentLayout._label.Length; num2++)
{
_currentLayout._label[num2].text = "_";
}
UIEventListener uIEventListener2 = UIEventListener.Get(m_InputClearBtn.gameObject);
uIEventListener2.onClick = (UIEventListener.VoidDelegate)Delegate.Combine(uIEventListener2.onClick, new UIEventListener.VoidDelegate(ClearNum));
Invoke("SetButtonEnabled", 0.01f);
}
private void SetButtonEnabled()
{
CurrentDialogBase.SetButtonDisable(isEnableOK: true);
}
public void InputNum(GameObject g)
{
if (InputIndex <= _maxIndex)
{
string text = g.name;
_currentLayout._label[InputIndex].text = text;
JoinNums();
InputIndex++;
if (InputIndex > _maxIndex)
{
CurrentDialogBase.SetButtonDisable(isEnableOK: false);
}
}
}
public void ClearNum(GameObject g)
{
if (InputIndex > 0)
{
InputIndex--;
_currentLayout._label[InputIndex].text = "_";
CurrentDialogBase.SetButtonDisable(isEnableOK: true);
}
}
private void JoinNums()
{
string text = "";
for (int i = 0; i < _currentLayout._label.Length && !(_currentLayout._label[i].text == "_"); i++)
{
text += _currentLayout._label[i].text;
}
InputID = text;
}
private void Paste()
{
string clipboard = ClipboardHelper.Clipboard;
clipboard = Regex.Replace(clipboard, "[-]", (Match match) => ((char)(match.Value[0] - 65296 + 48)).ToString());
clipboard = Regex.Replace(clipboard, "\\s", "");
if (UIUtil.IsValidIdDigits(clipboard, _currentLayout._label.Length))
{
for (int num = 0; num < _currentLayout._label.Length; num++)
{
_currentLayout._label[num].text = "_";
}
for (int num2 = 0; num2 < clipboard.Length; num2++)
{
_currentLayout._label[num2].text = clipboard[num2].ToString();
JoinNums();
}
InputIndex = clipboard.Length;
CurrentDialogBase.SetButtonDisable(isEnableOK: false);
}
}
}