refactor 7:

- 拆分 CombatScheduler,将公用方法与字段拆分为:
    - FlowCoordinator
    - RuntimeContext
- 地图侧现在收口为“MapData 初始快照 + CombatCoinChangedEventArgs 同步 + 独立命令桥接”
This commit is contained in:
2026-03-07 19:42:17 +08:00
parent eb818e6295
commit b38088c3ea
25 changed files with 1031 additions and 786 deletions
@@ -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);
}
}
}