namespace Aeshnidae.Codex; /// /// Read from Settings.json in the deployed mod folder; written with defaults on first /// run. Nothing here touches the sections' content - each mod renders its own pages. /// public class Settings { public const string FileName = "Settings.json"; /// /// The weenie the Codex is made from. 364 is retail's blank "Book": fifty pages of a /// thousand characters, the writable kind vendors sold - so the client already /// knows how to open it, page it and render it. Changing this to a book with fewer /// pages truncates the Codex; the contents page says how many fit. /// public uint BookWcid { get; set; } = 364; /// What the book is called. Also how an existing one is recognised, so rename with care. public string Name { get; set; } = "Aelrynth Codex"; /// The line under the title when the book is examined. public string Inscription { get; set; } = "Everything the server knows about you, rewritten each time you open it."; /// A dat icon id to use instead of the book's own. 0 keeps the book's icon. public uint IconOverride { get; set; } = 0; /// Hand a Codex to every character that enters the world without one. public bool GrantOnLogin { get; set; } = true; /// /// Characters per page. Retail parchment was 1,000 and the book window was built /// for it; a page longer than the book's own MaxNumCharsPerPage is cut regardless. /// public int MaxCharsPerPage { get; set; } = 1000; /// /// The mods whose CodexPage is asked for pages, in book order. A mod that is off, /// or has no CodexPage, is skipped. /codex sections shows which answer. /// public string[] Sections { get; set; } = { "Aeshnidae.Bank", "Aeshnidae.SkillMastery", "Aeshnidae.ResonanceAuras", "Aeshnidae.QuestBonus", "Aeshnidae.Enlightenment", "Aeshnidae.Leaderboard", }; private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true, ReadCommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true, }; public static Settings Load(string modPath) { var path = Path.Combine(modPath, FileName); try { if (File.Exists(path)) { var loaded = JsonSerializer.Deserialize(File.ReadAllText(path), JsonOptions) ?? new Settings(); loaded.Sections ??= Array.Empty(); return loaded; } var defaults = new Settings(); defaults.Save(modPath); ModManager.Log($"[{Mod.Name}] wrote default settings to {path}"); return defaults; } catch (Exception ex) { ModManager.Log($"[{Mod.Name}] could not read {path}, using defaults: {ex.Message}", ModManager.LogLevel.Warn); return new Settings(); } } public void Save(string modPath) { try { File.WriteAllText(Path.Combine(modPath, FileName), JsonSerializer.Serialize(this, JsonOptions)); } catch (Exception ex) { ModManager.Log($"[{Mod.Name}] could not save settings: {ex.Message}", ModManager.LogLevel.Error); } } }