refactor 5:

- MapData.cs 现在会携带战斗初始上下文:
    - InitialCoin
    - 建塔 TowerStatsData 快照
    - TryConsumeCoin / AddCoin 运行时回调
- CombatLoadingState.cs 负责从 CombatInRunResourceManager 读取 coin 和 build stats 快照,组装 MapData 后再交给加载链。
- CombatLoadSession.cs 改成接收外部构造好的 MapData,不再自己只塞一个 LevelId。
- CombatScheduler.cs 不再在 Start() 里直接发起地图加载,加载细节回到 CombatLoadingState。
- MapEntity.cs 已经不再直接读 GameEntry.CombatNode 的 coin / build count / build stats,也不再通过它做 coin 读写:
    - 初始 coin 和 build stats 从 MapData 读取
    - 后续 coin 通过 CombatCoinChangedEventArgs 同步
    - 建塔/升级/拆塔时的 coin 变更通过 MapData 注入回调执行
This commit is contained in:
2026-03-07 15:12:18 +08:00
parent ccb4738b96
commit ca7b2f2dca
5 changed files with 213 additions and 22 deletions
@@ -45,7 +45,7 @@ namespace GeometryTD.CustomComponent
_currentMap = null;
}
public bool StartLoading(DRLevel level, out string errorMessage)
public bool StartLoading(DRLevel level, MapData mapData, out string errorMessage)
{
errorMessage = null;
if (_entity == null)
@@ -54,7 +54,7 @@ namespace GeometryTD.CustomComponent
return false;
}
if (!TryShowMap(level, out errorMessage))
if (!TryShowMap(level, mapData, out errorMessage))
{
return false;
}
@@ -224,7 +224,7 @@ namespace GeometryTD.CustomComponent
}
}
private bool TryShowMap(DRLevel level, out string errorMessage)
private bool TryShowMap(DRLevel level, MapData mapData, out string errorMessage)
{
errorMessage = null;
if (level == null)
@@ -242,7 +242,10 @@ namespace GeometryTD.CustomComponent
}
_loadingMapEntityId = _entity.GenerateSerialId();
_entity.ShowMap(new MapData(_loadingMapEntityId, level.Id, Vector3.zero), mapAssetName);
MapData resolvedMapData = mapData != null
? mapData.CloneForEntity(_loadingMapEntityId, Vector3.zero)
: new MapData(_loadingMapEntityId, level.Id, Vector3.zero);
_entity.ShowMap(resolvedMapData, mapAssetName);
return true;
}
@@ -274,4 +277,4 @@ namespace GeometryTD.CustomComponent
_isCombatInfoFormReady = false;
}
}
}
}
@@ -120,11 +120,6 @@ namespace GeometryTD.CustomComponent
return HandleStartFailure($"CombatScheduler start failed. Level '{level.Id}' has no phase data.");
}
if (!_loadSession.StartLoading(level, out string loadError))
{
return HandleStartFailure($"CombatScheduler start failed. {loadError}");
}
ChangeState(new CombatLoadingState(this));
Log.Info(
"CombatScheduler started. Level={0}, PhaseCount={1}.",
@@ -1,3 +1,8 @@
using System.Collections.Generic;
using GeometryTD.Definition;
using GeometryTD.Entity.EntityData;
using UnityEngine;
namespace GeometryTD.CustomComponent
{
public partial class CombatScheduler
@@ -8,6 +13,21 @@ namespace GeometryTD.CustomComponent
{
}
public override void OnEnter()
{
if (Scheduler._currentLevel == null)
{
Scheduler.EnterFailureFallback("Combat loading failed. Current level is null.");
return;
}
MapData mapData = BuildMapData();
if (!Scheduler._loadSession.StartLoading(Scheduler._currentLevel, mapData, out string errorMessage))
{
Scheduler.EnterFailureFallback($"Combat loading failed. {errorMessage}");
}
}
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
_ = elapseSeconds;
@@ -20,6 +40,29 @@ namespace GeometryTD.CustomComponent
Scheduler.TryBeginNextPhase();
}
private MapData BuildMapData()
{
List<TowerStatsData> buildTowerStatsSnapshot = new();
for (int i = 0; i < Scheduler._combatInRunResourceManager.CurrentBuildTowerCount; i++)
{
if (Scheduler._combatInRunResourceManager.TryGetBuildTowerStats(i, out TowerStatsData stats) &&
stats != null)
{
buildTowerStatsSnapshot.Add(stats);
}
}
return new MapData(
entityId: 0,
typeId: 0,
levelId: Scheduler._currentLevel.Id,
position: Vector3.zero,
initialCoin: Scheduler._combatInRunResourceManager.CurrentCoin,
buildTowerStatsSnapshot: buildTowerStatsSnapshot,
tryConsumeCoin: Scheduler.TryConsumeCoin,
addCoin: Scheduler.AddCoin);
}
}
}
}