mirror of
https://github.com/sal063/AC6_recomp
synced 2026-08-21 23:00:53 -04:00
Fix user_data_root and update_data_root being ignored in the config file
Both settings were consumed during startup before the config file was loaded, so a toml-set value arrived too late to matter and the game recreated its data tree in Documents regardless. Only through the command line or arguments worked. Path resolution now runs after config load, and command-line > toml > default precedence is made explicit rather than an accident of ordering, so a saved config can no longer override a command-line value (game_iso had the same latent hole).
This commit is contained in:
+7
@@ -165,6 +165,13 @@ struct FlagEntry {
|
||||
bool has_session_default = false;
|
||||
std::string session_default;
|
||||
std::string session_driver;
|
||||
// Set by cvar::Init when the value came from the command line. Config-file
|
||||
// load skips applying to these entries so per-launch overrides keep their
|
||||
// precedence (cmdline > toml > default) even for cvars consumed after
|
||||
// LoadConfig; the toml value is still recorded as
|
||||
// user_set/user_value so the next SaveConfig round-trips the user's saved
|
||||
// choice instead of dropping it.
|
||||
bool cmdline_set = false;
|
||||
};
|
||||
|
||||
std::vector<FlagEntry>& GetRegistry();
|
||||
|
||||
+39
-3
@@ -59,6 +59,30 @@ std::string FlagNameToEnvVar(std::string_view name) {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ValidateConstraints(const FlagEntry& entry, std::string_view value);
|
||||
|
||||
// Config-load path for one flag when the command line already set it: the
|
||||
// command line wins for the LIVE value (cmdline > toml > default),
|
||||
// but the toml value must still become the user-owned config value or the
|
||||
// next SaveConfig would silently drop the user's saved setting.
|
||||
// Returns true when the flag was handled here (skip the normal set).
|
||||
bool RecordConfigValueOverriddenByCmdline(const std::string& name, const std::string& value) {
|
||||
std::lock_guard lock(GetRegistryMutex());
|
||||
auto it = GetRegistryIndex().find(name);
|
||||
if (it == GetRegistryIndex().end()) {
|
||||
return false;
|
||||
}
|
||||
auto& entry = GetRegistryStorage()[it->second];
|
||||
if (!entry.cmdline_set) {
|
||||
return false;
|
||||
}
|
||||
if (ValidateConstraints(entry, value)) {
|
||||
entry.user_set = true;
|
||||
entry.user_value = value;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Recursively apply TOML values
|
||||
void ApplyTomlTable(const toml::table& table, const std::string& prefix) {
|
||||
for (const auto& [key, value] : table) {
|
||||
@@ -81,7 +105,9 @@ void ApplyTomlTable(const toml::table& table, const std::string& prefix) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (SetFlagByName(full_key, value_str)) {
|
||||
if (RecordConfigValueOverriddenByCmdline(full_key, value_str)) {
|
||||
REXLOG_DEBUG("Config: {} = {} (command line takes precedence)", full_key, value_str);
|
||||
} else if (SetFlagByName(full_key, value_str)) {
|
||||
REXLOG_DEBUG("Config: {} = {}", full_key, value_str);
|
||||
} else {
|
||||
REXLOG_WARN("Config: unknown cvar '{}'", full_key);
|
||||
@@ -592,11 +618,20 @@ std::vector<std::string> Init(int argc, char** argv) {
|
||||
if (entry.type == FlagType::Boolean) {
|
||||
app.add_flag_function(
|
||||
"--" + entry.name + ",!--no-" + entry.name,
|
||||
[&entry](int64_t count) { entry.setter(count > 0 ? "true" : "false"); },
|
||||
[&entry](int64_t count) {
|
||||
if (entry.setter(count > 0 ? "true" : "false")) {
|
||||
entry.cmdline_set = true;
|
||||
}
|
||||
},
|
||||
entry.description);
|
||||
} else {
|
||||
app.add_option_function<std::string>(
|
||||
"--" + entry.name, [&entry](const std::string& val) { entry.setter(val); },
|
||||
"--" + entry.name,
|
||||
[&entry](const std::string& val) {
|
||||
if (entry.setter(val)) {
|
||||
entry.cmdline_set = true;
|
||||
}
|
||||
},
|
||||
entry.description);
|
||||
}
|
||||
}
|
||||
@@ -713,6 +748,7 @@ void ResetAllForTesting() {
|
||||
entry.has_session_default = false;
|
||||
entry.session_default.clear();
|
||||
entry.session_driver.clear();
|
||||
entry.cmdline_set = false;
|
||||
}
|
||||
}
|
||||
ClearPendingRestartFlags();
|
||||
|
||||
+41
-33
@@ -342,39 +342,6 @@ bool ReXApp::ResolveGameSource(const std::filesystem::path& exe_dir,
|
||||
bool ReXApp::OnInitialize() {
|
||||
auto exe_dir = rex::filesystem::GetExecutableFolder();
|
||||
|
||||
// Game directory: positional arg or default to exe_dir/assets
|
||||
std::filesystem::path game_dir;
|
||||
if (auto arg = GetArgument("game_directory")) {
|
||||
game_dir = *arg;
|
||||
} else {
|
||||
game_dir = exe_dir / "assets";
|
||||
}
|
||||
|
||||
// User data: cvar override, or platform user directory
|
||||
std::filesystem::path user_dir;
|
||||
std::string user_data_cvar = REXCVAR_GET(user_data_root);
|
||||
if (!user_data_cvar.empty()) {
|
||||
// to_path: the toml string is UTF-8, not the ANSI codepage a bare path
|
||||
// construction would assume on Windows (same rule as game_iso/dlc_dir).
|
||||
user_dir = rex::to_path(user_data_cvar);
|
||||
} else {
|
||||
user_dir = rex::filesystem::GetUserFolder() / GetName();
|
||||
}
|
||||
|
||||
// Update data: cvar override, or empty (opt-in)
|
||||
std::filesystem::path update_dir;
|
||||
std::string update_data_cvar = REXCVAR_GET(update_data_root);
|
||||
if (!update_data_cvar.empty()) {
|
||||
update_dir = rex::to_path(update_data_cvar);
|
||||
}
|
||||
|
||||
// Allow subclass to override path defaults
|
||||
PathConfig path_config{game_dir, user_dir, update_dir};
|
||||
OnConfigurePaths(path_config);
|
||||
game_data_root_ = std::move(path_config.game_data_root);
|
||||
user_data_root_ = std::move(path_config.user_data_root);
|
||||
update_data_root_ = std::move(path_config.update_data_root);
|
||||
|
||||
auto config_path = exe_dir / (std::string(GetName()) + ".toml");
|
||||
|
||||
// Load saved config (CVARs) before anything reads them
|
||||
@@ -446,6 +413,47 @@ bool ReXApp::OnInitialize() {
|
||||
|
||||
REXLOG_INFO("{} starting", GetName());
|
||||
|
||||
// Data-root resolution. Runs after LoadConfig, next to the game-data
|
||||
// resolution below and for the same reason: these cvars used to be
|
||||
// consumed at the top of this function, BEFORE the toml was parsed, so a
|
||||
// user_data_root/update_data_root set in the config file silently did
|
||||
// nothing - only the command line ever worked. Nothing between
|
||||
// LoadConfig and this point derives a path from the user root (log and
|
||||
// crash paths come from log_file/exe_dir).
|
||||
|
||||
// Game directory: positional arg or default to exe_dir/assets
|
||||
std::filesystem::path game_dir;
|
||||
if (auto arg = GetArgument("game_directory")) {
|
||||
game_dir = *arg;
|
||||
} else {
|
||||
game_dir = exe_dir / "assets";
|
||||
}
|
||||
|
||||
// User data: cvar override, or platform user directory
|
||||
std::filesystem::path user_dir;
|
||||
std::string user_data_cvar = REXCVAR_GET(user_data_root);
|
||||
if (!user_data_cvar.empty()) {
|
||||
// to_path: the toml string is UTF-8, not the ANSI codepage a bare path
|
||||
// construction would assume on Windows (same rule as game_iso/dlc_dir).
|
||||
user_dir = rex::to_path(user_data_cvar);
|
||||
} else {
|
||||
user_dir = rex::filesystem::GetUserFolder() / GetName();
|
||||
}
|
||||
|
||||
// Update data: cvar override, or empty (opt-in)
|
||||
std::filesystem::path update_dir;
|
||||
std::string update_data_cvar = REXCVAR_GET(update_data_root);
|
||||
if (!update_data_cvar.empty()) {
|
||||
update_dir = rex::to_path(update_data_cvar);
|
||||
}
|
||||
|
||||
// Allow subclass to override path defaults
|
||||
PathConfig path_config{game_dir, user_dir, update_dir};
|
||||
OnConfigurePaths(path_config);
|
||||
game_data_root_ = std::move(path_config.game_data_root);
|
||||
user_data_root_ = std::move(path_config.user_data_root);
|
||||
update_data_root_ = std::move(path_config.update_data_root);
|
||||
|
||||
// Resolve where the game's data comes from. Runs after LoadConfig so the
|
||||
// game_iso / iso_direct toml overrides apply.
|
||||
std::filesystem::path game_image;
|
||||
|
||||
Reference in New Issue
Block a user