From 1a17d186db67fa3a92a0cbc802d3316c6a9720b2 Mon Sep 17 00:00:00 2001 From: m Date: Tue, 2 May 2023 16:33:39 -0500 Subject: [PATCH 01/23] custom GSC loading --- src/client/component/script.cpp | 54 ++++++++++++++++++++------------- src/client/game/structs.hpp | 2 ++ src/client/game/symbols.hpp | 5 +++ 3 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 4a9e3eb6..6cc659db 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -12,6 +12,8 @@ namespace script { namespace { + constexpr size_t GSC_MAGIC = 0x1C000A0D43534780; + utils::hook::detour db_findxassetheader_hook; utils::hook::detour gscr_get_bgb_remaining_hook; @@ -23,11 +25,6 @@ namespace script return (itr == loaded_scripts.end()) ? nullptr : itr->second; } - void print_loading_script(const std::string& name) - { - printf("Loading GSC script '%s'\n", name.data()); - } - void load_script(std::string& name, const std::string& data) { auto& allocator = *utils::memory::get_allocator(); @@ -49,11 +46,14 @@ namespace script } auto* rawfile = allocator.allocate(); - rawfile->name = name.c_str(); + rawfile->name = name.data(); rawfile->buffer = file_string; rawfile->len = static_cast(data.length()); loaded_scripts[name] = rawfile; + + const auto base_name = name.substr(0, name.size() - 4); // .gsc suffix will be readded by Scr_LoadScript + game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, base_name.data()); } void load_scripts_folder(const std::string& script_dir) @@ -64,15 +64,18 @@ namespace script } const auto scripts = utils::io::list_files(script_dir); - for (const auto& script : scripts) { std::string data; auto script_file = script.generic_string(); if (!std::filesystem::is_directory(script) && utils::io::read_file(script_file, &data)) { - print_loading_script(script_file); - load_script(script_file, data); + if (data.size() >= sizeof(GSC_MAGIC) && !std::memcmp(data.data(), &GSC_MAGIC, sizeof(GSC_MAGIC))) + { + auto base_name = script_file.substr(0, script_file.size() - 4); + printf("Loading GSC script '%s'\n", base_name.data()); + load_script(script_file, data); + } } else if (std::filesystem::is_directory(script)) { @@ -86,7 +89,8 @@ namespace script loaded_scripts = {}; const utils::nt::library host{}; load_scripts_folder((game::get_appdata_path() / "data/scripts").string()); - load_scripts_folder((host.get_folder() / "boiii/scripts").string()); + auto path = (host.get_folder() / "boiii/scripts").string(); + load_scripts_folder(path); } game::RawFile* db_findxassetheader_stub(const game::XAssetType type, const char* name, @@ -104,9 +108,10 @@ namespace script auto* script = get_loaded_script(name); if (script) { - // Copy over the checksum of the original script + /* + // TODO: don't check checksums for custom GSC, but only for stock scripts we override utils::hook::copy(const_cast(script->buffer + 0x8), asset_header->buffer + 0x8, 4); - + */ return script; } @@ -117,23 +122,30 @@ namespace script { game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 255); } + + utils::hook::detour load_gametype_script_hook; + + void load_gametype_script_stub() + { + if (!game::Com_IsInGame() || game::Com_IsRunningUILevel()) + { + load_gametype_script_hook.invoke(); + return; + } + + load_gametype_script_hook.invoke(); + load_scripts(); + } } struct component final : generic_component { void post_unpack() override { - if (game::is_server()) - { - load_scripts(); - } - else - { - scheduler::once(load_scripts, scheduler::pipeline::renderer); - } - db_findxassetheader_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_findxassetheader_stub); gscr_get_bgb_remaining_hook.create(game::select(0x141A8CAB0, 0x1402D2310), gscr_get_bgb_remaining_stub); + + load_gametype_script_hook.create(0x141AAD850_g, load_gametype_script_stub); } }; }; diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 883c243b..1c6a22e0 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -1814,7 +1814,9 @@ namespace game PlayerSoundsTable* playerSounds; PlayerFXTable* playerFX; SharedWeaponSounds* sharedWeaponSounds; + */ RawFile* rawfile; + /* StringTable* stringTable; StructuredTable* structuredTable; LeaderboardDef* leaderboardDef; diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index a0513a45..f78016bd 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -35,6 +35,7 @@ namespace game 0x1420F4E00, 0x1404FE5C0 }; WEAK symbol Com_IsRunningUILevel{0x142148350}; + WEAK symbol Com_IsInGame{0x1421482C0}; WEAK symbol Com_SwitchMode{ 0x14214A4D0 }; @@ -80,6 +81,9 @@ namespace game WEAK symbol StuckInClient{0x1415A8360, 0x14023BFE0}; + // GScr + WEAK symbol GScr_LoadGametypeScript{0x14092F680, 0x0}; + // Live WEAK symbol Live_GetConnectivityInformation{0x141E0C380}; @@ -175,6 +179,7 @@ namespace game 0x0, 0x1402F5FF0 }; WEAK symbol Scr_GetNumParam{0x0, 0x140171320}; + WEAK symbol Scr_LoadScript{0x1412C83F0}; WEAK symbol Cinematic_StartPlayback{0x1412BE3A0}; From 8034967a74abf41783dbfce354ba63844e729826 Mon Sep 17 00:00:00 2001 From: m Date: Tue, 9 May 2023 03:03:57 -0500 Subject: [PATCH 02/23] cleanup some stuff lol --- src/client/component/script.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 6cc659db..d6dc8fa5 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -16,6 +16,7 @@ namespace script utils::hook::detour db_findxassetheader_hook; utils::hook::detour gscr_get_bgb_remaining_hook; + utils::hook::detour load_gametype_script_hook; std::unordered_map loaded_scripts; @@ -25,6 +26,11 @@ namespace script return (itr == loaded_scripts.end()) ? nullptr : itr->second; } + void print_loading_script(const std::string& name) + { + printf("Loading GSC script '%s'\n", name.data()); + } + void load_script(std::string& name, const std::string& data) { auto& allocator = *utils::memory::get_allocator(); @@ -64,6 +70,7 @@ namespace script } const auto scripts = utils::io::list_files(script_dir); + for (const auto& script : scripts) { std::string data; @@ -73,7 +80,7 @@ namespace script if (data.size() >= sizeof(GSC_MAGIC) && !std::memcmp(data.data(), &GSC_MAGIC, sizeof(GSC_MAGIC))) { auto base_name = script_file.substr(0, script_file.size() - 4); - printf("Loading GSC script '%s'\n", base_name.data()); + print_loading_script(script_file); load_script(script_file, data); } } @@ -89,8 +96,7 @@ namespace script loaded_scripts = {}; const utils::nt::library host{}; load_scripts_folder((game::get_appdata_path() / "data/scripts").string()); - auto path = (host.get_folder() / "boiii/scripts").string(); - load_scripts_folder(path); + load_scripts_folder((host.get_folder() / "boiii/scripts").string()); } game::RawFile* db_findxassetheader_stub(const game::XAssetType type, const char* name, @@ -108,10 +114,8 @@ namespace script auto* script = get_loaded_script(name); if (script) { - /* // TODO: don't check checksums for custom GSC, but only for stock scripts we override - utils::hook::copy(const_cast(script->buffer + 0x8), asset_header->buffer + 0x8, 4); - */ + //utils::hook::copy(const_cast(script->buffer + 0x8), asset_header->buffer + 0x8, 4); return script; } @@ -123,8 +127,6 @@ namespace script game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 255); } - utils::hook::detour load_gametype_script_hook; - void load_gametype_script_stub() { if (!game::Com_IsInGame() || game::Com_IsRunningUILevel()) @@ -144,7 +146,6 @@ namespace script { db_findxassetheader_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_findxassetheader_stub); gscr_get_bgb_remaining_hook.create(game::select(0x141A8CAB0, 0x1402D2310), gscr_get_bgb_remaining_stub); - load_gametype_script_hook.create(0x141AAD850_g, load_gametype_script_stub); } }; From 3907a763510b16337829f0acf38181edf24b1cfd Mon Sep 17 00:00:00 2001 From: m Date: Thu, 11 May 2023 00:47:35 -0500 Subject: [PATCH 03/23] valid checksums + dedi support --- src/client/component/script.cpp | 30 +++++++++++++++++++++--------- src/client/game/structs.hpp | 2 -- src/client/game/symbols.hpp | 9 +++------ 3 files changed, 24 insertions(+), 17 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 3573e345..6a1da9a7 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -15,8 +15,9 @@ namespace script constexpr size_t GSC_MAGIC = 0x1C000A0D43534780; utils::hook::detour db_findxassetheader_hook; - utils::hook::detour gscr_get_bgb_remaining_hook; utils::hook::detour load_gametype_script_hook; + utils::hook::detour server_script_checksum_hook; + utils::hook::detour gscr_get_bgb_remaining_hook; std::unordered_map loaded_scripts; @@ -113,19 +114,12 @@ namespace script auto* script = get_loaded_script(name); if (script) { - // TODO: don't check checksums for custom GSC, but only for stock scripts we override - //utils::hook::copy(const_cast(script->buffer + 0x8), asset_header->buffer + 0x8, 4); return script; } return asset_header; } - void gscr_get_bgb_remaining_stub(game::scriptInstance_t inst, void* entref) - { - game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 255); - } - void load_gametype_script_stub() { if (!game::Com_IsInGame() || game::Com_IsRunningUILevel()) @@ -137,15 +131,33 @@ namespace script load_gametype_script_hook.invoke(); load_scripts(); } + + int server_script_checksum_stub() + { + return 1; + } + + void gscr_get_bgb_remaining_stub(game::scriptInstance_t inst, void* entref) + { + game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 255); + } } struct component final : generic_component { void post_unpack() override { + // Return custom or overrided scripts if found db_findxassetheader_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_findxassetheader_stub); + + // Load our scripts when the gametype script is loaded + load_gametype_script_hook.create(game::select(0x141AAD850, 0x1402D7140), load_gametype_script_stub); + + // Force GSC checksums to be valid + utils::hook::call(game::select(0x1408F2E5D, 0x1400E2D22), server_script_checksum_stub); + + // Workaround for "Out of X" gobblegum gscr_get_bgb_remaining_hook.create(game::select(0x141A8CAB0, 0x1402D2310), gscr_get_bgb_remaining_stub); - load_gametype_script_hook.create(0x141AAD850_g, load_gametype_script_stub); } }; }; diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index c635953c..bc861685 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -1814,9 +1814,7 @@ namespace game PlayerSoundsTable* playerSounds; PlayerFXTable* playerFX; SharedWeaponSounds* sharedWeaponSounds; - */ RawFile* rawfile; - /* StringTable* stringTable; StructuredTable* structuredTable; LeaderboardDef* leaderboardDef; diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index a909c00d..e18c8917 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -34,8 +34,8 @@ namespace game WEAK symbol Com_GametypeSettings_GetUInt{ 0x1420F4E00, 0x1404FE5C0 }; - WEAK symbol Com_IsRunningUILevel{0x142148350}; - WEAK symbol Com_IsInGame{0x1421482C0}; + WEAK symbol Com_IsRunningUILevel{0x142148350, 0x14045C070}; + WEAK symbol Com_IsInGame{0x1421482C0, 0x140504B90}; WEAK symbol Com_SwitchMode{ 0x14214A4D0 }; @@ -81,9 +81,6 @@ namespace game WEAK symbol StuckInClient{0x1415A8360, 0x14023BFE0}; - // GScr - WEAK symbol GScr_LoadGametypeScript{0x14092F680, 0x0}; - // Live WEAK symbol Live_GetConnectivityInformation{0x141E0C380}; @@ -180,7 +177,7 @@ namespace game 0x0, 0x1402F5FF0 }; WEAK symbol Scr_GetNumParam{0x0, 0x140171320}; - WEAK symbol Scr_LoadScript{0x1412C83F0}; + WEAK symbol Scr_LoadScript{0x1412C83F0, 0x140156610}; WEAK symbol Cinematic_StartPlayback{0x1412BE3A0}; From 1050340b860b40a7e79f3e7dd0360203a8216339 Mon Sep 17 00:00:00 2001 From: m Date: Fri, 12 May 2023 21:40:16 -0500 Subject: [PATCH 04/23] fix dedi address --- src/client/game/symbols.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index e18c8917..b942cae4 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -34,7 +34,7 @@ namespace game WEAK symbol Com_GametypeSettings_GetUInt{ 0x1420F4E00, 0x1404FE5C0 }; - WEAK symbol Com_IsRunningUILevel{0x142148350, 0x14045C070}; + WEAK symbol Com_IsRunningUILevel{0x142148350, 0x140504BD0}; WEAK symbol Com_IsInGame{0x1421482C0, 0x140504B90}; WEAK symbol Com_SwitchMode{ 0x14214A4D0 From 4fe501cf80aa23369dfd8d0340c28a1bdaee4607 Mon Sep 17 00:00:00 2001 From: m Date: Fri, 12 May 2023 21:52:08 -0500 Subject: [PATCH 05/23] tiny cleanup --- src/client/component/script.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 6a1da9a7..e02f3ed1 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -16,7 +16,6 @@ namespace script utils::hook::detour db_findxassetheader_hook; utils::hook::detour load_gametype_script_hook; - utils::hook::detour server_script_checksum_hook; utils::hook::detour gscr_get_bgb_remaining_hook; std::unordered_map loaded_scripts; @@ -59,8 +58,7 @@ namespace script loaded_scripts[name] = rawfile; - const auto base_name = name.substr(0, name.size() - 4); // .gsc suffix will be readded by Scr_LoadScript - game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, base_name.data()); + game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, name.substr(0, name.size() - 4).data()); // .gsc suffix will be readded by Scr_LoadScript } void load_scripts_folder(const std::string& script_dir) From 966458a129c672ae19a4824583a209ef21840269 Mon Sep 17 00:00:00 2001 From: m Date: Sat, 13 May 2023 16:32:50 -0500 Subject: [PATCH 06/23] don't use detour, check size of name --- src/client/component/script.cpp | 23 +++++++++++++++++------ src/client/game/symbols.hpp | 2 ++ 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index e02f3ed1..9b9475b7 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -15,7 +15,6 @@ namespace script constexpr size_t GSC_MAGIC = 0x1C000A0D43534780; utils::hook::detour db_findxassetheader_hook; - utils::hook::detour load_gametype_script_hook; utils::hook::detour gscr_get_bgb_remaining_hook; std::unordered_map loaded_scripts; @@ -51,14 +50,26 @@ namespace script name.erase(i, host_path.length()); } + auto base_name = name; + if (utils::string::ends_with(name, ".gsc")) + { + base_name = name.substr(0, name.size() - 4); // .gsc suffix will be readded by Scr_LoadScript + } + + if (base_name.size() < 1) + { + printf("Not loading GSC script '%s' due to invalid name.\n", name.data()); + return; + } + auto* rawfile = allocator.allocate(); - rawfile->name = name.data(); + rawfile->name = name.data(); // use script name with .gsc suffix for FindXAssetHeader hook rawfile->buffer = file_string; rawfile->len = static_cast(data.length()); loaded_scripts[name] = rawfile; - game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, name.substr(0, name.size() - 4).data()); // .gsc suffix will be readded by Scr_LoadScript + game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, base_name.data()); } void load_scripts_folder(const std::string& script_dir) @@ -122,11 +133,11 @@ namespace script { if (!game::Com_IsInGame() || game::Com_IsRunningUILevel()) { - load_gametype_script_hook.invoke(); + game::GScr_LoadGametypeScript(); return; } - load_gametype_script_hook.invoke(); + game::GScr_LoadGametypeScript(); load_scripts(); } @@ -149,7 +160,7 @@ namespace script db_findxassetheader_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_findxassetheader_stub); // Load our scripts when the gametype script is loaded - load_gametype_script_hook.create(game::select(0x141AAD850, 0x1402D7140), load_gametype_script_stub); + utils::hook::call(game::select(0x141AAF37C, 0x1402D8C7F), load_gametype_script_stub); // Force GSC checksums to be valid utils::hook::call(game::select(0x1408F2E5D, 0x1400E2D22), server_script_checksum_stub); diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index b942cae4..4a6bb389 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -216,6 +216,8 @@ namespace game 0x1422E9410, 0x1405811E0 }; + WEAK symbol GScr_LoadGametypeScript{0x141AAD850, 0x1402D7140}; + // Variables WEAK symbol cmd_functions{0x15689DF58, 0x14946F860}; WEAK symbol sv_cmd_args{0x15689AE30, 0x14944C740}; From 3748b5e51f43a13ef375065962a25af82c72e910 Mon Sep 17 00:00:00 2001 From: m Date: Sun, 14 May 2023 03:02:11 -0500 Subject: [PATCH 07/23] use empty --- src/client/component/script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 9b9475b7..52e4db34 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -56,7 +56,7 @@ namespace script base_name = name.substr(0, name.size() - 4); // .gsc suffix will be readded by Scr_LoadScript } - if (base_name.size() < 1) + if (base_name.empty()) { printf("Not loading GSC script '%s' due to invalid name.\n", name.data()); return; From 925e77bdd88f37dbba4cd454fac67d412b4c967f Mon Sep 17 00:00:00 2001 From: m Date: Sun, 14 May 2023 03:05:42 -0500 Subject: [PATCH 08/23] format --- src/client/component/script.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index ade06be1..6be36484 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -60,8 +60,8 @@ namespace script printf("Not loading GSC script '%s' due to invalid name.\n", name.data()); return; } - - auto* raw_file = allocator.allocate(); + + auto* raw_file = allocator.allocate(); raw_file->name = allocator.duplicate_string(name); // use script name with .gsc suffix for FindXAssetHeader hook raw_file->buffer = allocator.duplicate_string(data); raw_file->len = static_cast(data.length()); From 55b74e44a7bd109e3cc93bb21930ae486d1fd5dd Mon Sep 17 00:00:00 2001 From: m Date: Sun, 14 May 2023 03:18:49 -0500 Subject: [PATCH 09/23] fix build lol --- src/client/component/script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 6be36484..b3a9de14 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -156,7 +156,7 @@ namespace script void post_unpack() override { // Return custom or overrided scripts if found - db_findxassetheader_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_findxassetheader_stub); + db_find_x_asset_header_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_find_x_asset_header_stub); // Load our scripts when the gametype script is loaded utils::hook::call(game::select(0x141AAF37C, 0x1402D8C7F), load_gametype_script_stub); From a6111f811eea73a7087bbbb1e6cde9f1058447a5 Mon Sep 17 00:00:00 2001 From: m Date: Sun, 14 May 2023 03:32:59 -0500 Subject: [PATCH 10/23] return if not gsc --- src/client/component/script.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index b3a9de14..eae739b0 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -50,14 +50,16 @@ namespace script } auto base_name = name; - if (utils::string::ends_with(name, ".gsc")) + if (!utils::string::ends_with(name, ".gsc")) { - base_name = name.substr(0, name.size() - 4); // .gsc suffix will be readded by Scr_LoadScript + printf("GSC script '%s' failed to load due to invalid suffix.\n", name.data()); + return; } + base_name = name.substr(0, name.size() - 4); // .gsc suffix will be readded by Scr_LoadScript if (base_name.empty()) { - printf("Not loading GSC script '%s' due to invalid name.\n", name.data()); + printf("GSC script '%s' failed to load due to invalid name.\n", name.data()); return; } From 07885a7920916737538cd659103e788389bc4f63 Mon Sep 17 00:00:00 2001 From: m Date: Sun, 14 May 2023 03:40:47 -0500 Subject: [PATCH 11/23] free script allocations --- src/client/component/script.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index eae739b0..d551b278 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -15,8 +15,10 @@ namespace script constexpr size_t GSC_MAGIC = 0x1C000A0D43534780; utils::hook::detour db_find_x_asset_header_hook; + utils::hook::detour g_shutdown_game_hook; utils::hook::detour gscr_get_bgb_remaining_hook; + utils::memory::allocator allocator; std::unordered_map loaded_scripts; game::RawFile* get_loaded_script(const std::string& name) @@ -32,8 +34,6 @@ namespace script void load_script(std::string& name, const std::string& data) { - auto& allocator = *utils::memory::get_allocator(); - const auto appdata_path = (game::get_appdata_path() / "data/").generic_string(); const auto host_path = (utils::nt::library{}.get_folder() / "boiii/").generic_string(); @@ -130,6 +130,13 @@ namespace script return asset_header; } + void g_shutdown_game_stub(bool free_scripts) + { + loaded_scripts.clear(); + allocator.clear(); + g_shutdown_game_hook.invoke(free_scripts); + } + void load_gametype_script_stub() { if (!game::Com_IsInGame() || game::Com_IsRunningUILevel()) @@ -160,6 +167,9 @@ namespace script // Return custom or overrided scripts if found db_find_x_asset_header_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_find_x_asset_header_stub); + // Free our scripts when the game ends + g_shutdown_game_hook.create(game::select(0x141A02900, 0x1402ADD70), g_shutdown_game_stub); + // Load our scripts when the gametype script is loaded utils::hook::call(game::select(0x141AAF37C, 0x1402D8C7F), load_gametype_script_stub); From a59462f3c3c9bf3572b843285c2c1fcc55bd392f Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 14 May 2023 10:02:32 +0100 Subject: [PATCH 12/23] feat: game_event component --- src/client/component/game_event.cpp | 58 +++++++++++++++++++++++++++++ src/client/component/game_event.hpp | 7 ++++ src/client/component/script.cpp | 8 ++-- src/client/game/symbols.hpp | 9 +++++ 4 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 src/client/component/game_event.cpp create mode 100644 src/client/component/game_event.hpp diff --git a/src/client/component/game_event.cpp b/src/client/component/game_event.cpp new file mode 100644 index 00000000..1ac93daa --- /dev/null +++ b/src/client/component/game_event.cpp @@ -0,0 +1,58 @@ +#include +#include "loader/component_loader.hpp" +#include + +#include "game_event.hpp" + +#include + +namespace game_event +{ + namespace + { + std::vector> g_init_game_tasks_; + std::vector> g_shutdown_game_tasks_; + + void rope_init_ropes_stub() + { + for (const auto& func : g_init_game_tasks_) + { + func(); + } + + game::Rope_InitRopes(); + } + + void mantle_shutdown_anims_stub() + { + for (const auto& func : g_init_game_tasks_) + { + func(); + } + + game::Mantle_ShutdownAnims(); + } + } + + void on_g_init_game(const std::function& callback) + { + g_init_game_tasks_.emplace_back(callback); + } + + void on_g_shutdown_game(const std::function& callback) + { + g_shutdown_game_tasks_.emplace_back(callback); + } + + class component final : public generic_component + { + public: + void post_unpack() override + { + utils::hook::call(game::select(0x1419DD6EC, 0x1402ABC1B), rope_init_ropes_stub); + utils::hook::call(game::select(0x141A02AAD, 0x1402ADF1D), rope_init_ropes_stub); + } + }; +} + +REGISTER_COMPONENT(game_event::component) diff --git a/src/client/component/game_event.hpp b/src/client/component/game_event.hpp new file mode 100644 index 00000000..875cc719 --- /dev/null +++ b/src/client/component/game_event.hpp @@ -0,0 +1,7 @@ +#pragma once + +namespace game_event +{ + void on_g_init_game(const std::function& callback); + void on_g_shutdown_game(const std::function& callback); +} diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index d551b278..0a0bfceb 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -2,7 +2,7 @@ #include "loader/component_loader.hpp" #include "game/game.hpp" -#include "scheduler.hpp" +#include "game_event.hpp" #include #include @@ -15,7 +15,6 @@ namespace script constexpr size_t GSC_MAGIC = 0x1C000A0D43534780; utils::hook::detour db_find_x_asset_header_hook; - utils::hook::detour g_shutdown_game_hook; utils::hook::detour gscr_get_bgb_remaining_hook; utils::memory::allocator allocator; @@ -130,11 +129,10 @@ namespace script return asset_header; } - void g_shutdown_game_stub(bool free_scripts) + void clear_script_memory() { loaded_scripts.clear(); allocator.clear(); - g_shutdown_game_hook.invoke(free_scripts); } void load_gametype_script_stub() @@ -168,7 +166,7 @@ namespace script db_find_x_asset_header_hook.create(game::select(0x141420ED0, 0x1401D5FB0), db_find_x_asset_header_stub); // Free our scripts when the game ends - g_shutdown_game_hook.create(game::select(0x141A02900, 0x1402ADD70), g_shutdown_game_stub); + game_event::on_g_shutdown_game(clear_script_memory); // Load our scripts when the gametype script is loaded utils::hook::call(game::select(0x141AAF37C, 0x1402D8C7F), load_gametype_script_stub); diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index a40f6ce2..ee415ce6 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -113,6 +113,15 @@ namespace game WEAK symbol Sys_GetTLS{0x1421837B0, 0x140525EB0}; WEAK symbol Sys_IsDatabaseReady{0x142183A60}; + // Rope + WEAK symbol Rope_InitRopes{0x1420D8D00, 0x1404E4300}; + + // Glass + WEAK symbol GlassSv_Shutdown{0x1425AA7A0, 0x14065BCC0}; + + // Mantle + WEAK symbol Mantle_ShutdownAnims{0x142678C80, 0x1406A1B50}; + // Unnamed WEAK symbol CopyString{0x1422AC220, 0x14056BD70}; From a38a148582ac5f200d8378b9883ac8fd9e24046c Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 14 May 2023 10:06:20 +0100 Subject: [PATCH 13/23] big fix --- src/client/component/game_event.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/component/game_event.cpp b/src/client/component/game_event.cpp index 1ac93daa..91ccf016 100644 --- a/src/client/component/game_event.cpp +++ b/src/client/component/game_event.cpp @@ -25,7 +25,7 @@ namespace game_event void mantle_shutdown_anims_stub() { - for (const auto& func : g_init_game_tasks_) + for (const auto& func : g_shutdown_game_tasks_) { func(); } @@ -50,7 +50,7 @@ namespace game_event void post_unpack() override { utils::hook::call(game::select(0x1419DD6EC, 0x1402ABC1B), rope_init_ropes_stub); - utils::hook::call(game::select(0x141A02AAD, 0x1402ADF1D), rope_init_ropes_stub); + utils::hook::call(game::select(0x141A02AAD, 0x1402ADF1D), mantle_shutdown_anims_stub); } }; } From 1f7c0476dda26472877b747a4b7d51cfbeb3ffd2 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 14 May 2023 10:51:18 +0100 Subject: [PATCH 14/23] tiny addition to a stub in script --- src/client/component/script.cpp | 8 ++++-- src/client/game/structs.hpp | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 0a0bfceb..c968afcc 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -63,7 +63,8 @@ namespace script } auto* raw_file = allocator.allocate(); - raw_file->name = allocator.duplicate_string(name); // use script name with .gsc suffix for FindXAssetHeader hook + // use script name with .gsc suffix for DB_FindXAssetHeader hook + raw_file->name = allocator.duplicate_string(name); raw_file->buffer = allocator.duplicate_string(data); raw_file->len = static_cast(data.length()); @@ -152,7 +153,7 @@ namespace script return 1; } - void gscr_get_bgb_remaining_stub(game::scriptInstance_t inst, void* entref) + void scr_loot_get_utem_quantity_stub(game::scriptInstance_t inst, game::scr_entref_t entref) { game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 255); } @@ -175,7 +176,8 @@ namespace script utils::hook::call(game::select(0x1408F2E5D, 0x1400E2D22), server_script_checksum_stub); // Workaround for "Out of X" gobblegum - gscr_get_bgb_remaining_hook.create(game::select(0x141A8CAB0, 0x1402D2310), gscr_get_bgb_remaining_stub); + gscr_get_bgb_remaining_hook.create(game::select(0x141A8CAB0, 0x1402D2310), + scr_loot_get_utem_quantity_stub); } }; }; diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 94d6bfbc..19f6b28e 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -19,6 +19,18 @@ namespace game CONTROLLER_INDEX_COUNT = 0x4, }; + enum LocalClientNum_t + { + INVALID_LOCAL_CLIENT = -1, + LOCAL_CLIENT_0 = 0x0, + LOCAL_CLIENT_FIRST = 0x0, + LOCAL_CLIENT_KEYBOARD_AND_MOUSE = 0x0, + LOCAL_CLIENT_1 = 0x1, + LOCAL_CLIENT_2 = 0x2, + LOCAL_CLIENT_3 = 0x3, + LOCAL_CLIENT_COUNT = 0x4, + }; + enum eGameModes { MODE_GAME_MATCHMAKING_PLAYLIST = 0x0, @@ -1636,6 +1648,44 @@ namespace game static_assert(sizeof(client_s_cl) == 0xE5170); #endif + union Weapon + { + struct + { + unsigned __int64 weaponIdx : 9; + unsigned __int64 attachment1 : 6; + unsigned __int64 attachment2 : 6; + unsigned __int64 attachment3 : 6; + unsigned __int64 attachment4 : 6; + unsigned __int64 attachment5 : 6; + unsigned __int64 attachment6 : 6; + unsigned __int64 attachment7 : 6; + unsigned __int64 attachment8 : 6; + unsigned __int64 padding : 7; + } _anon_0; + uint64_t weaponData; + }; + + union EntRefUnion + { + int32_t entnum; + uint32_t hudElemIndex; + uint32_t pathNodeIndex; + __int16 vehicleNodeIndex; + unsigned __int16 absDynEntIndex; + Weapon weapon; + uint64_t val; + }; + + struct scr_entref_t + { + EntRefUnion u; + unsigned __int16 classnum; + LocalClientNum_t client; + }; + + static_assert(sizeof(scr_entref_t) == 0x10); + enum scriptInstance_t { SCRIPTINSTANCE_SERVER = 0x0, From 0265c5cd2de4ce22158720746a5ca1019e73f6cd Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 14 May 2023 10:54:22 +0100 Subject: [PATCH 15/23] fix filesystem usage --- src/client/component/script.cpp | 4 ++-- src/client/game/structs.hpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index c968afcc..d9df3339 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -105,8 +105,8 @@ namespace script { loaded_scripts = {}; const utils::nt::library host{}; - load_scripts_folder((game::get_appdata_path() / "data/scripts").string()); - load_scripts_folder((host.get_folder() / "boiii/scripts").string()); + load_scripts_folder((game::get_appdata_path() / "data"/ "scripts").string()); + load_scripts_folder((host.get_folder() / "boiii" / "scripts").string()); } game::RawFile* db_find_x_asset_header_stub(const game::XAssetType type, const char* name, diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 19f6b28e..11105105 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -10,7 +10,7 @@ namespace game enum ControllerIndex_t { - INVALID_CONTROLLER_PORT = 0xFFFFFFFF, + INVALID_CONTROLLER_PORT = -1, CONTROLLER_INDEX_FIRST = 0x0, CONTROLLER_INDEX_0 = 0x0, CONTROLLER_INDEX_1 = 0x1, @@ -922,7 +922,7 @@ namespace game enum LobbyNetworkMode { - LOBBY_NETWORKMODE_INVALID = 0xFFFFFFFF, + LOBBY_NETWORKMODE_INVALID = -1, LOBBY_NETWORKMODE_LOCAL = 0x0, LOBBY_NETWORKMODE_LAN = 0x1, LOBBY_NETWORKMODE_LIVE = 0x2, @@ -931,7 +931,7 @@ namespace game enum LobbyMainMode { - LOBBY_MAINMODE_INVALID = 0xFFFFFFFF, + LOBBY_MAINMODE_INVALID = -1, LOBBY_MAINMODE_CP = 0x0, LOBBY_MAINMODE_MP = 0x1, LOBBY_MAINMODE_ZM = 0x2, @@ -1153,8 +1153,8 @@ namespace game enum HksObjectType { - TANY = 0xFFFFFFFE, - TNONE = 0xFFFFFFFF, + TANY = -1, + TNONE = -1, TNIL = 0x0, TBOOLEAN = 0x1, TLIGHTUSERDATA = 0x2, From 96b20484483e637f11abd8291efb74de9c58b738 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 14 May 2023 10:58:48 +0100 Subject: [PATCH 16/23] use noexcept function --- src/client/component/script.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index d9df3339..10645dc4 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -82,11 +82,12 @@ namespace script const auto scripts = utils::io::list_files(script_dir); + std::error_code e; for (const auto& script : scripts) { std::string data; auto script_file = script.generic_string(); - if (!std::filesystem::is_directory(script) && utils::io::read_file(script_file, &data)) + if (!std::filesystem::is_directory(script, e) && utils::io::read_file(script_file, &data)) { if (data.size() >= sizeof(GSC_MAGIC) && !std::memcmp(data.data(), &GSC_MAGIC, sizeof(GSC_MAGIC))) { @@ -94,7 +95,7 @@ namespace script load_script(script_file, data); } } - else if (std::filesystem::is_directory(script)) + else if (std::filesystem::is_directory(script, e)) { load_scripts_folder(script_file); } @@ -153,7 +154,8 @@ namespace script return 1; } - void scr_loot_get_utem_quantity_stub(game::scriptInstance_t inst, game::scr_entref_t entref) + void scr_loot_get_utem_quantity_stub([[maybe_unused]] game::scriptInstance_t inst, + [[maybe_unused]] game::scr_entref_t entref) { game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 255); } From d933a59e838f8cd87ca2cb92b6454b1d92eb7ce1 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Sun, 14 May 2023 11:35:39 +0100 Subject: [PATCH 17/23] big brain fix for 3arc scripts folder meme --- src/client/component/script.cpp | 49 +++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 10645dc4..ce98f97d 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -31,7 +31,7 @@ namespace script printf("Loading GSC script '%s'\n", name.data()); } - void load_script(std::string& name, const std::string& data) + void load_script(std::string& name, const std::string& data, const bool is_custom) { const auto appdata_path = (game::get_appdata_path() / "data/").generic_string(); const auto host_path = (utils::nt::library{}.get_folder() / "boiii/").generic_string(); @@ -55,11 +55,15 @@ namespace script return; } - base_name = name.substr(0, name.size() - 4); // .gsc suffix will be readded by Scr_LoadScript - if (base_name.empty()) + if (is_custom) { - printf("GSC script '%s' failed to load due to invalid name.\n", name.data()); - return; + // .gsc suffix will be added back by Scr_LoadScript + base_name = name.substr(0, name.size() - 4); + if (base_name.empty()) + { + printf("GSC script '%s' failed to load due to invalid name.\n", name.data()); + return; + } } auto* raw_file = allocator.allocate(); @@ -70,10 +74,13 @@ namespace script loaded_scripts[name] = raw_file; - game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, base_name.data()); + if (is_custom) + { + game::Scr_LoadScript(game::SCRIPTINSTANCE_SERVER, base_name.data()); + } } - void load_scripts_folder(const std::string& script_dir) + void load_scripts_folder(const std::string& script_dir, const bool is_custom) { if (!utils::io::directory_exists(script_dir)) { @@ -92,22 +99,33 @@ namespace script if (data.size() >= sizeof(GSC_MAGIC) && !std::memcmp(data.data(), &GSC_MAGIC, sizeof(GSC_MAGIC))) { print_loading_script(script_file); - load_script(script_file, data); + load_script(script_file, data, is_custom); } + + continue; } - else if (std::filesystem::is_directory(script, e)) + + // Do not traverse directories for custom scripts. + // TODO: Add game type specific scripts. custom-scripts/cp, custom-scripts/mp and /custom-scripts/zm + if (std::filesystem::is_directory(script, e) && !is_custom) { - load_scripts_folder(script_file); + load_scripts_folder(script_file, is_custom); } } } void load_scripts() { - loaded_scripts = {}; const utils::nt::library host{}; - load_scripts_folder((game::get_appdata_path() / "data"/ "scripts").string()); - load_scripts_folder((host.get_folder() / "boiii" / "scripts").string()); + load_scripts_folder((game::get_appdata_path() / "data"/ "scripts").string(), false); + load_scripts_folder((host.get_folder() / "boiii" / "scripts").string(), false); + } + + void load_custom_scripts() + { + const utils::nt::library host{}; + load_scripts_folder((game::get_appdata_path() / "data" / "custom-scripts").string(), true); + load_scripts_folder((host.get_folder() / "boiii" / "custom-scripts").string(), true); } game::RawFile* db_find_x_asset_header_stub(const game::XAssetType type, const char* name, @@ -147,6 +165,7 @@ namespace script game::GScr_LoadGametypeScript(); load_scripts(); + load_custom_scripts(); } int server_script_checksum_stub() @@ -154,7 +173,7 @@ namespace script return 1; } - void scr_loot_get_utem_quantity_stub([[maybe_unused]] game::scriptInstance_t inst, + void scr_loot_get_item_quantity_stub([[maybe_unused]] game::scriptInstance_t inst, [[maybe_unused]] game::scr_entref_t entref) { game::Scr_AddInt(game::SCRIPTINSTANCE_SERVER, 255); @@ -179,7 +198,7 @@ namespace script // Workaround for "Out of X" gobblegum gscr_get_bgb_remaining_hook.create(game::select(0x141A8CAB0, 0x1402D2310), - scr_loot_get_utem_quantity_stub); + scr_loot_get_item_quantity_stub); } }; }; From d38c27442fa21146db29dcdf4b302a37d4cd56c0 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 14 May 2023 14:44:10 +0100 Subject: [PATCH 18/23] Use underscore --- src/client/component/script.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index ce98f97d..60522061 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -124,8 +124,8 @@ namespace script void load_custom_scripts() { const utils::nt::library host{}; - load_scripts_folder((game::get_appdata_path() / "data" / "custom-scripts").string(), true); - load_scripts_folder((host.get_folder() / "boiii" / "custom-scripts").string(), true); + load_scripts_folder((game::get_appdata_path() / "data" / "custom_scripts").string(), true); + load_scripts_folder((host.get_folder() / "boiii" / "custom_scripts").string(), true); } game::RawFile* db_find_x_asset_header_stub(const game::XAssetType type, const char* name, From 14fcff3dd0ef5730b388c6e8ee1de4d6df248897 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 14 May 2023 17:31:57 +0100 Subject: [PATCH 19/23] remove underscore --- src/client/component/game_event.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/client/component/game_event.cpp b/src/client/component/game_event.cpp index 91ccf016..0d3689ba 100644 --- a/src/client/component/game_event.cpp +++ b/src/client/component/game_event.cpp @@ -10,8 +10,8 @@ namespace game_event { namespace { - std::vector> g_init_game_tasks_; - std::vector> g_shutdown_game_tasks_; + std::vector> g_init_game_tasks; + std::vector> g_shutdown_game_tasks; void rope_init_ropes_stub() { From eff801ede0350a371fb21c61e7c5ce3fe6266f4c Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 14 May 2023 17:33:09 +0100 Subject: [PATCH 20/23] Update structs.hpp --- src/client/game/structs.hpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/client/game/structs.hpp b/src/client/game/structs.hpp index 11105105..2f80831c 100644 --- a/src/client/game/structs.hpp +++ b/src/client/game/structs.hpp @@ -1652,16 +1652,16 @@ namespace game { struct { - unsigned __int64 weaponIdx : 9; - unsigned __int64 attachment1 : 6; - unsigned __int64 attachment2 : 6; - unsigned __int64 attachment3 : 6; - unsigned __int64 attachment4 : 6; - unsigned __int64 attachment5 : 6; - unsigned __int64 attachment6 : 6; - unsigned __int64 attachment7 : 6; - unsigned __int64 attachment8 : 6; - unsigned __int64 padding : 7; + uint64_t weaponIdx : 9; + uint64_t attachment1 : 6; + uint64_t attachment2 : 6; + uint64_t attachment3 : 6; + uint64_t attachment4 : 6; + uint64_t attachment5 : 6; + uint64_t attachment6 : 6; + uint64_t attachment7 : 6; + uint64_t attachment8 : 6; + uint64_t padding : 7; } _anon_0; uint64_t weaponData; }; @@ -1671,8 +1671,8 @@ namespace game int32_t entnum; uint32_t hudElemIndex; uint32_t pathNodeIndex; - __int16 vehicleNodeIndex; - unsigned __int16 absDynEntIndex; + short vehicleNodeIndex; + unsigned short absDynEntIndex; Weapon weapon; uint64_t val; }; @@ -1680,7 +1680,7 @@ namespace game struct scr_entref_t { EntRefUnion u; - unsigned __int16 classnum; + unsigned short classnum; LocalClientNum_t client; }; From f8384b5cabfbfe62e0ca503d0ade3a9707900a82 Mon Sep 17 00:00:00 2001 From: Edo Date: Sun, 14 May 2023 17:33:53 +0100 Subject: [PATCH 21/23] fix comp --- src/client/component/game_event.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/client/component/game_event.cpp b/src/client/component/game_event.cpp index 0d3689ba..27d4370d 100644 --- a/src/client/component/game_event.cpp +++ b/src/client/component/game_event.cpp @@ -15,7 +15,7 @@ namespace game_event void rope_init_ropes_stub() { - for (const auto& func : g_init_game_tasks_) + for (const auto& func : g_init_game_tasks) { func(); } @@ -25,7 +25,7 @@ namespace game_event void mantle_shutdown_anims_stub() { - for (const auto& func : g_shutdown_game_tasks_) + for (const auto& func : g_shutdown_game_tasks) { func(); } @@ -36,12 +36,12 @@ namespace game_event void on_g_init_game(const std::function& callback) { - g_init_game_tasks_.emplace_back(callback); + g_init_game_tasks.emplace_back(callback); } void on_g_shutdown_game(const std::function& callback) { - g_shutdown_game_tasks_.emplace_back(callback); + g_shutdown_game_tasks.emplace_back(callback); } class component final : public generic_component From bdf67845295bb96dddb5df0285890e82a5f22e14 Mon Sep 17 00:00:00 2001 From: FutureRave Date: Mon, 15 May 2023 22:00:13 +0100 Subject: [PATCH 22/23] thread safety is important --- src/client/component/game_event.cpp | 34 ++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/client/component/game_event.cpp b/src/client/component/game_event.cpp index 27d4370d..2925cfd5 100644 --- a/src/client/component/game_event.cpp +++ b/src/client/component/game_event.cpp @@ -4,31 +4,39 @@ #include "game_event.hpp" +#include #include namespace game_event { namespace { - std::vector> g_init_game_tasks; - std::vector> g_shutdown_game_tasks; + using event_task = std::vector>; + utils::concurrency::container g_init_game_tasks; + utils::concurrency::container g_shutdown_game_tasks; void rope_init_ropes_stub() { - for (const auto& func : g_init_game_tasks) + g_init_game_tasks.access([](event_task& tasks) { - func(); - } + for (const auto& func : tasks) + { + func(); + } + }); game::Rope_InitRopes(); } void mantle_shutdown_anims_stub() { - for (const auto& func : g_shutdown_game_tasks) + g_shutdown_game_tasks.access([](event_task& tasks) { - func(); - } + for (const auto& func : tasks) + { + func(); + } + }); game::Mantle_ShutdownAnims(); } @@ -36,12 +44,18 @@ namespace game_event void on_g_init_game(const std::function& callback) { - g_init_game_tasks.emplace_back(callback); + g_init_game_tasks.access([&callback](event_task& tasks) + { + tasks.emplace_back(callback); + }); } void on_g_shutdown_game(const std::function& callback) { - g_shutdown_game_tasks.emplace_back(callback); + g_shutdown_game_tasks.access([&callback](event_task& tasks) + { + tasks.emplace_back(callback); + }); } class component final : public generic_component From b94d2633d234765fb251d20e86144cfade9392c7 Mon Sep 17 00:00:00 2001 From: m Date: Mon, 15 May 2023 18:07:25 -0500 Subject: [PATCH 23/23] very tiny cleanup [skip ci] --- src/client/component/script.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/client/component/script.cpp b/src/client/component/script.cpp index 60522061..1e3cdb75 100644 --- a/src/client/component/script.cpp +++ b/src/client/component/script.cpp @@ -117,15 +117,17 @@ namespace script void load_scripts() { const utils::nt::library host{}; - load_scripts_folder((game::get_appdata_path() / "data"/ "scripts").string(), false); - load_scripts_folder((host.get_folder() / "boiii" / "scripts").string(), false); - } - void load_custom_scripts() - { - const utils::nt::library host{}; - load_scripts_folder((game::get_appdata_path() / "data" / "custom_scripts").string(), true); - load_scripts_folder((host.get_folder() / "boiii" / "custom_scripts").string(), true); + const auto data_folder = game::get_appdata_path() / "data"; + const auto boiii_folder = host.get_folder() / "boiii"; + + // scripts folder is for overriding stock scripts the game uses + load_scripts_folder((data_folder / "scripts").string(), false); + load_scripts_folder((boiii_folder / "scripts").string(), false); + + // custom_scripts is for loading completely custom scripts the game doesn't use + load_scripts_folder((data_folder / "custom_scripts").string(), true); + load_scripts_folder((boiii_folder / "custom_scripts").string(), true); } game::RawFile* db_find_x_asset_header_stub(const game::XAssetType type, const char* name, @@ -165,7 +167,6 @@ namespace script game::GScr_LoadGametypeScript(); load_scripts(); - load_custom_scripts(); } int server_script_checksum_stub()