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, ICombatSchedulerHost schedulerHost, 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(schedulerHost, 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; } 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 != null ? mapLoadContext.InitialMapData.CloneForEntity(_loadingMapEntityId, Vector3.zero) : new MapData(_loadingMapEntityId, level.Id, Vector3.zero); MapEntityLoadContext resolvedLoadContext = new MapEntityLoadContext( resolvedMapData, mapLoadContext?.TryConsumeCoin, mapLoadContext?.AddCoin); _entity.ShowMap(resolvedLoadContext, mapAssetName); return true; } private bool TryOpenCombatInfoForm(ICombatSchedulerHost schedulerHost, out string errorMessage) { errorMessage = null; if (_combatInfoFormUseCase == null) { _combatInfoFormUseCase = new CombatInfoFormUseCase(); GameEntry.UIRouter.BindUIUseCase(UIFormType.CombatInfoForm, _combatInfoFormUseCase); } _combatInfoFormUseCase.Configure( () => BuildCombatInfoFormRawData(schedulerHost), () => schedulerHost != null && schedulerHost.CanEndCombat && schedulerHost.TryEndCombatByPlayer(), () => schedulerHost != null && schedulerHost.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(ICombatSchedulerHost schedulerHost) { if (schedulerHost == null) { return null; } DRLevel level = schedulerHost.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, baseHpMax, schedulerHost.CanEndCombat); } private void CloseCombatInfoForm() { GameEntry.UIRouter.CloseUI(UIFormType.CombatInfoForm); _loadingCombatInfoFormSerialId = null; _isCombatInfoFormReady = false; } } }