Files
SVSimServer/SVSim.BattleEngine/Engine/Wizard/AINetworkBattleManager.cs
gamer147 824309ec44 feat(battle-engine): close the AI-simulation subsystem (verbatim)
Copied the 89 uncopied AI*SimulationUtility/extension files defining the
AIVirtualCard/AIVirtualField extension methods; the compile loop then auto-closed
the revealed type deps (~3049 files total, drift-clean). 10.0k -> 62 errors.
2026-06-05 20:30:59 -04:00

504 lines
17 KiB
C#

using System;
using System.Collections.Generic;
using UnityEngine;
using Wizard.Battle;
using Wizard.Battle.Phase;
using Wizard.Battle.Recovery;
using Wizard.Battle.View.Vfx;
using Wizard.BattleMgr;
namespace Wizard;
public class AINetworkBattleManager : NetworkBattleManagerBase
{
private AITurnControl _aiTurnControl;
private Func<VfxBase> _turnTransitionFunc;
private VfxBase _initiateGameEndFunc;
private bool _sendFinshBattleTask;
private bool _isWin;
public AIBattleInfoReceiver BattleInfoReceiver { get; protected set; }
public AINetworkBattleManager(IBattleMgrContentsCreator contentsCreator)
: base(contentsCreator)
{
_turnTransitionFunc = null;
}
protected override void NetworkBattleManagerSetup()
{
DataMgr dataMgr = GameMgr.GetIns().GetDataMgr();
dataMgr.SetDeckMaxCount(40, isSelf: true);
dataMgr.SetDeckMaxCount(40, isSelf: false);
IsShowDisconnectPanel = false;
IsShowOpponentDisconnectPanel = false;
NotReplaceCardList = new List<ReplaceReceivedCard.CardIdAndIndex>();
base.validateSkillIndexList = new List<ValidateSkillData>();
RegisterActionManager = new RegisterActionManager(this);
base.RegisterUnapprovedList = new List<RegisterUnapproved>();
base.registerSelectTypeSkillIndexList = new List<int>();
sendKeyActionDataManager = new SendKeyActionDataManager();
TouchControl = new NetworkTouchControl(this, _battleCamera, _backGround);
networkTouchControl = TouchControl as NetworkTouchControl;
JudgeResultReceiveCode = NetworkBattleReceiver.RESULT_CODE.NotFinish;
if (base.IsRecovery || GameMgr.GetIns().IsReplayBattle)
{
networkTouchControl.SetDisableTouch();
base.networkBattleData = new NetworkRecoveryBattleData(this);
networkReceiver = new NetworkReplayBattleReceiver(this);
OperateReceive = new RecoveryOperateReceive(this, RegisterActionManager, OperateMgr, base.networkBattleData);
int selfIdxSeed = (base.IsRecovery ? _contentsCreator.RecoveryManager.IdxChangeSeed : Data.ReplayBattleInfo.IdxChangeSeed);
int oppIdxSeed = (GameMgr.GetIns().IsReplayBattle ? Data.ReplayBattleInfo.OppoIdxChangeSeed : (-1));
CreateXorShift(selfIdxSeed, oppIdxSeed);
BattleEnemy.EnableEnemyAI = false;
}
else
{
base.networkBattleData = new NetworkBattleData(this);
networkReceiver = new NetworkBattleReceiver(this);
OperateReceive = new OperateReceive(this, RegisterActionManager, OperateMgr, base.networkBattleData);
}
OperateMgr.SetTouchControl(TouchControl);
networkConsistency = new NetworkConsistency(this);
_networkBattleSetupCardEventBase = new NetworkAIBattleSetupCardEvent(this, RegisterActionManager, base.networkBattleData);
operateReceiveChecker = new OperateReceiveChecker(this, base.networkBattleData);
_intervalCheckList = new List<NetworkBattleIntervalCheckerBase>();
base.opponentRecoveryToDispChecker = new OpponentRecoveryToDispChecker();
base.disconnectToDispChecker = new DisconnectToDispChecker();
_intervalCheckList.Add(base.disconnectToDispChecker);
base.disconnectToLoseChecker = new DisconnectToLoseChecker();
base.disconnectToLoseChecker.OnDisconnectLose += delegate
{
DisconnectLose();
};
base.disconnectToLoseChecker.OnBeforeDisconnectLose += delegate
{
BeforeDisconnectLose();
};
_intervalCheckList.Add(base.disconnectToLoseChecker);
base.notMulliganEndToJudgeChecker = new NullNotMulliganEndToJudgeChecker();
base.notTurnEndToLoseChecker = new NullNotTurnEndToLoseChecker(this);
base.receiveTurnEndToJudgeResult = new NullReceiveTurnEndToJudgeResult();
_intervalCheckList.Add(base.notTurnEndToLoseChecker);
base.notTurnStartToLoseChecker = new NullNotTurnStartToLoseChecker();
_intervalCheckList.Add(base.notTurnStartToLoseChecker);
SendIntervalTriggerMain = new AISendIntervalTrigger();
base.NetworkSender = new NetworkBattleSender(this, RegisterActionManager, base.RegisterUnapprovedList, networkConsistency);
_aiTurnControl = new AITurnControl();
if (!base.IsRecovery)
{
SettingOpponentAliveEvent();
IsStopIntervalCheck = false;
ToolboxGame.RealTimeNetworkAgent.StartPreparedStartTimer(DateTime.Now);
ToolboxGame.RealTimeNetworkAgent.StartRecoveryRecording();
}
}
protected override void DisconnectLose()
{
JudgeErrorDialog(isError: false);
}
public override VfxBase ChangePhase(IPhase phase)
{
if (phase is NetworkMulliganPhase || (phase is MainPhase && base.IsRecovery))
{
base.notMulliganEndToJudgeChecker.StartChecker();
base.disconnectToDispChecker.OnDisp += delegate
{
ControlDisconnectOffTouchAndView(flag: true);
};
base.disconnectToDispChecker.OnErase += delegate
{
ControlDisconnectOffTouchAndView(flag: false);
};
}
if (phase is OpeningPhase)
{
ConnectionReportTrigger.ConnectionReport(this);
}
return base.ChangePhase(phase);
}
public override void Update(float dt)
{
base.Update(dt);
if (_turnTransitionFunc != null && ToolboxGame.RealTimeNetworkAgent != null && ToolboxGame.RealTimeNetworkAgent.PlayerNetworkStatus.IsAlive)
{
base.VfxMgr.RegisterSequentialVfx(_turnTransitionFunc.GetAllFuncVfxResults());
_turnTransitionFunc = null;
}
if (_initiateGameEndFunc != null && ToolboxGame.RealTimeNetworkAgent != null && ToolboxGame.RealTimeNetworkAgent.PlayerNetworkStatus.IsAlive)
{
base.VfxMgr.RegisterSequentialVfx(_initiateGameEndFunc);
_initiateGameEndFunc = null;
}
if (ToolboxGame.RealTimeNetworkAgent != null && _turnTransitionFunc == null && !IsBattleEnd && BattleEnemy.IsSelfTurn)
{
_aiTurnControl.Update(EnemyAI);
}
}
public override void SetupBattlePlayersEvent()
{
BattlePlayer.OnSetupCardEvent += SetupCardEvent;
BattleEnemy.OnSetupCardEvent += SetupCardEvent;
BattlePlayer.OnSetupClassEvent += SetupPlayerClassEvent;
BattleEnemy.OnSetupClassEvent += SetupOpponentClassEvent;
BattlePlayer.Setup(BattleEnemy);
BattleEnemy.Setup(BattlePlayer);
BattlePlayer.OnTurnEnd += delegate
{
base.VfxMgr.Cancel();
return NullVfx.GetInstance();
};
}
protected override void SetupNetworkEvent(bool isRecovery)
{
BattlePlayer.OnPlayerActive += delegate
{
if (turnEndTimeController != null)
{
turnEndTimeController.StartCountDown("AIOnPlayerActive");
}
};
BattlePlayer battlePlayer = BattlePlayer;
battlePlayer.OnPostTurnEndComplete = (Action)Delegate.Combine(battlePlayer.OnPostTurnEndComplete, (Action)delegate
{
if (turnEndTimeController != null)
{
turnEndTimeController.EndCountDown("AIOnTurnEndComplete");
}
SendTurnEndAction();
});
BattleEnemy.OnTurnStartBeforeDraw += delegate
{
if (!IsVirtualBattle)
{
_aiTurnControl.StartTurnTimer();
}
return NullVfx.GetInstance();
};
BattleEnemy battleEnemy = BattleEnemy;
battleEnemy.OnPostTurnEndComplete = (Action)Delegate.Combine(battleEnemy.OnPostTurnEndComplete, (Action)delegate
{
if (!IsVirtualBattle)
{
_aiTurnControl.StopTurnTimer();
}
});
}
public override void InitiateGameEndSequence(bool hasWon)
{
if (ToolboxGame.RealTimeNetworkAgent != null && ToolboxGame.RealTimeNetworkAgent.PlayerNetworkStatus.IsAlive)
{
if (!_sendFinshBattleTask)
{
_sendFinshBattleTask = true;
_isWin = hasWon;
BattleFinishToEffectClear();
BattleFinishToStopIntervalChecker();
ToolboxGame.RealTimeNetworkAgent.FinishBattleTask(this);
}
}
else
{
_initiateGameEndFunc = InstantVfx.Create(delegate
{
InitiateGameEndSequence(hasWon);
});
}
}
public override void FinishBattleEffect(bool classDead)
{
classDead = !_isWin;
if (classDead)
{
BattleCardBase battleCardBase = GetBattlePlayer(classDead).Class;
if (battleCardBase.Life >= 1 && !battleCardBase.IsDead)
{
battleCardBase.FlagCardAsDestroyedByKiller();
FINISH_TYPE finishTypeByStatus = GetFinishTypeByStatus();
base.VfxMgr.RegisterSequentialVfx(DeadClass(classDead, finishTypeByStatus));
}
}
base.VfxMgr.RegisterSequentialVfx(InstantVfx.Create(delegate
{
base.InitiateGameEndSequence(!classDead);
}));
}
public override VfxBase JudgeBattleResult()
{
if (BattlePlayer.Class.IsDead && BattleEnemy.Class.IsDead)
{
return InstantVfx.Create(delegate
{
InitiateGameEndSequence(!BattlePlayer.IsSelfTurn);
});
}
if (BattlePlayer.Class.IsDead)
{
return InstantVfx.Create(delegate
{
InitiateGameEndSequence(hasWon: false);
});
}
if (BattleEnemy.Class.IsDead)
{
return InstantVfx.Create(delegate
{
InitiateGameEndSequence(hasWon: true);
});
}
return NullVfx.GetInstance();
}
protected override void SetupEvent()
{
base.SetupEvent();
BattlePlayer.OnShortageDeck += () => OnShortageDeck(BattlePlayer);
BattleEnemy.OnShortageDeck += () => OnShortageDeck(BattleEnemy);
SetUpTurnTransitionEvent();
}
private void SetUpTurnTransitionEvent()
{
BattlePlayer.OnTurnEndFinish += delegate
{
if (IsVirtualBattle || base.IsRecovery)
{
return NullVfx.GetInstance();
}
_turnTransitionFunc = null;
_turnTransitionFunc = (Func<VfxBase>)Delegate.Combine(_turnTransitionFunc, new Func<VfxBase>(base.ControlTurnStartOpponent));
return NullVfx.GetInstance();
};
BattleEnemy.OnTurnEndFinish += delegate
{
if (IsVirtualBattle || base.IsRecovery)
{
return NullVfx.GetInstance();
}
_turnTransitionFunc = null;
_turnTransitionFunc = (Func<VfxBase>)Delegate.Combine(_turnTransitionFunc, new Func<VfxBase>(base.ControlTurnStartPlayer));
return NullVfx.GetInstance();
};
}
protected override void SetupBattlePlayerRegisterEvents(BattlePlayerBase battlePlayer)
{
}
protected override void SetupNetworkActionProcessorEvent(ActionProcessor processor, bool isPlayer)
{
}
public override void SetupFieldAndHandAfterRecovery(Action onEndRecoveryCallback, RecoveryOperationInfo aiBattleRecoveryData = null)
{
if (aiBattleRecoveryData.SetupInfo.HasMulliganInfo)
{
BattlePlayer.PlayerBattleView.ClearPlayQueue();
BattleEnemy.BattleEnemyView.ClearPlayQueue();
RecreateCardViews(BattlePlayer.InPlayCards);
RecreateCardViews(BattlePlayer.HandCardList);
RecreateCardViews(BattlePlayer.DeckCardList);
RecreateCardViews(BattlePlayer.ReservedCardList);
RecreateCardViews(BattleEnemy.InPlayCards);
RecreateCardViews(BattleEnemy.HandCardList);
RecreateCardViews(BattleEnemy.DeckCardList);
RecreateCardViews(BattleEnemy.ReservedCardList);
RefreshHealthVfx refreshHealthVfx = new RefreshHealthVfx(BattlePlayer);
RefreshHealthVfx refreshHealthVfx2 = new RefreshHealthVfx(BattleEnemy);
ParallelVfxPlayer parallelVfxPlayer = ParallelVfxPlayer.Create(BattlePlayer.BattleView.Recovery(doseFirst: false), BattleEnemy.BattleView.Recovery(doseFirst: false), refreshHealthVfx, refreshHealthVfx2);
VfxBase vfxBase = (BattleEnemy.IsSelfTurn ? BattleEnemy.CreateThinkingVfx(this) : NullVfx.GetInstance());
SequentialVfxPlayer vfx = SequentialVfxPlayer.Create(RecoveryAfterMulliganPhase.RestoreUI(this), parallelVfxPlayer, HandViewBase.CreateHideCardMeshesVfx(BattleEnemy.HandCardList), vfxBase, InstantVfx.Create(delegate
{
ResetLeaderAnimation(BattlePlayer, BattleEnemy);
}));
base.VfxMgr.RegisterSequentialVfx(vfx);
}
}
public override void RecoveryEnd()
{
base.IsRecovery = false;
SettingOpponentAliveEvent();
IsStopIntervalCheck = false;
SetUpTurnTransitionEvent();
networkTouchControl.SetEnableTouch();
NetworkBattleData networkBattleData = base.networkBattleData;
base.networkBattleData = new NetworkBattleData(this);
base.networkBattleData.isPlayerMulliganEnd = networkBattleData.isPlayerMulliganEnd;
base.networkBattleData.isOppoMulliganEnd = networkBattleData.isOppoMulliganEnd;
base.networkBattleData.SetReceiveData(networkBattleData.GetReceiveData());
base.networkBattleData.isEnemyFirstTurn = networkBattleData.isEnemyFirstTurn;
_networkBattleSetupCardEventBase.OverwriteNetworkBattleData(base.networkBattleData);
SetupCreateBattleCardFunc(createCardWithoutGameObject: false);
OperateMgr operateMgr = OperateMgr;
OperateMgr = CreateOperateMgr();
OperateMgr.SetUpRecoveryEvent(operateMgr);
StartRecoveryRecording();
operateMgr = null;
OperateReceive = new OperateReceive(this, RegisterActionManager, OperateMgr, base.networkBattleData);
if (_phase is NetworkMulliganPhase)
{
(_phase as NetworkMulliganPhase).MulliganEventSetting();
}
operateReceiveChecker = new OperateReceiveChecker(this, base.networkBattleData);
networkReceiver = new NetworkBattleReceiver(this);
SetupNetworkEvent(isRecovery: true);
if (_specialWinVfx == null)
{
ClearRegisterCardList();
}
BattleEnemy.EnableEnemyAI = true;
BattlePlayer.Emotion.Enable = true;
BattleEnemy.Emotion.Enable = true;
if (BattleEnemy.IsSelfTurn)
{
EnemyAI.StopEnemyAI();
EnemyAI.ExecuteEnemyAI(useWait: true);
}
ConnectionReportTrigger.ConnectionReport(this);
}
protected override void FirstRecoverySetting()
{
if (!base.IsRecovery)
{
StartRecoveryRecording();
}
}
protected override int CreateBackgroundId()
{
if (_contentsCreator is RecoveryNetworkBattleMgrContentsCreator)
{
int backGroundId = ((RecoveryNetworkBattleMgrContentsCreator)_contentsCreator).RecoveryControllerInstance.AIBattleRecoveryData.SetupInfo.BackGroundId;
if (backGroundId >= 0)
{
return backGroundId;
}
}
return CalculationRandomStage();
}
public override void FinishBattle()
{
EnemyAI.StopEnemyAI();
}
public override void RecoveryTimeOutSetting(float extendTime, bool isMulliganEnd, long startTime = -1L)
{
if (!isMulliganEnd)
{
if (MulliganMgr != null)
{
MulliganMgr.GetMulliganInfo().SetExtendTime(extendTime);
}
return;
}
if (!BattlePlayer.IsSelfTurn)
{
if (startTime != -1)
{
_aiTurnControl.SetAndStartTurnTimer(DateTimeOffset.FromUnixTimeSeconds(startTime).LocalDateTime);
}
return;
}
if (turnEndTimeController == null)
{
TurnEndButtonUI component = SBattleLoad.m_TurnEndBtnUI.GetComponent<TurnEndButtonUI>();
turnEndTimeController = new TurnEndTimeController(this, BattlePlayer, component);
}
if (!turnEndTimeController.IsCountdownRunning())
{
turnEndTimeController.StartCountDown("SetTimeoutSetting");
}
turnEndTimeController.SetExtendTime(extendTime);
}
public void SetupMulliganLaunchCompleteEvent()
{
_contentsCreator.RecoveryRecordManager.SetupMulliganStartTimeRecorderEvent(this);
}
public override VfxBase StartBattle()
{
SequentialVfxPlayer sequentialVfxPlayer = SequentialVfxPlayer.Create();
LocalLog.SetLastTraceLogTurn(1);
sequentialVfxPlayer.Register(ChangePhase(base.PhaseCreator.CreateMainPhase()));
if (IsFirst)
{
sequentialVfxPlayer.Register(BattlePlayer.StartTurnControl("AIFirst"));
}
else
{
sequentialVfxPlayer.Register(BattleEnemy.StartTurnControl());
}
return sequentialVfxPlayer;
}
public override void SetupEnemyAI()
{
EnemyAI enemyAI = new RankMatchEnemyAI();
enemyAI.LoadBufferedBattleState();
EnemyAI = enemyAI;
BattleInfoReceiver = new AIBattleInfoReceiver(EnemyAI);
EnemyAI.InitOnGame(BattleEnemy, BattlePlayer);
if (!base.IsRecovery)
{
BattleEnemy.EnableEnemyAI = true;
}
}
public override BattleCardBase MetamorphoseCard(int cardId, bool isPlayer, int addIndex, SkillBase skill, bool isFusion = false)
{
return CreateBattleCardWithGameObject(new CardCreateInfo(cardId, isPlayer, skill.ApplyingTargetFilter is SkillTargetChosenCardsFilter, NetworkBattleDefine.NetworkCardPlaceState.None, isReferenceOpponentCard: false, skill), new IndexInfo(addIndex));
}
public override BattleCardBase CreateBattleCardWithGameObject(CardCreateInfo info, IndexInfo indexInfo, int repeatCount = -1, bool isVirtual = false, bool isActualCard = false)
{
CardParameter cardParameterFromId = CardMaster.GetInstanceForBattle().GetCardParameterFromId(info.Id);
BattlePlayerBase battlePlayer = GetBattlePlayer(info.IsPlayer);
int cardIndex = SetupCardIndex(battlePlayer, indexInfo.AddIndex);
GameObject cardGameObject = null;
if (!base.IsRecovery || !isVirtual)
{
cardGameObject = CreateBaseCardGameObject(cardParameterFromId, info.IsPlayer, cardIndex);
}
BattleCardBase battleCardBase = CreateBattleCard(info.Id, info.IsPlayer, cardGameObject, cardParameterFromId, battlePlayer, cardIndex);
if (!base.IsRecovery || !isVirtual)
{
SetupCardObjectMaterials(cardGameObject, battleCardBase);
}
return battleCardBase;
}
protected override void ControlDisconnectOffTouchAndView(bool flag)
{
if (!_sendFinshBattleTask)
{
base.ControlDisconnectOffTouchAndView(flag);
}
}
public override void PlayRetire()
{
if (RecoveryRecordManagerBase.IsExistsAINetworkRecoveryFile())
{
GameMgr.GetIns().GetDataMgr().SetRecoveryData(RecoveryOperationInfo.ReadRecoveryFile(OperationRecorderBase.RecordDirectoryPath + "recovery_ai_network.json"));
RecoveryRecordManagerBase.DeleteRecoveryFile();
}
base.PlayRetire();
}
}