#nullable enable using System.IO; using Cysharp.Threading.Tasks; using UnityEngine; namespace ShrinkDataSaver { public sealed class ShrinkDataSaverRuntimeConfig { public ShrinkDataSaverSettings? SettingsOverride { get; set; } public int CurrentSaveVersion { get; set; } = 1; public bool DontDestroyOnLoadDriver { get; set; } = true; } public static class ShrinkDataSaverRuntime { public static bool IsInitialized { get; private set; } public static void Initialize(ShrinkDataSaverRuntimeConfig? config = null) { if (IsInitialized) return; config ??= new ShrinkDataSaverRuntimeConfig(); var cfg = config.SettingsOverride ?? ShrinkDataSaverSettings.Instance; if (config.SettingsOverride) ShrinkDataSaverSettings.Instance = config.SettingsOverride; if (cfg == null) throw new System.InvalidOperationException("ShrinkDataSaverSettings instance is not available."); var rootPath = string.IsNullOrEmpty(cfg.customSavePath) ? Application.persistentDataPath : cfg.customSavePath; var savesDir = Path.Combine(rootPath, "saves"); var settingsPath = Path.Combine(rootPath, cfg.settingsFileName); var storage = new LocalStorageProvider(rootPath); ShrinkSettings.Initialize(storage, settingsPath); ShrinkSave.Initialize(storage, savesDir, cfg.saveFileExtension, config.CurrentSaveVersion); ShrinkSettings.LoadAsync().Forget(); ShrinkDataSaverLifecycleDriver.EnsureCreated(config.DontDestroyOnLoadDriver); IsInitialized = true; Debug.Log($"[ShrinkDataSaver] Runtime initialized. Root: {rootPath}"); } internal static void ResetForTesting() { IsInitialized = false; } } [DefaultExecutionOrder(-1999)] internal sealed class ShrinkDataSaverLifecycleDriver : MonoBehaviour { private static ShrinkDataSaverLifecycleDriver? _instance; private float _autoSaveTimer; public static void EnsureCreated(bool dontDestroyOnLoad) { if (_instance != null) return; var go = new GameObject("ShrinkDataSaverRuntimeDriver"); _instance = go.AddComponent(); if (dontDestroyOnLoad) DontDestroyOnLoad(go); } private void Update() { var interval = ShrinkSave.GetMinAutoSaveInterval(); if (interval <= 0f || ShrinkSave.LoadedSlot < 0) return; _autoSaveTimer += Time.unscaledDeltaTime; if (_autoSaveTimer < interval) return; _autoSaveTimer = 0f; ShrinkSave.SaveSlotAsync(ShrinkSave.LoadedSlot).Forget(); } private async void OnApplicationQuit() { await ShrinkSettings.SaveAsync(); } private async void OnApplicationPause(bool paused) { if (paused) await ShrinkSettings.SaveAsync(); } } }