refactor 7:
- 拆分 CombatScheduler,将公用方法与字段拆分为:
- FlowCoordinator
- RuntimeContext
- 地图侧现在收口为“MapData 初始快照 + CombatCoinChangedEventArgs 同步 + 独立命令桥接”
This commit is contained in:
@@ -15,9 +15,6 @@ namespace GeometryTD.Entity.EntityData
|
||||
[SerializeField] private BackpackInventoryData _inventorySnapshot;
|
||||
[SerializeField] private TowerItemData[] _participantTowerSnapshot = Array.Empty<TowerItemData>();
|
||||
|
||||
[NonSerialized] private Func<int, bool> _tryConsumeCoin;
|
||||
[NonSerialized] private Action<int> _addCoin;
|
||||
|
||||
public MapData(int entityId, int levelId, Vector3 position) : this(entityId, 0, levelId, position)
|
||||
{
|
||||
}
|
||||
@@ -36,9 +33,7 @@ namespace GeometryTD.Entity.EntityData
|
||||
int initialCoin,
|
||||
IReadOnlyList<TowerStatsData> buildTowerStatsSnapshot,
|
||||
BackpackInventoryData inventorySnapshot,
|
||||
IReadOnlyList<TowerItemData> participantTowerSnapshot,
|
||||
Func<int, bool> tryConsumeCoin,
|
||||
Action<int> addCoin) : base(entityId, typeId)
|
||||
IReadOnlyList<TowerItemData> participantTowerSnapshot) : base(entityId, typeId)
|
||||
{
|
||||
_levelId = levelId;
|
||||
Position = position;
|
||||
@@ -48,8 +43,6 @@ namespace GeometryTD.Entity.EntityData
|
||||
? InventoryCloneUtility.CloneInventory(inventorySnapshot)
|
||||
: null;
|
||||
SetParticipantTowerSnapshot(participantTowerSnapshot);
|
||||
_tryConsumeCoin = tryConsumeCoin;
|
||||
_addCoin = addCoin;
|
||||
}
|
||||
|
||||
public int LevelId
|
||||
@@ -70,34 +63,6 @@ namespace GeometryTD.Entity.EntityData
|
||||
: null;
|
||||
public IReadOnlyList<TowerItemData> ParticipantTowerSnapshot => _participantTowerSnapshot;
|
||||
|
||||
public void BindCombatCallbacks(Func<int, bool> tryConsumeCoin, Action<int> addCoin)
|
||||
{
|
||||
_tryConsumeCoin = tryConsumeCoin;
|
||||
_addCoin = addCoin;
|
||||
}
|
||||
|
||||
public bool TryConsumeCoin(int coin)
|
||||
{
|
||||
int requiredCoin = Mathf.Max(0, coin);
|
||||
if (requiredCoin <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return _tryConsumeCoin != null && _tryConsumeCoin.Invoke(requiredCoin);
|
||||
}
|
||||
|
||||
public void AddCoin(int coin)
|
||||
{
|
||||
int amount = Mathf.Max(0, coin);
|
||||
if (amount <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_addCoin?.Invoke(amount);
|
||||
}
|
||||
|
||||
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
|
||||
{
|
||||
stats = null;
|
||||
@@ -141,9 +106,7 @@ namespace GeometryTD.Entity.EntityData
|
||||
_initialCoin,
|
||||
_buildTowerStatsSnapshot,
|
||||
_inventorySnapshot,
|
||||
_participantTowerSnapshot,
|
||||
_tryConsumeCoin,
|
||||
_addCoin);
|
||||
_participantTowerSnapshot);
|
||||
}
|
||||
|
||||
public void SetParticipantTowerSnapshot(IReadOnlyList<TowerItemData> participantTowerSnapshot)
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
|
||||
namespace GeometryTD.Entity.EntityData
|
||||
{
|
||||
public sealed class MapEntityLoadContext
|
||||
{
|
||||
public MapEntityLoadContext(MapData initialMapData, Func<int, bool> tryConsumeCoin, Action<int> addCoin)
|
||||
{
|
||||
InitialMapData = initialMapData;
|
||||
TryConsumeCoin = tryConsumeCoin;
|
||||
AddCoin = addCoin;
|
||||
}
|
||||
|
||||
public MapData InitialMapData { get; }
|
||||
public Func<int, bool> TryConsumeCoin { get; }
|
||||
public Action<int> AddCoin { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ba39a6e9c0948b386b8b0189e3541da
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -56,6 +56,17 @@ namespace GeometryTD
|
||||
|
||||
public static void ShowMap(this EntityComponent entityComponent, MapData data, string mapAssetName)
|
||||
{
|
||||
ShowMap(entityComponent, new MapEntityLoadContext(data, null, null), mapAssetName);
|
||||
}
|
||||
|
||||
public static void ShowMap(this EntityComponent entityComponent, MapEntityLoadContext loadContext)
|
||||
{
|
||||
ShowMap(entityComponent, loadContext, null);
|
||||
}
|
||||
|
||||
public static void ShowMap(this EntityComponent entityComponent, MapEntityLoadContext loadContext, string mapAssetName)
|
||||
{
|
||||
MapData data = loadContext?.InitialMapData;
|
||||
if (data == null)
|
||||
{
|
||||
Log.Warning("Map data is invalid.");
|
||||
@@ -64,7 +75,7 @@ namespace GeometryTD
|
||||
|
||||
string resolvedMapAssetName = string.IsNullOrEmpty(mapAssetName) ? data.LevelId.ToString() : mapAssetName;
|
||||
string mapAssetPath = AssetUtility.GetLevelMapAsset(resolvedMapAssetName);
|
||||
entityComponent.ShowEntity(data.Id, typeof(MapEntity), mapAssetPath, "Map", Constant.AssetPriority.MapAsset, data);
|
||||
entityComponent.ShowEntity(data.Id, typeof(MapEntity), mapAssetPath, "Map", Constant.AssetPriority.MapAsset, loadContext);
|
||||
}
|
||||
|
||||
private static void ShowEntity(this EntityComponent entityComponent, Type logicType, string entityGroup,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using GeometryTD.CustomComponent;
|
||||
using GeometryTD.CustomEvent;
|
||||
using GameFramework.Event;
|
||||
using GeometryTD.Map;
|
||||
using GeometryTD.Definition;
|
||||
using GeometryTD.Entity.EntityData;
|
||||
@@ -37,10 +35,8 @@ namespace GeometryTD.Entity
|
||||
private CombatSelectInputService _combatSelectInputService;
|
||||
private TowerPlacementService _towerPlacementService;
|
||||
private TowerSelectionPresenter _towerSelectionPresenter;
|
||||
|
||||
private CombatSelectUseCaseConfigurator _combatSelectUseCaseConfigurator;
|
||||
private int _currentCoin;
|
||||
private bool _isCoinEventSubscribed;
|
||||
private MapCombatRuntimeBridge _combatRuntimeBridge;
|
||||
|
||||
public IReadOnlyList<Vector3Int> PathCells => _mapTopologyService != null
|
||||
? _mapTopologyService.PathCells
|
||||
@@ -110,22 +106,21 @@ namespace GeometryTD.Entity
|
||||
InitializeMapTopologyService();
|
||||
InitializeTowerPlacementService();
|
||||
InitializeTowerSelectionPresenter();
|
||||
InitializeCombatRuntimeBridge();
|
||||
}
|
||||
|
||||
protected override void OnShow(object userData)
|
||||
{
|
||||
base.OnShow(userData);
|
||||
|
||||
_mapData = userData as MapData;
|
||||
MapEntityLoadContext loadContext = ResolveLoadContext(userData);
|
||||
_mapData = loadContext?.InitialMapData;
|
||||
if (_mapData == null)
|
||||
{
|
||||
Log.Warning("MapData is invalid for map entity '{0}'.", Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
_currentCoin = Mathf.Max(0, _mapData.InitialCoin);
|
||||
SubscribeCombatEvents();
|
||||
}
|
||||
|
||||
base.OnShow(_mapData);
|
||||
|
||||
_combatRuntimeBridge?.Initialize(loadContext, name);
|
||||
|
||||
RefreshTiles();
|
||||
ConfigureCombatSelectUseCase();
|
||||
@@ -134,7 +129,7 @@ namespace GeometryTD.Entity
|
||||
|
||||
protected override void OnHide(bool isShutdown, object userData)
|
||||
{
|
||||
UnsubscribeCombatEvents();
|
||||
_combatRuntimeBridge?.Reset();
|
||||
HideCombatSelectForm();
|
||||
_towerPlacementService?.HideAndClearAllPlacedTowers();
|
||||
ClearSelectionState();
|
||||
@@ -240,6 +235,14 @@ namespace GeometryTD.Entity
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeCombatRuntimeBridge()
|
||||
{
|
||||
if (_combatRuntimeBridge == null)
|
||||
{
|
||||
_combatRuntimeBridge = new MapCombatRuntimeBridge();
|
||||
}
|
||||
}
|
||||
|
||||
private void ConfigureCombatSelectUseCase()
|
||||
{
|
||||
_combatSelectFormUseCase.SetCoinProvider(GetCurrentCoin);
|
||||
@@ -257,6 +260,21 @@ namespace GeometryTD.Entity
|
||||
_mapData != null ? _mapData.ParticipantTowerSnapshot : null);
|
||||
}
|
||||
|
||||
private MapEntityLoadContext ResolveLoadContext(object userData)
|
||||
{
|
||||
if (userData is MapEntityLoadContext loadContext)
|
||||
{
|
||||
return loadContext;
|
||||
}
|
||||
|
||||
if (userData is MapData legacyMapData)
|
||||
{
|
||||
return new MapEntityLoadContext(legacyMapData, null, null);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void HandleCombatSelectInput()
|
||||
{
|
||||
if (!_enableCombatSelectInput || !Input.GetMouseButtonDown(0))
|
||||
@@ -379,38 +397,6 @@ namespace GeometryTD.Entity
|
||||
GameEntry.UIRouter.CloseUI(UIFormType.CombatSelectForm);
|
||||
}
|
||||
|
||||
private void SubscribeCombatEvents()
|
||||
{
|
||||
if (_isCoinEventSubscribed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.Event.Subscribe(CombatCoinChangedEventArgs.EventId, OnCombatCoinChanged);
|
||||
_isCoinEventSubscribed = true;
|
||||
}
|
||||
|
||||
private void UnsubscribeCombatEvents()
|
||||
{
|
||||
if (!_isCoinEventSubscribed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
GameEntry.Event.Unsubscribe(CombatCoinChangedEventArgs.EventId, OnCombatCoinChanged);
|
||||
_isCoinEventSubscribed = false;
|
||||
}
|
||||
|
||||
private void OnCombatCoinChanged(object sender, GameEventArgs e)
|
||||
{
|
||||
if (e is not CombatCoinChangedEventArgs args)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_currentCoin = Mathf.Max(0, args.CurrentCoin);
|
||||
}
|
||||
|
||||
private int GetCurrentBuildTowerCount()
|
||||
{
|
||||
if (_mapData == null)
|
||||
@@ -434,12 +420,12 @@ namespace GeometryTD.Entity
|
||||
return false;
|
||||
}
|
||||
|
||||
return _mapData.TryConsumeCoin(requiredCoin);
|
||||
return _combatRuntimeBridge != null && _combatRuntimeBridge.TryConsumeCoin(requiredCoin);
|
||||
}
|
||||
|
||||
private int GetCurrentCoin()
|
||||
{
|
||||
return Mathf.Max(0, _currentCoin);
|
||||
return Mathf.Max(0, _combatRuntimeBridge != null ? _combatRuntimeBridge.CurrentCoin : 0);
|
||||
}
|
||||
|
||||
private void AddCoin(int coin)
|
||||
@@ -450,7 +436,7 @@ namespace GeometryTD.Entity
|
||||
return;
|
||||
}
|
||||
|
||||
_mapData?.AddCoin(amount);
|
||||
_combatRuntimeBridge?.AddCoin(amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user