using System; using System.Collections.Generic; using System.Threading.Tasks; using UnityEngine; namespace Bootstrap { /// /// A service that provides information about the boot completion status /// and allows systems to register for callbacks when boot is complete. /// public static class BootCompletionService { /// /// True if the boot process has fully completed /// public static bool IsBootComplete { get; private set; } /// /// Timestamp when the boot completed (Time.realtimeSinceStartup) /// public static float BootCompletionTime { get; private set; } /// /// Event triggered when boot process completes. /// Will be triggered immediately for new subscribers if boot is already complete. /// public static event Action OnBootComplete; /// /// Actions to be executed in a specific order once boot completes /// private static readonly List _orderedInitActions = new List(); /// /// Task completion source for async boot completion waiting /// private static TaskCompletionSource _bootCompletionTask; /// /// Initialize the service - called by CustomBoot /// [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterSceneLoad)] private static void Initialize() { // Reset state IsBootComplete = false; _bootCompletionTask = new TaskCompletionSource(); // Subscribe to CustomBoot completion event CustomBoot.OnBootCompleted += HandleBootCompleted; Debug.Log("[BootCompletionService] Initialized and waiting for boot completion"); } /// /// Handler for when CustomBoot reports completion /// private static void HandleBootCompleted() { if (IsBootComplete) return; // Avoid duplicate triggers IsBootComplete = true; BootCompletionTime = Time.realtimeSinceStartup; Debug.Log($"[BootCompletionService] Boot completed at {BootCompletionTime:F2}s since startup"); // Execute ordered initialization actions ExecuteOrderedInitActions(); // Complete the task _bootCompletionTask.TrySetResult(true); // Trigger the event OnBootComplete?.Invoke(); } /// /// Execute the registered ordered initialization actions /// private static void ExecuteOrderedInitActions() { // Sort actions by priority _orderedInitActions.Sort((a, b) => a.Priority.CompareTo(b.Priority)); foreach (var action in _orderedInitActions) { try { Debug.Log($"[BootCompletionService] Executing priority {action.Priority} initialization: {action.Name}"); action.Action?.Invoke(); } catch (Exception e) { Debug.LogError($"[BootCompletionService] Error executing initialization action '{action.Name}': {e.Message}\n{e.StackTrace}"); } } // Clear the list after execution _orderedInitActions.Clear(); } /// /// Register an action to be executed when boot is complete. /// If boot is already complete, the action will execute immediately. /// /// The action to execute /// Lower numbers execute first (default: 100) /// Optional name for debugging public static void RegisterInitAction(Action action, int priority = 100, string name = null) { if (action == null) return; name = name ?? $"Anonymous_{_orderedInitActions.Count}"; if (IsBootComplete) { // Boot already completed, execute immediately Debug.Log($"[BootCompletionService] Executing late initialization: {name} (boot already complete)"); try { action.Invoke(); } catch (Exception e) { Debug.LogError($"[BootCompletionService] Error executing late initialization action '{name}': {e.Message}\n{e.StackTrace}"); } } else { // Add to ordered list _orderedInitActions.Add(new OrderedInitAction { Action = action, Priority = priority, Name = name }); Debug.Log($"[BootCompletionService] Registered initialization action: {name} with priority {priority}"); } } /// /// Returns a task that completes when the boot process is complete. /// If boot is already complete, returns a completed task. /// public static Task WaitForBootCompletionAsync() { if (IsBootComplete) { return Task.CompletedTask; } return _bootCompletionTask.Task; } /// /// Structure for ordered initialization actions /// private class OrderedInitAction { public Action Action; public int Priority; public string Name; } } }