Dispatch notifies in correct context

This commit is contained in:
Federico Cecchetto 2022-07-05 03:36:17 +02:00
parent df53923c9e
commit 785301b405
2 changed files with 41 additions and 2 deletions

View File

@ -14,6 +14,7 @@
#include "game/scripting/lua/engine.hpp" #include "game/scripting/lua/engine.hpp"
#include <utils/hook.hpp> #include <utils/hook.hpp>
#include <utils/concurrency.hpp>
namespace scripting namespace scripting
{ {
@ -38,6 +39,8 @@ namespace scripting
utils::hook::detour respawn_hook; utils::hook::detour respawn_hook;
utils::hook::detour scr_run_current_threads_hook;
game::dvar_t* scr_auto_respawn = nullptr; game::dvar_t* scr_auto_respawn = nullptr;
std::string current_file; std::string current_file;
@ -45,6 +48,9 @@ namespace scripting
std::unordered_map<unsigned int, std::string> canonical_string_table; std::unordered_map<unsigned int, std::string> canonical_string_table;
using notify_list = std::vector<event>;
utils::concurrency::container<notify_list> scheduled_notifies;
void vm_notify_stub(const unsigned int notify_list_owner_id, const game::scr_string_t string_value, void vm_notify_stub(const unsigned int notify_list_owner_id, const game::scr_string_t string_value,
game::VariableValue* top) game::VariableValue* top)
{ {
@ -60,16 +66,28 @@ namespace scripting
e.arguments.emplace_back(*value); e.arguments.emplace_back(*value);
} }
lua::engine::notify(e); scheduled_notifies.access([&](notify_list& list)
{
list.push_back(e);
});
} }
vm_notify_hook.invoke<void>(notify_list_owner_id, string_value, top); vm_notify_hook.invoke<void>(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) void client_spawn_stub(const game::gentity_s* client)
{ {
client_spawn_hook.invoke<void>(client); client_spawn_hook.invoke<void>(client);
scr_auto_respawn->current.enabled = true; scr_auto_respawn->current.enabled = true;
clear_scheduler_notifies();
lua::engine::start(); lua::engine::start();
} }
@ -80,6 +98,7 @@ namespace scripting
canonical_string_table.clear(); canonical_string_table.clear();
} }
clear_scheduler_notifies();
lua::engine::stop(); lua::engine::stop();
g_shutdown_game_hook.invoke<void>(free_scripts); g_shutdown_game_hook.invoke<void>(free_scripts);
} }
@ -158,6 +177,7 @@ namespace scripting
if (save_game != nullptr) if (save_game != nullptr)
{ {
scr_auto_respawn->current.enabled = true; scr_auto_respawn->current.enabled = true;
clear_scheduler_notifies();
lua::engine::start(); lua::engine::start();
} }
return result; return result;
@ -179,6 +199,23 @@ namespace scripting
respawn_hook.invoke<void>(); respawn_hook.invoke<void>();
} }
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<void>();
}
} }
class component final : public component_interface 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"); scr_auto_respawn = dvars::register_bool("scr_autoRespawn", true, 0, "Automatically respawn player on death");
respawn_hook.create(0x1404B1E00, respawn_stub); respawn_hook.create(0x1404B1E00, respawn_stub);
scr_run_current_threads_hook.create(0x1405C8370, scr_run_current_threads_stub);
scheduler::loop([]() scheduler::loop([]()
{ {
lua::engine::run_frame(); lua::engine::run_frame();

View File

@ -44,7 +44,7 @@ namespace scripting::lua
sol::state& state_; sol::state& state_;
std::atomic_int64_t current_listener_id_ = 0; std::atomic_int64_t current_listener_id_ = 0;
using task_list = std::list<event_listener>; using task_list = std::vector<event_listener>;
utils::concurrency::container<task_list> new_callbacks_; utils::concurrency::container<task_list> new_callbacks_;
utils::concurrency::container<task_list, std::recursive_mutex> callbacks_; utils::concurrency::container<task_list, std::recursive_mutex> callbacks_;