From ab7c7172b88e7952fdfd2042502111cb8b07237e Mon Sep 17 00:00:00 2001 From: SepComet <2428390463@qq.com> Date: Sat, 7 Mar 2026 15:22:24 +0800 Subject: [PATCH] =?UTF-8?q?refactor=206:=20-=20CombatInfoFormUseCase.cs=20?= =?UTF-8?q?=E6=94=B9=E6=88=90=E5=9B=9E=E8=B0=83=E9=A9=B1=E5=8A=A8=EF=BC=9A?= =?UTF-8?q?=20=20=20=20=20-=20=E4=B8=8D=E5=86=8D=E7=9B=B4=E6=8E=A5?= =?UTF-8?q?=E8=AF=BB=20GameEntry.CombatNode=20=20=20=20=20-=20=E7=94=B1=20?= =?UTF-8?q?CombatLoadSession.cs=20=E5=9C=A8=E6=89=93=E5=BC=80=20CombatInfo?= =?UTF-8?q?Form=20=E5=89=8D=E6=B3=A8=E5=85=A5=20modelProvider=20=E5=92=8C?= =?UTF-8?q?=20TryEndCombat=20=E5=9B=9E=E8=B0=83=20-=20CombatSelectFormUseC?= =?UTF-8?q?ase.cs=20=E7=9A=84=E9=BB=98=E8=AE=A4=20coin=20provider=20?= =?UTF-8?q?=E6=94=B9=E6=88=90=E8=BF=94=E5=9B=9E=200=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E5=81=B7=E5=81=B7=20fallback=20=E5=88=B0=20GameEntry.?= =?UTF-8?q?CombatNode=20-=20CombatFinishFormUseCase.cs=20=E5=8E=BB?= =?UTF-8?q?=E6=8E=89=E4=BA=86=E6=9C=AA=E5=87=86=E5=A4=87=20summary=20?= =?UTF-8?q?=E6=97=B6=E5=AF=B9=20GameEntry.CombatNode=20=E7=9A=84=E5=85=9C?= =?UTF-8?q?=E5=BA=95=E8=AF=BB=E5=8F=96=20-=20MapData.cs=20=E8=BF=9B?= =?UTF-8?q?=E4=B8=80=E6=AD=A5=E8=A1=A5=E5=85=85=E4=BA=86=E6=88=98=E6=96=97?= =?UTF-8?q?=E5=88=9D=E5=A7=8B=E5=BF=AB=E7=85=A7=EF=BC=9A=20=20=20=20=20-?= =?UTF-8?q?=20InventorySnapshot=20=20=20=20=20-=20ParticipantTowerSnapshot?= =?UTF-8?q?=20-=20CombatLoadingState.cs=20=E7=8E=B0=E5=9C=A8=E4=BC=9A?= =?UTF-8?q?=E6=8A=8A=E8=BF=99=E4=BA=9B=E8=83=8C=E5=8C=85/=E5=8F=82?= =?UTF-8?q?=E6=88=98=E5=A1=94=E5=BF=AB=E7=85=A7=E4=B9=9F=E4=B8=80=E8=B5=B7?= =?UTF-8?q?=E6=89=93=E8=BF=9B=20MapData=20-=20MapEntity.cs=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=BB=BA=E5=A1=94=E9=9D=A2=E6=9D=BF=E6=97=B6=E4=B8=8D?= =?UTF-8?q?=E5=86=8D=E7=9B=B4=E6=8E=A5=E8=AF=BB=20PlayerInventory=EF=BC=8C?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=E7=94=A8=20MapData=20=E9=87=8C=E7=9A=84?= =?UTF-8?q?=E5=BF=AB=E7=85=A7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CombatScheduler/CombatLoadSession.cs | 32 ++++++++++- .../CombatStates/CombatLoadingState.cs | 9 ++- .../Scripts/Entity/EntityData/MapData.cs | 29 ++++++++++ .../Scripts/Entity/EntityLogic/MapEntity.cs | 10 +--- .../Combat/UseCase/CombatFinishFormUseCase.cs | 8 +-- .../Combat/UseCase/CombatInfoFormUseCase.cs | 57 +++++++++++-------- .../Combat/UseCase/CombatSelectFormUseCase.cs | 7 +-- 7 files changed, 105 insertions(+), 47 deletions(-) diff --git a/Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatLoadSession.cs b/Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatLoadSession.cs index cdf2579..f0c1155 100644 --- a/Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatLoadSession.cs +++ b/Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatScheduler/CombatLoadSession.cs @@ -45,7 +45,7 @@ namespace GeometryTD.CustomComponent _currentMap = null; } - public bool StartLoading(DRLevel level, MapData mapData, out string errorMessage) + public bool StartLoading(DRLevel level, MapData mapData, CombatScheduler scheduler, out string errorMessage) { errorMessage = null; if (_entity == null) @@ -59,7 +59,7 @@ namespace GeometryTD.CustomComponent return false; } - if (!TryOpenCombatInfoForm(out errorMessage)) + if (!TryOpenCombatInfoForm(scheduler, out errorMessage)) { return false; } @@ -249,7 +249,7 @@ namespace GeometryTD.CustomComponent return true; } - private bool TryOpenCombatInfoForm(out string errorMessage) + private bool TryOpenCombatInfoForm(CombatScheduler scheduler, out string errorMessage) { errorMessage = null; if (_combatInfoFormUseCase == null) @@ -258,6 +258,10 @@ namespace GeometryTD.CustomComponent GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatInfoForm, _combatInfoFormUseCase); } + _combatInfoFormUseCase.Configure( + () => BuildCombatInfoFormRawData(scheduler), + () => scheduler != null && scheduler.CanEndCombat && scheduler.TryEndCombatByPlayer()); + int? serialId = GameEntry.UIRouter.OpenUI(UIFormType.CombatInfoForm); if (!serialId.HasValue) { @@ -270,6 +274,28 @@ namespace GeometryTD.CustomComponent return true; } + private static CombatInfoFormRawData BuildCombatInfoFormRawData(CombatScheduler scheduler) + { + if (scheduler == null) + { + return null; + } + + DRLevel level = scheduler.CurrentLevel; + LevelThemeType themeType = level != null ? level.LevelThemeType : LevelThemeType.None; + int levelId = level != null ? level.Id : 0; + int baseHpMax = level != null ? Mathf.Max(0, level.BaseHp) : 0; + return CombatInfoFormUseCase.BuildRawData( + themeType, + levelId, + scheduler.DisplayPhaseIndex, + scheduler.PhaseCount, + scheduler.CurrentCoin, + scheduler.CurrentBaseHp, + baseHpMax, + scheduler.CanEndCombat); + } + private void CloseCombatInfoForm() { GameEntry.UIRouter.CloseUI(UIFormType.CombatInfoForm); diff --git a/Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatStates/CombatLoadingState.cs b/Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatStates/CombatLoadingState.cs index 4567c92..33050ae 100644 --- a/Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatStates/CombatLoadingState.cs +++ b/Assets/GameMain/Scripts/CustomComponent/CombatNode/CombatStates/CombatLoadingState.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using GeometryTD.Definition; using GeometryTD.Entity.EntityData; +using GeometryTD.UI; using UnityEngine; namespace GeometryTD.CustomComponent @@ -22,7 +23,7 @@ namespace GeometryTD.CustomComponent } MapData mapData = BuildMapData(); - if (!Scheduler._loadSession.StartLoading(Scheduler._currentLevel, mapData, out string errorMessage)) + if (!Scheduler._loadSession.StartLoading(Scheduler._currentLevel, mapData, Scheduler, out string errorMessage)) { Scheduler.EnterFailureFallback($"Combat loading failed. {errorMessage}"); } @@ -60,6 +61,12 @@ namespace GeometryTD.CustomComponent position: Vector3.zero, initialCoin: Scheduler._combatInRunResourceManager.CurrentCoin, buildTowerStatsSnapshot: buildTowerStatsSnapshot, + inventorySnapshot: GameEntry.PlayerInventory != null + ? GameEntry.PlayerInventory.GetInventorySnapshot() + : null, + participantTowerSnapshot: GameEntry.PlayerInventory != null + ? GameEntry.PlayerInventory.GetParticipantTowerSnapshot() + : null, tryConsumeCoin: Scheduler.TryConsumeCoin, addCoin: Scheduler.AddCoin); } diff --git a/Assets/GameMain/Scripts/Entity/EntityData/MapData.cs b/Assets/GameMain/Scripts/Entity/EntityData/MapData.cs index 977c164..730f5c3 100644 --- a/Assets/GameMain/Scripts/Entity/EntityData/MapData.cs +++ b/Assets/GameMain/Scripts/Entity/EntityData/MapData.cs @@ -12,6 +12,8 @@ namespace GeometryTD.Entity.EntityData [SerializeField] private int _levelId = 0; [SerializeField] private int _initialCoin = 0; [SerializeField] private TowerStatsData[] _buildTowerStatsSnapshot = Array.Empty(); + [SerializeField] private BackpackInventoryData _inventorySnapshot; + [SerializeField] private TowerItemData[] _participantTowerSnapshot = Array.Empty(); [NonSerialized] private Func _tryConsumeCoin; [NonSerialized] private Action _addCoin; @@ -33,6 +35,8 @@ namespace GeometryTD.Entity.EntityData Vector3 position, int initialCoin, IReadOnlyList buildTowerStatsSnapshot, + BackpackInventoryData inventorySnapshot, + IReadOnlyList participantTowerSnapshot, Func tryConsumeCoin, Action addCoin) : base(entityId, typeId) { @@ -40,6 +44,10 @@ namespace GeometryTD.Entity.EntityData Position = position; _initialCoin = Mathf.Max(0, initialCoin); SetBuildTowerStatsSnapshot(buildTowerStatsSnapshot); + _inventorySnapshot = inventorySnapshot != null + ? InventoryCloneUtility.CloneInventory(inventorySnapshot) + : null; + SetParticipantTowerSnapshot(participantTowerSnapshot); _tryConsumeCoin = tryConsumeCoin; _addCoin = addCoin; } @@ -57,6 +65,10 @@ namespace GeometryTD.Entity.EntityData } public int CurrentBuildTowerCount => _buildTowerStatsSnapshot != null ? _buildTowerStatsSnapshot.Length : 0; + public BackpackInventoryData InventorySnapshot => _inventorySnapshot != null + ? InventoryCloneUtility.CloneInventory(_inventorySnapshot) + : null; + public IReadOnlyList ParticipantTowerSnapshot => _participantTowerSnapshot; public void BindCombatCallbacks(Func tryConsumeCoin, Action addCoin) { @@ -128,8 +140,25 @@ namespace GeometryTD.Entity.EntityData position, _initialCoin, _buildTowerStatsSnapshot, + _inventorySnapshot, + _participantTowerSnapshot, _tryConsumeCoin, _addCoin); } + + public void SetParticipantTowerSnapshot(IReadOnlyList participantTowerSnapshot) + { + if (participantTowerSnapshot == null || participantTowerSnapshot.Count <= 0) + { + _participantTowerSnapshot = Array.Empty(); + return; + } + + _participantTowerSnapshot = new TowerItemData[participantTowerSnapshot.Count]; + for (int i = 0; i < participantTowerSnapshot.Count; i++) + { + _participantTowerSnapshot[i] = InventoryCloneUtility.CloneTower(participantTowerSnapshot[i]); + } + } } } diff --git a/Assets/GameMain/Scripts/Entity/EntityLogic/MapEntity.cs b/Assets/GameMain/Scripts/Entity/EntityLogic/MapEntity.cs index 3c96445..43fa1b1 100644 --- a/Assets/GameMain/Scripts/Entity/EntityLogic/MapEntity.cs +++ b/Assets/GameMain/Scripts/Entity/EntityLogic/MapEntity.cs @@ -243,12 +243,6 @@ namespace GeometryTD.Entity private void ConfigureCombatSelectUseCase() { _combatSelectFormUseCase.SetCoinProvider(GetCurrentCoin); - BackpackInventoryData inventorySnapshot = GameEntry.PlayerInventory != null - ? GameEntry.PlayerInventory.GetInventorySnapshot() - : null; - IReadOnlyList participantTowers = GameEntry.PlayerInventory != null - ? GameEntry.PlayerInventory.GetParticipantTowerSnapshot() - : null; _combatSelectUseCaseConfigurator?.Configure( _combatSelectFormUseCase, GetCurrentCoin, @@ -259,8 +253,8 @@ namespace GeometryTD.Entity _destroyGain, _buildTowerCosts, GetCurrentBuildTowerCount(), - inventorySnapshot, - participantTowers); + _mapData != null ? _mapData.InventorySnapshot : null, + _mapData != null ? _mapData.ParticipantTowerSnapshot : null); } private void HandleCombatSelectInput() diff --git a/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatFinishFormUseCase.cs b/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatFinishFormUseCase.cs index 7eee4d7..55eb122 100644 --- a/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatFinishFormUseCase.cs +++ b/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatFinishFormUseCase.cs @@ -45,12 +45,8 @@ namespace GeometryTD.UI { if (!_isSummaryPrepared) { - _defeatedEnemyCount = GameEntry.CombatNode != null - ? Mathf.Max(0, GameEntry.CombatNode.LastDefeatedEnemyCount) - : 0; - _gainedGold = GameEntry.CombatNode != null - ? Mathf.Max(0, GameEntry.CombatNode.LastGainedGold) - : 0; + _defeatedEnemyCount = 0; + _gainedGold = 0; _rewardInventory = null; } diff --git a/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatInfoFormUseCase.cs b/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatInfoFormUseCase.cs index 3fdb665..161f0d9 100644 --- a/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatInfoFormUseCase.cs +++ b/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatInfoFormUseCase.cs @@ -1,9 +1,14 @@ +using System; using GeometryTD.Definition; +using UnityEngine; namespace GeometryTD.UI { public class CombatInfoFormUseCase : IUIUseCase { + private Func _modelProvider; + private Func _tryEndCombat; + public CombatInfoFormRawData CreateInitialModel() { return BuildModel(); @@ -14,43 +19,49 @@ namespace GeometryTD.UI return BuildModel(); } + public void Configure(Func modelProvider, Func tryEndCombat) + { + _modelProvider = modelProvider; + _tryEndCombat = tryEndCombat; + } + public bool TryEndCombat() { - if (GameEntry.CombatNode == null || !GameEntry.CombatNode.CanEndCombat) + if (_tryEndCombat == null) { return false; } - return GameEntry.CombatNode.TryEndCombatByPlayer(); + return _tryEndCombat.Invoke(); } - private static CombatInfoFormRawData BuildModel() + private CombatInfoFormRawData BuildModel() { - if (GameEntry.CombatNode == null) - { - return null; - } - - var level = GameEntry.CombatNode.CurrentLevel; - LevelThemeType themeType = level != null ? level.LevelThemeType : GameEntry.CombatNode.CurrentThemeType; - int levelId = level != null ? level.Id : 0; - int baseHpMax = level != null ? level.BaseHp : 0; - int enemyHpRateMultiplier = ResolveEnemyHpRateMultiplier( - GameEntry.CombatNode.CurrentPhaseIndex, - GameEntry.CombatNode.CurrentLevelPhaseCount); + return _modelProvider != null ? _modelProvider.Invoke() : null; + } + public static CombatInfoFormRawData BuildRawData( + LevelThemeType themeType, + int levelId, + int currentPhaseIndex, + int totalPhaseCount, + int coin, + int baseHp, + int baseHpMax, + bool canEnd) + { return new CombatInfoFormRawData { LevelThemeType = themeType, LevelId = levelId, - CurrentPhaseIndex = GameEntry.CombatNode.CurrentPhaseIndex, - TotalPhaseCount = GameEntry.CombatNode.CurrentLevelPhaseCount, - Coin = GameEntry.CombatNode.CurrentCoin, - BaseHp = GameEntry.CombatNode.CurrentBaseHp, - BaseHpMax = baseHpMax, - EnemyHpRateMultiplier = enemyHpRateMultiplier, + CurrentPhaseIndex = Mathf.Max(0, currentPhaseIndex), + TotalPhaseCount = Mathf.Max(0, totalPhaseCount), + Coin = Mathf.Max(0, coin), + BaseHp = Mathf.Max(0, baseHp), + BaseHpMax = Mathf.Max(0, baseHpMax), + EnemyHpRateMultiplier = ResolveEnemyHpRateMultiplier(currentPhaseIndex, totalPhaseCount), CanPause = true, - CanEnd = GameEntry.CombatNode.CanEndCombat + CanEnd = canEnd }; } @@ -61,7 +72,7 @@ namespace GeometryTD.UI return 1; } - int completedLoopCount = UnityEngine.Mathf.Max(0, (currentPhaseIndex - 1) / totalPhaseCount); + int completedLoopCount = Mathf.Max(0, (currentPhaseIndex - 1) / totalPhaseCount); if (completedLoopCount >= 30) { return int.MaxValue; diff --git a/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatSelectFormUseCase.cs b/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatSelectFormUseCase.cs index 7351736..26e8c20 100644 --- a/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatSelectFormUseCase.cs +++ b/Assets/GameMain/Scripts/UI/Combat/UseCase/CombatSelectFormUseCase.cs @@ -269,12 +269,7 @@ namespace GeometryTD.UI private static int DefaultCoinProvider() { - if (GameEntry.CombatNode == null) - { - return 0; - } - - return Mathf.Max(0, GameEntry.CombatNode.CurrentCoin); + return 0; } private static bool CanExecute(Option option, int currentCoin)