mirror of
https://github.com/open-goal/jak-project.git
synced 2024-11-23 06:09:57 +00:00
game: allow overriding the config directory location (#3477)
This is primarily driven for proper mod-support. Mods would like to isolate their settings and saves (potentially) and that is currently done by find-and-replacing code before building. Bad! Additionally, this has the side-effect of allowing for portable installations of the game so, win-win. Testing in progress, i'll merge once it is ready.
This commit is contained in:
parent
fee0a435fc
commit
a021c392ec
@ -57,6 +57,14 @@ fs::path get_user_home_dir() {
|
||||
#endif
|
||||
}
|
||||
|
||||
struct {
|
||||
bool initialized = false;
|
||||
fs::path path_to_data_folder;
|
||||
fs::path user_config_dir_override = "";
|
||||
// by default - if the config dir is overridden, we don't use the default save location
|
||||
bool use_overridden_config_dir_for_saves = true;
|
||||
} g_file_path_info;
|
||||
|
||||
fs::path get_user_config_dir() {
|
||||
fs::path config_base_path;
|
||||
#ifdef _WIN32
|
||||
@ -80,36 +88,52 @@ fs::path get_user_config_dir() {
|
||||
|
||||
fs::path get_user_settings_dir(GameVersion game_version) {
|
||||
auto game_version_name = game_version_names[game_version];
|
||||
return get_user_config_dir() / game_version_name / "settings";
|
||||
auto config_dir = get_user_config_dir();
|
||||
if (!g_file_path_info.user_config_dir_override.empty()) {
|
||||
config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL";
|
||||
}
|
||||
return config_dir / game_version_name / "settings";
|
||||
}
|
||||
|
||||
fs::path get_user_memcard_dir(GameVersion game_version) {
|
||||
auto game_version_name = game_version_names[game_version];
|
||||
return get_user_config_dir() / game_version_name / "saves";
|
||||
auto config_dir = get_user_config_dir();
|
||||
if (!g_file_path_info.user_config_dir_override.empty() &&
|
||||
g_file_path_info.use_overridden_config_dir_for_saves) {
|
||||
config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL";
|
||||
}
|
||||
return config_dir / game_version_name / "saves";
|
||||
}
|
||||
|
||||
fs::path get_user_screenshots_dir(GameVersion game_version) {
|
||||
auto game_version_name = game_version_names[game_version];
|
||||
return get_user_config_dir() / game_version_name / "screenshots";
|
||||
auto config_dir = get_user_config_dir();
|
||||
if (!g_file_path_info.user_config_dir_override.empty()) {
|
||||
config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL";
|
||||
}
|
||||
return config_dir / game_version_name / "screenshots";
|
||||
}
|
||||
|
||||
fs::path get_user_misc_dir(GameVersion game_version) {
|
||||
auto game_version_name = game_version_names[game_version];
|
||||
return get_user_config_dir() / game_version_name / "misc";
|
||||
auto config_dir = get_user_config_dir();
|
||||
if (!g_file_path_info.user_config_dir_override.empty()) {
|
||||
config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL";
|
||||
}
|
||||
return config_dir / game_version_name / "misc";
|
||||
}
|
||||
|
||||
fs::path get_user_features_dir(GameVersion game_version) {
|
||||
auto game_version_name = game_version_names[game_version];
|
||||
auto path = get_user_config_dir() / game_version_name / "features";
|
||||
auto config_dir = get_user_config_dir();
|
||||
if (!g_file_path_info.user_config_dir_override.empty()) {
|
||||
config_dir = g_file_path_info.user_config_dir_override / "OpenGOAL";
|
||||
}
|
||||
auto path = config_dir / game_version_name / "features";
|
||||
file_util::create_dir_if_needed(path);
|
||||
return path;
|
||||
}
|
||||
|
||||
struct {
|
||||
bool initialized = false;
|
||||
fs::path path_to_data;
|
||||
} gFilePathInfo;
|
||||
|
||||
fs::path g_iso_data_directory = "";
|
||||
|
||||
/*!
|
||||
@ -173,29 +197,30 @@ std::optional<fs::path> try_get_data_dir() {
|
||||
}
|
||||
|
||||
bool setup_project_path(std::optional<fs::path> project_path_override) {
|
||||
if (gFilePathInfo.initialized) {
|
||||
if (g_file_path_info.initialized) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (project_path_override) {
|
||||
gFilePathInfo.path_to_data = fs::absolute(project_path_override.value());
|
||||
gFilePathInfo.initialized = true;
|
||||
lg::info("Using explicitly set project path: {}", gFilePathInfo.path_to_data.string());
|
||||
g_file_path_info.path_to_data_folder = fs::absolute(project_path_override.value());
|
||||
g_file_path_info.initialized = true;
|
||||
lg::info("Using explicitly set project path: {}",
|
||||
g_file_path_info.path_to_data_folder.string());
|
||||
return true;
|
||||
}
|
||||
|
||||
auto data_path = try_get_data_dir();
|
||||
if (data_path) {
|
||||
gFilePathInfo.path_to_data = *data_path;
|
||||
gFilePathInfo.initialized = true;
|
||||
g_file_path_info.path_to_data_folder = *data_path;
|
||||
g_file_path_info.initialized = true;
|
||||
lg::info("Using data path: {}", data_path->string());
|
||||
return true;
|
||||
}
|
||||
|
||||
auto development_repo_path = try_get_jak_project_path();
|
||||
if (development_repo_path) {
|
||||
gFilePathInfo.path_to_data = *development_repo_path;
|
||||
gFilePathInfo.initialized = true;
|
||||
g_file_path_info.path_to_data_folder = *development_repo_path;
|
||||
g_file_path_info.initialized = true;
|
||||
lg::info("Using development repo path: {}", *development_repo_path);
|
||||
return true;
|
||||
}
|
||||
@ -204,9 +229,15 @@ bool setup_project_path(std::optional<fs::path> project_path_override) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void override_user_config_dir(fs::path user_config_dir_override,
|
||||
bool use_overridden_config_dir_for_saves) {
|
||||
g_file_path_info.user_config_dir_override = user_config_dir_override;
|
||||
g_file_path_info.use_overridden_config_dir_for_saves = use_overridden_config_dir_for_saves;
|
||||
}
|
||||
|
||||
fs::path get_jak_project_dir() {
|
||||
ASSERT(gFilePathInfo.initialized);
|
||||
return gFilePathInfo.path_to_data;
|
||||
ASSERT(g_file_path_info.initialized);
|
||||
return g_file_path_info.path_to_data_folder;
|
||||
}
|
||||
|
||||
fs::path get_iso_dir_for_game(GameVersion game_version) {
|
||||
|
@ -41,8 +41,11 @@ void set_iso_data_dir(const fs::path& directory);
|
||||
bool create_dir_if_needed(const fs::path& path);
|
||||
bool create_dir_if_needed_for_file(const std::string& path);
|
||||
bool create_dir_if_needed_for_file(const fs::path& path);
|
||||
std::string get_current_executable_path();
|
||||
std::optional<std::string> try_get_project_path_from_path(const std::string& path);
|
||||
bool setup_project_path(std::optional<fs::path> project_path_override);
|
||||
void override_user_config_dir(fs::path user_config_dir_override,
|
||||
bool use_overridden_config_dir_for_saves);
|
||||
std::string get_file_path(const std::vector<std::string>& path);
|
||||
void write_binary_file(const std::string& name, const void* data, size_t size);
|
||||
void write_binary_file(const fs::path& name, const void* data, size_t size);
|
||||
|
@ -55,6 +55,7 @@ u32 Init(GameVersion version) {
|
||||
prof().instant_event("ROOT");
|
||||
|
||||
g_debug_settings = game_settings::DebugSettings();
|
||||
g_debug_settings.load_settings();
|
||||
{
|
||||
auto p = scoped_prof("startup::gfx::get_renderer");
|
||||
g_global_settings.renderer = GetRenderer(GfxPipeline::OpenGL);
|
||||
|
@ -526,7 +526,7 @@ void link_control::jak1_finish(bool jump_from_c_to_goal) {
|
||||
*EnableMethodSet = *EnableMethodSet + m_keep_debug;
|
||||
|
||||
ObjectFileHeader* ofh = m_link_block_ptr.cast<ObjectFileHeader>().c();
|
||||
lg::info("link finish: {}", m_object_name);
|
||||
lg::debug("link finish: {}", m_object_name);
|
||||
if (ofh->object_file_version == 3) {
|
||||
// todo check function type of entry
|
||||
|
||||
|
@ -544,7 +544,7 @@ void link_control::jak2_finish(bool jump_from_c_to_goal) {
|
||||
*EnableMethodSet = *EnableMethodSet + m_keep_debug;
|
||||
|
||||
ObjectFileHeader* ofh = m_link_block_ptr.cast<ObjectFileHeader>().c();
|
||||
lg::info("link finish: {}", m_object_name);
|
||||
lg::debug("link finish: {}", m_object_name);
|
||||
if (ofh->object_file_version == 3) {
|
||||
// todo check function type of entry
|
||||
|
||||
|
@ -42,7 +42,7 @@ void setup_logging(const std::string& game_name, bool verbose, bool disable_ansi
|
||||
lg::set_flush_level(lg::level::debug);
|
||||
} else {
|
||||
lg::set_file_level(lg::level::debug);
|
||||
lg::set_stdout_level(lg::level::warn);
|
||||
lg::set_stdout_level(lg::level::info);
|
||||
lg::set_flush_level(lg::level::warn);
|
||||
}
|
||||
if (disable_ansi_colors) {
|
||||
@ -96,11 +96,14 @@ int main(int argc, char** argv) {
|
||||
bool disable_avx2 = false;
|
||||
bool disable_display = false;
|
||||
bool enable_profiling = false;
|
||||
bool enable_portable = false;
|
||||
bool disable_save_location_override = false;
|
||||
std::string profile_until_event = "";
|
||||
std::string gpu_test = "";
|
||||
std::string gpu_test_out_path = "";
|
||||
int port_number = -1;
|
||||
fs::path project_path_override;
|
||||
fs::path user_config_dir_override;
|
||||
std::vector<std::string> game_args;
|
||||
CLI::App app{"OpenGOAL Game Runtime"};
|
||||
app.add_flag("--version", show_version, "Display the built revision");
|
||||
@ -112,6 +115,12 @@ int main(int argc, char** argv) {
|
||||
app.add_flag("--no-avx2", disable_avx2, "Disable AVX2 for testing");
|
||||
app.add_flag("--no-display", disable_display, "Disable video display");
|
||||
app.add_flag("--profile", enable_profiling, "Enables profiling immediately from startup");
|
||||
app.add_flag("--portable", enable_portable,
|
||||
"Save settings and saves relative to the game's executable, takes precedence over "
|
||||
"--config-path");
|
||||
app.add_flag("--disable_save_location_override", disable_save_location_override,
|
||||
"If --config-path is provided along with this flag, saves will still be loaded and "
|
||||
"stored to the default location");
|
||||
app.add_option("--profile-until-event", profile_until_event,
|
||||
"Stops recording profile events once an event with this name is seen");
|
||||
app.add_option("--gpu-test", gpu_test,
|
||||
@ -120,6 +129,8 @@ int main(int argc, char** argv) {
|
||||
"Where to store the gpu test result file");
|
||||
app.add_option("--proj-path", project_path_override,
|
||||
"Specify the location of the 'data/' folder");
|
||||
app.add_option("--config-path", user_config_dir_override,
|
||||
"Override the location where all user configuration and saves are saved");
|
||||
app.footer(game_arg_documentation());
|
||||
app.add_option("Game Args", game_args,
|
||||
"Remaining arguments (after '--') that are passed-through to the game itself");
|
||||
@ -127,6 +138,17 @@ int main(int argc, char** argv) {
|
||||
app.allow_extras();
|
||||
CLI11_PARSE(app, argc, argv);
|
||||
|
||||
// Override the user's config dir, potentially (either because it was explicitly provided
|
||||
// or because it's portable mode)
|
||||
if (enable_portable) {
|
||||
lg::info("Portable mod enabled");
|
||||
user_config_dir_override = file_util::get_current_executable_path();
|
||||
}
|
||||
if (!user_config_dir_override.empty()) {
|
||||
lg::info("Overriding config directory with: {}", user_config_dir_override.string());
|
||||
file_util::override_user_config_dir(user_config_dir_override, !disable_save_location_override);
|
||||
}
|
||||
|
||||
if (show_version) {
|
||||
lg::print("{}", build_revision());
|
||||
return 0;
|
||||
|
@ -33,7 +33,9 @@ void from_json(const json& j, DebugSettings& obj) {
|
||||
json_deserialize_if_exists(hide_imgui_key);
|
||||
}
|
||||
|
||||
DebugSettings::DebugSettings() {
|
||||
DebugSettings::DebugSettings() {}
|
||||
|
||||
void DebugSettings::load_settings() {
|
||||
try {
|
||||
std::string file_path =
|
||||
(file_util::get_user_misc_dir(g_game_version) / "debug-settings.json").string();
|
||||
@ -71,7 +73,9 @@ void from_json(const json& j, DisplaySettings& obj) {
|
||||
json_deserialize_if_exists(window_ypos);
|
||||
}
|
||||
|
||||
DisplaySettings::DisplaySettings() {
|
||||
DisplaySettings::DisplaySettings() {}
|
||||
|
||||
void DisplaySettings::load_settings() {
|
||||
try {
|
||||
std::string file_path =
|
||||
(file_util::get_user_settings_dir(g_game_version) / "display-settings.json").string();
|
||||
@ -114,7 +118,9 @@ void from_json(const json& j, InputSettings& obj) {
|
||||
json_deserialize_if_exists(keyboard_enabled);
|
||||
}
|
||||
|
||||
InputSettings::InputSettings() {
|
||||
InputSettings::InputSettings() {}
|
||||
|
||||
void InputSettings::load_settings() {
|
||||
try {
|
||||
keyboard_binds = DEFAULT_KEYBOARD_BINDS;
|
||||
mouse_binds = DEFAULT_MOUSE_BINDS;
|
||||
@ -131,6 +137,7 @@ InputSettings::InputSettings() {
|
||||
lg::error("Error encountered when attempting to load input settings {}", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void InputSettings::save_settings() {
|
||||
json data = *this;
|
||||
auto file_path = file_util::get_user_settings_dir(g_game_version) / "input-settings.json";
|
||||
|
@ -25,6 +25,7 @@ struct DebugSettings {
|
||||
float text_max_range = 0;
|
||||
u32 hide_imgui_key = SDLK_LALT;
|
||||
|
||||
void load_settings();
|
||||
void save_settings();
|
||||
};
|
||||
void to_json(json& j, const DebugSettings& obj);
|
||||
@ -39,6 +40,7 @@ struct DisplaySettings {
|
||||
int window_ypos = 50;
|
||||
int display_id = 0;
|
||||
|
||||
void load_settings();
|
||||
void save_settings();
|
||||
};
|
||||
|
||||
@ -60,6 +62,7 @@ struct InputSettings {
|
||||
bool keyboard_temp_enabled =
|
||||
false; // not saved or restored, flips on if no controllers are detected
|
||||
|
||||
void load_settings();
|
||||
void save_settings();
|
||||
};
|
||||
|
||||
|
@ -12,6 +12,7 @@ DisplayManager::DisplayManager(SDL_Window* window)
|
||||
prof().instant_event("ROOT");
|
||||
{
|
||||
auto p = scoped_prof("display_manager::init");
|
||||
m_display_settings.load_settings();
|
||||
#ifdef _WIN32
|
||||
// Windows hint to disable OS level forced scaling and allow native resolution at non 100%
|
||||
// scales
|
||||
|
@ -22,6 +22,7 @@ InputManager::InputManager()
|
||||
prof().instant_event("ROOT");
|
||||
{
|
||||
auto p = scoped_prof("input_manager::init");
|
||||
m_settings->load_settings();
|
||||
{
|
||||
auto p = scoped_prof("input_manager::init::sdl_init_subsystem");
|
||||
// initializing the controllers on startup can sometimes take a very long time
|
||||
|
@ -379,9 +379,11 @@ void Workspace::tracked_file_will_save(const LSPSpec::DocumentUri& file_uri) {
|
||||
}
|
||||
}
|
||||
|
||||
void Workspace::update_global_index(const GameVersion game_version){
|
||||
// TODO - project wide indexing potentially (ie. finding references)
|
||||
// clang-format off
|
||||
void Workspace::update_global_index(const GameVersion game_version) {
|
||||
// TODO - project wide indexing potentially (ie. finding references)
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
void Workspace::stop_tracking_file(const LSPSpec::DocumentUri& file_uri) {
|
||||
m_tracked_ir_files.erase(file_uri);
|
||||
|
Loading…
Reference in New Issue
Block a user