using Godot; using Godot.Collections; using Mr.BrickAdventures.scripts.components; namespace Mr.BrickAdventures.Autoloads; /// /// Game orchestrator - handles scene transitions and game flow. /// State lives in GameStateStore; query it directly for reads/writes. /// public partial class GameManager : Node { [Export] public Array LevelScenes { get; set; } = []; public PlayerController Player { get => GetPlayer(); private set => _player = value; } private PlayerController _player; private SpeedRunManager SpeedRunManager => SpeedRunManager.Instance; private GameStateStore Store => GameStateStore.Instance; public static GameManager Instance { get; private set; } public override void _Ready() { Instance = this; EventBus.Instance.PlayerSpawned += OnPlayerSpawned; } public override void _ExitTree() { if (Instance == this) Instance = null; if (EventBus.Instance != null) EventBus.Instance.PlayerSpawned -= OnPlayerSpawned; } private void OnPlayerSpawned(PlayerController player) { _player = player; player.TreeExiting += () => { if (_player == player) _player = null; }; } #region Game Flow public void StartNewGame() { Store?.ResetAll(); SpeedRunManager?.StartTimer(); GetTree().ChangeSceneToPacked(LevelScenes[0]); SaveSystem.Instance.SaveGame(); EventBus.EmitGameStarted(); } public void ContinueGame() { var save = SaveSystem.Instance; if (!save.LoadGame()) { GD.PrintErr("Failed to load game. Starting a new game instead."); StartNewGame(); return; } var idx = Store?.Player.CurrentLevel ?? 0; if (idx < LevelScenes.Count) { GetTree().ChangeSceneToPacked(LevelScenes[idx]); EventBus.EmitGameContinued(); } else { GD.PrintErr("No levels unlocked to continue."); } } public void RestartGame() { Store?.ResetAll(); GetTree().ChangeSceneToPacked(LevelScenes[0]); SaveSystem.Instance.SaveGame(); } public void OnLevelComplete() { if (Store == null) return; var levelIndex = Store.Player.CurrentLevel; Store.MarkLevelComplete(levelIndex); Store.CommitSessionCoins(); Store.CommitSessionSkills(); var completionTime = SpeedRunManager?.GetCurrentLevelTime() ?? 0.0; EventBus.EmitLevelCompleted(levelIndex, GetTree().CurrentScene, completionTime); Store.ResetSession(); TryToGoToNextLevel(); SaveSystem.Instance.SaveGame(); } public void TryToGoToNextLevel() { if (Store == null) return; var next = Store.Player.CurrentLevel + 1; if (next < LevelScenes.Count && Store.IsLevelUnlocked(next)) { Store.Player.CurrentLevel = next; GetTree().ChangeSceneToPacked(LevelScenes[next]); EventBus.EmitLevelStarted(next, GetTree().CurrentScene); } } public void PauseGame() { Engine.TimeScale = 0; EventBus.EmitGamePaused(); } public void ResumeGame() { Engine.TimeScale = 1; EventBus.EmitGameResumed(); } public void QuitGame() => GetTree().Quit(); #endregion #region Player Lookup public PlayerController GetPlayer() { if (_player != null && IsInstanceValid(_player)) return _player; _player = null; return null; } #endregion }