From cfe871380547b4887f923d3889ce7a74bd14a5e9 Mon Sep 17 00:00:00 2001 From: Federico Cecchetto Date: Sat, 10 Sep 2022 22:59:55 +0200 Subject: [PATCH] Support loading fastfiles from appdata --- src/client/component/fastfiles.cpp | 69 ++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 14 deletions(-) diff --git a/src/client/component/fastfiles.cpp b/src/client/component/fastfiles.cpp index 8ad93908..a5ae2c0b 100644 --- a/src/client/component/fastfiles.cpp +++ b/src/client/component/fastfiles.cpp @@ -6,6 +6,7 @@ #include "fastfiles.hpp" #include "command.hpp" #include "console.hpp" +#include "filesystem.hpp" #include #include @@ -148,15 +149,11 @@ namespace fastfiles if (localized) { const auto language = game::SEH_GetCurrentLanguageCode(); - if (!try_load_zone(language + "_"s + name, false) && language != "eng"s) - { - try_load_zone("eng_" + name, false); - } + try_load_zone(language + "_"s + name, false); } if (!fastfiles::exists(name)) { - console::debug("fastfile %s doesn't exist\n", name.data()); return false; } @@ -168,32 +165,73 @@ namespace fastfiles return true; } + HANDLE find_fastfile(const std::string& filename, bool check_loc_folder) + { + std::string path{}; + std::string loc_folder{}; + + if (check_loc_folder && game::DB_IsLocalized(filename.data())) + { + const auto handle = find_fastfile(filename, false); + if (handle != reinterpret_cast(-1)) + { + return handle; + } + + loc_folder = game::SEH_GetCurrentLanguageName() + "/"s; + } + + if (!filesystem::find_file(loc_folder + filename, &path)) + { + if (!filesystem::find_file("zone/"s + loc_folder + filename, &path)) + { + return reinterpret_cast(-1); + } + } + + return CreateFileA(path.data(), 0x80000000, 1u, 0, 3u, 0x60000000u, 0); + } + utils::hook::detour sys_createfile_hook; HANDLE sys_create_file_stub(game::Sys_Folder folder, const char* base_filename) { const auto* fs_basepath = game::Dvar_FindVar("fs_basepath"); const auto* fs_game = game::Dvar_FindVar("fs_game"); - std::string dir = fs_basepath ? fs_basepath->current.string : ""; - std::string mod_dir = fs_game ? fs_game->current.string : ""; + const std::string dir = fs_basepath ? fs_basepath->current.string : ""; + const std::string mod_dir = fs_game ? fs_game->current.string : ""; + const std::string name = base_filename; - if (base_filename == "mod.ff"s) + if (name == "mod.ff") { if (!mod_dir.empty()) { - auto path = utils::string::va("%s\\%s\\%s", dir.data(), mod_dir.data(), base_filename); + const auto path = utils::string::va("%s\\%s\\%s", + dir.data(), mod_dir.data(), base_filename); + if (utils::io::file_exists(path)) { return CreateFileA(path, 0x80000000, 1u, 0, 3u, 0x60000000u, 0); } } - return (HANDLE)-1; + + return reinterpret_cast(-1); + } + + if (name.ends_with(".ff")) + { + const auto handle = find_fastfile(name, true); + if (handle != reinterpret_cast(-1)) + { + return handle; + } } return sys_createfile_hook.invoke(folder, base_filename); } - template inline void merge(std::vector* target, T* source, size_t length) + template + inline void merge(std::vector* target, T* source, size_t length) { if (source) { @@ -204,7 +242,8 @@ namespace fastfiles } } - template inline void merge(std::vector* target, std::vector source) + template + inline void merge(std::vector* target, std::vector source) { for (auto& entry : source) { @@ -252,8 +291,10 @@ namespace fastfiles bool exists(const std::string& zone) { const auto is_localized = game::DB_IsLocalized(zone.data()); - const auto handle = game::Sys_CreateFile((is_localized ? game::SF_ZONE_LOC : game::SF_ZONE), utils::string::va("%s.ff", zone.data())); - if (handle != (HANDLE)-1) + const auto handle = game::Sys_CreateFile((is_localized ? game::SF_ZONE_LOC : game::SF_ZONE), + utils::string::va("%s.ff", zone.data())); + + if (handle != reinterpret_cast(-1)) { CloseHandle(handle); return true;