using UnityEngine; using AppleHills.Core.Settings; using System; using System.Collections.Generic; using AppleHills.Core.Interfaces; using Core; using UI; using Bootstrap; /// /// Singleton manager for global game state and settings. Provides accessors for various gameplay parameters. /// public class GameManager : MonoBehaviour { private static GameManager _instance; private static bool _isQuitting = false; /// /// Singleton instance of the GameManager. No longer creates an instance if one doesn't exist. /// public static GameManager Instance => _instance; [Header("Settings Status")] [SerializeField] private bool _settingsLoaded = false; [SerializeField] private bool _developerSettingsLoaded = false; public bool SettingsLoaded => _settingsLoaded; public bool DeveloperSettingsLoaded => _developerSettingsLoaded; [Header("Game State")] [SerializeField] private bool _isPaused = false; /// /// Current pause state of the game /// public bool IsPaused => _isPaused; // List of pausable components that have registered with the GameManager private List _pausableComponents = new List(); // Events for pause state changes public event Action OnGamePaused; public event Action OnGameResumed; void Awake() { _instance = this; // Create settings provider if it doesn't exist SettingsProvider.Instance.gameObject.name = "Settings Provider"; // Create developer settings provider if it doesn't exist DeveloperSettingsProvider.Instance.gameObject.name = "Developer Settings Provider"; // Load all settings synchronously during Awake InitializeSettings(); InitializeDeveloperSettings(); // Register for post-boot initialization BootCompletionService.RegisterInitAction(InitializePostBoot); // DontDestroyOnLoad(gameObject); } private void InitializePostBoot() { // Find and subscribe to PauseMenu events PauseMenu pauseMenu = PauseMenu.Instance; if (pauseMenu != null) { pauseMenu.OnGamePaused += OnPauseMenuPaused; pauseMenu.OnGameResumed += OnPauseMenuResumed; Logging.Debug("[GameManager] Subscribed to PauseMenu events"); } else { Logging.Warning("[GameManager] PauseMenu not found. Pause functionality won't work properly."); } } private void OnDestroy() { // Unsubscribe from PauseMenu events PauseMenu pauseMenu = FindFirstObjectByType(); if (pauseMenu != null) { pauseMenu.OnGamePaused -= OnPauseMenuPaused; pauseMenu.OnGameResumed -= OnPauseMenuResumed; } } /// /// Register a component as pausable, so it receives pause/resume notifications /// /// The pausable component to register public void RegisterPausableComponent(IPausable component) { if (component != null && !_pausableComponents.Contains(component)) { _pausableComponents.Add(component); // If the game is already paused, pause the component immediately if (_isPaused) { component.Pause(); } Logging.Debug($"[GameManager] Registered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}"); } } /// /// Unregister a pausable component /// /// The pausable component to unregister public void UnregisterPausableComponent(IPausable component) { if (component != null && _pausableComponents.Contains(component)) { _pausableComponents.Remove(component); Logging.Debug($"[GameManager] Unregistered pausable component: {(component as MonoBehaviour)?.name ?? "Unknown"}"); } } /// /// Called when the PauseMenu broadcasts a pause event /// private void OnPauseMenuPaused() { PauseGame(); } /// /// Called when the PauseMenu broadcasts a resume event /// private void OnPauseMenuResumed() { ResumeGame(); } /// /// Pause the game and notify all registered pausable components /// public void PauseGame() { if (_isPaused) return; // Already paused _isPaused = true; // Pause all registered components foreach (var component in _pausableComponents) { component.Pause(); } // Broadcast pause event OnGamePaused?.Invoke(); Logging.Debug($"[GameManager] Game paused. Paused {_pausableComponents.Count} components."); } /// /// Resume the game and notify all registered pausable components /// public void ResumeGame() { if (!_isPaused) return; // Already running _isPaused = false; // Resume all registered components foreach (var component in _pausableComponents) { component.DoResume(); } // Broadcast resume event OnGameResumed?.Invoke(); Logging.Debug($"[GameManager] Game resumed. Resumed {_pausableComponents.Count} components."); } /// /// Toggle the pause state of the game /// public void TogglePause() { if (_isPaused) ResumeGame(); else PauseGame(); } private void InitializeSettings() { Logging.Debug("Starting settings initialization..."); // Load settings synchronously var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous(); var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous(); var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous(); // Register settings with service locator if (playerSettings != null) { ServiceLocator.Register(playerSettings); Logging.Debug("PlayerFollowerSettings registered successfully"); } else { Debug.LogError("Failed to load PlayerFollowerSettings"); } if (interactionSettings != null) { ServiceLocator.Register(interactionSettings); Logging.Debug("InteractionSettings registered successfully"); } else { Debug.LogError("Failed to load InteractionSettings"); } if (minigameSettings != null) { ServiceLocator.Register(minigameSettings); Logging.Debug("MinigameSettings registered successfully"); } else { Debug.LogError("Failed to load MinigameSettings"); } // Log success _settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null; if (_settingsLoaded) { Logging.Debug("All settings loaded and registered with ServiceLocator"); } else { Logging.Warning("Some settings failed to load - check that all settings assets exist and are marked as Addressables"); } } /// /// Check for and initialize developer settings. /// private void InitializeDeveloperSettings() { Logging.Debug("Starting developer settings initialization..."); // Load developer settings var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings(); _developerSettingsLoaded = divingDevSettings != null; if (_developerSettingsLoaded) { Logging.Debug("All developer settings loaded successfully"); } else { Logging.Warning("Some developer settings failed to load"); } } void OnApplicationQuit() { _isQuitting = true; ServiceLocator.Clear(); } // Helper method to get settings private T GetSettings() where T : class { return ServiceLocator.Get(); } /// /// Returns the entire settings object of specified type. /// /// Type of settings to retrieve /// The settings object or null if not found public static T GetSettingsObject() where T : class { return Instance?.GetSettings(); } /// /// Returns the developer settings object of specified type. /// /// Type of developer settings to retrieve /// The developer settings object or null if not found public static T GetDeveloperSettings() where T : BaseDeveloperSettings { return DeveloperSettingsProvider.Instance?.GetSettings(); } // LEFTOVER LEGACY SETTINGS public float PlayerStopDistance => GetSettings()?.PlayerStopDistance ?? 6.0f; public float PlayerStopDistanceDirectInteraction => GetSettings()?.PlayerStopDistanceDirectInteraction ?? 2.0f; public float DefaultPuzzlePromptRange => GetSettings()?.DefaultPuzzlePromptRange ?? 3.0f; }