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:
@@ -26,7 +26,6 @@ public class NetworkBattleSender
|
||||
public enum JUDGE_RESULT_STATUS
|
||||
{
|
||||
BattleFinishToJudge = 100,
|
||||
RecoveryBattleFinishToJudge = 110,
|
||||
RetrySend = 200,
|
||||
FailedToRetryJudgeResult = 201,
|
||||
OppoDisconnectVictory = 300,
|
||||
@@ -40,14 +39,9 @@ public class NetworkBattleSender
|
||||
MulliganLose = 601,
|
||||
BattleStopToJudgeResult = 700,
|
||||
ReceiveRetire = 800,
|
||||
ReplayRetireDiff = 801,
|
||||
ReceiveConsistencyLose = 900,
|
||||
Invalid = 901,
|
||||
WatchJudgeResult = 1000,
|
||||
RecoveryError = 1100,
|
||||
SwapTimeoutError = 1200,
|
||||
Debug = 9999
|
||||
}
|
||||
WatchJudgeResult = 1000}
|
||||
|
||||
public enum SELECT_SKILL_OPERATION
|
||||
{
|
||||
@@ -79,13 +73,9 @@ public class NetworkBattleSender
|
||||
|
||||
public enum HAND_URI_TYPE
|
||||
{
|
||||
TOUCH_URI = 1,
|
||||
SELECT_SKILL_URI = 2,
|
||||
SELECT_OBJECT_URI = 3,
|
||||
TURN_END_READY_URI = 4,
|
||||
SLIDE_OBJECT_URI = 5,
|
||||
HAND_NODE_ERROR = 99
|
||||
}
|
||||
SLIDE_OBJECT_URI = 5 }
|
||||
|
||||
private NetworkBattleManagerBase _battleMgr;
|
||||
|
||||
@@ -95,14 +85,8 @@ public class NetworkBattleSender
|
||||
|
||||
private List<EmitData> _alreadyEmitList = new List<EmitData>();
|
||||
|
||||
public const float RETRY_INTERVAL = 0.5f;
|
||||
|
||||
private bool _isEmitStop_OutsideJudgeResult;
|
||||
|
||||
public static string PlayActionLogMsg = "";
|
||||
|
||||
private int _lastTouchIndex;
|
||||
|
||||
private BattleCardBase _lastSelectedCard;
|
||||
|
||||
private BattleCardBase _selectedSlideCard;
|
||||
@@ -111,8 +95,6 @@ public class NetworkBattleSender
|
||||
|
||||
private DateTime _oldSlideCurrentLocalTime;
|
||||
|
||||
private DateTime _oldSelectCurrentLocalTime;
|
||||
|
||||
public NetworkBattleSender(NetworkBattleManagerBase battlemgr, RegisterActionManager registerList, List<RegisterUnapproved> unapprovedList, NetworkConsistency consistency)
|
||||
{
|
||||
_battleMgr = battlemgr;
|
||||
@@ -141,7 +123,7 @@ public class NetworkBattleSender
|
||||
public void SendTurnStart()
|
||||
{
|
||||
Dictionary<string, object> dictionary = _sendCardDataMaker.MakePlayActionsSendCardData(null, null, null, isEvol: false, null, isTurnStart: true);
|
||||
dictionary.Add("actionSeq", ToolboxGame.RealTimeNetworkAgent.GetTurnSequence());
|
||||
dictionary.Add("actionSeq", _battleMgr.InstanceNetworkAgent.GetTurnSequence());
|
||||
EmitMsg(NetworkBattleDefine.NetworkBattleURI.TurnStart, dictionary);
|
||||
}
|
||||
|
||||
@@ -171,7 +153,7 @@ public class NetworkBattleSender
|
||||
|
||||
public void SendTurnEnd(bool isNextTurnTimeDecrement, bool isNowTurnTimeDecrement, bool final)
|
||||
{
|
||||
if (final || ToolboxGame.RealTimeNetworkAgent.GetTurnState())
|
||||
if (final || _battleMgr.InstanceNetworkAgent.GetTurnState())
|
||||
{
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
||||
_networkConsistency.SetupConsistency();
|
||||
@@ -180,7 +162,7 @@ public class NetworkBattleSender
|
||||
List<int> list = new List<int>();
|
||||
list.Add(_battleMgr.GetBattlePlayer(isPlayer: true).CemeteryList.Count);
|
||||
list.Add(_battleMgr.GetBattlePlayer(isPlayer: false).CemeteryList.Count);
|
||||
dictionary.Add("actionSeq", ToolboxGame.RealTimeNetworkAgent.GetTurnSequence());
|
||||
dictionary.Add("actionSeq", _battleMgr.InstanceNetworkAgent.GetTurnSequence());
|
||||
dictionary.Add("cemetery", list);
|
||||
if (final)
|
||||
{
|
||||
@@ -199,11 +181,6 @@ public class NetworkBattleSender
|
||||
SendTurnEnd(isNextTurnTimeDecrement: false, isNowTurnTimeDecrement: false, final: true);
|
||||
}
|
||||
|
||||
public void SendRecoveryEnd()
|
||||
{
|
||||
EmitMsg(NetworkBattleDefine.NetworkBattleURI.RecoveryEnd);
|
||||
}
|
||||
|
||||
public void SendJudge()
|
||||
{
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
||||
@@ -216,64 +193,7 @@ public class NetworkBattleSender
|
||||
{
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
||||
dictionary[NetworkBattleDefine.NetworkParameterNames[NetworkBattleDefine.NetworkParameter.stamp]] = stamp;
|
||||
ToolboxGame.RealTimeNetworkAgent.EmitMsgPack(NetworkBattleDefine.NetworkBattleURI.ChatStamp, dictionary, null, isGetableAck: false);
|
||||
}
|
||||
|
||||
public void SendTouch(int idx, bool isSelf)
|
||||
{
|
||||
if (_lastTouchIndex != idx)
|
||||
{
|
||||
_lastTouchIndex = idx;
|
||||
_emitHandParameterList.Clear();
|
||||
_emitHandParameterList.Add(_lastTouchIndex);
|
||||
_emitHandParameterList.Add(isSelf ? 1 : 0);
|
||||
ToolboxGame.RealTimeNetworkAgent.EmitHandData(_emitHandParameterList, HAND_URI_TYPE.TOUCH_URI);
|
||||
}
|
||||
}
|
||||
|
||||
public void SendSelectSkill(SELECT_SKILL_OPERATION selectSkillOperation, bool isEvolveTargetSelect, string operationNum, List<int> activeSelectSkillIndexList, bool isBurialRite, bool isChoiceBrave)
|
||||
{
|
||||
bool flag = selectSkillOperation != SELECT_SKILL_OPERATION.SelectChoiceCard;
|
||||
if (operationNum.IsNotNullOrEmpty() && !flag)
|
||||
{
|
||||
DateTime now = DateTime.Now;
|
||||
TimeSpan elapsedTimeByTimeSpan = TimeUtil.GetElapsedTimeByTimeSpan(now, _oldSelectCurrentLocalTime);
|
||||
float num = (float)elapsedTimeByTimeSpan.Milliseconds / 1000f;
|
||||
if (elapsedTimeByTimeSpan.Seconds == 0 && num < 0.5f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
_oldSelectCurrentLocalTime = now;
|
||||
}
|
||||
List<object> list = new List<object>();
|
||||
list.Add((int)selectSkillOperation);
|
||||
list.Add(isEvolveTargetSelect);
|
||||
list.Add(isBurialRite);
|
||||
if (!string.IsNullOrEmpty(operationNum))
|
||||
{
|
||||
list.Add(operationNum);
|
||||
}
|
||||
if (isChoiceBrave)
|
||||
{
|
||||
if (string.IsNullOrEmpty(operationNum))
|
||||
{
|
||||
list.Add("0");
|
||||
}
|
||||
list.Add("1");
|
||||
}
|
||||
if (activeSelectSkillIndexList.Count > 0)
|
||||
{
|
||||
if (!isChoiceBrave)
|
||||
{
|
||||
if (string.IsNullOrEmpty(operationNum))
|
||||
{
|
||||
list.Add("0");
|
||||
}
|
||||
list.Add("0");
|
||||
}
|
||||
list.Add(activeSelectSkillIndexList);
|
||||
}
|
||||
ToolboxGame.RealTimeNetworkAgent.EmitHandData(list, HAND_URI_TYPE.SELECT_SKILL_URI, flag);
|
||||
_battleMgr.InstanceNetworkAgent.EmitMsgPack(NetworkBattleDefine.NetworkBattleURI.ChatStamp, dictionary, null, isGetableAck: false);
|
||||
}
|
||||
|
||||
public void SendSelectObject(BattleCardBase selectedCard)
|
||||
@@ -294,7 +214,7 @@ public class NetworkBattleSender
|
||||
}
|
||||
_emitHandParameterList.Clear();
|
||||
_emitHandParameterList.Add(empty);
|
||||
ToolboxGame.RealTimeNetworkAgent.EmitHandData(_emitHandParameterList, HAND_URI_TYPE.SELECT_OBJECT_URI);
|
||||
_battleMgr.InstanceNetworkAgent.EmitHandData(_emitHandParameterList, HAND_URI_TYPE.SELECT_OBJECT_URI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,7 +222,7 @@ public class NetworkBattleSender
|
||||
{
|
||||
_emitHandParameterList.Clear();
|
||||
_emitHandParameterList.Add(isShortenedTurn);
|
||||
ToolboxGame.RealTimeNetworkAgent.EmitHandData(_emitHandParameterList, HAND_URI_TYPE.TURN_END_READY_URI);
|
||||
_battleMgr.InstanceNetworkAgent.EmitHandData(_emitHandParameterList, HAND_URI_TYPE.TURN_END_READY_URI);
|
||||
}
|
||||
|
||||
public void SendSlideObject(SLIDE_OBJECT_TYPE slideObjectType, BattleCardBase selectedCard, BattleCardBase attackingCard)
|
||||
@@ -342,12 +262,7 @@ public class NetworkBattleSender
|
||||
_emitHandParameterList.Clear();
|
||||
_emitHandParameterList.Add(item);
|
||||
_emitHandParameterList.Add(item2);
|
||||
ToolboxGame.RealTimeNetworkAgent.EmitHandData(_emitHandParameterList, HAND_URI_TYPE.SLIDE_OBJECT_URI);
|
||||
}
|
||||
|
||||
public void ResetSelectedSlideCard()
|
||||
{
|
||||
_selectedSlideCard = null;
|
||||
_battleMgr.InstanceNetworkAgent.EmitHandData(_emitHandParameterList, HAND_URI_TYPE.SLIDE_OBJECT_URI);
|
||||
}
|
||||
|
||||
public void EmitRetry(NetworkBattleDefine.NetworkBattleURI uri)
|
||||
@@ -409,7 +324,7 @@ public class NetworkBattleSender
|
||||
}
|
||||
else
|
||||
{
|
||||
LocalLog.AccumulateLastTraceLog("NotEchoData isVirtual" + BattleManagerBase.GetIns().IsVirtualBattle + " " + StackTraceUtility.ExtractStackTrace());
|
||||
LocalLog.AccumulateLastTraceLog("NotEchoData isVirtual" + _battleMgr.IsVirtualBattle + " " + StackTraceUtility.ExtractStackTrace());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -444,7 +359,7 @@ public class NetworkBattleSender
|
||||
}
|
||||
if (uri == NetworkBattleDefine.NetworkBattleURI.PlayActions && !_battleMgr.GetBattlePlayer(isPlayer: true).IsSelfTurn)
|
||||
{
|
||||
LocalLog.AccumulateTraceLog("588157NotMyturnPlay" + PlayActionLogMsg);
|
||||
LocalLog.AccumulateTraceLog("588157NotMyturnPlay");
|
||||
return false;
|
||||
}
|
||||
Dictionary<string, object> dictionary = new Dictionary<string, object>();
|
||||
@@ -455,8 +370,8 @@ public class NetworkBattleSender
|
||||
dictionary.Add(data.Key, data.Value);
|
||||
}
|
||||
}
|
||||
_alreadyEmitList.Add(new EmitData(uri.ToString(), dictionary, ToolboxGame.RealTimeNetworkAgent.LastEmitSeqNumber));
|
||||
ToolboxGame.RealTimeNetworkAgent.EmitMsgPack(uri, dataList, null, isGetableAck, -1, isStockData: true, isNotActiveSeq);
|
||||
_alreadyEmitList.Add(new EmitData(uri.ToString(), dictionary, _battleMgr.InstanceNetworkAgent.LastEmitSeqNumber));
|
||||
_battleMgr.InstanceNetworkAgent.EmitMsgPack(uri, dataList, null, isGetableAck, -1, isStockData: true, isNotActiveSeq);
|
||||
_battleMgr.SendIntervalTriggerMain.SendDataCheck(_battleMgr, uri);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user