diff --git a/Api/Utility/NovelConfig.cs b/Api/Utility/NovelConfig.cs index ac20278..93b3898 100644 --- a/Api/Utility/NovelConfig.cs +++ b/Api/Utility/NovelConfig.cs @@ -19,6 +19,11 @@ namespace Milimoe.FunGame.Core.Api.Utility /// public static string RootPath { get; set; } = "novels"; + /// + /// 是否允许 + /// + public bool Readonly { get; set; } = false; + /// /// 模组的名称 /// @@ -29,6 +34,12 @@ namespace Milimoe.FunGame.Core.Api.Utility /// public string FileName { get; set; } = file_name; + /// + /// 断言方法字典 + /// 都有显示的条件,反序列化 json 文件时,会根据其名称来分配具体的断言方法 + /// + public Dictionary> Predicates { get; set; } = []; + /// /// 使用索引器给指定key赋值,不存在key会新增 /// @@ -62,29 +73,24 @@ namespace Milimoe.FunGame.Core.Api.Utility /// /// /// - public new void Add(string key, NovelNode value) - { - if (value != null) - { - if (TryGetValue(key, out _)) base[key] = value; - else base.Add(key, value); - } - } + public new void Add(string key, NovelNode value) => base[key] = value; /// /// 从指定路径加载配置文件,并根据其文件名,转换为本框架所需的文件 + /// 为 false 时将不会复制此文件至配置文件目录并且不允许 /// 需要注意: 用于检查加载的文件名是否在配置文件目录中已经存在 /// 如果不使用此检查,使用 时可能会覆盖原有文件(程序目录/(通常是 novels)//[所选的文件名].json) /// /// /// + /// /// /// /// /// /// /// - public static NovelConfig LoadFrom(string path, string novelName, bool checkConflict = true, Dictionary>? predicates = null) + public static NovelConfig LoadFrom(string path, string novelName, bool copyToRootPath = true, bool checkConflict = true, Dictionary>? predicates = null) { if (!File.Exists(path)) { @@ -92,28 +98,42 @@ namespace Milimoe.FunGame.Core.Api.Utility } string fileName = Path.GetFileNameWithoutExtension(path); - string dpath = $@"{AppDomain.CurrentDomain.BaseDirectory}{RootPath}/{novelName}"; - string fpath = $@"{dpath}/{fileName}.json"; - if (checkConflict && File.Exists(fpath)) + NovelConfig config; + if (copyToRootPath) { - throw new InvalidOperationException($"文件 {fileName}.json 已存在,请先重命名。"); + string dpath = $@"{AppDomain.CurrentDomain.BaseDirectory}{RootPath}/{novelName}"; + string fpath = $@"{dpath}/{fileName}.json"; + if (checkConflict && File.Exists(fpath)) + { + throw new InvalidOperationException($"文件 {fileName}.json 已存在,请先重命名。"); + } + + // 确保目录存在 + ExistsDirectoryAndCreate(novelName); + + // 复制文件内容 + string json = File.ReadAllText(path, General.DefaultEncoding); + if (NetworkUtility.JsonDeserialize>(json) is null) + { + throw new InvalidDataException($"文件 {path} 内容为空或格式不正确。"); + } + File.WriteAllText(fpath, json, General.DefaultEncoding); + + config = new(novelName, fileName); + config.LoadConfig(predicates); } - - // 确保目录存在 - ExistsDirectoryAndCreate(novelName); - - // 复制文件内容 - string json = File.ReadAllText(path, General.DefaultEncoding); - if (NetworkUtility.JsonDeserialize>(json) is null) + else { - throw new InvalidDataException($"文件 {path} 内容为空或格式不正确。"); + // 从新文件加载配置 + config = new(novelName, fileName) + { + Readonly = true + }; + string json = File.ReadAllText(path, General.DefaultEncoding); + Dictionary dict = NetworkUtility.JsonDeserialize>(json) ?? []; + config.LoadConfig(dict, predicates); } - File.WriteAllText(fpath, json, General.DefaultEncoding); - - // 从新文件加载配置 - NovelConfig config = new(novelName, fileName); - config.LoadConfig(predicates); return config; } @@ -130,80 +150,98 @@ namespace Milimoe.FunGame.Core.Api.Utility { string json = File.ReadAllText(fpath, General.DefaultEncoding); Dictionary dict = NetworkUtility.JsonDeserialize>(json) ?? []; - Clear(); - foreach (string key in dict.Keys) + LoadConfig(dict, predicates); + } + } + + /// + /// 根据断言方法字典重新生成小说的字典 + /// + /// + /// + private void LoadConfig(Dictionary dict, Dictionary>? predicates = null) + { + if (predicates != null) + { + foreach (string key in predicates.Keys) { - NovelNode obj = dict[key]; - base.Add(key, obj); - if (obj.Values.TryGetValue(nameof(NovelNode.Previous), out object? value) && value is string prevKey && dict.Values.FirstOrDefault(n => n.Key == prevKey) is NovelNode prev) + // 直接覆盖 + Predicates[key] = predicates[key]; + } + } + Clear(); + foreach (string key in dict.Keys) + { + NovelNode obj = dict[key]; + base.Add(key, obj); + if (obj.Values.TryGetValue(nameof(NovelNode.Previous), out object? value) && value is string prevKey && dict.Values.FirstOrDefault(n => n.Key == prevKey) is NovelNode prev) + { + obj.Previous = prev; + } + if (obj.Values.TryGetValue(nameof(NovelNode.NextNodes), out value) && value is List nextKeys) + { + foreach (string nextKey in nextKeys) { - obj.Previous = prev; - } - if (obj.Values.TryGetValue(nameof(NovelNode.NextNodes), out value) && value is List nextKeys) - { - foreach (string nextKey in nextKeys) + if (dict.TryGetValue(nextKey, out NovelNode? node) && node != null) { - if (dict.TryGetValue(nextKey, out NovelNode? node) && node != null) + obj.NextNodes.Add(node); + } + } + } + if (Predicates != null) + { + if (obj.Values.TryGetValue(nameof(NovelNode.AndPredicates), out object? value2) && value2 is List aps) + { + foreach (string ap in aps) + { + if (Predicates.TryGetValue(ap, out Func? value3) && value3 != null) { - obj.NextNodes.Add(node); + obj.AndPredicates[ap] = value3; } } } - if (predicates != null) + if (obj.Values.TryGetValue(nameof(NovelNode.OrPredicates), out value2) && value2 is List ops) { - if (obj.Values.TryGetValue(nameof(NovelNode.AndPredicates), out object? value2) && value2 is List aps) + foreach (string op in ops) + { + if (Predicates.TryGetValue(op, out Func? value3) && value3 != null) + { + obj.OrPredicates[op] = value3; + } + } + } + } + foreach (NovelOption option in obj.Options) + { + if (option.Values.TryGetValue(nameof(NovelOption.Targets), out object? value2) && value2 is List targets) + { + foreach (string targetKey in targets) + { + if (dict.TryGetValue(targetKey, out NovelNode? node) && node != null) + { + option.Targets.Add(node); + } + } + } + if (Predicates != null) + { + if (option.Values.TryGetValue(nameof(NovelNode.AndPredicates), out object? value3) && value3 is List aps) { foreach (string ap in aps) { - if (predicates.TryGetValue(ap, out Func? value3) && value3 != null) + if (Predicates.TryGetValue(ap, out Func? value4) && value4 != null) { - obj.AndPredicates[ap] = value3; + option.AndPredicates[ap] = value4; } } } - if (obj.Values.TryGetValue(nameof(NovelNode.OrPredicates), out value2) && value2 is List ops) + if (option.Values.TryGetValue(nameof(NovelNode.OrPredicates), out value3) && value3 is List ops) { foreach (string op in ops) { - if (predicates.TryGetValue(op, out Func? value3) && value3 != null) + if (Predicates.TryGetValue(op, out Func? value4) && value4 != null) { - obj.OrPredicates[op] = value3; - } - } - } - } - foreach (NovelOption option in obj.Options) - { - if (option.Values.TryGetValue(nameof(NovelOption.Targets), out object? value2) && value2 is List targets) - { - foreach (string targetKey in targets) - { - if (dict.TryGetValue(targetKey, out NovelNode? node) && node != null) - { - option.Targets.Add(node); - } - } - } - if (predicates != null) - { - if (option.Values.TryGetValue(nameof(NovelNode.AndPredicates), out object? value3) && value3 is List aps) - { - foreach (string ap in aps) - { - if (predicates.TryGetValue(ap, out Func? value4) && value4 != null) - { - option.AndPredicates[ap] = value4; - } - } - } - if (option.Values.TryGetValue(nameof(NovelNode.OrPredicates), out value3) && value3 is List ops) - { - foreach (string op in ops) - { - if (predicates.TryGetValue(op, out Func? value4) && value4 != null) - { - option.OrPredicates[op] = value4; - } + option.OrPredicates[op] = value4; } } } @@ -217,6 +255,10 @@ namespace Milimoe.FunGame.Core.Api.Utility /// public void SaveConfig() { + if (Readonly) + { + return; + } string json = NetworkUtility.JsonSerialize((Dictionary)this); string dpath = $@"{AppDomain.CurrentDomain.BaseDirectory}{RootPath}/{NovelName}"; string fpath = $@"{dpath}/{FileName}.json"; diff --git a/Api/Utility/TextReader.cs b/Api/Utility/TextReader.cs index 6ed1091..07a90ae 100644 --- a/Api/Utility/TextReader.cs +++ b/Api/Utility/TextReader.cs @@ -90,6 +90,7 @@ namespace Milimoe.FunGame.Core.Api.Utility WriteINI("Server", "Key", ""); WriteINI("Server", "Status", "1"); WriteINI("Server", "BannedList", ""); + WriteINI("Server", "UseDesktopParameters", "true"); /** * ServerMail */