diff --git a/src/loader/module_loader.hpp b/src/loader/module_loader.hpp index 9477f6e..76ec816 100644 --- a/src/loader/module_loader.hpp +++ b/src/loader/module_loader.hpp @@ -24,6 +24,20 @@ public: } }; + template + static T* get() + { + for(const auto& module_ : *modules_) + { + if(typeid(*module_.get()) == typeid(T)) + { + return reinterpret_cast(module_.get()); + } + } + + return nullptr; + } + static void register_module(std::unique_ptr&& module); static bool post_start(); diff --git a/src/module/notification.cpp b/src/module/notification.cpp deleted file mode 100644 index 6ad3a05..0000000 --- a/src/module/notification.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include "loader/module_loader.hpp" -#include "notification.hpp" -#include "utils/hook.hpp" - -std::mutex notification::mutex_; -std::vector> notification::callbacks_; - -void notification::post_load() -{ - utils::hook(SELECT_VALUE(0x6109F3, 0x56B637, 0x4EDFF7), &vm_notify_stub, HOOK_CALL).install()->quick(); - utils::hook(SELECT_VALUE(0x6128BE, 0x56D541, 0x4EFAF9), &vm_notify_stub, HOOK_CALL).install()->quick(); - - if (game::is_sp()) - { - utils::hook(0x610970, &vm_notify_stub, HOOK_JUMP).install()->quick(); - } - - //scripting::on_start(cleanup); - scripting::on_stop(cleanup); -} - -void notification::pre_destroy() -{ - cleanup(); -} - -void notification::listen(const std::function& callback) -{ - std::lock_guard _(mutex_); - callbacks_.push_back(callback); -} - -void notification::cleanup() -{ - std::lock_guard _(mutex_); - callbacks_.clear(); -} - -void notification::dispatch(game::scripting::event* event) -{ - decltype(callbacks_) copy; - { - std::lock_guard _(mutex_); - copy = callbacks_; - } - - for (const auto& callback : copy) - { - callback(event); - } -} - -void notification::vm_notify_stub(const unsigned int notify_id, const unsigned short type, - game::native::VariableValue* stack) -{ - try - { - game::scripting::event e; - e.name = game::native::SL_ConvertToString(type); - e.entity_id = notify_id; - - if (e.name == "touch") return; // Skip that for now - - //printf("%X: %s\n", e.entity_id, e.name.data()); - - for (auto value = stack; value->type != game::native::SCRIPT_END; --value) - { - e.arguments.emplace_back(*value); - } - - dispatch(&e); - } - catch (std::exception& e) - { - scripting::propagate_error(e); - } - - game::native::VM_Notify(notify_id, type, stack); -} - -REGISTER_MODULE(notification) diff --git a/src/module/notification.hpp b/src/module/notification.hpp deleted file mode 100644 index d81b9e4..0000000 --- a/src/module/notification.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once -#include "loader/module_loader.hpp" -#include "game/scripting/event.hpp" -#include "scripting.hpp" - -class notification final : public module -{ -public: - void post_load() override; - void pre_destroy() override; - - static void listen(const std::function& callback); - -private: - static std::mutex mutex_; - static std::vector> callbacks_; - - static void cleanup(); - static void dispatch(game::scripting::event* event); - - static void vm_notify_stub(unsigned int notify_id, unsigned short type, game::native::VariableValue* stack); -}; diff --git a/src/module/scripting.cpp b/src/module/scripting.cpp index 53babe7..968cf2e 100644 --- a/src/module/scripting.cpp +++ b/src/module/scripting.cpp @@ -1,61 +1,35 @@ #include -#include "notification.hpp" +#include "utils/hook.hpp" #include "utils/io.hpp" + #include "scheduler.hpp" +#include "scripting.hpp" utils::hook scripting::start_hook_; utils::hook scripting::stop_hook_; -std::mutex scripting::mutex_; -std::vector> scripting::start_callbacks_; -std::vector> scripting::stop_callbacks_; - -void scripting::post_start() -{ - on_start([this]() - { - try - { - this->load_scripts(); - notification::listen([this](game::scripting::event* event) - { - for(const auto& script : this->scripts_) - { - script->get_event_handler()->dispatch(event); - } - }); - } - catch (std::exception& e) - { - propagate_error(e); - } - }); - on_stop([this]() - { - this->scripts_.clear(); - }); -} - void scripting::post_load() { - start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), []() - { - start_execution(); - reinterpret_cast(start_hook_.get_original())(); - }, HOOK_CALL)->install()->quick(); + start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), &start_execution_stub, HOOK_CALL) // + ->install() // + ->quick(); - stop_hook_.initialize(SELECT_VALUE(0x528B04, 0x569E46, 0x4F03FA), []() + stop_hook_.initialize(SELECT_VALUE(0x528B04, 0x569E46, 0x4F03FA), &stop_execution_stub, HOOK_CALL) // + ->install() // + ->quick(); + + utils::hook(SELECT_VALUE(0x6109F3, 0x56B637, 0x4EDFF7), &vm_notify_stub, HOOK_CALL).install()->quick(); + utils::hook(SELECT_VALUE(0x6128BE, 0x56D541, 0x4EFAF9), &vm_notify_stub, HOOK_CALL).install()->quick(); + + if (game::is_sp()) { - stop_execution(); - reinterpret_cast(stop_hook_.get_original())(); - }, HOOK_CALL)->install()->quick(); + utils::hook(0x610970, &vm_notify_stub, HOOK_JUMP).install()->quick(); + } } void scripting::pre_destroy() { this->scripts_.clear(); - start_callbacks_.clear(); - stop_callbacks_.clear(); } void scripting::load_scripts() @@ -80,16 +54,29 @@ void scripting::load_scripts() } } -void scripting::on_start(const std::function& callback) +void scripting::start_execution() { - std::lock_guard _(mutex_); - start_callbacks_.push_back(callback); + try + { + this->load_scripts(); + } + catch (std::exception& e) + { + propagate_error(e); + } } -void scripting::on_stop(const std::function& callback) +void scripting::stop_execution() { - std::lock_guard _(mutex_); - stop_callbacks_.push_back(callback); + this->scripts_.clear(); +} + +void scripting::dispatch(game::scripting::event* event) +{ + for (const auto& script : this->scripts_) + { + script->get_event_handler()->dispatch(event); + } } void scripting::propagate_error(const std::exception& e) @@ -101,33 +88,44 @@ void scripting::propagate_error(const std::exception& e) scheduler::error("Script execution error\n(see console for actual details)\n", 5); } -void scripting::start_execution() +void scripting::start_execution_stub() { - decltype(start_callbacks_) copy; - { - std::lock_guard _(mutex_); - copy = start_callbacks_; - } - - for (const auto& callback : copy) - { - callback(); - } + module_loader::get()->start_execution(); + reinterpret_cast(start_hook_.get_original())(); } -void scripting::stop_execution() +void scripting::stop_execution_stub() { - decltype(stop_callbacks_) copy; + module_loader::get()->stop_execution(); + reinterpret_cast(stop_hook_.get_original())(); +} + +void scripting::vm_notify_stub(const unsigned int notify_id, const unsigned short type, + game::native::VariableValue* stack) +{ + try { - std::lock_guard _(mutex_); - copy = stop_callbacks_; - std::reverse(copy.begin(), copy.end()); + game::scripting::event e; + e.name = game::native::SL_ConvertToString(type); + e.entity_id = notify_id; + + if (e.name == "touch") return; // Skip that for now + + //printf("%X: %s\n", e.entity_id, e.name.data()); + + for (auto value = stack; value->type != game::native::SCRIPT_END; --value) + { + e.arguments.emplace_back(*value); + } + + module_loader::get()->dispatch(&e); + } + catch (std::exception& e) + { + propagate_error(e); } - for (const auto& callback : copy) - { - callback(); - } + game::native::VM_Notify(notify_id, type, stack); } REGISTER_MODULE(scripting) diff --git a/src/module/scripting.hpp b/src/module/scripting.hpp index 5b4999a..14bbe8b 100644 --- a/src/module/scripting.hpp +++ b/src/module/scripting.hpp @@ -6,13 +6,9 @@ class scripting final : public module { public: - void post_start() override; void post_load() override; void pre_destroy() override; - static void on_start(const std::function& callback); - static void on_stop(const std::function& callback); - static void propagate_error(const std::exception& e); private: @@ -20,13 +16,16 @@ private: void load_scripts(); + void start_execution(); + void stop_execution(); + + void dispatch(game::scripting::event* event); + static utils::hook start_hook_; static utils::hook stop_hook_; - static std::mutex mutex_; - static std::vector> start_callbacks_; - static std::vector> stop_callbacks_; - - static void start_execution(); - static void stop_execution(); + static void start_execution_stub(); + static void stop_execution_stub(); + static void vm_notify_stub(const unsigned int notify_id, const unsigned short type, + game::native::VariableValue* stack); };