226 lines
8.1 KiB
C#
226 lines
8.1 KiB
C#
using System;
|
|
using BriarQueen.Data.Identifiers;
|
|
using BriarQueen.Framework.Assets;
|
|
using BriarQueen.Framework.Coordinators.Events;
|
|
using BriarQueen.Framework.Events.UI;
|
|
using BriarQueen.Framework.Managers.IO;
|
|
using BriarQueen.Framework.Managers.Levels;
|
|
using BriarQueen.Framework.Registries;
|
|
using Cysharp.Threading.Tasks;
|
|
using UnityEditor;
|
|
using UnityEngine;
|
|
using UnityEngine.ResourceManagement.AsyncOperations;
|
|
using UnityEngine.ResourceManagement.ResourceProviders;
|
|
using UnityEngine.SceneManagement;
|
|
using VContainer;
|
|
|
|
namespace BriarQueen.Framework.Services.Game
|
|
{
|
|
public class GameService
|
|
{
|
|
private readonly AddressableManager _addressableManager;
|
|
private readonly AssetRegistry _assetRegistry;
|
|
private readonly EventCoordinator _eventCoordinator;
|
|
private readonly LevelManager _levelManager;
|
|
private readonly SaveManager _saveManager;
|
|
|
|
private AsyncOperationHandle<SceneInstance> _gameSceneHandle;
|
|
private AsyncOperationHandle<SceneInstance> _mainMenuSceneHandle;
|
|
private AsyncOperationHandle<SceneInstance>? _uiSceneHandle;
|
|
|
|
public bool IsMainMenuSceneLoaded {get; private set;}
|
|
|
|
[Inject]
|
|
public GameService(
|
|
SaveManager saveManager,
|
|
EventCoordinator eventCoordinator,
|
|
AddressableManager addressableManager,
|
|
LevelManager levelManager,
|
|
AssetRegistry assetRegistry)
|
|
{
|
|
_saveManager = saveManager;
|
|
_eventCoordinator = eventCoordinator;
|
|
_addressableManager = addressableManager;
|
|
_levelManager = levelManager;
|
|
_assetRegistry = assetRegistry;
|
|
}
|
|
|
|
public async UniTask LoadUIAndMainMenuScene()
|
|
{
|
|
if (_assetRegistry == null ||
|
|
!_assetRegistry.TryGetReference(AssetKeyIdentifiers.Get(SceneKey.UIScene), out var uiSceneRef))
|
|
{
|
|
Debug.LogError("[GameService] UI Scene reference not found in registry.");
|
|
return;
|
|
}
|
|
|
|
_uiSceneHandle = await _addressableManager.LoadSceneAsync(uiSceneRef);
|
|
if (!_uiSceneHandle.Value.IsValid())
|
|
{
|
|
Debug.LogError("[GameService] Failed to load UI Scene.");
|
|
return;
|
|
}
|
|
|
|
// After UI is loaded, we fade to black to prevent pops
|
|
_eventCoordinator.PublishImmediate(new FadeEvent(false, 0.2f));
|
|
await UniTask.Delay(TimeSpan.FromSeconds(0.5f));
|
|
await UniTask.NextFrame();
|
|
await LoadMainMenu();
|
|
}
|
|
|
|
public async UniTask LoadMainMenu()
|
|
{
|
|
const float fadeDuration = 1f;
|
|
|
|
_eventCoordinator.PublishImmediate(new FadeEvent(false, fadeDuration));
|
|
await UniTask.Delay(TimeSpan.FromSeconds(fadeDuration));
|
|
|
|
await UnloadGameSceneIfLoaded();
|
|
|
|
if (_assetRegistry == null ||
|
|
!_assetRegistry.TryGetReference(
|
|
AssetKeyIdentifiers.Get(SceneKey.MainMenuScene),
|
|
out var mainMenuSceneRef))
|
|
{
|
|
Debug.LogError("[GameService] Main menu scene reference missing.");
|
|
return;
|
|
}
|
|
|
|
_mainMenuSceneHandle = await _addressableManager.LoadSceneAsync(mainMenuSceneRef);
|
|
|
|
if (!_mainMenuSceneHandle.IsValid())
|
|
{
|
|
Debug.LogError("[GameService] Failed to load Main Menu scene.");
|
|
return;
|
|
}
|
|
|
|
SceneManager.SetActiveScene(_mainMenuSceneHandle.Result.Scene);
|
|
IsMainMenuSceneLoaded = true;
|
|
|
|
await UniTask.NextFrame();
|
|
|
|
_eventCoordinator.PublishImmediate(new FadeEvent(true, fadeDuration));
|
|
}
|
|
|
|
public async UniTask StartGame()
|
|
{
|
|
await EnterGameplayLoop();
|
|
}
|
|
|
|
private async UniTask EnterGameplayLoop()
|
|
{
|
|
_eventCoordinator.PublishImmediate(new RequestUIOverrideEvent(false));
|
|
_eventCoordinator.PublishImmediate(new FadeEvent(false, 0.35f));
|
|
|
|
if (_mainMenuSceneHandle.IsValid())
|
|
{
|
|
await _addressableManager.UnloadSceneAsync(_mainMenuSceneHandle);
|
|
IsMainMenuSceneLoaded = false;
|
|
}
|
|
|
|
var currentSave = _saveManager.CurrentSave;
|
|
if (currentSave == null)
|
|
{
|
|
Debug.LogError("[GameService] Cannot start game because CurrentSave is null.");
|
|
await LoadMainMenu();
|
|
return;
|
|
}
|
|
|
|
Debug.Log($"[GameService] Loading scene '{currentSave.CurrentSceneID}'...");
|
|
|
|
if (!currentSave.OpeningCinematicPlayed)
|
|
{
|
|
if (_assetRegistry == null ||
|
|
!_assetRegistry.TryGetReference(
|
|
AssetKeyIdentifiers.Get(SceneKey.OpeningCinematicScene),
|
|
out var cinematicScene))
|
|
{
|
|
Debug.LogError("[GameService] Opening cinematic scene reference missing.");
|
|
await LoadMainMenu();
|
|
return;
|
|
}
|
|
|
|
var loadedSceneHandle = await _addressableManager.LoadSceneAsync(cinematicScene);
|
|
if (!loadedSceneHandle.IsValid())
|
|
{
|
|
Debug.LogError("[GameService] Failed to load opening cinematic scene.");
|
|
await LoadMainMenu();
|
|
return;
|
|
}
|
|
|
|
await SwapGameSceneHandle(loadedSceneHandle);
|
|
}
|
|
else
|
|
{
|
|
if (_assetRegistry == null ||
|
|
!_assetRegistry.TryGetReference(currentSave.CurrentSceneID, out var chapterSceneRef))
|
|
{
|
|
Debug.LogError($"[GameService] Scene reference missing for '{currentSave.CurrentSceneID}'.");
|
|
await LoadMainMenu();
|
|
return;
|
|
}
|
|
|
|
Debug.Log($"[GameService] Loading chapter scene '{currentSave.CurrentSceneID}'...");
|
|
var loadedSceneHandle = await _addressableManager.LoadSceneAsync(chapterSceneRef);
|
|
if (!loadedSceneHandle.IsValid())
|
|
{
|
|
Debug.LogError($"[GameService] Failed to load chapter scene '{currentSave.CurrentSceneID}'.");
|
|
await LoadMainMenu();
|
|
return;
|
|
}
|
|
|
|
await SwapGameSceneHandle(loadedSceneHandle);
|
|
|
|
var levelLoaded = await _levelManager.LoadLevel(currentSave.CurrentLevelID);
|
|
if (!levelLoaded)
|
|
{
|
|
Debug.LogError(
|
|
$"[GameService] Failed to load level '{currentSave.CurrentLevelID}'. Returning to main menu.");
|
|
await LoadMainMenu();
|
|
return;
|
|
}
|
|
}
|
|
|
|
_eventCoordinator.PublishImmediate(new FadeEvent(true, 0.35f));
|
|
}
|
|
|
|
public async UniTask UnloadGameSceneIfLoaded()
|
|
{
|
|
if (_gameSceneHandle.IsValid())
|
|
{
|
|
await _addressableManager.UnloadSceneAsync(_gameSceneHandle);
|
|
_gameSceneHandle = default;
|
|
}
|
|
}
|
|
|
|
public async UniTask SwapGameSceneHandle(AsyncOperationHandle<SceneInstance> nextSceneHandle)
|
|
{
|
|
if (!nextSceneHandle.IsValid())
|
|
{
|
|
Debug.LogError("[GameService] SwapGameSceneHandle called with invalid nextSceneHandle.");
|
|
return;
|
|
}
|
|
|
|
if (_gameSceneHandle.IsValid() && _gameSceneHandle.Equals(nextSceneHandle))
|
|
{
|
|
_gameSceneHandle = nextSceneHandle;
|
|
return;
|
|
}
|
|
|
|
if (_gameSceneHandle.IsValid())
|
|
await _addressableManager.UnloadSceneAsync(_gameSceneHandle);
|
|
|
|
_gameSceneHandle = nextSceneHandle;
|
|
SceneManager.SetActiveScene(nextSceneHandle.Result.Scene);
|
|
}
|
|
|
|
public void QuitGame()
|
|
{
|
|
#if UNITY_EDITOR
|
|
EditorApplication.isPlaying = false;
|
|
#else
|
|
Application.Quit();
|
|
#endif
|
|
}
|
|
}
|
|
} |