geometry-tower-defense-base/src-ref/CustomComponent/CombatNode/CombatScheduler/CombatLoadSession.cs

316 lines
10 KiB
C#

using GameFramework.Resource;
using GeometryTD.CustomUtility;
using GeometryTD.DataTable;
using GeometryTD.Definition;
using GeometryTD.Entity;
using GeometryTD.Entity.EntityData;
using GeometryTD.UI;
using UnityEngine;
using UnityGameFramework.Runtime;
namespace GeometryTD.CustomComponent
{
internal sealed class CombatLoadSession
{
internal enum EventHandleStatus : byte
{
Ignored = 0,
Succeeded = 1,
Failed = 2
}
private EntityComponent _entity;
private CombatInfoFormUseCase _combatInfoFormUseCase;
private int _loadingMapEntityId;
private int _loadedMapEntityId;
private int? _loadingCombatInfoFormSerialId;
private bool _isCombatInfoFormReady;
private MapEntity _currentMap;
public MapEntity CurrentMap => _currentMap;
public bool IsReady => _currentMap != null && _isCombatInfoFormReady;
public void OnInit(EntityComponent entityComponent)
{
_entity = entityComponent;
Reset();
}
public void Reset()
{
_loadingMapEntityId = 0;
_loadedMapEntityId = 0;
_loadingCombatInfoFormSerialId = null;
_isCombatInfoFormReady = false;
_currentMap = null;
}
public bool StartLoading(DRLevel level, MapEntityLoadContext mapLoadContext, ICombatSchedulerPort schedulerPort, out string errorMessage)
{
errorMessage = null;
if (_entity == null)
{
errorMessage = "CombatLoadSession start failed. Entity component is null.";
return false;
}
if (!TryShowMap(level, mapLoadContext, out errorMessage))
{
return false;
}
if (!TryOpenCombatInfoForm(schedulerPort, out errorMessage))
{
return false;
}
return true;
}
public void RefreshCombatInfoForm(DRLevel currentLevel)
{
if (currentLevel == null)
{
return;
}
GameEntry.UIRouter.OpenUI(UIFormType.CombatInfoForm);
}
public void Cleanup()
{
if (_entity == null)
{
return;
}
if (_loadingMapEntityId != 0 && _entity.IsLoadingEntity(_loadingMapEntityId))
{
_entity.HideEntity(_loadingMapEntityId);
}
if (_currentMap != null)
{
_entity.HideEntity(_currentMap);
}
else if (_loadedMapEntityId != 0)
{
UnityGameFramework.Runtime.Entity loadedMapEntity = _entity.GetEntity(_loadedMapEntityId);
if (loadedMapEntity != null)
{
_entity.HideEntity(loadedMapEntity);
}
}
CloseCombatInfoForm();
}
public EventHandleStatus HandleShowEntitySuccess(ShowEntitySuccessEventArgs args, out string errorMessage)
{
errorMessage = null;
if (args == null)
{
return EventHandleStatus.Ignored;
}
if (args.EntityLogicType != typeof(MapEntity) || args.Entity == null ||
args.Entity.Id != _loadingMapEntityId)
{
return EventHandleStatus.Ignored;
}
_loadedMapEntityId = _loadingMapEntityId;
_loadingMapEntityId = 0;
_currentMap = args.Entity.Logic as MapEntity;
if (_currentMap == null)
{
errorMessage = $"Loaded map entity logic is invalid. EntityId={args.Entity.Id}.";
return EventHandleStatus.Failed;
}
return EventHandleStatus.Succeeded;
}
public EventHandleStatus HandleShowEntityFailure(ShowEntityFailureEventArgs args, out string errorMessage)
{
errorMessage = null;
if (args == null)
{
return EventHandleStatus.Ignored;
}
if (args.EntityLogicType != typeof(MapEntity) || args.EntityId != _loadingMapEntityId)
{
return EventHandleStatus.Ignored;
}
_loadingMapEntityId = 0;
_currentMap = null;
errorMessage = $"Map load failed. Asset='{args.EntityAssetName}', Error='{args.ErrorMessage}'.";
return EventHandleStatus.Failed;
}
public void HandleHideEntityComplete(HideEntityCompleteEventArgs args)
{
if (args == null)
{
return;
}
if (args.EntityId == _loadedMapEntityId)
{
_loadedMapEntityId = 0;
_currentMap = null;
}
if (args.EntityId == _loadingMapEntityId)
{
_loadingMapEntityId = 0;
}
}
public EventHandleStatus HandleOpenUIFormSuccess(OpenUIFormSuccessEventArgs args, out string errorMessage)
{
errorMessage = null;
if (args == null || !_loadingCombatInfoFormSerialId.HasValue || args.UIForm == null)
{
return EventHandleStatus.Ignored;
}
if (args.UIForm.SerialId != _loadingCombatInfoFormSerialId.Value)
{
return EventHandleStatus.Ignored;
}
_isCombatInfoFormReady = args.UIForm.Logic is CombatInfoForm;
if (!_isCombatInfoFormReady)
{
errorMessage = "CombatInfoForm open success but form logic type is invalid.";
return EventHandleStatus.Failed;
}
return EventHandleStatus.Succeeded;
}
public EventHandleStatus HandleOpenUIFormFailure(OpenUIFormFailureEventArgs args, out string errorMessage)
{
errorMessage = null;
if (args == null || !_loadingCombatInfoFormSerialId.HasValue)
{
return EventHandleStatus.Ignored;
}
if (args.SerialId != _loadingCombatInfoFormSerialId.Value)
{
return EventHandleStatus.Ignored;
}
_isCombatInfoFormReady = false;
errorMessage = $"CombatInfoForm load failed. Asset='{args.UIFormAssetName}', Error='{args.ErrorMessage}'.";
return EventHandleStatus.Failed;
}
public void HandleCloseUIFormComplete(CloseUIFormCompleteEventArgs args)
{
if (args == null || !_loadingCombatInfoFormSerialId.HasValue)
{
return;
}
if (args.SerialId == _loadingCombatInfoFormSerialId.Value)
{
_loadingCombatInfoFormSerialId = null;
_isCombatInfoFormReady = false;
}
}
private bool TryShowMap(DRLevel level, MapEntityLoadContext mapLoadContext, out string errorMessage)
{
errorMessage = null;
if (level == null)
{
errorMessage = "CombatLoadSession map load failed. Level is null.";
return false;
}
if (mapLoadContext?.InitialMapData == null)
{
errorMessage = "CombatLoadSession map load failed. MapEntityLoadContext is missing initial map data.";
return false;
}
string mapAssetName = level.Id.ToString();
string mapAssetPath = AssetUtility.GetLevelMapAsset(mapAssetName);
if (GameEntry.Resource.HasAsset(mapAssetPath) == HasAssetResult.NotExist)
{
errorMessage = $"CombatLoadSession map asset not found. Level='{level.Id}', Asset='{mapAssetPath}'.";
return false;
}
_loadingMapEntityId = _entity.GenerateSerialId();
MapData resolvedMapData = mapLoadContext.InitialMapData.CloneForEntity(_loadingMapEntityId, Vector3.zero);
MapEntityLoadContext resolvedLoadContext = new MapEntityLoadContext(
resolvedMapData,
mapLoadContext.TryConsumeCoin,
mapLoadContext.AddCoin);
_entity.ShowMap(resolvedLoadContext, mapAssetName);
return true;
}
private bool TryOpenCombatInfoForm(ICombatSchedulerPort schedulerPort, out string errorMessage)
{
errorMessage = null;
if (_combatInfoFormUseCase == null)
{
_combatInfoFormUseCase = new CombatInfoFormUseCase();
GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatInfoForm, _combatInfoFormUseCase);
}
_combatInfoFormUseCase.Configure(
() => 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)
{
errorMessage = "CombatLoadSession failed to open CombatInfoForm.";
return false;
}
_loadingCombatInfoFormSerialId = serialId.Value;
_isCombatInfoFormReady = GameEntry.UI.HasUIForm(serialId.Value);
return true;
}
private static CombatInfoFormRawData BuildCombatInfoFormRawData(ICombatSchedulerPort schedulerPort)
{
if (schedulerPort == null)
{
return null;
}
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,
schedulerPort.DisplayPhaseIndex,
schedulerPort.PhaseCount,
schedulerPort.CurrentCoin,
schedulerPort.CurrentBaseHp,
baseHpMax,
schedulerPort.CanEndCombat);
}
private void CloseCombatInfoForm()
{
GameEntry.UIRouter.CloseUI(UIFormType.CombatInfoForm);
_loadingCombatInfoFormSerialId = null;
_isCombatInfoFormReady = false;
}
}
}