using System.IO; using NeoModLoader.api; using NeoModLoader.constants; using NeoModLoader.services; namespace IdleSpectator; /// /// NML ModConfig accessors for Idle Spectator. /// public static class ModSettings { public const string GroupId = "Spectator"; public const string EnabledId = "enabled"; public const string ShowWatchReasonsId = "show_watch_reasons"; public const string ShowDossierCaptionId = "show_dossier_caption"; public const string ChronicleEnabledId = "chronicle_enabled"; public const string DebugStateProbeId = "debug_state_probe"; public const string GravestonesEnabledId = "gravestones_enabled"; public const string GravestoneMaxStacksId = "gravestone_max_stacks"; public const string GravestoneTtlSecondsId = "gravestone_ttl_seconds"; public const int DefaultGravestoneMaxStacks = 1000; public const int DefaultGravestoneTtlSeconds = 300; private static ModConfig _config; public static bool Enabled => GetBool(EnabledId, defaultValue: true); public static bool ShowWatchReasons => GetBool(ShowWatchReasonsId, defaultValue: true); public static bool ShowDossierCaption => GetBool(ShowDossierCaptionId, defaultValue: true); public static bool ChronicleEnabled => GetBool(ChronicleEnabledId, defaultValue: true); public static bool DebugStateProbe => GetBool(DebugStateProbeId, defaultValue: true); public static bool GravestonesEnabled => GetBool(GravestonesEnabledId, defaultValue: true); public static int GravestoneMaxStacks => GetInt(GravestoneMaxStacksId, DefaultGravestoneMaxStacks, min: 0, max: 2000); public static int GravestoneTtlSeconds => GetInt(GravestoneTtlSecondsId, DefaultGravestoneTtlSeconds, min: 30, max: 1800); public static ModConfig Load(ModDeclare declare) { string persistentPath = Path.Combine(Paths.ModsConfigPath, declare.UID + ".config"); ModConfig persistent = new ModConfig(persistentPath, pIsPersistent: true); string defaultsPath = Path.Combine(declare.FolderPath, Paths.ModDefaultConfigFileName); if (File.Exists(defaultsPath)) { ModConfig defaults = new ModConfig(defaultsPath); persistent.MergeWith(defaults); } _config = persistent; return _config; } /// NML config callback: IdleSpectator.ModSettings:OnEnabledChanged public static void OnEnabledChanged(bool enabled) { if (!enabled && SpectatorMode.Active) { SpectatorMode.SetActive(false); LogService.LogInfo("[IdleSpectator] Disabled via settings"); } if (!enabled) { GraveMarkers.Clear(); } } public static bool TrySetBool(string id, bool value) { if (_config == null || string.IsNullOrEmpty(id)) { return false; } try { ModConfigItem item = _config[GroupId][id]; item.SetValue(value); // Ensure settings callbacks apply even if NML does not fire them from SetValue. if (id == EnabledId) { OnEnabledChanged(value); } return true; } catch (System.Exception ex) { LogService.LogInfo($"[IdleSpectator] TrySetBool failed for {id}: {ex.Message}"); return false; } } public static bool TrySetInt(string id, int value) { if (_config == null || string.IsNullOrEmpty(id)) { return false; } try { ModConfigItem item = _config[GroupId][id]; item.SetValue(value); return true; } catch (System.Exception ex) { LogService.LogInfo($"[IdleSpectator] TrySetInt failed for {id}: {ex.Message}"); return false; } } private static bool GetBool(string id, bool defaultValue) { if (_config == null) { return defaultValue; } try { ModConfigItem item = _config[GroupId][id]; object value = item.GetValue(); if (value is bool b) { return b; } } catch { // Fall through to default. } return defaultValue; } private static int GetInt(string id, int defaultValue, int min, int max) { if (_config == null) { return UnityEngine.Mathf.Clamp(defaultValue, min, max); } try { ModConfigItem item = _config[GroupId][id]; object value = item.GetValue(); if (value is int i) { return UnityEngine.Mathf.Clamp(i, min, max); } if (value is long l) { return UnityEngine.Mathf.Clamp((int)l, min, max); } if (value is float f) { return UnityEngine.Mathf.Clamp(UnityEngine.Mathf.RoundToInt(f), min, max); } } catch { // Fall through to default. } return UnityEngine.Mathf.Clamp(defaultValue, min, max); } }