using UnityEngine; using System.Collections.Generic; using PuzzleS; using UnityEngine.SceneManagement; /// /// Manages puzzle step registration, dependency management, and step completion for the puzzle system. /// public class PuzzleManager : MonoBehaviour { private static PuzzleManager _instance; private static bool _isQuitting = false; /// /// Singleton instance of the PuzzleManager. /// public static PuzzleManager Instance { get { if (_instance == null && Application.isPlaying && !_isQuitting) { _instance = FindAnyObjectByType(); if (_instance == null) { var go = new GameObject("PuzzleManager"); _instance = go.AddComponent(); // DontDestroyOnLoad(go); } } return _instance; } } private HashSet completedSteps = new HashSet(); private HashSet unlockedSteps = new HashSet(); // Registration for ObjectiveStepBehaviour private Dictionary stepBehaviours = new Dictionary(); // Runtime dependency graph private Dictionary> runtimeDependencies = new Dictionary>(); void Awake() { _instance = this; // DontDestroyOnLoad(gameObject); SceneManager.sceneLoaded += OnSceneLoaded; } void OnDestroy() { SceneManager.sceneLoaded -= OnSceneLoaded; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { BuildRuntimeDependencies(); UnlockInitialSteps(); } /// /// Registers a step behaviour with the manager. /// /// The step behaviour to register. public void RegisterStepBehaviour(ObjectiveStepBehaviour behaviour) { if (behaviour?.stepData == null) return; if (!stepBehaviours.ContainsKey(behaviour.stepData)) { stepBehaviours.Add(behaviour.stepData, behaviour); Debug.Log($"[Puzzles] Registered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); } } /// /// Unregisters a step behaviour from the manager. /// /// The step behaviour to unregister. public void UnregisterStepBehaviour(ObjectiveStepBehaviour behaviour) { if (behaviour?.stepData == null) return; stepBehaviours.Remove(behaviour.stepData); Debug.Log($"[Puzzles] Unregistered step: {behaviour.stepData.stepId} on {behaviour.gameObject.name}"); } /// /// Builds the runtime dependency graph for all registered steps. /// private void BuildRuntimeDependencies() { runtimeDependencies = PuzzleGraphUtility.BuildDependencyGraph(stepBehaviours.Keys); foreach (var step in runtimeDependencies.Keys) { foreach (var dep in runtimeDependencies[step]) { Debug.Log($"[Puzzles] Step {step.stepId} depends on {dep.stepId}"); } } Debug.Log($"[Puzzles] Runtime dependencies built. Total steps: {stepBehaviours.Count}"); } /// /// Unlocks all initial steps (those with no dependencies). /// private void UnlockInitialSteps() { var initialSteps = PuzzleGraphUtility.FindInitialSteps(runtimeDependencies); foreach (var step in initialSteps) { Debug.Log($"[Puzzles] Initial step unlocked: {step.stepId}"); UnlockStep(step); } } /// /// Called when a step is completed. Unlocks dependent steps if their dependencies are met. /// /// The completed step. public void OnStepCompleted(PuzzleStepSO step) { if (completedSteps.Contains(step)) return; completedSteps.Add(step); Debug.Log($"[Puzzles] Step completed: {step.stepId}"); foreach (var unlock in step.unlocks) { if (AreRuntimeDependenciesMet(unlock)) { Debug.Log($"[Puzzles] Unlocking step {unlock.stepId} after completing {step.stepId}"); UnlockStep(unlock); } else { Debug.Log($"[Puzzles] Step {unlock.stepId} not unlocked yet, waiting for other dependencies"); } } CheckPuzzleCompletion(); } /// /// Checks if all dependencies for a step are met. /// /// The step to check. /// True if all dependencies are met, false otherwise. private bool AreRuntimeDependenciesMet(PuzzleStepSO step) { if (!runtimeDependencies.ContainsKey(step) || runtimeDependencies[step].Count == 0) return true; foreach (var dep in runtimeDependencies[step]) { if (!completedSteps.Contains(dep)) return false; } return true; } /// /// Unlocks a specific step and notifies its behaviour. /// /// The step to unlock. private void UnlockStep(PuzzleStepSO step) { if (unlockedSteps.Contains(step)) return; unlockedSteps.Add(step); if (stepBehaviours.TryGetValue(step, out var behaviour)) { behaviour.UnlockStep(); } Debug.Log($"[Puzzles] Step unlocked: {step.stepId}"); } /// /// Checks if the puzzle is complete (all steps finished). /// private void CheckPuzzleCompletion() { if (completedSteps.Count == stepBehaviours.Count) { Debug.Log("[Puzzles] Puzzle complete! All steps finished."); // TODO: Fire puzzle complete event or trigger outcome logic } } void OnApplicationQuit() { _isQuitting = true; } }