(client) feat:支持定义实体的碰撞体大小和偏移;建筑支持定义实体建筑和瓦片建筑,建筑支持指定按钮回调;添加存档管理器;Dev支持设置是否暂停;实体允许定义事件组;添加基地界面 (#57)

Co-authored-by: m0_75251201 <m0_75251201@noreply.gitcode.com>
Reviewed-on: http://47.107.252.169:3000/Roguelite-Game-Developing-Team/Gen_Hack-and-Slash-Roguelite/pulls/57
This commit is contained in:
2025-09-28 15:02:57 +08:00
parent 87a8abe86c
commit aff747be17
232 changed files with 39203 additions and 4161 deletions

View File

@@ -1,4 +1,3 @@
using System.Collections.Generic;
using System.IO;
using Managers;
@@ -10,7 +9,7 @@ namespace Configs
{
/// <summary>
/// 配置管理器,采用单例模式,负责读取、修改、存储应用程序配置。
/// 继承自 Utils.Singleton<ConfigManager> 和 ILaunchManager。
/// 继承自 Utils.Singleton&lt;ConfigManager&gt; 和 ILaunchManager。
/// </summary>
public class ConfigManager : Utils.Singleton<ConfigManager>, ILaunchManager
{
@@ -20,9 +19,9 @@ namespace Configs
private const string CONFIG_FILE_NAME = "app_config.json";
/// <summary>
/// 完整的配置文件路径
/// Application.persistentDataPath 在PC上是 C:/Users/用户名/AppData/LocalLow/公司名/项目名/
/// 在Android/iOS上是持久存储路径
/// 完整的配置文件路径,文件位于程序的可执行文件同级目录。
/// 在编辑器中:通常是 Assets 文件夹的父目录。
/// 在构建后:与可执行文件(例如 .exe在同一目录下
/// </summary>
private readonly string _configFilePath;
@@ -36,9 +35,15 @@ namespace Configs
/// </summary>
public ConfigManager()
{
_configFilePath = Path.Combine(Application.persistentDataPath, CONFIG_FILE_NAME);
string appDirectory = Path.GetDirectoryName(Application.dataPath);
if (string.IsNullOrEmpty(appDirectory))
{
appDirectory = Application.dataPath;
}
_configFilePath = Path.Combine(appDirectory, CONFIG_FILE_NAME);
_configData = new Dictionary<string, JToken>();
Debug.Log($"ConfigManager initialized. Config file path: {_configFilePath}");
Debug.Log($"ConfigManager 初始化。配置文件路径: {_configFilePath}");
}
public string StepDescription => "载入配置文件";
@@ -71,29 +76,42 @@ namespace Configs
{
try
{
string json = File.ReadAllText(_configFilePath);
var json = File.ReadAllText(_configFilePath);
if (string.IsNullOrWhiteSpace(json))
{
Debug.LogWarning($"ConfigManager: 配置文件 '{_configFilePath}' 为空。正在创建默认配置。");
CreateDefaultConfig();
SaveConfig();
return;
}
_configData = JsonConvert.DeserializeObject<Dictionary<string, JToken>>(json);
if (_configData == null)
{
Debug.LogWarning($"ConfigManager: 配置文件 '{_configFilePath}' 包含无效结构。正在创建默认配置。");
CreateDefaultConfig();
SaveConfig();
}
}
catch (JsonException ex)
{
Debug.LogError(
$"ConfigManager: Failed to deserialize config file. Creating default config. Error: {ex.Message}");
$"ConfigManager: 反序列化配置文件 '{_configFilePath}' 失败。正在创建默认配置。错误: {ex.Message}");
CreateDefaultConfig();
SaveConfig(); // 保存默认配置
SaveConfig();
}
catch (IOException ex)
{
Debug.LogError(
$"ConfigManager: Failed to read config file. Creating default config. Error: {ex.Message}");
$"ConfigManager: 读取配置文件 '{_configFilePath}' 失败。正在创建默认配置。错误: {ex.Message}");
CreateDefaultConfig();
SaveConfig(); // 保存默认配置
SaveConfig();
}
}
else
{
Debug.Log("ConfigManager: Config file not found. Creating default config.");
Debug.Log($"ConfigManager: 配置文件 '{_configFilePath}' 未找到。正在创建默认配置。");
CreateDefaultConfig();
SaveConfig(); // 保存默认配置
SaveConfig();
}
}
@@ -103,9 +121,11 @@ namespace Configs
private void CreateDefaultConfig()
{
_configData = new Dictionary<string, JToken>();
SetValue("playerAffiliation","player");
SetValue("outsideDimension","DefaultOutsideDimension");
SetValue("insideDimension","DefaultInsideDimension");
SetValue("playerAffiliation", "player");
SetValue("outsideDimension", "DefaultOutsideDimension");
SetValue("insideDimension", "DefaultInsideDimension");
SetValue("baseDimension", "DefaultBaseDimension");
SetValue("configVersion", 1);
}
/// <summary>
@@ -115,18 +135,21 @@ namespace Configs
{
try
{
// 使用 Formatting.Indented 使 JSON 文件更具可读性
string json = JsonConvert.SerializeObject(_configData, Formatting.Indented);
var json = JsonConvert.SerializeObject(_configData, Formatting.Indented);
File.WriteAllText(_configFilePath, json);
Debug.Log("ConfigManager: Configuration saved successfully.");
Debug.Log($"ConfigManager: 配置已保存到 '{_configFilePath}'。");
}
catch (JsonException ex)
{
Debug.LogError($"ConfigManager: Failed to serialize config data. Error: {ex.Message}");
Debug.LogError($"ConfigManager: 序列化配置数据失败。错误: {ex.Message}");
}
catch (IOException ex)
{
Debug.LogError($"ConfigManager: Failed to write config file. Error: {ex.Message}");
Debug.LogError($"ConfigManager: 写入配置文件 '{_configFilePath}' 失败。请检查权限。错误: {ex.Message}");
}
catch (System.UnauthorizedAccessException ex)
{
Debug.LogError($"ConfigManager: 写入配置文件 '{_configFilePath}' 权限被拒绝。请以管理员身份运行或更改文件夹权限。错误: {ex.Message}");
}
}
@@ -139,23 +162,29 @@ namespace Configs
/// <returns>配置值或默认值。</returns>
public T GetValue<T>(string key, T defaultValue = default(T))
{
if (_configData.TryGetValue(key, out JToken jToken))
if (_configData.TryGetValue(key, out var jToken))
{
try
{
// JToken.ToObject<T>() 能够智能地将 JToken 转换为目标类型 T
return jToken.ToObject<T>();
}
catch (JsonException ex)
{
Debug.LogWarning(
$"ConfigManager: Failed to convert value for key '{key}' to type '{typeof(T).Name}'. " +
$"Returning default value. Error: {ex.Message}");
$"ConfigManager: 键 '{key}' 的值从 '{jToken}' 转换为类型 '{typeof(T).Name}' 失败。" +
$"返回默认值 '{defaultValue}'。错误: {ex.Message}");
return defaultValue;
}
catch (System.FormatException ex)
{
Debug.LogWarning(
$"ConfigManager: 键 '{key}' 的值从 '{jToken}' 转换为类型 '{typeof(T).Name}' 时格式错误。" +
$"返回默认值 '{defaultValue}'。错误: {ex.Message}");
return defaultValue;
}
}
Debug.LogWarning($"ConfigManager: Key '{key}' not found. Returning default value '{defaultValue}'.");
Debug.LogWarning($"ConfigManager: 未找到键 '{key}'。返回默认值 '{defaultValue}'");
return defaultValue;
}
@@ -169,21 +198,20 @@ namespace Configs
{
if (string.IsNullOrEmpty(key))
{
Debug.LogError("ConfigManager: Cannot set value with an empty or null key.");
Debug.LogError("ConfigManager: 键不能为空。");
return;
}
try
{
// JToken.FromObject(value) 能够将任何对象转换为 JToken
_configData[key] = JToken.FromObject(value);
Debug.Log(
$"ConfigManager: Value for key '{key}' set to '{value}'. Remember to call SaveConfig() to persist changes.");
$"ConfigManager: '{key}' 的值设置为 '{value}'。请调用 SaveConfig() 持久化更改。");
}
catch (JsonException ex)
{
Debug.LogError(
$"ConfigManager: Failed to convert value '{value}' for key '{key}' to JToken. Error: {ex.Message}");
$"ConfigManager: 键 '{key}' 的值 '{value}' 转换为 JToken 失败。错误: {ex.Message}");
}
}
@@ -206,11 +234,11 @@ namespace Configs
{
if (_configData.Remove(key))
{
Debug.Log($"ConfigManager: Key '{key}' removed. Remember to call SaveConfig() to persist changes.");
Debug.Log($"ConfigManager: '{key}' 已移除。请调用 SaveConfig() 持久化更改。");
return true;
}
Debug.LogWarning($"ConfigManager: Attempted to remove non-existent key '{key}'.");
Debug.LogWarning($"ConfigManager: 尝试移除不存在的键 '{key}'");
return false;
}
@@ -221,10 +249,8 @@ namespace Configs
/// <returns>对应的 JToken如果键不存在则为 null。</returns>
public JToken GetRawJToken(string key)
{
_configData.TryGetValue(key, out JToken jToken);
_configData.TryGetValue(key, out var jToken);
return jToken;
}
}
}
}