diff --git a/src/client/component/scripting.cpp b/src/client/component/scripting.cpp index bcb273cf..5418a772 100644 --- a/src/client/component/scripting.cpp +++ b/src/client/component/scripting.cpp @@ -14,6 +14,7 @@ #include "game/scripting/lua/engine.hpp" #include +#include namespace scripting { @@ -38,6 +39,8 @@ namespace scripting utils::hook::detour respawn_hook; + utils::hook::detour scr_run_current_threads_hook; + game::dvar_t* scr_auto_respawn = nullptr; std::string current_file; @@ -45,6 +48,9 @@ namespace scripting std::unordered_map canonical_string_table; + using notify_list = std::vector; + utils::concurrency::container scheduled_notifies; + void vm_notify_stub(const unsigned int notify_list_owner_id, const game::scr_string_t string_value, game::VariableValue* top) { @@ -60,16 +66,28 @@ namespace scripting e.arguments.emplace_back(*value); } - lua::engine::notify(e); + scheduled_notifies.access([&](notify_list& list) + { + list.push_back(e); + }); } vm_notify_hook.invoke(notify_list_owner_id, string_value, top); } + void clear_scheduler_notifies() + { + scheduled_notifies.access([](notify_list& list) + { + list.clear(); + }); + } + void client_spawn_stub(const game::gentity_s* client) { client_spawn_hook.invoke(client); scr_auto_respawn->current.enabled = true; + clear_scheduler_notifies(); lua::engine::start(); } @@ -80,6 +98,7 @@ namespace scripting canonical_string_table.clear(); } + clear_scheduler_notifies(); lua::engine::stop(); g_shutdown_game_hook.invoke(free_scripts); } @@ -158,6 +177,7 @@ namespace scripting if (save_game != nullptr) { scr_auto_respawn->current.enabled = true; + clear_scheduler_notifies(); lua::engine::start(); } return result; @@ -179,6 +199,23 @@ namespace scripting respawn_hook.invoke(); } + + void scr_run_current_threads_stub() + { + notify_list list_copy{}; + scheduled_notifies.access([&](notify_list& list) + { + list_copy = list; + list.clear(); + }); + + for (const auto& e : list_copy) + { + lua::engine::notify(e); + } + + scr_run_current_threads_hook.invoke(); + } } class component final : public component_interface @@ -200,6 +237,8 @@ namespace scripting scr_auto_respawn = dvars::register_bool("scr_autoRespawn", true, 0, "Automatically respawn player on death"); respawn_hook.create(0x1404B1E00, respawn_stub); + scr_run_current_threads_hook.create(0x1405C8370, scr_run_current_threads_stub); + scheduler::loop([]() { lua::engine::run_frame(); diff --git a/src/client/game/scripting/lua/event_handler.hpp b/src/client/game/scripting/lua/event_handler.hpp index 99009017..981392e7 100644 --- a/src/client/game/scripting/lua/event_handler.hpp +++ b/src/client/game/scripting/lua/event_handler.hpp @@ -44,7 +44,7 @@ namespace scripting::lua sol::state& state_; std::atomic_int64_t current_listener_id_ = 0; - using task_list = std::list; + using task_list = std::vector; utils::concurrency::container new_callbacks_; utils::concurrency::container callbacks_;