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
*/