First commit for private source control. Older commits available on Github.
This commit is contained in:
226
Assets/Scripts/Framework/Services/Game/GameService.cs
Normal file
226
Assets/Scripts/Framework/Services/Game/GameService.cs
Normal file
@@ -0,0 +1,226 @@
|
||||
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
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user