Config(配置系統)
ll/api/Config.h · 通用
概述
Config 模塊提供了用於加載和保存模組配置文件(JSON 格式)的模板函數。它利用 Reflection(反射) 模塊進行自動序列化/反序列化,支持帶版本號的配置及自動遷移。
頭文件
| 頭文件 | 說明 |
|---|---|
ll/api/Config.h | saveConfig、loadConfig 及相關工具 |
概念
IsConfig
配置類型必須滿足:
ll::reflection::Reflectable<T>— 類型必須是聚合體(用於反射)- 具有整數類型的
version字段
C++
namespace ll::config {
template <class T>
concept IsConfig = ll::reflection::Reflectable<T>
&& std::integral<std::remove_cvref_t<decltype((std::declval<T>().version))>>;
}核心函數
saveConfig
C++
template <IsConfig T, class J = nlohmann::ordered_json>
bool saveConfig(T const& config, std::filesystem::path const& path);將 config 序列化為 JSON 並寫入 path。成功時返回 true。
loadConfig
C++
template <IsConfig T, class J = nlohmann::ordered_json, class F = bool(T&, J&)>
bool loadConfig(T& config, std::filesystem::path const& path, F&& updater = defaultConfigUpdater<T, J>);從 path 加載配置到 config。如果文件不存在,則保存當前 config 作為默認值。返回 true 表示無需重寫(版本匹配)。
行為:
- 文件不存在 → 保存默認配置,返回
false - 文件存在但版本不同 → 調用
updater,返回false - 文件存在且版本匹配 → 直接反序列化,返回
true
defaultConfigUpdater
C++
template <class T, class J>
bool defaultConfigUpdater(T& config, J& data);默認更新策略:使用 merge_patch 將現有文件內容合併到默認配置上,在添加新字段的同時保留用戶的修改。
使用方法
定義配置結構體
C++
#include "ll/api/Config.h"
struct MyConfig {
int version = 1;
std::string greeting = "Hello";
int maxPlayers = 20;
bool enableFeatureX = false;
};Note
結構體必須是聚合類型(無用戶定義構造函數、無私有成員、無虛函數),反射才能正常工作。
加載和保存
C++
#include "ll/api/Config.h"
#include "ll/api/mod/Mod.h"
void loadMyConfig(ll::mod::Mod& mod) {
MyConfig config;
auto configPath = mod.getConfigDir() / "config.json";
bool upToDate = ll::config::loadConfig(config, configPath);
if (!upToDate) {
// 配置已创建或已迁移,保存更新后的版本
ll::config::saveConfig(config, configPath);
}
mod.getLogger().info("问候语: {}", config.greeting);
mod.getLogger().info("最大玩家数: {}", config.maxPlayers);
}自定義更新器
C++
#include "ll/api/Config.h"
struct MyConfigV2 {
int version = 2;
std::string greeting = "Hello";
int maxPlayers = 20;
bool enableFeatureX = false;
std::string newField = "default"; // v2 中新增
};
bool myUpdater(MyConfigV2& config, nlohmann::ordered_json& data) {
int oldVersion = data.value("version", 1);
if (oldVersion == 1) {
// 从 v1 迁移:保留旧的 "greeting" 值
if (data.contains("greeting")) {
config.greeting = data["greeting"];
}
}
data.erase("version");
auto patch = ll::reflection::serialize<nlohmann::ordered_json>(config);
patch.value().merge_patch(data);
data = *std::move(patch);
return true;
}
void loadConfigV2(ll::mod::Mod& mod) {
MyConfigV2 config;
ll::config::loadConfig(config, mod.getConfigDir() / "config.json", myUpdater);
}生成的 JSON 示例
對於上述 MyConfig 結構體,生成的 JSON 如下:
JSON
{
"version": 1,
"greeting": "Hello",
"maxPlayers": 20,
"enableFeatureX": false
}相關模塊
- Reflection(反射) — 提供配置使用的
serialize/deserialize - Mod(模組系統) —
Mod::getConfigDir()返回配置目錄