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:
@@ -1,601 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Wizard;
|
||||
using Wizard.Battle.View.Vfx;
|
||||
using Wizard.BattleMgr;
|
||||
using Wizard.RoomMatch;
|
||||
|
||||
public class NetworkWatchBattleMgr : NetworkBattleManagerBase
|
||||
{
|
||||
private class SelectObjectHandCard
|
||||
{
|
||||
private const float SELECT_CARD_MOVE_POS_Y = 45f;
|
||||
|
||||
private Vector3 _selectedPos;
|
||||
|
||||
public BattleCardBase CardBase { get; private set; }
|
||||
|
||||
public SelectObjectHandCard(BattleCardBase cardBase, bool isOwner)
|
||||
{
|
||||
CardBase = cardBase;
|
||||
if (isOwner)
|
||||
{
|
||||
_selectedPos = new Vector3(0f, 45f, 0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
_selectedPos = new Vector3(0f, -45f, 0f);
|
||||
}
|
||||
}
|
||||
|
||||
public VfxBase CreateVfxSelectMove()
|
||||
{
|
||||
return CreateVfxMoveHandCard(CardBase.BattleCardView.CardWrapObject, _selectedPos);
|
||||
}
|
||||
|
||||
public VfxBase CreateVfxResetPos()
|
||||
{
|
||||
return CreateVfxMoveHandCard(CardBase.BattleCardView.CardWrapObject, Vector3.zero);
|
||||
}
|
||||
|
||||
public void ResetOriginalPosition()
|
||||
{
|
||||
iTween.Stop(CardBase.BattleCardView.CardWrapObject);
|
||||
CardBase.BattleCardView.CardWrapObject.transform.localPosition = Vector3.zero;
|
||||
}
|
||||
|
||||
private VfxBase CreateVfxMoveHandCard(GameObject cardObj, Vector3 position)
|
||||
{
|
||||
return InstantVfx.Create(delegate
|
||||
{
|
||||
if (!(cardObj == null))
|
||||
{
|
||||
iTween.MoveTo(cardObj, iTween.Hash("position", position, "time", 0.2f, "islocal", true, "easetype", iTween.EaseType.easeInOutExpo));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public WatcherDisconnectChecker watcherDisconnectChecker;
|
||||
|
||||
public WatcherLeaveChecker watcherLeaveChecker;
|
||||
|
||||
public DialogBase disconnectDialog;
|
||||
|
||||
public bool IsHandCardInvisible;
|
||||
|
||||
private SelectObjectHandCard _cardSelectedByOwner;
|
||||
|
||||
private SelectObjectHandCard _cardSelectedByGuest;
|
||||
|
||||
private bool _isConventionWatch;
|
||||
|
||||
private bool _isGathering;
|
||||
|
||||
protected bool isResultDone;
|
||||
|
||||
private int MyPageReturnIndex
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!_isConventionWatch)
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
public NetworkWatchBattleMgr(IBattleMgrContentsCreator contentsCreator)
|
||||
: base(contentsCreator)
|
||||
{
|
||||
TouchControl = new WatchTouchControl(this, _battleCamera, _backGround);
|
||||
OperateMgr.SetTouchControl(TouchControl);
|
||||
base.networkBattleData = new NetworkWatchBattleData(this);
|
||||
networkReceiver = new NetworkWatchBattleReceiver(this);
|
||||
_networkBattleSetupCardEventBase = new NetworkWatchBattleSetupCardEvent(this, RegisterActionManager, base.networkBattleData);
|
||||
base.recoveryToDispChecker = new RecoveryToDispChecker();
|
||||
OperateReceive = (GameMgr.GetIns().IsNewReplayBattle ? new NewReplayOperateReceive(this, RegisterActionManager, OperateMgr, base.networkBattleData) : CreateOperateReceive());
|
||||
base.disconnectToDispChecker.OnDisp += delegate
|
||||
{
|
||||
ControlDisconnectOffTouchAndView(flag: true);
|
||||
};
|
||||
base.disconnectToDispChecker.OnErase += delegate
|
||||
{
|
||||
ControlDisconnectOffTouchAndView(flag: false);
|
||||
};
|
||||
BattleFinishToStopIntervalChecker();
|
||||
IsHandCardInvisible = GameMgr.GetIns().IsWatchHandInvisible;
|
||||
GameMgr.GetIns().IsWatchHandInvisible = false;
|
||||
RoomConnectController connectController = RoomBase.ConnectController;
|
||||
if (connectController != null)
|
||||
{
|
||||
_isConventionWatch = connectController.IsConvention;
|
||||
_isGathering = connectController.IsGathering;
|
||||
}
|
||||
SetUpDisconnectCheck();
|
||||
}
|
||||
|
||||
protected override void OpponentAliveCallback()
|
||||
{
|
||||
base.OpponentAliveCallback();
|
||||
watcherLeaveChecker.FinishChecker();
|
||||
}
|
||||
|
||||
protected override void OpponentDisconnectCallback()
|
||||
{
|
||||
base.OpponentDisconnectCallback();
|
||||
watcherLeaveChecker.StartCheckerIfNotStarted();
|
||||
}
|
||||
|
||||
protected override void ControlDisconnectOffTouchAndView(bool flag)
|
||||
{
|
||||
}
|
||||
|
||||
public override void DisposeBattleGameObj()
|
||||
{
|
||||
base.DisposeBattleGameObj();
|
||||
BattleCoroutine.GetInstance().StopAllCoroutines();
|
||||
if (watcherDisconnectChecker != null)
|
||||
{
|
||||
watcherDisconnectChecker.FinishChecker();
|
||||
}
|
||||
if (watcherLeaveChecker != null)
|
||||
{
|
||||
watcherLeaveChecker.FinishChecker();
|
||||
}
|
||||
IsHandCardInvisible = false;
|
||||
}
|
||||
|
||||
protected virtual void SetUpDisconnectCheck()
|
||||
{
|
||||
watcherDisconnectChecker = new WatcherDisconnectChecker();
|
||||
watcherDisconnectChecker.OnDisp += delegate
|
||||
{
|
||||
StartWatcherDisconnect(flag: true);
|
||||
};
|
||||
watcherDisconnectChecker.OnErase += delegate
|
||||
{
|
||||
StartWatcherDisconnect(flag: false);
|
||||
};
|
||||
watcherLeaveChecker = new WatcherLeaveChecker();
|
||||
watcherLeaveChecker.SetBattleMgr(this);
|
||||
watcherLeaveChecker.OnDisp += delegate
|
||||
{
|
||||
StartCompetitorLeave(flag: true);
|
||||
};
|
||||
watcherLeaveChecker.OnErase += delegate
|
||||
{
|
||||
StartCompetitorLeave(flag: false);
|
||||
};
|
||||
}
|
||||
|
||||
private UIManager.ChangeViewSceneParam GetMyPageReturnParam()
|
||||
{
|
||||
UIManager.ChangeViewSceneParam changeViewSceneParam = new UIManager.ChangeViewSceneParam();
|
||||
changeViewSceneParam.MyPageMenuIndex = MyPageReturnIndex;
|
||||
changeViewSceneParam.IsCutCardMotion = true;
|
||||
if (MyPageReturnIndex == 2)
|
||||
{
|
||||
changeViewSceneParam.OnFinishChangeView = delegate
|
||||
{
|
||||
MyPageMenu.Instance.GoToRoomMatch();
|
||||
};
|
||||
}
|
||||
return changeViewSceneParam;
|
||||
}
|
||||
|
||||
private void StartWatcherDisconnect(bool flag)
|
||||
{
|
||||
watcherDisconnectChecker.StopChecker();
|
||||
if (flag)
|
||||
{
|
||||
base.BattleUIContainer.ButtonControl.HideAllMenu(isWithoutSE: true);
|
||||
disconnectDialog = UIManager.GetInstance().CreateDialogClose(isSystem: true);
|
||||
disconnectDialog.SetSize(DialogBase.Size.M);
|
||||
disconnectDialog.SetTitleLabel(Data.SystemText.Get("Common_0021"));
|
||||
disconnectDialog.SetText(Data.SystemText.Get("RoomBattle_0049"));
|
||||
disconnectDialog.AddButton(DialogBase.ButtonType.OK);
|
||||
disconnectDialog.SetPanelDepth(6000);
|
||||
disconnectDialog.SetFadeButtonEnabled(flag: false);
|
||||
DialogBase dialogBase = disconnectDialog;
|
||||
dialogBase.onPushButton1 = (Action)Delegate.Combine(dialogBase.onPushButton1, (Action)delegate
|
||||
{
|
||||
UIManager.GetInstance().StartCoroutine(GetBattleControl().BattleEnd(delegate
|
||||
{
|
||||
UIManager.ChangeViewSceneParam myPageReturnParam = GetMyPageReturnParam();
|
||||
if (_isGathering)
|
||||
{
|
||||
UIManager.GetInstance().ChangeViewScene(UIManager.ViewScene.Gathering);
|
||||
}
|
||||
else
|
||||
{
|
||||
UIManager.GetInstance().ChangeViewScene(UIManager.ViewScene.MyPage, myPageReturnParam);
|
||||
}
|
||||
}));
|
||||
RoomBase.DestroyMyRoomInfo();
|
||||
});
|
||||
}
|
||||
else if (disconnectDialog != null)
|
||||
{
|
||||
disconnectDialog.Close();
|
||||
disconnectDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void StartCompetitorLeave(bool flag)
|
||||
{
|
||||
watcherLeaveChecker.StopChecker();
|
||||
if (flag)
|
||||
{
|
||||
base.BattleUIContainer.ButtonControl.HideAllMenu(isWithoutSE: true);
|
||||
disconnectDialog = UIManager.GetInstance().CreateDialogClose(isSystem: true);
|
||||
disconnectDialog.SetSize(DialogBase.Size.M);
|
||||
disconnectDialog.SetTitleLabel(Data.SystemText.Get("Common_0021"));
|
||||
disconnectDialog.SetText(Data.SystemText.Get("RoomBattle_0098"));
|
||||
disconnectDialog.AddButton(DialogBase.ButtonType.OK);
|
||||
disconnectDialog.SetPanelDepth(6000);
|
||||
disconnectDialog.SetFadeButtonEnabled(flag: false);
|
||||
DialogBase dialogBase = disconnectDialog;
|
||||
dialogBase.onPushButton1 = (Action)Delegate.Combine(dialogBase.onPushButton1, (Action)delegate
|
||||
{
|
||||
UIManager.GetInstance().StartCoroutine(GetBattleControl().BattleEnd(delegate
|
||||
{
|
||||
UIManager.ChangeViewSceneParam myPageReturnParam = GetMyPageReturnParam();
|
||||
if (_isGathering)
|
||||
{
|
||||
UIManager.GetInstance().ChangeViewScene(UIManager.ViewScene.Gathering);
|
||||
}
|
||||
else
|
||||
{
|
||||
UIManager.GetInstance().ChangeViewScene(UIManager.ViewScene.MyPage, myPageReturnParam);
|
||||
}
|
||||
}));
|
||||
RoomBase.DestroyMyRoomInfo();
|
||||
});
|
||||
}
|
||||
else if (disconnectDialog != null)
|
||||
{
|
||||
disconnectDialog.Close();
|
||||
disconnectDialog = null;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void FirstRecoverySetting()
|
||||
{
|
||||
}
|
||||
|
||||
public override void RecoveryRecordSkillTarget(IEnumerable<BattleCardBase> targetCards)
|
||||
{
|
||||
}
|
||||
|
||||
protected override int CreateBackgroundId()
|
||||
{
|
||||
return GameMgr.GetIns().GetNetworkUserInfoData().GetFieldId();
|
||||
}
|
||||
|
||||
public override void SetBattleMenuBtnVisibility()
|
||||
{
|
||||
}
|
||||
|
||||
public override void StartOpening(int FirstAttack)
|
||||
{
|
||||
base.StartOpening(FirstAttack);
|
||||
ITurnEndButtonUI turnEndButtonUI = BattlePlayer.PlayerBattleView.TurnEndButtonUI;
|
||||
turnEndButtonUI._isButtonForcedOff = true;
|
||||
turnEndButtonUI.DisableButton();
|
||||
turnEndTimeController = new WatchTurnEndTimeController(this, BattlePlayer, turnEndButtonUI);
|
||||
if (GameMgr.GetIns().IsAdminWatch)
|
||||
{
|
||||
ESelectSkillSideLog.SetActive(value: true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void SetupEvent()
|
||||
{
|
||||
base.SetupEvent();
|
||||
}
|
||||
|
||||
public override void SendTurnEnd()
|
||||
{
|
||||
}
|
||||
|
||||
public override void SetupCardEvent(BattleCardBase card)
|
||||
{
|
||||
base.SetupCardEvent(card);
|
||||
card.OnPlay += delegate
|
||||
{
|
||||
if (card.HasSpellCharge)
|
||||
{
|
||||
GameObject child = card.BattleCardView.GetChild("SpellBoostCount");
|
||||
if (child != null)
|
||||
{
|
||||
child.SetActive(value: false);
|
||||
}
|
||||
}
|
||||
ResetPositionHandCard(card);
|
||||
return NullVfx.GetInstance();
|
||||
};
|
||||
card.OnDestroy += CreateVfxResetPositionByCardBase;
|
||||
card.OnBanish += CreateVfxResetPositionByCardBase;
|
||||
card.OnReturnCard += CreateVfxResetPositionByCardBase;
|
||||
card.OnMetamorphose += CreateVfxResetPositionByCardBase;
|
||||
card.OnGetOn += CreateVfxResetPositionByCardBase;
|
||||
}
|
||||
|
||||
private void ResetPositionHandCard(BattleCardBase card)
|
||||
{
|
||||
if (_cardSelectedByOwner != null && card == _cardSelectedByOwner.CardBase)
|
||||
{
|
||||
_cardSelectedByOwner.ResetOriginalPosition();
|
||||
}
|
||||
if (_cardSelectedByGuest != null && card == _cardSelectedByGuest.CardBase)
|
||||
{
|
||||
_cardSelectedByGuest.ResetOriginalPosition();
|
||||
}
|
||||
}
|
||||
|
||||
public VfxBase CreateVfxResetPositionByCardBase(BattleCardBase card, SkillProcessor skill)
|
||||
{
|
||||
ParallelVfxPlayer parallelVfxPlayer = ParallelVfxPlayer.Create();
|
||||
if (_cardSelectedByOwner != null && _cardSelectedByOwner.CardBase == card)
|
||||
{
|
||||
parallelVfxPlayer.Register(_cardSelectedByOwner.CreateVfxResetPos());
|
||||
}
|
||||
else if (_cardSelectedByGuest != null && _cardSelectedByGuest.CardBase == card)
|
||||
{
|
||||
parallelVfxPlayer.Register(_cardSelectedByGuest.CreateVfxResetPos());
|
||||
}
|
||||
return parallelVfxPlayer;
|
||||
}
|
||||
|
||||
public void ToggleSelectHandCardMove(BattleCardBase selectedCard, bool isOwner)
|
||||
{
|
||||
if (selectedCard == null)
|
||||
{
|
||||
SelectObjectHandCard selectObjectHandCard = null;
|
||||
if (isOwner)
|
||||
{
|
||||
selectObjectHandCard = _cardSelectedByOwner;
|
||||
_cardSelectedByOwner = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
selectObjectHandCard = _cardSelectedByGuest;
|
||||
_cardSelectedByGuest = null;
|
||||
}
|
||||
if (selectObjectHandCard != null)
|
||||
{
|
||||
base.VfxMgr.RegisterSequentialVfx(selectObjectHandCard.CreateVfxResetPos());
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (BattleManagerBase.GetIns().GetBattlePlayer(isOwner).IsSelfTurn)
|
||||
{
|
||||
base.SlideObjectReceiveCtrl.CancelSlide();
|
||||
}
|
||||
if (isOwner)
|
||||
{
|
||||
if (_cardSelectedByOwner != null)
|
||||
{
|
||||
if (_cardSelectedByOwner.CardBase == selectedCard)
|
||||
{
|
||||
return;
|
||||
}
|
||||
base.VfxMgr.RegisterSequentialVfx(_cardSelectedByOwner.CreateVfxResetPos());
|
||||
}
|
||||
_cardSelectedByOwner = new SelectObjectHandCard(selectedCard, isOwner);
|
||||
base.VfxMgr.RegisterSequentialVfx(_cardSelectedByOwner.CreateVfxSelectMove());
|
||||
return;
|
||||
}
|
||||
if (_cardSelectedByGuest != null)
|
||||
{
|
||||
if (_cardSelectedByGuest.CardBase == selectedCard)
|
||||
{
|
||||
return;
|
||||
}
|
||||
base.VfxMgr.RegisterSequentialVfx(_cardSelectedByGuest.CreateVfxResetPos());
|
||||
}
|
||||
_cardSelectedByGuest = new SelectObjectHandCard(selectedCard, isOwner);
|
||||
base.VfxMgr.RegisterSequentialVfx(_cardSelectedByGuest.CreateVfxSelectMove());
|
||||
}
|
||||
|
||||
public override void SetupBattlePlayersEvent()
|
||||
{
|
||||
base.SetupBattlePlayersEvent();
|
||||
SetUpRetireEvent();
|
||||
}
|
||||
|
||||
protected virtual void SetUpRetireEvent()
|
||||
{
|
||||
BattlePlayer.PlayerBattleView.OnRetire += delegate
|
||||
{
|
||||
base.VfxMgr.Clear();
|
||||
if (RoomBase.ConnectController.IsGathering)
|
||||
{
|
||||
GetBattleControl().BattleEnd(UIManager.ViewScene.Gathering, null, delegate(UIManager.ChangeViewSceneParam param)
|
||||
{
|
||||
param.IsUpdateFooterMenuTexture = true;
|
||||
});
|
||||
RoomBase.DestroyMyRoomInfo();
|
||||
}
|
||||
else
|
||||
{
|
||||
GetBattleControl().BattleEnd(UIManager.ViewScene.MyPage, delegate
|
||||
{
|
||||
if (MyPageMenu.Instance != null)
|
||||
{
|
||||
MyPageMenu.Instance.ChangeMenu(MyPageReturnIndex);
|
||||
if (MyPageReturnIndex == 2)
|
||||
{
|
||||
MyPageMenu.Instance.GoToRoomMatch();
|
||||
}
|
||||
}
|
||||
});
|
||||
RoomBase.DestroyMyRoomInfo();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public override VfxBase StartBattle()
|
||||
{
|
||||
SequentialVfxPlayer sequentialVfxPlayer = SequentialVfxPlayer.Create();
|
||||
sequentialVfxPlayer.Register(ChangePhase(base.PhaseCreator.CreateMainPhase()));
|
||||
return sequentialVfxPlayer;
|
||||
}
|
||||
|
||||
protected override NetworkOperationCollectionBase CreateNetworkOperationCollection(NetworkBattleReceiver.ReceiveData receivedData, bool isPlayer)
|
||||
{
|
||||
return new WatchOperationCollection(this, OperateMgr, receivedData, base.networkBattleData, isPlayer);
|
||||
}
|
||||
|
||||
protected override bool IsOperateReceiveCheck()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReceiveRetire(bool isWin)
|
||||
{
|
||||
if (isWin)
|
||||
{
|
||||
JudgeResultReceiveCode = NetworkBattleReceiver.RESULT_CODE.RetireWin;
|
||||
SettingResultUI_SpecialResultTypeText(BATTLE_RESULT_TYPE.WIN);
|
||||
FinishBattleEffect(classDead: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
JudgeResultReceiveCode = NetworkBattleReceiver.RESULT_CODE.RetireLose;
|
||||
SettingResultUI_SpecialResultTypeText(BATTLE_RESULT_TYPE.LOSE);
|
||||
FinishBattleEffect(classDead: true);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void FinishBattleSend(NetworkBattleSender.JUDGE_RESULT_STATUS log, bool isWin = false, bool isNotRetry = false)
|
||||
{
|
||||
if (isResultDone)
|
||||
{
|
||||
return;
|
||||
}
|
||||
isResultDone = true;
|
||||
if (JudgeResultReceiveCode == NetworkBattleReceiver.RESULT_CODE.NotFinish)
|
||||
{
|
||||
JudgeResultReceiveCode = JudgeCurrentFinishStatus();
|
||||
if (JudgeResultReceiveCode == NetworkBattleReceiver.RESULT_CODE.NotFinish)
|
||||
{
|
||||
LocalLog.AccumulateLastTraceLog("FinishBattleSend NotStatus" + isWin);
|
||||
if (isWin)
|
||||
{
|
||||
JudgeResultReceiveCode = NetworkBattleReceiver.RESULT_CODE.DisconnectWin;
|
||||
}
|
||||
else
|
||||
{
|
||||
JudgeResultReceiveCode = NetworkBattleReceiver.RESULT_CODE.DisconnectLose;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch (JudgeResultReceiveCode)
|
||||
{
|
||||
case NetworkBattleReceiver.RESULT_CODE.NoContest:
|
||||
case NetworkBattleReceiver.RESULT_CODE.Invalid:
|
||||
SettingResultUI_SpecialResultTypeText(BATTLE_RESULT_TYPE.CONSISTENCY);
|
||||
FinishBattleEffect(classDead: false);
|
||||
break;
|
||||
case NetworkBattleReceiver.RESULT_CODE.LifeLose:
|
||||
case NetworkBattleReceiver.RESULT_CODE.DeckoutLose:
|
||||
case NetworkBattleReceiver.RESULT_CODE.SpecialLose:
|
||||
case NetworkBattleReceiver.RESULT_CODE.MaxTurnLose:
|
||||
base.VfxMgr.RegisterSequentialVfx(InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(hasWon: false);
|
||||
}));
|
||||
break;
|
||||
case NetworkBattleReceiver.RESULT_CODE.RetireLose:
|
||||
case NetworkBattleReceiver.RESULT_CODE.DisconnectLose:
|
||||
case NetworkBattleReceiver.RESULT_CODE.FirstcardLose:
|
||||
case NetworkBattleReceiver.RESULT_CODE.TurnendLose:
|
||||
case NetworkBattleReceiver.RESULT_CODE.TurnstartLose:
|
||||
RegisterDestryoy(isPlayer: true);
|
||||
base.VfxMgr.RegisterSequentialVfx(InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(hasWon: false);
|
||||
}));
|
||||
break;
|
||||
case NetworkBattleReceiver.RESULT_CODE.LifeWin:
|
||||
case NetworkBattleReceiver.RESULT_CODE.DeckoutWin:
|
||||
case NetworkBattleReceiver.RESULT_CODE.SpecialWin:
|
||||
base.VfxMgr.RegisterSequentialVfx(InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(hasWon: true);
|
||||
}));
|
||||
break;
|
||||
case NetworkBattleReceiver.RESULT_CODE.RetireWin:
|
||||
case NetworkBattleReceiver.RESULT_CODE.DisconnectWin:
|
||||
case NetworkBattleReceiver.RESULT_CODE.FirstcardWin:
|
||||
case NetworkBattleReceiver.RESULT_CODE.TurnendWin:
|
||||
case NetworkBattleReceiver.RESULT_CODE.TurnstartWin:
|
||||
RegisterDestryoy(isPlayer: false);
|
||||
base.VfxMgr.RegisterSequentialVfx(InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(hasWon: true);
|
||||
}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected void RegisterDestryoy(bool isPlayer)
|
||||
{
|
||||
BattleCardBase battleCardBase = GetBattlePlayer(isPlayer).Class;
|
||||
if (battleCardBase.Life >= 1)
|
||||
{
|
||||
battleCardBase.FlagCardAsDestroyedByKiller();
|
||||
FINISH_TYPE finishTypeByStatus = GetFinishTypeByStatus();
|
||||
base.VfxMgr.RegisterSequentialVfx(DeadClass(isPlayer, finishTypeByStatus));
|
||||
}
|
||||
}
|
||||
|
||||
public void FinishBattleSpecialEffect(BATTLE_RESULT_TYPE battleResult)
|
||||
{
|
||||
bool isPlayer = true;
|
||||
switch (battleResult)
|
||||
{
|
||||
case BATTLE_RESULT_TYPE.WIN:
|
||||
isPlayer = true;
|
||||
break;
|
||||
case BATTLE_RESULT_TYPE.LOSE:
|
||||
isPlayer = false;
|
||||
break;
|
||||
case BATTLE_RESULT_TYPE.CONSISTENCY:
|
||||
BattleResultControl.SetBattleFinishConsistency();
|
||||
isPlayer = true;
|
||||
break;
|
||||
}
|
||||
base.VfxMgr.RegisterSequentialVfx(InstantVfx.Create(delegate
|
||||
{
|
||||
InitiateGameEndSequence(isPlayer);
|
||||
}));
|
||||
}
|
||||
|
||||
protected virtual OperateReceive CreateOperateReceive()
|
||||
{
|
||||
return new WatchOperateReceive(this, RegisterActionManager, OperateMgr, base.networkBattleData);
|
||||
}
|
||||
|
||||
public override bool IsSkillConditionCheckSkill(int cardIdx)
|
||||
{
|
||||
if (!base.IsSkillConditionCheckSkill(cardIdx))
|
||||
{
|
||||
return base.networkBattleData.GetReceiveData().ActiveSelectSkillIndexList.Count > 0;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool IsReceivedSkillConditionCheck(int movement, SkillBase skill)
|
||||
{
|
||||
if (base.networkBattleData.GetReceiveData().ActiveSelectSkillIndexList.Count > 0)
|
||||
{
|
||||
return base.networkBattleData.GetReceiveData().ActiveSelectSkillIndexList.Contains(skill.SkillPrm.ownerCard.Skills.IndexOf(skill));
|
||||
}
|
||||
return base.IsReceivedSkillConditionCheck(movement, skill);
|
||||
}
|
||||
}
|
||||
using Wizard.Battle.View.Vfx;
|
||||
using Wizard.BattleMgr;
|
||||
|
||||
// PASS-6 STUB: 578-line body dropped. NetworkWatchBattleMgr is the client-side
|
||||
// spectator battle manager (watch-touch-control, watcher-leave/disconnect checkers,
|
||||
// select-object-hand-card VFX). Never constructed in headless — the node uses
|
||||
// HeadlessNetworkBattleMgr : NetworkStandardBattleMgr, a sibling subtree.
|
||||
// NetworkWatchBattleReceiver (which IS on the headless path via
|
||||
// NetworkReplayBattleReceiver's inheritance) does NOT cast its mgr ref to
|
||||
// NetworkWatchBattleMgr — it works through NetworkBattleManagerBase, so the mgr
|
||||
// body's absence is invisible to the receive path.
|
||||
//
|
||||
// The three surface members below are compile-load-bearing:
|
||||
// - disconnectDialog: field read by WatcherLeaveChecker (only constructed from
|
||||
// within this class — dies in the analyzer cascade).
|
||||
// - CreateVfxResetPositionByCardBase: called from WatchPlayCardAction via
|
||||
// `(_battleMgr as NetworkWatchBattleMgr).…` — cast returns null in headless.
|
||||
// - ToggleSelectHandCardMove: called from WatchOperationCollection.
|
||||
// SelectObjectOperation on `_watchBattleMgr`. The recovery path takes the
|
||||
// NetworkBattleManagerBase ctor overload that leaves `_watchBattleMgr` null,
|
||||
// so this method's only would-be invocation NREs; safe as a signature stub.
|
||||
public class NetworkWatchBattleMgr : NetworkBattleManagerBase
|
||||
{
|
||||
|
||||
public NetworkWatchBattleMgr(IBattleMgrContentsCreator contentsCreator) : base(contentsCreator) { }
|
||||
public void ToggleSelectHandCardMove(BattleCardBase selectedCard, bool isOwner) { }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user