diff --git a/src/game/game.cpp b/src/game/game.cpp index 9dccfa7..4aa9fb6 100644 --- a/src/game/game.cpp +++ b/src/game/game.cpp @@ -32,7 +32,7 @@ namespace game { ++scrVarGlob[4 * value->u.entityId]; } - else if (value->type == SCRIPT_STRING) + else if ((value->type & ~1) == SCRIPT_STRING) { static const auto size = is_sp() ? 16 : 12; const auto ref_count = reinterpret_cast(*scrMemTreePub + size * value diff --git a/src/module/notification.cpp b/src/module/notification.cpp index 1ffb4d9..a0d479e 100644 --- a/src/module/notification.cpp +++ b/src/module/notification.cpp @@ -3,6 +3,9 @@ #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(); @@ -12,6 +15,40 @@ void notification::post_load() { 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(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, @@ -26,10 +63,7 @@ void notification::vm_notify_stub(const unsigned int notify_id, const unsigned s e.arguments.emplace_back(*value); } - if(!e.arguments.empty()) - { - printf(""); - } + dispatch(&e); game::native::VM_Notify(notify_id, type, stack); } diff --git a/src/module/notification.hpp b/src/module/notification.hpp index df0e806..ab0a1ff 100644 --- a/src/module/notification.hpp +++ b/src/module/notification.hpp @@ -14,7 +14,16 @@ 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(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 252313e..3242cfe 100644 --- a/src/module/scripting.cpp +++ b/src/module/scripting.cpp @@ -1,5 +1,7 @@ #include -#include "scripting.hpp" +#include "notification.hpp" +#include "utils/io.hpp" +#include "utils/string.hpp" utils::hook scripting::start_hook_; utils::hook scripting::stop_hook_; @@ -10,12 +12,12 @@ std::vector> scripting::stop_callbacks_; scripting::variable::variable(game::native::VariableValue value) : value_(value) { - game::native::AddRefToValue(&value); + //game::native::AddRefToValue(&value); } scripting::variable::~variable() { - game::native::RemoveRefToValue(this->value_.type, this->value_.u); + //game::native::RemoveRefToValue(this->value_.type, this->value_.u); } scripting::variable::operator game::native::VariableValue() const @@ -23,6 +25,15 @@ scripting::variable::operator game::native::VariableValue() const return this->value_; } +void scripting::post_start() +{ + on_start(std::bind(&scripting::initialize, this)); + on_stop([this]() + { + this->chai_ = {}; + }); +} + void scripting::post_load() { start_hook_.initialize(SELECT_VALUE(0x50C575, 0x50D4F2, 0x48A026), []() @@ -36,16 +47,6 @@ void scripting::post_load() stop_execution(); static_cast(stop_hook_.get_original())(); }, HOOK_CALL)->install()->quick(); - - on_start([this]() - { - this->chai_ = std::make_unique(); - }); - - on_stop([this]() - { - this->chai_ = {}; - }); } void scripting::pre_destroy() @@ -55,6 +56,52 @@ void scripting::pre_destroy() stop_callbacks_.clear(); } +void scripting::initialize() +{ + this->chai_ = std::make_unique(); + this->chai_->add(chaiscript::fun([](const std::string& string) + { + printf("%s\n", string.data()); + }), "print"); + + this->chai_->add(chaiscript::fun( + [this](const std::function&)>& callback) + { + std::lock_guard _(mutex_); + this->callbacks_.push_back(callback); + }), "onNotify"); + + this->load_scripts(); + + notification::listen([this](notification::event* event) + { + decltype(this->callbacks_) copy; + { + std::lock_guard _(mutex_); + copy = this->callbacks_; + } + + for (const auto& callback : copy) + { + callback(event->name, {}); + } + }); +} + +void scripting::load_scripts() const +{ + const auto scripts = utils::io::list_files("open-iw5/scripts/"); + + for (const auto& script : scripts) + { + if (script.substr(script.find_last_of('.') + 1) == "chai") + { + this->chai_->eval_file(script); + } + } +} + void scripting::on_start(const std::function& callback) { std::lock_guard _(mutex_); @@ -69,8 +116,7 @@ void scripting::on_stop(const std::function& callback) void scripting::start_execution() { - std::vector> copy; - + decltype(start_callbacks_) copy; { std::lock_guard _(mutex_); copy = start_callbacks_; @@ -84,11 +130,11 @@ void scripting::start_execution() void scripting::stop_execution() { - std::vector> copy; - + decltype(stop_callbacks_) copy; { std::lock_guard _(mutex_); copy = stop_callbacks_; + std::reverse(copy.begin(), copy.end()); } for (const auto& callback : copy) diff --git a/src/module/scripting.hpp b/src/module/scripting.hpp index df413ca..a96c15e 100644 --- a/src/module/scripting.hpp +++ b/src/module/scripting.hpp @@ -18,6 +18,7 @@ public: game::native::VariableValue value_; }; + void post_start() override; void post_load() override; void pre_destroy() override; @@ -26,6 +27,10 @@ public: private: std::unique_ptr chai_; + std::vector&)>> callbacks_; + + void initialize(); + void load_scripts() const; static utils::hook start_hook_; static utils::hook stop_hook_;