规范类命名

This commit is contained in:
SepComet
2026-03-08 17:00:21 +08:00
parent 47ed27bebb
commit 548bc77ba6
35 changed files with 417 additions and 384 deletions
@@ -45,7 +45,7 @@ namespace GeometryTD.CustomComponent
_currentMap = null;
}
public bool StartLoading(DRLevel level, MapEntityLoadContext mapLoadContext, ICombatSchedulerHost schedulerHost, out string errorMessage)
public bool StartLoading(DRLevel level, MapEntityLoadContext mapLoadContext, ICombatSchedulerPort schedulerPort, out string errorMessage)
{
errorMessage = null;
if (_entity == null)
@@ -59,7 +59,7 @@ namespace GeometryTD.CustomComponent
return false;
}
if (!TryOpenCombatInfoForm(schedulerHost, out errorMessage))
if (!TryOpenCombatInfoForm(schedulerPort, out errorMessage))
{
return false;
}
@@ -257,7 +257,7 @@ namespace GeometryTD.CustomComponent
return true;
}
private bool TryOpenCombatInfoForm(ICombatSchedulerHost schedulerHost, out string errorMessage)
private bool TryOpenCombatInfoForm(ICombatSchedulerPort schedulerPort, out string errorMessage)
{
errorMessage = null;
if (_combatInfoFormUseCase == null)
@@ -267,9 +267,9 @@ namespace GeometryTD.CustomComponent
}
_combatInfoFormUseCase.Configure(
() => BuildCombatInfoFormRawData(schedulerHost),
() => schedulerHost != null && schedulerHost.CanEndCombat && schedulerHost.TryEndCombatByPlayer(),
() => schedulerHost != null && schedulerHost.TryDebugFail("Manual debug fail from CombatInfoForm."));
() => BuildCombatInfoFormRawData(schedulerPort),
() => schedulerPort != null && schedulerPort.CanEndCombat && schedulerPort.TryEndCombatByPlayer(),
() => schedulerPort != null && schedulerPort.TryDebugFail("Manual debug fail from CombatInfoForm."));
int? serialId = GameEntry.UIRouter.OpenUI(UIFormType.CombatInfoForm);
if (!serialId.HasValue)
@@ -283,26 +283,26 @@ namespace GeometryTD.CustomComponent
return true;
}
private static CombatInfoFormRawData BuildCombatInfoFormRawData(ICombatSchedulerHost schedulerHost)
private static CombatInfoFormRawData BuildCombatInfoFormRawData(ICombatSchedulerPort schedulerPort)
{
if (schedulerHost == null)
if (schedulerPort == null)
{
return null;
}
DRLevel level = schedulerHost.CurrentLevel;
DRLevel level = schedulerPort.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,
schedulerHost.DisplayPhaseIndex,
schedulerHost.PhaseCount,
schedulerHost.CurrentCoin,
schedulerHost.CurrentBaseHp,
schedulerPort.DisplayPhaseIndex,
schedulerPort.PhaseCount,
schedulerPort.CurrentCoin,
schedulerPort.CurrentBaseHp,
baseHpMax,
schedulerHost.CanEndCombat);
schedulerPort.CanEndCombat);
}
private void CloseCombatInfoForm()
@@ -7,7 +7,7 @@ using UnityEngine;
namespace GeometryTD.CustomComponent
{
internal sealed class CombatInRunResourceManager
internal sealed class CombatRunResourceStore
{
private readonly List<TowerStatsData> _buildTowerStatsSnapshot = new();
private readonly List<TowerItemData> _participantTowerSnapshot = new();
@@ -11,58 +11,58 @@ using UnityGameFramework.Runtime;
namespace GeometryTD.CustomComponent
{
public partial class CombatScheduler : ICombatSchedulerHost
public partial class CombatScheduler : ICombatSchedulerPort
{
private readonly CombatSchedulerRuntimeContext _context = new();
private readonly CombatSchedulerFlowCoordinator _flowCoordinator;
private readonly CombatSchedulerRuntime _runtime = new();
private readonly CombatSchedulerCoordinator _coordinator;
private bool _initialized;
public CombatScheduler()
{
_flowCoordinator = new CombatSchedulerFlowCoordinator(this, _context);
_coordinator = new CombatSchedulerCoordinator(this, _runtime);
}
public bool IsRunning =>
_context.CurrentState is CombatLoadingState or CombatRunningPhaseState or CombatWaitingForPhaseEndState;
_runtime.CurrentState is CombatLoadingState or CombatRunningPhaseState or CombatWaitingForPhaseEndState;
public bool IsCompleted => _context.IsCompleted;
public DRLevel CurrentLevel => _context.CurrentLevel;
public DRLevelPhase CurrentPhase => _context.PhaseLoopRuntime.CurrentPhase;
public MapEntity CurrentMap => _context.LoadSession.CurrentMap;
public int DisplayPhaseIndex => _context.PhaseLoopRuntime.DisplayPhaseIndex;
public int PhaseCount => _context.PhaseLoopRuntime.PhaseCount;
public bool CanEndCombat => _context.PhaseLoopRuntime.CanEndCombat;
public int CurrentCoin => _context.CombatInRunResourceManager.CurrentCoin;
public int CurrentGold => _context.CombatInRunResourceManager.CurrentGold;
public int CurrentBaseHp => _context.CombatInRunResourceManager.CurrentBaseHp;
public int CurrentBuildTowerCount => _context.CombatInRunResourceManager.CurrentBuildTowerCount;
public int DefeatedEnemyCount => _context.EnemyManager.DefeatedEnemyCount;
public int GainedCoin => _context.CombatInRunResourceManager.GainedCoin;
public int GainedGold => _context.CombatInRunResourceManager.GainedGold;
public bool IsCompleted => _runtime.IsCompleted;
public DRLevel CurrentLevel => _runtime.CurrentLevel;
public DRLevelPhase CurrentPhase => _runtime.PhaseLoopRuntime.CurrentPhase;
public MapEntity CurrentMap => _runtime.LoadSession.CurrentMap;
public int DisplayPhaseIndex => _runtime.PhaseLoopRuntime.DisplayPhaseIndex;
public int PhaseCount => _runtime.PhaseLoopRuntime.PhaseCount;
public bool CanEndCombat => _runtime.PhaseLoopRuntime.CanEndCombat;
public int CurrentCoin => _runtime.CombatRunResourceStore.CurrentCoin;
public int CurrentGold => _runtime.CombatRunResourceStore.CurrentGold;
public int CurrentBaseHp => _runtime.CombatRunResourceStore.CurrentBaseHp;
public int CurrentBuildTowerCount => _runtime.CombatRunResourceStore.CurrentBuildTowerCount;
public int DefeatedEnemyCount => _runtime.EnemyManager.DefeatedEnemyCount;
public int GainedCoin => _runtime.CombatRunResourceStore.GainedCoin;
public int GainedGold => _runtime.CombatRunResourceStore.GainedGold;
public void OnInit(Action<bool> combatEndedCallback)
{
_context.CombatEndedCallback = combatEndedCallback;
_runtime.CombatEndedCallback = combatEndedCallback;
if (!_initialized)
{
_context.Entity = GameEntry.Entity;
_context.EventBridge.Bind(
_runtime.Entity = GameEntry.Entity;
_runtime.EventBridge.Bind(
OnShowEntitySuccess,
OnShowEntityFailure,
OnHideEntityComplete,
OnOpenUIFormSuccess,
OnOpenUIFormFailure,
OnCloseUIFormComplete);
_context.EnemyManager.OnInit(this);
_context.LoadSession.OnInit(_context.Entity);
_flowCoordinator.EnsureCombatFinishFormUseCaseBound();
_flowCoordinator.EnsureRewardSelectFormUseCaseBound();
_runtime.EnemyManager.OnInit(this);
_runtime.LoadSession.OnInit(_runtime.Entity);
_coordinator.EnsureCombatFinishFormUseCaseBound();
_coordinator.EnsureRewardSelectFormUseCaseBound();
_initialized = true;
}
_flowCoordinator.ResetRuntime();
_coordinator.ResetRuntime();
}
public bool Start(
@@ -74,37 +74,37 @@ namespace GeometryTD.CustomComponent
RunNodeType nodeType = RunNodeType.None,
int sequenceIndex = -1)
{
if (!_initialized || _context.Entity == null)
if (!_initialized || _runtime.Entity == null)
{
return _flowCoordinator.HandleStartFailure("CombatScheduler start failed. Runtime is not initialized.");
return _coordinator.HandleStartFailure("CombatScheduler start failed. Runtime is not initialized.");
}
if (level == null || phases == null || phases.Count <= 0)
{
return _flowCoordinator.HandleStartFailure("CombatScheduler start failed. Invalid level or phase data.");
return _coordinator.HandleStartFailure("CombatScheduler start failed. Invalid level or phase data.");
}
_flowCoordinator.CleanupAllCombatEntities();
_flowCoordinator.CloseCombatFinishForm();
_flowCoordinator.CloseRewardSelectForm();
_flowCoordinator.CloseDialogForm();
_context.EnemyManager.EndPhase();
_context.EnemyManager.ResetCombatStats();
_flowCoordinator.ResetRuntime();
_context.IsFinishAsVictory = true;
_coordinator.CleanupAllCombatEntities();
_coordinator.CloseCombatFinishForm();
_coordinator.CloseRewardSelectForm();
_coordinator.CloseDialogForm();
_runtime.EnemyManager.EndPhase();
_runtime.EnemyManager.ResetCombatStats();
_coordinator.ResetRuntime();
_runtime.IsFinishAsVictory = true;
_context.CurrentLevel = level;
_context.RunId = runId;
_context.NodeId = nodeId;
_context.NodeType = nodeType;
_context.SequenceIndex = sequenceIndex;
_context.CombatInRunResourceManager.InitializeForCombat(level);
_runtime.CurrentLevel = level;
_runtime.RunId = runId;
_runtime.NodeId = nodeId;
_runtime.NodeType = nodeType;
_runtime.SequenceIndex = sequenceIndex;
_runtime.CombatRunResourceStore.InitializeForCombat(level);
for (int i = 0; i < phases.Count; i++)
{
DRLevelPhase phase = phases[i];
if (phase != null)
{
_context.PhaseBuffer.Add(phase);
_runtime.PhaseBuffer.Add(phase);
}
}
@@ -112,27 +112,27 @@ namespace GeometryTD.CustomComponent
{
foreach (var pair in spawnEntriesByPhaseId)
{
_context.SpawnEntriesByPhaseId[pair.Key] = pair.Value;
_runtime.SpawnEntriesByPhaseId[pair.Key] = pair.Value;
}
}
_context.PhaseLoopRuntime.SetPhases(_context.PhaseBuffer);
if (_context.PhaseLoopRuntime.PhaseCount <= 0)
_runtime.PhaseLoopRuntime.SetPhases(_runtime.PhaseBuffer);
if (_runtime.PhaseLoopRuntime.PhaseCount <= 0)
{
return _flowCoordinator.HandleStartFailure($"CombatScheduler start failed. Level '{level.Id}' has no phase data.");
return _coordinator.HandleStartFailure($"CombatScheduler start failed. Level '{level.Id}' has no phase data.");
}
ChangeState(new CombatLoadingState(_context, _flowCoordinator));
ChangeState(new CombatLoadingState(_runtime, _coordinator));
Log.Info(
"CombatScheduler started. Level={0}, PhaseCount={1}.",
_context.CurrentLevel.Id,
_context.PhaseLoopRuntime.PhaseCount);
_runtime.CurrentLevel.Id,
_runtime.PhaseLoopRuntime.PhaseCount);
return true;
}
public void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
_context.CurrentState?.OnUpdate(elapseSeconds, realElapseSeconds);
_runtime.CurrentState?.OnUpdate(elapseSeconds, realElapseSeconds);
}
public void OnDestroy()
@@ -142,33 +142,33 @@ namespace GeometryTD.CustomComponent
return;
}
_context.CurrentState?.OnExit();
_context.CurrentState?.OnDestroy();
_context.CurrentState = null;
_flowCoordinator.CleanupAllCombatEntities();
_flowCoordinator.CloseCombatFinishForm();
_flowCoordinator.CloseRewardSelectForm();
_flowCoordinator.CloseDialogForm();
_context.EnemyManager.OnDestroy();
_flowCoordinator.ResetRuntime();
_context.EventBridge.Unbind();
_context.CombatFinishFormUseCase = null;
_context.RewardSelectFormUseCase = null;
_context.CombatEndedCallback = null;
_runtime.CurrentState?.OnExit();
_runtime.CurrentState?.OnDestroy();
_runtime.CurrentState = null;
_coordinator.CleanupAllCombatEntities();
_coordinator.CloseCombatFinishForm();
_coordinator.CloseRewardSelectForm();
_coordinator.CloseDialogForm();
_runtime.EnemyManager.OnDestroy();
_coordinator.ResetRuntime();
_runtime.EventBridge.Unbind();
_runtime.CombatFinishFormUseCase = null;
_runtime.RewardSelectFormUseCase = null;
_runtime.CombatEndedCallback = null;
_context.Entity = null;
_runtime.Entity = null;
_initialized = false;
}
public bool TryEndCombatByPlayer()
{
if (_context.CurrentState is not CombatRunningPhaseState &&
_context.CurrentState is not CombatWaitingForPhaseEndState)
if (_runtime.CurrentState is not CombatRunningPhaseState &&
_runtime.CurrentState is not CombatWaitingForPhaseEndState)
{
return false;
}
return _context.PhaseLoopRuntime.TryRequestEndCombat();
return _runtime.PhaseLoopRuntime.TryRequestEndCombat();
}
public void OnEnemyReachedBase(DREnemy enemy)
@@ -184,7 +184,7 @@ namespace GeometryTD.CustomComponent
return;
}
_flowCoordinator.ApplyBaseDamage(resolvedBaseDamage);
_coordinator.ApplyBaseDamage(resolvedBaseDamage);
}
public void OnEnemyDefeated(DREnemy enemy)
@@ -194,18 +194,18 @@ namespace GeometryTD.CustomComponent
return;
}
EnemyDropResolveContext context = new(
EnemyDropContext context = new(
enemy,
_context.PhaseLoopRuntime.DisplayPhaseIndex,
_flowCoordinator.ResolveCurrentThemeType());
EnemyDropResolveResult result = _context.EnemyDropResolver.Resolve(context);
_context.CombatInRunResourceManager.AddEnemyDefeatedReward(result.Coin, result.Gold);
_context.CombatInRunResourceManager.AddEnemyDefeatedLoot(result.LootItem);
_runtime.PhaseLoopRuntime.DisplayPhaseIndex,
_coordinator.ResolveCurrentThemeType());
EnemyDropResult result = _runtime.EnemyDropResolver.Resolve(context);
_runtime.CombatRunResourceStore.AddEnemyDefeatedReward(result.Coin, result.Gold);
_runtime.CombatRunResourceStore.AddEnemyDefeatedLoot(result.LootItem);
}
public bool OnCombatFinishReturnRequested()
{
if (_context.CurrentState is not CombatWaitingForReturnState waitingForReturnState)
if (_runtime.CurrentState is not CombatWaitingForReturnState waitingForReturnState)
{
return false;
}
@@ -216,68 +216,68 @@ namespace GeometryTD.CustomComponent
public bool TryConsumeCoin(int coin)
{
return _context.CombatInRunResourceManager.TryConsumeCoin(coin);
return _runtime.CombatRunResourceStore.TryConsumeCoin(coin);
}
public void AddCoin(int coin)
{
_context.CombatInRunResourceManager.AddCoin(coin);
_runtime.CombatRunResourceStore.AddCoin(coin);
}
public bool TryGetBuildTowerStats(int buildIndex, out TowerStatsData stats)
{
return _context.CombatInRunResourceManager.TryGetBuildTowerStats(buildIndex, out stats);
return _runtime.CombatRunResourceStore.TryGetBuildTowerStats(buildIndex, out stats);
}
public bool TryDebugFail(string errorMessage)
{
if (_context.IsCompleted || _context.CurrentState == null || _context.CurrentState is CombatFailedState)
if (_runtime.IsCompleted || _runtime.CurrentState == null || _runtime.CurrentState is CombatFailedState)
{
return false;
}
_flowCoordinator.EnterFailureFallback(string.IsNullOrWhiteSpace(errorMessage)
_coordinator.EnterFailureFallback(string.IsNullOrWhiteSpace(errorMessage)
? "Manual debug fail."
: errorMessage);
return _context.CurrentState is CombatFailedState;
return _runtime.CurrentState is CombatFailedState;
}
void ICombatSchedulerHost.ChangeState(CombatStateBase nextState)
void ICombatSchedulerPort.ChangeState(CombatStateBase nextState)
{
ChangeState(nextState);
}
internal void ChangeState(CombatStateBase nextState)
{
if (ReferenceEquals(_context.CurrentState, nextState))
if (ReferenceEquals(_runtime.CurrentState, nextState))
{
return;
}
_context.CurrentState?.OnExit();
_context.CurrentState?.OnDestroy();
_context.CurrentState = nextState;
_context.CurrentState?.OnInit();
_context.CurrentState?.OnEnter();
_runtime.CurrentState?.OnExit();
_runtime.CurrentState?.OnDestroy();
_runtime.CurrentState = nextState;
_runtime.CurrentState?.OnInit();
_runtime.CurrentState?.OnEnter();
}
#region Event Handlers
private void OnShowEntitySuccess(ShowEntitySuccessEventArgs args)
{
var status = _context.LoadSession.HandleShowEntitySuccess(args, out string errorMessage);
var status = _runtime.LoadSession.HandleShowEntitySuccess(args, out string errorMessage);
if (status == CombatLoadSession.EventHandleStatus.Failed)
{
_flowCoordinator.EnterFailureFallback(errorMessage);
_coordinator.EnterFailureFallback(errorMessage);
return;
}
if (status == CombatLoadSession.EventHandleStatus.Succeeded)
{
MapEntity map = _context.LoadSession.CurrentMap;
MapEntity map = _runtime.LoadSession.CurrentMap;
Log.Info(
"Map ready. LevelId={0}, PathCells={1}, FoundationCells={2}, Spawners={3}, House={4}.",
_context.CurrentLevel != null ? _context.CurrentLevel.Id : 0,
_runtime.CurrentLevel != null ? _runtime.CurrentLevel.Id : 0,
map.PathCells.Count,
map.FoundationCells.Count,
map.Spawners.Length,
@@ -287,39 +287,39 @@ namespace GeometryTD.CustomComponent
private void OnShowEntityFailure(ShowEntityFailureEventArgs args)
{
var status = _context.LoadSession.HandleShowEntityFailure(args, out string errorMessage);
var status = _runtime.LoadSession.HandleShowEntityFailure(args, out string errorMessage);
if (status == CombatLoadSession.EventHandleStatus.Failed)
{
_flowCoordinator.EnterFailureFallback(errorMessage);
_coordinator.EnterFailureFallback(errorMessage);
}
}
private void OnHideEntityComplete(HideEntityCompleteEventArgs args)
{
_context.LoadSession.HandleHideEntityComplete(args);
_runtime.LoadSession.HandleHideEntityComplete(args);
}
private void OnOpenUIFormSuccess(OpenUIFormSuccessEventArgs args)
{
var status = _context.LoadSession.HandleOpenUIFormSuccess(args, out string errorMessage);
var status = _runtime.LoadSession.HandleOpenUIFormSuccess(args, out string errorMessage);
if (status == CombatLoadSession.EventHandleStatus.Failed)
{
_flowCoordinator.EnterFailureFallback(errorMessage);
_coordinator.EnterFailureFallback(errorMessage);
}
}
private void OnOpenUIFormFailure(OpenUIFormFailureEventArgs args)
{
var status = _context.LoadSession.HandleOpenUIFormFailure(args, out string errorMessage);
var status = _runtime.LoadSession.HandleOpenUIFormFailure(args, out string errorMessage);
if (status == CombatLoadSession.EventHandleStatus.Failed)
{
_flowCoordinator.EnterFailureFallback(errorMessage);
_coordinator.EnterFailureFallback(errorMessage);
}
}
private void OnCloseUIFormComplete(CloseUIFormCompleteEventArgs args)
{
_context.LoadSession.HandleCloseUIFormComplete(args);
_runtime.LoadSession.HandleCloseUIFormComplete(args);
}
#endregion
@@ -9,21 +9,21 @@ using UnityGameFramework.Runtime;
namespace GeometryTD.CustomComponent
{
internal sealed class CombatSchedulerFlowCoordinator
internal sealed class CombatSchedulerCoordinator
{
private readonly ICombatSchedulerHost _schedulerHost;
private readonly CombatSchedulerRuntimeContext _context;
public ICombatSchedulerHost Host => _schedulerHost;
private readonly ICombatSchedulerPort _schedulerPort;
private readonly CombatSchedulerRuntime _runtime;
public ICombatSchedulerPort Port => _schedulerPort;
public CombatSchedulerFlowCoordinator(ICombatSchedulerHost schedulerHost, CombatSchedulerRuntimeContext context)
public CombatSchedulerCoordinator(ICombatSchedulerPort schedulerPort, CombatSchedulerRuntime runtime)
{
_schedulerHost = schedulerHost;
_context = context;
_schedulerPort = schedulerPort;
_runtime = runtime;
}
public void ChangeState(CombatStateBase nextState)
{
_schedulerHost.ChangeState(nextState);
_schedulerPort.ChangeState(nextState);
}
public int ResolveEnemyHpRateMultiplier(int displayPhaseIndex, int phaseCount)
@@ -44,40 +44,40 @@ namespace GeometryTD.CustomComponent
public void ResetRuntime()
{
_context.CurrentState = null;
_context.PhaseBuffer.Clear();
_context.SpawnEntriesByPhaseId.Clear();
_context.PhaseLoopRuntime.Reset();
_context.LoadSession.Reset();
_context.CombatInRunResourceManager.Reset();
_context.EnemyDropResolver.Reset();
_context.SettlementContext = null;
_context.CurrentLevel = null;
_context.IsFinishAsVictory = true;
_context.IsCompleted = false;
_context.NodeEnterFired = false;
_context.RunId = null;
_context.NodeId = 0;
_context.NodeType = RunNodeType.None;
_context.SequenceIndex = -1;
_runtime.CurrentState = null;
_runtime.PhaseBuffer.Clear();
_runtime.SpawnEntriesByPhaseId.Clear();
_runtime.PhaseLoopRuntime.Reset();
_runtime.LoadSession.Reset();
_runtime.CombatRunResourceStore.Reset();
_runtime.EnemyDropResolver.Reset();
_runtime.SettlementContext = null;
_runtime.CurrentLevel = null;
_runtime.IsFinishAsVictory = true;
_runtime.IsCompleted = false;
_runtime.NodeEnterFired = false;
_runtime.RunId = null;
_runtime.NodeId = 0;
_runtime.NodeType = RunNodeType.None;
_runtime.SequenceIndex = -1;
}
public void CleanupAllCombatEntities()
{
_context.LoadSession.Cleanup();
_context.EnemyManager.CleanupTrackedEnemies();
_runtime.LoadSession.Cleanup();
_runtime.EnemyManager.CleanupTrackedEnemies();
}
public void EnsureCombatFinishFormUseCaseBound()
{
_context.CombatFinishFormUseCase ??= new CombatFinishFormUseCase(_schedulerHost);
GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatFinishForm, _context.CombatFinishFormUseCase);
_runtime.CombatFinishFormUseCase ??= new CombatFinishFormUseCase(_schedulerPort);
GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatFinishForm, _runtime.CombatFinishFormUseCase);
}
public void EnsureRewardSelectFormUseCaseBound()
{
_context.RewardSelectFormUseCase ??= new RewardSelectFormUseCase();
GameEntry.UIRouter.BindUIUseCase(UIFormType.RewardSelectForm, _context.RewardSelectFormUseCase);
_runtime.RewardSelectFormUseCase ??= new RewardSelectFormUseCase();
GameEntry.UIRouter.BindUIUseCase(UIFormType.RewardSelectForm, _runtime.RewardSelectFormUseCase);
}
public void OpenCombatFailureDialog(string errorMessage)
@@ -96,30 +96,30 @@ namespace GeometryTD.CustomComponent
public bool TryBeginNextPhase()
{
if (!_context.PhaseLoopRuntime.TryEnterNextPhase(out DRLevelPhase nextPhase))
if (!_runtime.PhaseLoopRuntime.TryEnterNextPhase(out DRLevelPhase nextPhase))
{
_schedulerHost.ChangeState(new CombatSettlementState(_context, this, true));
_schedulerPort.ChangeState(new CombatSettlementState(_runtime, this, true));
return false;
}
_context.SpawnEntriesByPhaseId.TryGetValue(nextPhase.Id, out IReadOnlyList<DRLevelSpawnEntry> spawnEntries);
_schedulerHost.ChangeState(new CombatRunningPhaseState(_context, this, nextPhase, spawnEntries));
_runtime.SpawnEntriesByPhaseId.TryGetValue(nextPhase.Id, out IReadOnlyList<DRLevelSpawnEntry> spawnEntries);
_schedulerPort.ChangeState(new CombatRunningPhaseState(_runtime, this, nextPhase, spawnEntries));
return true;
}
public void EnterWaitingForPhaseEnd()
{
_schedulerHost.ChangeState(new CombatWaitingForPhaseEndState(_context, this));
_schedulerPort.ChangeState(new CombatWaitingForPhaseEndState(_runtime, this));
}
public void CompleteCurrentPhase()
{
_context.EnemyManager.EndPhase();
_runtime.EnemyManager.EndPhase();
Log.Info(
"CombatScheduler phase completed. Level={0}, Phase={1}, Elapsed={2:F2}s.",
_context.CurrentLevel != null ? _context.CurrentLevel.Id : 0,
_context.PhaseLoopRuntime.CurrentPhase != null ? _context.PhaseLoopRuntime.CurrentPhase.Id : 0,
_context.PhaseLoopRuntime.CurrentPhaseElapsed);
_runtime.CurrentLevel != null ? _runtime.CurrentLevel.Id : 0,
_runtime.PhaseLoopRuntime.CurrentPhase != null ? _runtime.PhaseLoopRuntime.CurrentPhase.Id : 0,
_runtime.PhaseLoopRuntime.CurrentPhaseElapsed);
TryBeginNextPhase();
}
@@ -132,7 +132,7 @@ namespace GeometryTD.CustomComponent
return true;
}
if (_context.PhaseLoopRuntime.IsEndCombatRequested)
if (_runtime.PhaseLoopRuntime.IsEndCombatRequested)
{
isVictory = true;
return true;
@@ -144,30 +144,30 @@ namespace GeometryTD.CustomComponent
public void OnFullBaseHpRewardSelected(RewardSelectItemRawData selectedReward)
{
if (_context.CurrentState is not CombatRewardSelectionState || _context.SettlementContext == null)
if (_runtime.CurrentState is not CombatRewardSelectionState || _runtime.SettlementContext == null)
{
return;
}
_context.SettlementFlowService.ApplySelectedReward(_context.SettlementContext, selectedReward);
_schedulerHost.ChangeState(new CombatFinishFormState(_context, this));
_runtime.CombatSettlementService.ApplySelectedReward(_runtime.SettlementContext, selectedReward);
_schedulerPort.ChangeState(new CombatFinishFormState(_runtime, this));
}
public void OnFullBaseHpRewardGiveUp()
{
if (_context.CurrentState is not CombatRewardSelectionState || _context.SettlementContext == null)
if (_runtime.CurrentState is not CombatRewardSelectionState || _runtime.SettlementContext == null)
{
return;
}
_schedulerHost.ChangeState(new CombatFinishFormState(_context, this));
_schedulerPort.ChangeState(new CombatFinishFormState(_runtime, this));
}
public LevelThemeType ResolveCurrentThemeType()
{
if (_context.CurrentLevel != null)
if (_runtime.CurrentLevel != null)
{
return _context.CurrentLevel.LevelThemeType;
return _runtime.CurrentLevel.LevelThemeType;
}
return LevelThemeType.None;
@@ -175,12 +175,12 @@ namespace GeometryTD.CustomComponent
public int ApplyBaseDamage(int damage)
{
return _context.CombatInRunResourceManager.ApplyBaseDamage(damage);
return _runtime.CombatRunResourceStore.ApplyBaseDamage(damage);
}
public int GetCurrentBaseHp()
{
return Mathf.Max(0, _context.CombatInRunResourceManager.CurrentBaseHp);
return Mathf.Max(0, _runtime.CombatRunResourceStore.CurrentBaseHp);
}
public void CloseCombatFinishForm()
@@ -204,10 +204,10 @@ namespace GeometryTD.CustomComponent
GameEntry.Event.Fire(
this,
NodeCompleteEventArgs.Create(
_context.RunId,
_context.NodeId,
_context.NodeType,
_context.SequenceIndex,
_runtime.RunId,
_runtime.NodeId,
_runtime.NodeType,
_runtime.SequenceIndex,
succeeded,
GameEntry.PlayerInventory != null ? GameEntry.PlayerInventory.GetInventorySnapshot() : null));
}
@@ -225,7 +225,7 @@ namespace GeometryTD.CustomComponent
public bool HandleStartFailure(string errorMessage)
{
Log.Warning("{0}", errorMessage);
_context.EnemyManager.EndPhase();
_runtime.EnemyManager.EndPhase();
CleanupAllCombatEntities();
CloseCombatFinishForm();
CloseRewardSelectForm();
@@ -236,18 +236,18 @@ namespace GeometryTD.CustomComponent
public void EnterFailureFallback(string errorMessage)
{
if (_context.CurrentState is CombatFailedState || _context.IsCompleted)
if (_runtime.CurrentState is CombatFailedState || _runtime.IsCompleted)
{
return;
}
_schedulerHost.ChangeState(new CombatFailedState(_context, this, errorMessage));
_schedulerPort.ChangeState(new CombatFailedState(_runtime, this, errorMessage));
}
public void OnCombatFailureDialogConfirmed(object userData)
{
_ = userData;
if (_context.CurrentState is not CombatFailedState || _context.IsCompleted)
if (_runtime.CurrentState is not CombatFailedState || _runtime.IsCompleted)
{
return;
}
@@ -257,10 +257,10 @@ namespace GeometryTD.CustomComponent
private void CompleteCombat(bool succeeded)
{
_context.IsCompleted = true;
_context.CurrentState = null;
_context.CombatInRunResourceManager.MarkCombatEnded();
_context.CombatEndedCallback?.Invoke(succeeded);
_runtime.IsCompleted = true;
_runtime.CurrentState = null;
_runtime.CombatRunResourceStore.MarkCombatEnded();
_runtime.CombatEndedCallback?.Invoke(succeeded);
}
}
}
@@ -8,7 +8,7 @@ using UnityGameFramework.Runtime;
namespace GeometryTD.CustomComponent
{
internal sealed class CombatSchedulerRuntimeContext
internal sealed class CombatSchedulerRuntime
{
public List<DRLevelPhase> PhaseBuffer { get; } = new();
public Dictionary<int, IReadOnlyList<DRLevelSpawnEntry>> SpawnEntriesByPhaseId { get; } = new();
@@ -16,9 +16,9 @@ namespace GeometryTD.CustomComponent
public PhaseLoopRuntime PhaseLoopRuntime { get; } = new();
public CombatLoadSession LoadSession { get; } = new();
public CombatEventBridge EventBridge { get; } = new();
public CombatInRunResourceManager CombatInRunResourceManager { get; } = new();
public CombatRunResourceStore CombatRunResourceStore { get; } = new();
public EnemyDropResolver EnemyDropResolver { get; } = new();
public CombatSettlementFlowService SettlementFlowService { get; } = new();
public CombatSettlementService CombatSettlementService { get; } = new();
public EntityComponent Entity { get; set; }
public DRLevel CurrentLevel { get; set; }
@@ -4,12 +4,12 @@ namespace GeometryTD.CustomComponent
{
internal sealed class CombatSettlementContext
{
public CombatSettlementFlowState Flow { get; } = new();
public CombatSettlementFlags Flags { get; } = new();
public CombatSettlementResult Result { get; } = new();
public CombatSettlementSummary Summary { get; } = new();
}
internal sealed class CombatSettlementFlowState
internal sealed class CombatSettlementFlags
{
public bool ShouldOpenRewardSelection;
public bool DidEnterRewardSelection;
@@ -8,7 +8,7 @@ using UnityGameFramework.Runtime;
namespace GeometryTD.CustomComponent
{
internal sealed class CombatSettlementFlowService
internal sealed class CombatSettlementService
{
private const int RewardSelectDisplayCount = 3;
private const float FullBaseHpGoldBonusRate = 0.3f;
@@ -21,13 +21,13 @@ namespace GeometryTD.CustomComponent
bool isVictory,
DRLevel currentLevel,
int defeatedEnemyCount,
CombatInRunResourceManager resourceManager)
CombatRunResourceStore resourceStore)
{
bool shouldOpenFullBaseHpRewardSelect = false;
ResolveSettlementByBaseHp(
isVictory,
currentLevel,
resourceManager,
resourceStore,
out int currentBaseHp,
out int maxBaseHp,
out int levelRewardGold,
@@ -40,19 +40,19 @@ namespace GeometryTD.CustomComponent
{
};
settlementContext.Result.IsVictory = isVictory;
settlementContext.Result.FinalCoin = Mathf.Max(0, resourceManager != null ? resourceManager.CurrentCoin : 0);
settlementContext.Result.FinalCoin = Mathf.Max(0, resourceStore != null ? resourceStore.CurrentCoin : 0);
settlementContext.Result.FinalBaseHp = currentBaseHp;
settlementContext.Result.MaxBaseHp = maxBaseHp;
settlementContext.Result.DefeatedEnemyCount = Mathf.Max(0, defeatedEnemyCount);
settlementContext.Result.GainedGold = Mathf.Max(0, resourceManager != null ? resourceManager.GainedGold : 0);
settlementContext.Result.RewardInventory = resourceManager != null
? resourceManager.GetRewardInventorySnapshot()
settlementContext.Result.GainedGold = Mathf.Max(0, resourceStore != null ? resourceStore.GainedGold : 0);
settlementContext.Result.RewardInventory = resourceStore != null
? resourceStore.GetRewardInventorySnapshot()
: new BackpackInventoryData();
settlementContext.Result.Penalty.ShouldApplyLowBaseHpPenalty = appliedLowBaseHpPenalty;
settlementContext.Result.Penalty.LowBaseHpEndurancePenaltyValue =
appliedLowBaseHpPenalty ? LowBaseHpTowerEndurancePenalty : 0f;
settlementContext.Flow.ShouldOpenRewardSelection = shouldOpenFullBaseHpRewardSelect;
settlementContext.Flow.DidEnterRewardSelection = false;
settlementContext.Flags.ShouldOpenRewardSelection = shouldOpenFullBaseHpRewardSelect;
settlementContext.Flags.DidEnterRewardSelection = false;
settlementContext.Summary.DefeatedEnemyCount = settlementContext.Result.DefeatedEnemyCount;
settlementContext.Summary.GainedGold = settlementContext.Result.GainedGold;
settlementContext.Summary.RewardInventory = settlementContext.Result.RewardInventory;
@@ -72,7 +72,7 @@ namespace GeometryTD.CustomComponent
public void CommitSettlementInventory(CombatSettlementContext settlementContext)
{
if (settlementContext == null || settlementContext.Flow.IsCommitted)
if (settlementContext == null || settlementContext.Flags.IsCommitted)
{
return;
}
@@ -82,7 +82,7 @@ namespace GeometryTD.CustomComponent
settlementContext.Result.RewardInventory = rewardInventory;
settlementContext.Summary.RewardInventory = rewardInventory;
settlementContext.Result.Penalty.AffectedTowerCount = ApplyDeferredSettlementPenalty(settlementContext);
settlementContext.Flow.IsCommitted = true;
settlementContext.Flags.IsCommitted = true;
}
public bool TryPrepareRewardSelection(
@@ -105,7 +105,7 @@ namespace GeometryTD.CustomComponent
RewardSelectDisplayCount);
if (candidateItems == null || candidateItems.Count <= 0)
{
settlementContext.Flow.ShouldOpenRewardSelection = false;
settlementContext.Flags.ShouldOpenRewardSelection = false;
return false;
}
@@ -123,7 +123,7 @@ namespace GeometryTD.CustomComponent
if (rewardPool.Count <= 0)
{
settlementContext.Flow.ShouldOpenRewardSelection = false;
settlementContext.Flags.ShouldOpenRewardSelection = false;
return false;
}
@@ -139,11 +139,11 @@ namespace GeometryTD.CustomComponent
RewardSelectFormRawData rawData = rewardSelectFormUseCase.CreateInitialModel();
if (rawData == null || rawData.RewardItems == null || rawData.RewardItems.Length <= 0)
{
settlementContext.Flow.ShouldOpenRewardSelection = false;
settlementContext.Flags.ShouldOpenRewardSelection = false;
return false;
}
settlementContext.Flow.DidEnterRewardSelection = true;
settlementContext.Flags.DidEnterRewardSelection = true;
GameEntry.UIRouter.OpenUI(UIFormType.RewardSelectForm, rawData);
return true;
}
@@ -175,7 +175,7 @@ namespace GeometryTD.CustomComponent
private static void ResolveSettlementByBaseHp(
bool isVictory,
DRLevel currentLevel,
CombatInRunResourceManager resourceManager,
CombatRunResourceStore resourceStore,
out int currentBaseHp,
out int maxBaseHp,
out int levelRewardGold,
@@ -184,8 +184,8 @@ namespace GeometryTD.CustomComponent
out bool appliedLowBaseHpPenalty,
out bool shouldOpenFullBaseHpRewardSelect)
{
currentBaseHp = Mathf.Max(0, resourceManager != null ? resourceManager.CurrentBaseHp : 0);
maxBaseHp = resourceManager != null ? Mathf.Max(0, resourceManager.MaxBaseHp) : 0;
currentBaseHp = Mathf.Max(0, resourceStore != null ? resourceStore.CurrentBaseHp : 0);
maxBaseHp = resourceStore != null ? Mathf.Max(0, resourceStore.MaxBaseHp) : 0;
if (maxBaseHp > 0)
{
currentBaseHp = Mathf.Clamp(currentBaseHp, 0, maxBaseHp);
@@ -197,7 +197,7 @@ namespace GeometryTD.CustomComponent
appliedLowBaseHpPenalty = false;
shouldOpenFullBaseHpRewardSelect = false;
if (!isVictory || resourceManager == null)
if (!isVictory || resourceStore == null)
{
return;
}
@@ -220,10 +220,10 @@ namespace GeometryTD.CustomComponent
}
}
int goldForBonusCalculation = Mathf.Max(0, resourceManager.GainedGold) + levelRewardGold;
int goldForBonusCalculation = Mathf.Max(0, resourceStore.GainedGold) + levelRewardGold;
bonusGold = bonusRate > 0f ? Mathf.FloorToInt(goldForBonusCalculation * bonusRate) : 0;
int settlementGold = levelRewardGold + bonusGold;
resourceManager.AddSettlementGold(settlementGold);
resourceStore.AddSettlementGold(settlementGold);
}
private static int ApplyDeferredSettlementPenalty(CombatSettlementContext settlementContext)
@@ -7,9 +7,9 @@ namespace GeometryTD.CustomComponent
private readonly string _errorMessage;
public CombatFailedState(
CombatSchedulerRuntimeContext context,
CombatSchedulerFlowCoordinator flow,
string errorMessage) : base(context, flow)
CombatSchedulerRuntime runtime,
CombatSchedulerCoordinator coordinator,
string errorMessage) : base(runtime, coordinator)
{
_errorMessage = errorMessage;
}
@@ -18,17 +18,17 @@ namespace GeometryTD.CustomComponent
{
Log.Error(
"CombatScheduler failed. LevelId={0}, {1}",
Context.CurrentLevel != null ? Context.CurrentLevel.Id : 0,
Runtime.CurrentLevel != null ? Runtime.CurrentLevel.Id : 0,
_errorMessage);
Context.EnemyManager.EndPhase();
Flow.CloseCombatFinishForm();
Flow.CloseRewardSelectForm();
Flow.OpenCombatFailureDialog(_errorMessage);
Runtime.EnemyManager.EndPhase();
Coordinator.CloseCombatFinishForm();
Coordinator.CloseRewardSelectForm();
Coordinator.OpenCombatFailureDialog(_errorMessage);
}
public override void OnExit()
{
Flow.CloseDialogForm();
Coordinator.CloseDialogForm();
}
}
}
@@ -2,24 +2,24 @@ namespace GeometryTD.CustomComponent
{
internal sealed class CombatFinishFormState : CombatStateBase
{
public CombatFinishFormState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
: base(context, flow)
public CombatFinishFormState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
: base(runtime, coordinator)
{
}
public override void OnEnter()
{
if (Context.SettlementContext == null)
if (Runtime.SettlementContext == null)
{
Flow.EnterFailureFallback("Combat finish form failed. Settlement context is missing.");
Coordinator.EnterFailureFallback("Combat finish form failed. Settlement context is missing.");
return;
}
Flow.EnsureCombatFinishFormUseCaseBound();
Context.SettlementFlowService.OpenCombatFinishForm(
Context.SettlementContext,
Context.CombatFinishFormUseCase);
Flow.ChangeState(new CombatWaitingForReturnState(Context, Flow));
Coordinator.EnsureCombatFinishFormUseCaseBound();
Runtime.CombatSettlementService.OpenCombatFinishForm(
Runtime.SettlementContext,
Runtime.CombatFinishFormUseCase);
Coordinator.ChangeState(new CombatWaitingForReturnState(Runtime, Coordinator));
}
}
}
@@ -8,23 +8,23 @@ namespace GeometryTD.CustomComponent
{
internal sealed class CombatLoadingState : CombatStateBase
{
public CombatLoadingState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
: base(context, flow)
public CombatLoadingState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
: base(runtime, coordinator)
{
}
public override void OnEnter()
{
if (Context.CurrentLevel == null)
if (Runtime.CurrentLevel == null)
{
Flow.EnterFailureFallback("Combat loading failed. Current level is null.");
Coordinator.EnterFailureFallback("Combat loading failed. Current level is null.");
return;
}
MapEntityLoadContext mapLoadContext = BuildMapLoadContext();
if (!Context.LoadSession.StartLoading(Context.CurrentLevel, mapLoadContext, Flow.Host, out string errorMessage))
if (!Runtime.LoadSession.StartLoading(Runtime.CurrentLevel, mapLoadContext, Coordinator.Port, out string errorMessage))
{
Flow.EnterFailureFallback($"Combat loading failed. {errorMessage}");
Coordinator.EnterFailureFallback($"Combat loading failed. {errorMessage}");
}
}
@@ -33,20 +33,20 @@ namespace GeometryTD.CustomComponent
_ = elapseSeconds;
_ = realElapseSeconds;
if (!Context.LoadSession.IsReady)
if (!Runtime.LoadSession.IsReady)
{
return;
}
Flow.TryBeginNextPhase();
Coordinator.TryBeginNextPhase();
}
private MapEntityLoadContext BuildMapLoadContext()
{
List<TowerStatsData> buildTowerStatsSnapshot = new();
for (int i = 0; i < Context.CombatInRunResourceManager.CurrentBuildTowerCount; i++)
for (int i = 0; i < Runtime.CombatRunResourceStore.CurrentBuildTowerCount; i++)
{
if (Context.CombatInRunResourceManager.TryGetBuildTowerStats(i, out TowerStatsData stats) &&
if (Runtime.CombatRunResourceStore.TryGetBuildTowerStats(i, out TowerStatsData stats) &&
stats != null)
{
buildTowerStatsSnapshot.Add(stats);
@@ -56,16 +56,16 @@ namespace GeometryTD.CustomComponent
MapData mapData = new MapData(
entityId: 0,
typeId: 0,
levelId: Context.CurrentLevel.Id,
levelId: Runtime.CurrentLevel.Id,
position: Vector3.zero,
initialCoin: Context.CombatInRunResourceManager.CurrentCoin,
initialCoin: Runtime.CombatRunResourceStore.CurrentCoin,
buildTowerStatsSnapshot: buildTowerStatsSnapshot,
inventorySnapshot: Context.CombatInRunResourceManager.GetCombatInventorySnapshot(),
participantTowerSnapshot: Context.CombatInRunResourceManager.GetParticipantTowerSnapshot());
inventorySnapshot: Runtime.CombatRunResourceStore.GetCombatInventorySnapshot(),
participantTowerSnapshot: Runtime.CombatRunResourceStore.GetParticipantTowerSnapshot());
return new MapEntityLoadContext(
mapData,
Context.CombatInRunResourceManager.TryConsumeCoin,
Context.CombatInRunResourceManager.AddCoin);
Runtime.CombatRunResourceStore.TryConsumeCoin,
Runtime.CombatRunResourceStore.AddCoin);
}
}
}
@@ -2,36 +2,36 @@ namespace GeometryTD.CustomComponent
{
internal sealed class CombatRewardSelectionState : CombatStateBase
{
public CombatRewardSelectionState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
: base(context, flow)
public CombatRewardSelectionState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
: base(runtime, coordinator)
{
}
public override void OnEnter()
{
if (Context.SettlementContext == null)
if (Runtime.SettlementContext == null)
{
Flow.EnterFailureFallback("Combat reward selection failed. Settlement context is missing.");
Coordinator.EnterFailureFallback("Combat reward selection failed. Settlement context is missing.");
return;
}
Flow.EnsureRewardSelectFormUseCaseBound();
if (!Context.SettlementFlowService.TryPrepareRewardSelection(
Context.SettlementContext,
Context.EnemyDropResolver,
Context.PhaseLoopRuntime.DisplayPhaseIndex,
Flow.ResolveCurrentThemeType(),
Context.RewardSelectFormUseCase,
Flow.OnFullBaseHpRewardSelected,
Flow.OnFullBaseHpRewardGiveUp))
Coordinator.EnsureRewardSelectFormUseCaseBound();
if (!Runtime.CombatSettlementService.TryPrepareRewardSelection(
Runtime.SettlementContext,
Runtime.EnemyDropResolver,
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
Coordinator.ResolveCurrentThemeType(),
Runtime.RewardSelectFormUseCase,
Coordinator.OnFullBaseHpRewardSelected,
Coordinator.OnFullBaseHpRewardGiveUp))
{
Flow.ChangeState(new CombatFinishFormState(Context, Flow));
Coordinator.ChangeState(new CombatFinishFormState(Runtime, Coordinator));
}
}
public override void OnExit()
{
Flow.CloseRewardSelectForm();
Coordinator.CloseRewardSelectForm();
}
}
}
@@ -11,10 +11,10 @@ namespace GeometryTD.CustomComponent
private readonly IReadOnlyList<DRLevelSpawnEntry> _spawnEntries;
public CombatRunningPhaseState(
CombatSchedulerRuntimeContext context,
CombatSchedulerFlowCoordinator flow,
CombatSchedulerRuntime runtime,
CombatSchedulerCoordinator coordinator,
DRLevelPhase phase,
IReadOnlyList<DRLevelSpawnEntry> spawnEntries) : base(context, flow)
IReadOnlyList<DRLevelSpawnEntry> spawnEntries) : base(runtime, coordinator)
{
_phase = phase;
_spawnEntries = spawnEntries;
@@ -22,59 +22,59 @@ namespace GeometryTD.CustomComponent
public override void OnEnter()
{
Context.EnemyManager.BeginPhase(_phase, _spawnEntries);
Runtime.EnemyManager.BeginPhase(_phase, _spawnEntries);
GameEntry.Event.Fire(
Flow,
Coordinator,
CombatProcessEventArgs.Create(
Context.PhaseLoopRuntime.DisplayPhaseIndex,
Context.PhaseLoopRuntime.PhaseCount));
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
Runtime.PhaseLoopRuntime.PhaseCount));
GameEntry.Event.Fire(
Flow,
Coordinator,
CombatEnemyHpRateChangedEventArgs.Create(
Flow.ResolveEnemyHpRateMultiplier(
Context.PhaseLoopRuntime.DisplayPhaseIndex,
Context.PhaseLoopRuntime.PhaseCount)));
Coordinator.ResolveEnemyHpRateMultiplier(
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
Runtime.PhaseLoopRuntime.PhaseCount)));
if (!Context.NodeEnterFired)
if (!Runtime.NodeEnterFired)
{
Context.NodeEnterFired = true;
Runtime.NodeEnterFired = true;
GameEntry.Event.Fire(
Flow,
Coordinator,
NodeEnterEventArgs.Create(
Context.RunId,
Context.NodeId,
Context.NodeType,
Context.SequenceIndex));
Runtime.RunId,
Runtime.NodeId,
Runtime.NodeType,
Runtime.SequenceIndex));
}
Log.Info(
"CombatScheduler phase started. Level={0}, Phase={1}, EndType={2}, Entries={3}.",
Context.CurrentLevel != null ? Context.CurrentLevel.Id : 0,
Context.PhaseLoopRuntime.DisplayPhaseIndex,
Runtime.CurrentLevel != null ? Runtime.CurrentLevel.Id : 0,
Runtime.PhaseLoopRuntime.DisplayPhaseIndex,
_phase.EndType,
_spawnEntries != null ? _spawnEntries.Count : 0);
}
public override void OnUpdate(float elapseSeconds, float realElapseSeconds)
{
if (Context.PhaseLoopRuntime.CurrentPhase == null)
if (Runtime.PhaseLoopRuntime.CurrentPhase == null)
{
Flow.EnterFailureFallback("CombatScheduler update failed. Current phase is null.");
Coordinator.EnterFailureFallback("CombatScheduler update failed. Current phase is null.");
return;
}
Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
Context.EnemyManager.OnUpdate(elapseSeconds, realElapseSeconds);
Runtime.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
Runtime.EnemyManager.OnUpdate(elapseSeconds, realElapseSeconds);
if (Flow.ShouldEnterSettlementFromActiveState(out bool isVictory))
if (Coordinator.ShouldEnterSettlementFromActiveState(out bool isVictory))
{
Flow.ChangeState(new CombatSettlementState(Context, Flow, isVictory));
Coordinator.ChangeState(new CombatSettlementState(Runtime, Coordinator, isVictory));
return;
}
if (Context.EnemyManager.IsPhaseSpawnCompleted)
if (Runtime.EnemyManager.IsPhaseSpawnCompleted)
{
Flow.EnterWaitingForPhaseEnd();
Coordinator.EnterWaitingForPhaseEnd();
}
}
}
@@ -5,30 +5,30 @@ namespace GeometryTD.CustomComponent
private readonly bool _isVictory;
public CombatSettlementState(
CombatSchedulerRuntimeContext context,
CombatSchedulerFlowCoordinator flow,
bool isVictory) : base(context, flow)
CombatSchedulerRuntime runtime,
CombatSchedulerCoordinator coordinator,
bool isVictory) : base(runtime, coordinator)
{
_isVictory = isVictory;
}
public override void OnEnter()
{
Context.EnemyManager.EndPhase();
Context.EnemyManager.CleanupTrackedEnemies();
Context.IsFinishAsVictory = _isVictory;
Context.SettlementContext = Context.SettlementFlowService.BuildSettlementContext(
Runtime.EnemyManager.EndPhase();
Runtime.EnemyManager.CleanupTrackedEnemies();
Runtime.IsFinishAsVictory = _isVictory;
Runtime.SettlementContext = Runtime.CombatSettlementService.BuildSettlementContext(
_isVictory,
Context.CurrentLevel,
Context.EnemyManager.DefeatedEnemyCount,
Context.CombatInRunResourceManager);
if (Context.SettlementContext.Flow.ShouldOpenRewardSelection)
Runtime.CurrentLevel,
Runtime.EnemyManager.DefeatedEnemyCount,
Runtime.CombatRunResourceStore);
if (Runtime.SettlementContext.Flags.ShouldOpenRewardSelection)
{
Flow.ChangeState(new CombatRewardSelectionState(Context, Flow));
Coordinator.ChangeState(new CombatRewardSelectionState(Runtime, Coordinator));
return;
}
Flow.ChangeState(new CombatFinishFormState(Context, Flow));
Coordinator.ChangeState(new CombatFinishFormState(Runtime, Coordinator));
}
}
}
@@ -2,13 +2,13 @@ namespace GeometryTD.CustomComponent
{
internal abstract class CombatStateBase
{
protected CombatSchedulerRuntimeContext Context { get; }
protected CombatSchedulerFlowCoordinator Flow { get; }
protected CombatSchedulerRuntime Runtime { get; }
protected CombatSchedulerCoordinator Coordinator { get; }
protected CombatStateBase(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
protected CombatStateBase(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
{
Context = context;
Flow = flow;
Runtime = runtime;
Coordinator = coordinator;
}
public virtual void OnInit()
@@ -4,8 +4,8 @@ namespace GeometryTD.CustomComponent
{
internal sealed class CombatWaitingForPhaseEndState : CombatStateBase
{
public CombatWaitingForPhaseEndState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
: base(context, flow)
public CombatWaitingForPhaseEndState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
: base(runtime, coordinator)
{
}
@@ -13,34 +13,34 @@ namespace GeometryTD.CustomComponent
{
_ = realElapseSeconds;
DRLevelPhase currentPhase = Context.PhaseLoopRuntime.CurrentPhase;
DRLevelPhase currentPhase = Runtime.PhaseLoopRuntime.CurrentPhase;
if (currentPhase == null)
{
Flow.EnterFailureFallback("CombatScheduler waiting phase failed. Current phase is null.");
Coordinator.EnterFailureFallback("CombatScheduler waiting phase failed. Current phase is null.");
return;
}
Context.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
Runtime.PhaseLoopRuntime.AdvancePhaseElapsed(elapseSeconds);
if (Flow.ShouldEnterSettlementFromActiveState(out bool isVictory))
if (Coordinator.ShouldEnterSettlementFromActiveState(out bool isVictory))
{
Flow.ChangeState(new CombatSettlementState(Context, Flow, isVictory));
Coordinator.ChangeState(new CombatSettlementState(Runtime, Coordinator, isVictory));
return;
}
PhaseEndConditionContext conditionContext = new(
currentPhase,
Context.PhaseLoopRuntime.CurrentPhaseElapsed,
Context.EnemyManager.IsPhaseSpawnCompleted,
Context.EnemyManager.AliveEnemyCount,
Context.EnemyManager.HasAliveBoss);
Runtime.PhaseLoopRuntime.CurrentPhaseElapsed,
Runtime.EnemyManager.IsPhaseSpawnCompleted,
Runtime.EnemyManager.AliveEnemyCount,
Runtime.EnemyManager.HasAliveBoss);
IPhaseEndCondition endCondition = PhaseEndConditionFactory.Create(currentPhase.EndType);
if (!endCondition.ShouldExit(conditionContext))
{
return;
}
Flow.CompleteCurrentPhase();
Coordinator.CompleteCurrentPhase();
}
}
}
@@ -4,8 +4,8 @@ namespace GeometryTD.CustomComponent
{
private bool _returnRequested;
public CombatWaitingForReturnState(CombatSchedulerRuntimeContext context, CombatSchedulerFlowCoordinator flow)
: base(context, flow)
public CombatWaitingForReturnState(CombatSchedulerRuntime runtime, CombatSchedulerCoordinator coordinator)
: base(runtime, coordinator)
{
}
@@ -24,17 +24,17 @@ namespace GeometryTD.CustomComponent
return;
}
if (Context.SettlementContext == null)
if (Runtime.SettlementContext == null)
{
Flow.EnterFailureFallback("Combat return failed. Settlement context is missing.");
Coordinator.EnterFailureFallback("Combat return failed. Settlement context is missing.");
return;
}
Context.SettlementFlowService.CommitSettlementInventory(Context.SettlementContext);
Context.LoadSession.Cleanup();
Flow.CloseCombatFinishForm();
Flow.CloseRewardSelectForm();
Flow.CompleteNormalCombatAndNotify(Context.IsFinishAsVictory);
Runtime.CombatSettlementService.CommitSettlementInventory(Runtime.SettlementContext);
Runtime.LoadSession.Cleanup();
Coordinator.CloseCombatFinishForm();
Coordinator.CloseRewardSelectForm();
Coordinator.CompleteNormalCombatAndNotify(Runtime.IsFinishAsVictory);
}
}
}
@@ -3,9 +3,9 @@ using GeometryTD.Definition;
namespace GeometryTD.CustomComponent
{
internal readonly struct EnemyDropResolveContext
internal readonly struct EnemyDropContext
{
public EnemyDropResolveContext(DREnemy enemy, int displayPhaseIndex, LevelThemeType themeType)
public EnemyDropContext(DREnemy enemy, int displayPhaseIndex, LevelThemeType themeType)
{
Enemy = enemy;
DisplayPhaseIndex = displayPhaseIndex;
@@ -31,12 +31,12 @@ namespace GeometryTD.CustomComponent
_nextDropItemInstanceId = 1;
}
public EnemyDropResolveResult Resolve(in EnemyDropResolveContext context)
public EnemyDropResult Resolve(in EnemyDropContext context)
{
DREnemy enemy = context.Enemy;
if (enemy == null)
{
return EnemyDropResolveResult.Empty;
return EnemyDropResult.Empty;
}
int coin = Mathf.Max(0, enemy.DropCoin);
@@ -58,7 +58,7 @@ namespace GeometryTD.CustomComponent
lootItem = droppedItem;
}
return new EnemyDropResolveResult(coin, gold, lootItem);
return new EnemyDropResult(coin, gold, lootItem);
}
public IReadOnlyList<TowerCompItemData> RollSettlementRewardCandidates(
@@ -2,11 +2,11 @@ using GeometryTD.Definition;
namespace GeometryTD.CustomComponent
{
internal readonly struct EnemyDropResolveResult
internal readonly struct EnemyDropResult
{
public static EnemyDropResolveResult Empty => new(0, 0, null);
public static EnemyDropResult Empty => new(0, 0, null);
public EnemyDropResolveResult(int coin, int gold, TowerCompItemData lootItem)
public EnemyDropResult(int coin, int gold, TowerCompItemData lootItem)
{
Coin = coin;
Gold = gold;
@@ -2,7 +2,7 @@ using GeometryTD.DataTable;
namespace GeometryTD.CustomComponent
{
internal interface ICombatSchedulerHost
internal interface ICombatSchedulerPort
{
DRLevel CurrentLevel { get; }
int DisplayPhaseIndex { get; }