From 9bacdda31c0bb05c0973d202face3036d690ad01 Mon Sep 17 00:00:00 2001 From: fed <58637860+fedddddd@users.noreply.github.com> Date: Sun, 13 Nov 2022 20:03:34 +0100 Subject: [PATCH] Fix gsc crash --- src/client/component/arena.cpp | 86 ++++++++++----------- src/client/component/bots.cpp | 9 ++- src/client/component/gsc/script_loading.cpp | 4 +- src/client/component/logfile.cpp | 7 +- src/client/component/scripting.cpp | 11 ++- src/client/component/scripting.hpp | 2 +- 6 files changed, 65 insertions(+), 54 deletions(-) diff --git a/src/client/component/arena.cpp b/src/client/component/arena.cpp index d546978f..0941ca79 100644 --- a/src/client/component/arena.cpp +++ b/src/client/component/arena.cpp @@ -12,63 +12,63 @@ #define MAX_ARENAS 64 -namespace +namespace arena { - std::recursive_mutex arena_mutex; - - bool parse_arena(const std::string& path) + namespace { - std::lock_guard _0(arena_mutex); + std::recursive_mutex arena_mutex; - std::string buffer{}; - if (filesystem::read_file(path, &buffer) && !buffer.empty()) + bool parse_arena(const std::string& path) { - *game::ui_num_arenas += game::GameInfo_ParseArenas(buffer.data(), MAX_ARENAS - *game::ui_num_arenas, + std::lock_guard _0(arena_mutex); + + std::string buffer{}; + if (filesystem::read_file(path, &buffer) && !buffer.empty()) + { + *game::ui_num_arenas += game::GameInfo_ParseArenas(buffer.data(), MAX_ARENAS - *game::ui_num_arenas, + &game::ui_arena_infos[*game::ui_num_arenas]); + return true; + } + + if (!game::DB_XAssetExists(game::ASSET_TYPE_RAWFILE, path.data()) || + game::DB_IsXAssetDefault(game::ASSET_TYPE_RAWFILE, path.data())) + { + return false; + } + + const auto rawfile = game::DB_FindXAssetHeader(game::ASSET_TYPE_RAWFILE, path.data(), 0).rawfile; + const auto len = game::DB_GetRawFileLen(rawfile); + + const auto rawfile_buffer = utils::memory::get_allocator()->allocate_array(len); + const auto _1 = gsl::finally([&] + { + utils::memory::get_allocator()->free(rawfile_buffer); + }); + + game::DB_GetRawBuffer(rawfile, rawfile_buffer, len); + *game::ui_num_arenas += game::GameInfo_ParseArenas(rawfile_buffer, MAX_ARENAS - *game::ui_num_arenas, &game::ui_arena_infos[*game::ui_num_arenas]); return true; } - if (!game::DB_XAssetExists(game::ASSET_TYPE_RAWFILE, path.data()) || - game::DB_IsXAssetDefault(game::ASSET_TYPE_RAWFILE, path.data())) + void load_arenas_stub() { - return false; - } - - const auto rawfile = game::DB_FindXAssetHeader(game::ASSET_TYPE_RAWFILE, path.data(), 0).rawfile; - const auto len = game::DB_GetRawFileLen(rawfile); + *game::ui_num_arenas = 0; + *game::ui_arena_buf_pos = 0; - const auto rawfile_buffer = utils::memory::get_allocator()->allocate_array(len); - const auto _1 = gsl::finally([&] - { - utils::memory::get_allocator()->free(rawfile_buffer); - }); + parse_arena("mp/basemaps.arena"); - game::DB_GetRawBuffer(rawfile, rawfile_buffer, len); - *game::ui_num_arenas += game::GameInfo_ParseArenas(rawfile_buffer, MAX_ARENAS - *game::ui_num_arenas, - &game::ui_arena_infos[*game::ui_num_arenas]); - return true; - } - - void load_arenas_stub() - { - *game::ui_num_arenas = 0; - *game::ui_arena_buf_pos = 0; - - parse_arena("mp/basemaps.arena"); - - // read usermap arena from disk - const auto mapname = game::Dvar_FindVar("ui_mapname"); - if (mapname && mapname->current.string) - { - const auto usermap_path = "usermaps/"s + mapname->current.string; - const auto arena_path = usermap_path + "/" + mapname->current.string + ".arena"; - parse_arena(arena_path); + // read usermap arena from disk + const auto mapname = game::Dvar_FindVar("ui_mapname"); + if (mapname && mapname->current.string) + { + const auto usermap_path = "usermaps/"s + mapname->current.string; + const auto arena_path = usermap_path + "/" + mapname->current.string + ".arena"; + parse_arena(arena_path); + } } } -} -namespace arena -{ class component final : public component_interface { public: diff --git a/src/client/component/bots.cpp b/src/client/component/bots.cpp index 1dc3bfc1..3cba3a48 100644 --- a/src/client/component/bots.cpp +++ b/src/client/component/bots.cpp @@ -151,10 +151,13 @@ namespace bots }); // Clear bot names and reset ID on game shutdown to allow new names to be added without restarting - scripting::on_shutdown([](int) + scripting::on_shutdown([](bool /*free_scripts*/, bool post_shutdown) { - bot_names.clear(); - bot_id = 0; + if (!post_shutdown) + { + bot_names.clear(); + bot_id = 0; + } }); } }; diff --git a/src/client/component/gsc/script_loading.cpp b/src/client/component/gsc/script_loading.cpp index 8e1a00b2..5d9c2cf5 100644 --- a/src/client/component/gsc/script_loading.cpp +++ b/src/client/component/gsc/script_loading.cpp @@ -417,9 +417,9 @@ namespace gsc // Increase script memory utils::hook::call(SELECT_VALUE(0x38639C_b, 0x15C4D6_b), pmem_init_stub); - scripting::on_shutdown([](int free_scripts) + scripting::on_shutdown([](bool free_scripts, bool post_shutdown) { - if (free_scripts) + if (free_scripts && post_shutdown) { xsk::gsc::h1::resolver::cleanup(); clear(); diff --git a/src/client/component/logfile.cpp b/src/client/component/logfile.cpp index 7177fdc3..ef1efb2e 100644 --- a/src/client/component/logfile.cpp +++ b/src/client/component/logfile.cpp @@ -403,9 +403,12 @@ namespace logfile return scripting::script_value{}; }); - scripting::on_shutdown([](int) + scripting::on_shutdown([](bool /*free_scripts*/, bool post_shutdown) { - say_callbacks.clear(); + if (!post_shutdown) + { + say_callbacks.clear(); + } }); } }; diff --git a/src/client/component/scripting.cpp b/src/client/component/scripting.cpp index 8e92ce6b..9f96504c 100644 --- a/src/client/component/scripting.cpp +++ b/src/client/component/scripting.cpp @@ -51,7 +51,7 @@ namespace scripting game::dvar_t* g_dump_scripts; - std::vector> shutdown_callbacks; + std::vector> shutdown_callbacks; std::unordered_map canonical_string_table; @@ -125,7 +125,7 @@ namespace scripting for (const auto& callback : shutdown_callbacks) { - callback(free_scripts); + callback(free_scripts, false); } scripting::notify(*game::levelEntityId, "shutdownGame_called", {1}); @@ -135,6 +135,11 @@ namespace scripting game::G_LogPrintf("------------------------------------------------------------\n"); g_shutdown_game_hook.invoke(free_scripts); + + for (const auto& callback : shutdown_callbacks) + { + callback(free_scripts, true); + } } void scr_add_class_field_stub(unsigned int classnum, game::scr_string_t name, unsigned int canonical_string, unsigned int offset) @@ -243,7 +248,7 @@ namespace scripting return scripting::find_token(id); } - void on_shutdown(const std::function& callback) + void on_shutdown(const std::function& callback) { shutdown_callbacks.push_back(callback); } diff --git a/src/client/component/scripting.hpp b/src/client/component/scripting.hpp index f1795603..12598b9c 100644 --- a/src/client/component/scripting.hpp +++ b/src/client/component/scripting.hpp @@ -14,7 +14,7 @@ namespace scripting extern std::string current_file; - void on_shutdown(const std::function& callback); + void on_shutdown(const std::function& callback); std::optional get_canonical_string(const unsigned int id); std::string get_token(unsigned int id); } \ No newline at end of file