diff --git a/src/openrct2-ui/windows/InstallTrack.cpp b/src/openrct2-ui/windows/InstallTrack.cpp index 586fdadf60..5add51362c 100644 --- a/src/openrct2-ui/windows/InstallTrack.cpp +++ b/src/openrct2-ui/windows/InstallTrack.cpp @@ -11,8 +11,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -430,22 +432,20 @@ static void WindowInstallTrackUpdatePreview() static void WindowInstallTrackDesign(rct_window* w) { - utf8 destPath[MAX_PATH]; - - platform_get_user_directory(destPath, "track", sizeof(destPath)); - if (!platform_ensure_directory_exists(destPath)) + auto env = OpenRCT2::GetContext()->GetPlatformEnvironment(); + auto destPath = env->GetDirectoryPath(OpenRCT2::DIRBASE::USER, OpenRCT2::DIRID::TRACK); + if (!platform_ensure_directory_exists(destPath.c_str())) { - log_error("Unable to create directory '%s'", destPath); + log_error("Unable to create directory '%s'", destPath.c_str()); context_show_error(STR_CANT_SAVE_TRACK_DESIGN, STR_NONE, {}); return; } - safe_strcat_path(destPath, _trackName.c_str(), sizeof(destPath)); - path_append_extension(destPath, ".td6", sizeof(destPath)); + destPath = Path::Combine(destPath, _trackName + ".td6"); if (File::Exists(destPath)) { - log_info("%s already exists, prompting user for a different track design name", destPath); + log_info("%s already exists, prompting user for a different track design name", destPath.c_str()); context_show_error(STR_UNABLE_TO_INSTALL_THIS_TRACK_DESIGN, STR_NONE, {}); WindowTextInputRawOpen( w, WIDX_INSTALL, STR_SELECT_NEW_NAME_FOR_TRACK_DESIGN, STR_AN_EXISTING_TRACK_DESIGN_ALREADY_HAS_THIS_NAME, {}, diff --git a/src/openrct2-ui/windows/LoadSave.cpp b/src/openrct2-ui/windows/LoadSave.cpp index 15742dc094..6f6abbfeab 100644 --- a/src/openrct2-ui/windows/LoadSave.cpp +++ b/src/openrct2-ui/windows/LoadSave.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -168,33 +169,37 @@ static utf8* GetLastDirectoryByType(int32_t type) } } -static void GetInitialDirectoryByType(const int32_t type, char* path, size_t pathSize) +static u8string GetInitialDirectoryByType(const int32_t type) { - const char* subdir = nullptr; + std::optional subdir = std::nullopt; switch (type & 0x0E) { case LOADSAVETYPE_GAME: - subdir = "save"; + subdir = OpenRCT2::DIRID::SAVE; break; case LOADSAVETYPE_LANDSCAPE: - subdir = "landscape"; + subdir = OpenRCT2::DIRID::LANDSCAPE; break; case LOADSAVETYPE_SCENARIO: - subdir = "scenario"; + subdir = OpenRCT2::DIRID::SCENARIO; break; case LOADSAVETYPE_TRACK: - subdir = "track"; + subdir = OpenRCT2::DIRID::TRACK; break; case LOADSAVETYPE_HEIGHTMAP: - subdir = "heightmap"; + subdir = OpenRCT2::DIRID::HEIGHTMAP; break; } - platform_get_user_directory(path, subdir, pathSize); + auto env = OpenRCT2::GetContext()->GetPlatformEnvironment(); + if (subdir.has_value()) + return env->GetDirectoryPath(OpenRCT2::DIRBASE::USER, subdir.value()); + else + return env->GetDirectoryPath(OpenRCT2::DIRBASE::USER); } static const char* GetFilterPatternByType(const int32_t type, const bool isSave) @@ -227,9 +232,15 @@ static int32_t WindowLoadsaveGetDir(const int32_t type, char* path, size_t pathS { const char* last_save = GetLastDirectoryByType(type); if (last_save != nullptr && Path::DirectoryExists(last_save)) + { safe_strcpy(path, last_save, pathSize); + } else - GetInitialDirectoryByType(type, path, pathSize); + { + auto result = GetInitialDirectoryByType(type); + path = String::Duplicate(result.c_str()); + pathSize = sizeof(path); + } return 1; } @@ -503,7 +514,8 @@ static void WindowLoadsaveMouseup(rct_window* w, rct_widgetindex widgetIndex) break; case WIDX_DEFAULT: - GetInitialDirectoryByType(_type, path, sizeof(path)); + auto result = GetInitialDirectoryByType(_type); + safe_strcpy(path, result.c_str(), sizeof(path)); WindowLoadsavePopulateList(w, isSave, path, _extension); WindowInitScrollWidgets(w); w->no_list_items = static_cast(_listItems.size()); diff --git a/src/openrct2/Context.cpp b/src/openrct2/Context.cpp index b0d51ed6a4..165b76d412 100644 --- a/src/openrct2/Context.cpp +++ b/src/openrct2/Context.cpp @@ -1535,18 +1535,3 @@ bool platform_open_common_file_dialog(utf8* outFilename, file_dialog_desc* desc, return false; } } - -/** - * This function is deprecated. - * Use IPlatformEnvironment instead. - */ -void platform_get_user_directory(utf8* outPath, const utf8* subDirectory, size_t outSize) -{ - auto env = GetContext()->GetPlatformEnvironment(); - auto path = env->GetDirectoryPath(DIRBASE::USER); - if (!String::IsNullOrEmpty(subDirectory)) - { - path = Path::Combine(path, subDirectory); - } - String::Set(outPath, outSize, path.c_str()); -} diff --git a/src/openrct2/Game.cpp b/src/openrct2/Game.cpp index bf96e6ba79..bb37608844 100644 --- a/src/openrct2/Game.cpp +++ b/src/openrct2/Game.cpp @@ -546,9 +546,9 @@ void save_game() } } -void save_game_cmd(const utf8* name /* = nullptr */) +void save_game_cmd(u8string_view name /* = {} */) { - if (name == nullptr) + if (name.empty()) { char savePath[MAX_PATH]; safe_strcpy(savePath, gScenarioSavePath.c_str(), MAX_PATH); @@ -559,20 +559,18 @@ void save_game_cmd(const utf8* name /* = nullptr */) } else { - char savePath[MAX_PATH]; - platform_get_user_directory(savePath, "save", sizeof(savePath)); - safe_strcat_path(savePath, name, sizeof(savePath)); - path_append_extension(savePath, ".park", sizeof(savePath)); + auto env = GetContext()->GetPlatformEnvironment(); + auto savePath = Path::Combine(env->GetDirectoryPath(DIRBASE::USER, DIRID::SAVE), u8string(name) + ".park"); save_game_with_name(savePath); } } -void save_game_with_name(const utf8* name) +void save_game_with_name(u8string_view name) { - log_verbose("Saving to %s", name); + log_verbose("Saving to %s", u8string(name).c_str()); if (scenario_save(name, 0x80000000 | (gConfigGeneral.save_plugin_data ? 1 : 0))) { - log_verbose("Saved to %s", name); + log_verbose("Saved to %s", u8string(name).c_str()); gCurrentLoadedPath = name; gScreenAge = 0; } @@ -665,12 +663,12 @@ static void limit_autosave_count(const size_t numberOfFilesToKeep, bool processL void game_autosave() { - const char* subDirectory = "save"; + auto subDirectory = DIRID::SAVE; const char* fileExtension = ".park"; uint32_t saveFlags = 0x80000000; if (gScreenFlags & SCREEN_FLAGS_EDITOR) { - subDirectory = "landscape"; + subDirectory = DIRID::LANDSCAPE; fileExtension = ".park"; saveFlags |= 2; } @@ -687,16 +685,13 @@ void game_autosave() int32_t autosavesToKeep = gConfigGeneral.autosave_amount; limit_autosave_count(autosavesToKeep - 1, (gScreenFlags & SCREEN_FLAGS_EDITOR)); - utf8 path[MAX_PATH]; - utf8 backupPath[MAX_PATH]; - platform_get_user_directory(path, subDirectory, sizeof(path)); - safe_strcat_path(path, "autosave", sizeof(path)); - platform_ensure_directory_exists(path); - safe_strcpy(backupPath, path, sizeof(backupPath)); - safe_strcat_path(path, timeName, sizeof(path)); - safe_strcat_path(backupPath, "autosave", sizeof(backupPath)); - safe_strcat(backupPath, fileExtension, sizeof(backupPath)); - safe_strcat(backupPath, ".bak", sizeof(backupPath)); + auto env = GetContext()->GetPlatformEnvironment(); + auto autosaveDir = Path::Combine(env->GetDirectoryPath(DIRBASE::USER, subDirectory), "autosave"); + platform_ensure_directory_exists(autosaveDir.c_str()); + + auto path = Path::Combine(autosaveDir, timeName); + auto backupFileName = u8string("autosave") + fileExtension + ".bak"; + auto backupPath = Path::Combine(autosaveDir, backupFileName); if (File::Exists(path)) { diff --git a/src/openrct2/Game.h b/src/openrct2/Game.h index 6fde94a0cc..cf48753338 100644 --- a/src/openrct2/Game.h +++ b/src/openrct2/Game.h @@ -166,8 +166,8 @@ bool game_is_not_paused(); void save_game(); void* create_save_game_as_intent(); void save_game_as(); -void save_game_cmd(const utf8* name = nullptr); -void save_game_with_name(const utf8* name); +void save_game_cmd(u8string_view name = {}); +void save_game_with_name(u8string_view name); void game_autosave(); void rct2_to_utf8_self(char* buffer, size_t length); void game_fix_save_vars(); diff --git a/src/openrct2/interface/InteractiveConsole.cpp b/src/openrct2/interface/InteractiveConsole.cpp index 0e510f85c9..8ea4dd576e 100644 --- a/src/openrct2/interface/InteractiveConsole.cpp +++ b/src/openrct2/interface/InteractiveConsole.cpp @@ -1355,29 +1355,30 @@ static int32_t cc_load_park([[maybe_unused]] InteractiveConsole& console, [[mayb return 0; } - char savePath[MAX_PATH]; + u8string savePath = {}; if (String::IndexOf(argv[0].c_str(), '/') == SIZE_MAX && String::IndexOf(argv[0].c_str(), '\\') == SIZE_MAX) { // no / or \ was included. File should be in save dir. - platform_get_user_directory(savePath, "save", sizeof(savePath)); - safe_strcat_path(savePath, argv[0].c_str(), sizeof(savePath)); + auto env = OpenRCT2::GetContext()->GetPlatformEnvironment(); + auto directory = env->GetDirectoryPath(OpenRCT2::DIRBASE::USER, OpenRCT2::DIRID::SAVE); + savePath = Path::Combine(directory, argv[0]); } else { - safe_strcpy(savePath, argv[0].c_str(), sizeof(savePath)); + savePath = argv[0]; } if (!String::EndsWith(savePath, ".sv6", true) && !String::EndsWith(savePath, ".sc6", true) && !String::EndsWith(savePath, ".park", true)) { - path_append_extension(savePath, ".park", sizeof(savePath)); + savePath += ".park"; } - if (context_load_park_from_file(savePath)) + if (context_load_park_from_file(savePath.c_str())) { - console.WriteFormatLine("Park %s was loaded successfully", savePath); + console.WriteFormatLine("Park %s was loaded successfully", savePath.c_str()); } else { - console.WriteFormatLine("Loading Park %s failed", savePath); + console.WriteFormatLine("Loading Park %s failed", savePath.c_str()); } return 1; } diff --git a/src/openrct2/interface/Screenshot.cpp b/src/openrct2/interface/Screenshot.cpp index 9d5d8c8dce..93b02f9fce 100644 --- a/src/openrct2/interface/Screenshot.cpp +++ b/src/openrct2/interface/Screenshot.cpp @@ -14,6 +14,7 @@ #include "../GameState.h" #include "../Intro.h" #include "../OpenRCT2.h" +#include "../PlatformEnvironment.h" #include "../actions/SetCheatAction.h" #include "../audio/audio.h" #include "../core/Console.hpp" @@ -102,9 +103,8 @@ static std::string screenshot_get_park_name() static std::string screenshot_get_directory() { - char screenshotPath[MAX_PATH]; - platform_get_user_directory(screenshotPath, "screenshot", sizeof(screenshotPath)); - return screenshotPath; + auto env = GetContext()->GetPlatformEnvironment(); + return env->GetDirectoryPath(DIRBASE::USER, DIRID::SCREENSHOT); } static std::pair screenshot_get_date_time() diff --git a/src/openrct2/network/NetworkBase.cpp b/src/openrct2/network/NetworkBase.cpp index 20ce656de6..d80780b083 100644 --- a/src/openrct2/network/NetworkBase.cpp +++ b/src/openrct2/network/NetworkBase.cpp @@ -947,10 +947,8 @@ void NetworkBase::SaveGroups() { if (GetMode() == NETWORK_MODE_SERVER) { - utf8 path[MAX_PATH]; - - platform_get_user_directory(path, nullptr, sizeof(path)); - safe_strcat_path(path, "groups.json", sizeof(path)); + auto env = GetContext().GetPlatformEnvironment(); + auto path = Path::Combine(env->GetDirectoryPath(DIRBASE::USER), "groups.json"); json_t jsonGroups = json_t::array(); for (auto& group : group_list) @@ -967,7 +965,7 @@ void NetworkBase::SaveGroups() } catch (const std::exception& ex) { - log_error("Unable to save %s: %s", path, ex.what()); + log_error("Unable to save %s: %s", path.c_str(), ex.what()); } } } @@ -1009,10 +1007,8 @@ void NetworkBase::LoadGroups() { group_list.clear(); - utf8 path[MAX_PATH]; - - platform_get_user_directory(path, nullptr, sizeof(path)); - safe_strcat_path(path, "groups.json", sizeof(path)); + auto env = GetContext().GetPlatformEnvironment(); + auto path = Path::Combine(env->GetDirectoryPath(DIRBASE::USER), "groups.json"); json_t jsonGroupConfig; if (File::Exists(path)) @@ -1023,7 +1019,7 @@ void NetworkBase::LoadGroups() } catch (const std::exception& e) { - log_error("Failed to read %s as JSON. Setting default groups. %s", path, e.what()); + log_error("Failed to read %s as JSON. Setting default groups. %s", path.c_str(), e.what()); } } diff --git a/src/openrct2/park/ParkFile.cpp b/src/openrct2/park/ParkFile.cpp index 0f143c70e4..0d083551f4 100644 --- a/src/openrct2/park/ParkFile.cpp +++ b/src/openrct2/park/ParkFile.cpp @@ -2229,7 +2229,7 @@ enum : uint32_t S6_SAVE_FLAG_AUTOMATIC = 1u << 31, }; -int32_t scenario_save(const utf8* path, int32_t flags) +int32_t scenario_save(u8string_view path, int32_t flags) { if (flags & S6_SAVE_FLAG_SCENARIO) { diff --git a/src/openrct2/platform/platform.h b/src/openrct2/platform/platform.h index b415a5a158..c76d71fb33 100644 --- a/src/openrct2/platform/platform.h +++ b/src/openrct2/platform/platform.h @@ -94,7 +94,6 @@ bool platform_lock_single_instance(); int32_t platform_get_drives(); uint32_t platform_get_ticks(); void platform_sleep(uint32_t ms); -void platform_get_user_directory(utf8* outPath, const utf8* subDirectory, size_t outSize); bool platform_open_common_file_dialog(utf8* outFilename, file_dialog_desc* desc, size_t outSize); std::string platform_get_rct1_steam_dir(); std::string platform_get_rct2_steam_dir(); diff --git a/src/openrct2/scenario/Scenario.cpp b/src/openrct2/scenario/Scenario.cpp index 7549477692..498740074e 100644 --- a/src/openrct2/scenario/Scenario.cpp +++ b/src/openrct2/scenario/Scenario.cpp @@ -16,10 +16,12 @@ #include "../GameState.h" #include "../OpenRCT2.h" #include "../ParkImporter.h" +#include "../PlatformEnvironment.h" #include "../audio/audio.h" #include "../config/Config.h" #include "../core/BitSet.hpp" #include "../core/Guard.hpp" +#include "../core/Path.hpp" #include "../core/Random.hpp" #include "../entity/Duck.h" #include "../entity/Guest.h" @@ -133,11 +135,9 @@ void scenario_begin() } // Set the last saved game path - char savePath[MAX_PATH]; - platform_get_user_directory(savePath, "save", sizeof(savePath)); - safe_strcat_path(savePath, park.Name.c_str(), sizeof(savePath)); - path_append_extension(savePath, ".park", sizeof(savePath)); - gScenarioSavePath = savePath; + auto env = GetContext()->GetPlatformEnvironment(); + auto savePath = env->GetDirectoryPath(DIRBASE::USER, DIRID::SAVE); + gScenarioSavePath = Path::Combine(savePath, park.Name + ".park"); gCurrentExpenditure = 0; gCurrentProfit = 0; diff --git a/src/openrct2/scenario/Scenario.h b/src/openrct2/scenario/Scenario.h index de060ff3ba..60f5788e28 100644 --- a/src/openrct2/scenario/Scenario.h +++ b/src/openrct2/scenario/Scenario.h @@ -179,7 +179,7 @@ random_engine_t::result_type scenario_rand(); uint32_t scenario_rand_max(uint32_t max); bool scenario_prepare_for_save(); -int32_t scenario_save(const utf8* path, int32_t flags); +int32_t scenario_save(u8string_view path, int32_t flags); void scenario_failure(); void scenario_success(); void scenario_success_submit_name(const char* name);