mirror of
https://github.com/project-redbud/FunGame-Core.git
synced 2025-04-23 12:39:35 +08:00
文本配置器添加只读读取;添加桌面版连接参数 (#111)
This commit is contained in:
parent
9e55587ea0
commit
99493f4e73
@ -19,6 +19,11 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static string RootPath { get; set; } = "novels";
|
public static string RootPath { get; set; } = "novels";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否允许 <see cref="SaveConfig"/>
|
||||||
|
/// </summary>
|
||||||
|
public bool Readonly { get; set; } = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 模组的名称
|
/// 模组的名称
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -29,6 +34,12 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string FileName { get; set; } = file_name;
|
public string FileName { get; set; } = file_name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 断言方法字典<para/>
|
||||||
|
/// <see cref="NovelNode"/> 和 <see cref="NovelOption"/> 都有显示的条件,反序列化 json 文件时,会根据其名称来分配具体的断言方法
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, Func<bool>> Predicates { get; set; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用索引器给指定key赋值,不存在key会新增
|
/// 使用索引器给指定key赋值,不存在key会新增
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -62,29 +73,24 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="key"></param>
|
/// <param name="key"></param>
|
||||||
/// <param name="value"></param>
|
/// <param name="value"></param>
|
||||||
public new void Add(string key, NovelNode value)
|
public new void Add(string key, NovelNode value) => base[key] = value;
|
||||||
{
|
|
||||||
if (value != null)
|
|
||||||
{
|
|
||||||
if (TryGetValue(key, out _)) base[key] = value;
|
|
||||||
else base.Add(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 从指定路径加载配置文件,并根据其文件名,转换为本框架所需的文件<para/>
|
/// 从指定路径加载配置文件,并根据其文件名,转换为本框架所需的文件<para/>
|
||||||
|
/// <paramref name="copyToRootPath"/> 为 false 时将不会复制此文件至配置文件目录并且不允许 <see cref="SaveConfig"/><para/>
|
||||||
/// 需要注意:<paramref name="checkConflict"/> 用于检查加载的文件名是否在配置文件目录中已经存在<para/>
|
/// 需要注意:<paramref name="checkConflict"/> 用于检查加载的文件名是否在配置文件目录中已经存在<para/>
|
||||||
/// 如果不使用此检查,使用 <see cref="SaveConfig"/> 时可能会覆盖原有文件(程序目录/<see cref="RootPath"/>(通常是 novels)/<paramref name="novelName"/>/[所选的文件名].json)
|
/// 如果不使用此检查,使用 <see cref="SaveConfig"/> 时可能会覆盖原有文件(程序目录/<see cref="RootPath"/>(通常是 novels)/<paramref name="novelName"/>/[所选的文件名].json)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path"></param>
|
/// <param name="path"></param>
|
||||||
/// <param name="novelName"></param>
|
/// <param name="novelName"></param>
|
||||||
|
/// <param name="copyToRootPath"></param>
|
||||||
/// <param name="checkConflict"></param>
|
/// <param name="checkConflict"></param>
|
||||||
/// <param name="predicates"></param>
|
/// <param name="predicates"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
/// <exception cref="FileNotFoundException" />
|
/// <exception cref="FileNotFoundException" />
|
||||||
/// <exception cref="InvalidOperationException" />
|
/// <exception cref="InvalidOperationException" />
|
||||||
/// <exception cref="InvalidDataException" />
|
/// <exception cref="InvalidDataException" />
|
||||||
public static NovelConfig LoadFrom(string path, string novelName, bool checkConflict = true, Dictionary<string, Func<bool>>? predicates = null)
|
public static NovelConfig LoadFrom(string path, string novelName, bool copyToRootPath = true, bool checkConflict = true, Dictionary<string, Func<bool>>? predicates = null)
|
||||||
{
|
{
|
||||||
if (!File.Exists(path))
|
if (!File.Exists(path))
|
||||||
{
|
{
|
||||||
@ -92,28 +98,42 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
|||||||
}
|
}
|
||||||
|
|
||||||
string fileName = Path.GetFileNameWithoutExtension(path);
|
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<Dictionary<string, NovelNode>>(json) is null)
|
||||||
|
{
|
||||||
|
throw new InvalidDataException($"文件 {path} 内容为空或格式不正确。");
|
||||||
|
}
|
||||||
|
File.WriteAllText(fpath, json, General.DefaultEncoding);
|
||||||
|
|
||||||
|
config = new(novelName, fileName);
|
||||||
|
config.LoadConfig(predicates);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
// 确保目录存在
|
|
||||||
ExistsDirectoryAndCreate(novelName);
|
|
||||||
|
|
||||||
// 复制文件内容
|
|
||||||
string json = File.ReadAllText(path, General.DefaultEncoding);
|
|
||||||
if (NetworkUtility.JsonDeserialize<Dictionary<string, NovelNode>>(json) is null)
|
|
||||||
{
|
{
|
||||||
throw new InvalidDataException($"文件 {path} 内容为空或格式不正确。");
|
// 从新文件加载配置
|
||||||
|
config = new(novelName, fileName)
|
||||||
|
{
|
||||||
|
Readonly = true
|
||||||
|
};
|
||||||
|
string json = File.ReadAllText(path, General.DefaultEncoding);
|
||||||
|
Dictionary<string, NovelNode> dict = NetworkUtility.JsonDeserialize<Dictionary<string, NovelNode>>(json) ?? [];
|
||||||
|
config.LoadConfig(dict, predicates);
|
||||||
}
|
}
|
||||||
File.WriteAllText(fpath, json, General.DefaultEncoding);
|
|
||||||
|
|
||||||
// 从新文件加载配置
|
|
||||||
NovelConfig config = new(novelName, fileName);
|
|
||||||
config.LoadConfig(predicates);
|
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@ -130,80 +150,98 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
|||||||
{
|
{
|
||||||
string json = File.ReadAllText(fpath, General.DefaultEncoding);
|
string json = File.ReadAllText(fpath, General.DefaultEncoding);
|
||||||
Dictionary<string, NovelNode> dict = NetworkUtility.JsonDeserialize<Dictionary<string, NovelNode>>(json) ?? [];
|
Dictionary<string, NovelNode> dict = NetworkUtility.JsonDeserialize<Dictionary<string, NovelNode>>(json) ?? [];
|
||||||
Clear();
|
LoadConfig(dict, predicates);
|
||||||
foreach (string key in dict.Keys)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 根据断言方法字典重新生成小说的字典
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="dict"></param>
|
||||||
|
/// <param name="predicates"></param>
|
||||||
|
private void LoadConfig(Dictionary<string, NovelNode> dict, Dictionary<string, Func<bool>>? predicates = null)
|
||||||
|
{
|
||||||
|
if (predicates != null)
|
||||||
|
{
|
||||||
|
foreach (string key in predicates.Keys)
|
||||||
{
|
{
|
||||||
NovelNode obj = dict[key];
|
// 直接覆盖
|
||||||
base.Add(key, obj);
|
Predicates[key] = predicates[key];
|
||||||
if (obj.Values.TryGetValue(nameof(NovelNode.Previous), out object? value) && value is string prevKey && dict.Values.FirstOrDefault(n => n.Key == prevKey) is NovelNode prev)
|
}
|
||||||
|
}
|
||||||
|
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<string> nextKeys)
|
||||||
|
{
|
||||||
|
foreach (string nextKey in nextKeys)
|
||||||
{
|
{
|
||||||
obj.Previous = prev;
|
if (dict.TryGetValue(nextKey, out NovelNode? node) && node != null)
|
||||||
}
|
|
||||||
if (obj.Values.TryGetValue(nameof(NovelNode.NextNodes), out value) && value is List<string> nextKeys)
|
|
||||||
{
|
|
||||||
foreach (string nextKey in nextKeys)
|
|
||||||
{
|
{
|
||||||
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<string> aps)
|
||||||
|
{
|
||||||
|
foreach (string ap in aps)
|
||||||
|
{
|
||||||
|
if (Predicates.TryGetValue(ap, out Func<bool>? 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<string> ops)
|
||||||
{
|
{
|
||||||
if (obj.Values.TryGetValue(nameof(NovelNode.AndPredicates), out object? value2) && value2 is List<string> aps)
|
foreach (string op in ops)
|
||||||
|
{
|
||||||
|
if (Predicates.TryGetValue(op, out Func<bool>? 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<string> 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<string> aps)
|
||||||
{
|
{
|
||||||
foreach (string ap in aps)
|
foreach (string ap in aps)
|
||||||
{
|
{
|
||||||
if (predicates.TryGetValue(ap, out Func<bool>? value3) && value3 != null)
|
if (Predicates.TryGetValue(ap, out Func<bool>? value4) && value4 != null)
|
||||||
{
|
{
|
||||||
obj.AndPredicates[ap] = value3;
|
option.AndPredicates[ap] = value4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (obj.Values.TryGetValue(nameof(NovelNode.OrPredicates), out value2) && value2 is List<string> ops)
|
if (option.Values.TryGetValue(nameof(NovelNode.OrPredicates), out value3) && value3 is List<string> ops)
|
||||||
{
|
{
|
||||||
foreach (string op in ops)
|
foreach (string op in ops)
|
||||||
{
|
{
|
||||||
if (predicates.TryGetValue(op, out Func<bool>? value3) && value3 != null)
|
if (Predicates.TryGetValue(op, out Func<bool>? value4) && value4 != null)
|
||||||
{
|
{
|
||||||
obj.OrPredicates[op] = value3;
|
option.OrPredicates[op] = value4;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
foreach (NovelOption option in obj.Options)
|
|
||||||
{
|
|
||||||
if (option.Values.TryGetValue(nameof(NovelOption.Targets), out object? value2) && value2 is List<string> 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<string> aps)
|
|
||||||
{
|
|
||||||
foreach (string ap in aps)
|
|
||||||
{
|
|
||||||
if (predicates.TryGetValue(ap, out Func<bool>? value4) && value4 != null)
|
|
||||||
{
|
|
||||||
option.AndPredicates[ap] = value4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (option.Values.TryGetValue(nameof(NovelNode.OrPredicates), out value3) && value3 is List<string> ops)
|
|
||||||
{
|
|
||||||
foreach (string op in ops)
|
|
||||||
{
|
|
||||||
if (predicates.TryGetValue(op, out Func<bool>? value4) && value4 != null)
|
|
||||||
{
|
|
||||||
option.OrPredicates[op] = value4;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,6 +255,10 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public void SaveConfig()
|
public void SaveConfig()
|
||||||
{
|
{
|
||||||
|
if (Readonly)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
string json = NetworkUtility.JsonSerialize((Dictionary<string, NovelNode>)this);
|
string json = NetworkUtility.JsonSerialize((Dictionary<string, NovelNode>)this);
|
||||||
string dpath = $@"{AppDomain.CurrentDomain.BaseDirectory}{RootPath}/{NovelName}";
|
string dpath = $@"{AppDomain.CurrentDomain.BaseDirectory}{RootPath}/{NovelName}";
|
||||||
string fpath = $@"{dpath}/{FileName}.json";
|
string fpath = $@"{dpath}/{FileName}.json";
|
||||||
|
@ -90,6 +90,7 @@ namespace Milimoe.FunGame.Core.Api.Utility
|
|||||||
WriteINI("Server", "Key", "");
|
WriteINI("Server", "Key", "");
|
||||||
WriteINI("Server", "Status", "1");
|
WriteINI("Server", "Status", "1");
|
||||||
WriteINI("Server", "BannedList", "");
|
WriteINI("Server", "BannedList", "");
|
||||||
|
WriteINI("Server", "UseDesktopParameters", "true");
|
||||||
/**
|
/**
|
||||||
* ServerMail
|
* ServerMail
|
||||||
*/
|
*/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user