diff --git a/src/client/component/notifies.cpp b/src/client/component/notifies.cpp index e9b1e2b3..e0e04d4b 100644 --- a/src/client/component/notifies.cpp +++ b/src/client/component/notifies.cpp @@ -59,7 +59,7 @@ namespace notifies const auto result = hook(self, sol::as_args(args)); scripting::lua::handle_error(result); - const auto value = scripting::lua::convert({ state, result }); + const auto value = scripting::lua::convert({state, result}); const auto type = value.get_raw().type; game::Scr_ClearOutParams(); diff --git a/src/client/component/ui_scripting.cpp b/src/client/component/ui_scripting.cpp index ff799919..bf0cfb16 100644 --- a/src/client/component/ui_scripting.cpp +++ b/src/client/component/ui_scripting.cpp @@ -15,6 +15,7 @@ #include "ui_scripting.hpp" #include "game/ui_scripting/lua/engine.hpp" +#include "game/ui_scripting/execution.hpp" #include #include @@ -26,6 +27,9 @@ namespace ui_scripting namespace { + unsigned int function_id = 0; + std::unordered_map converted_functions; + utils::hook::detour hksi_open_lib_hook; utils::hook::detour hksi_lual_error_hook; utils::hook::detour hksi_lual_error_hook2; @@ -106,6 +110,52 @@ namespace ui_scripting } } + int main_function_handler(game::hks::lua_State* state) + { + const auto value = state->m_apistack.base[-1]; + if (value.t != game::hks::TCFUNCTION) + { + return 0; + } + + const auto closure = value.v.cClosure; + if (converted_functions.find(closure) == converted_functions.end()) + { + return 0; + } + + const auto function = converted_functions[closure]; + const auto count = static_cast(state->m_apistack.top - state->m_apistack.base); + const auto arguments = get_return_values(count); + const auto s = function.lua_state(); + + std::vector converted_args; + + for (const auto& argument : arguments) + { + converted_args.push_back(lua::convert(s, argument)); + } + + const auto results = function(sol::as_args(converted_args)); + + for (const auto& result : results) + { + push_value(lua::convert({s, result})); + } + + return results.return_count(); + } + + void add_converted_function(game::hks::cclosure* closure, const sol::protected_function& function) + { + converted_functions[closure] = function; + } + + void clear_converted_functions() + { + converted_functions.clear(); + } + void enable_error_hook() { error_hook_enabled = true; diff --git a/src/client/component/ui_scripting.hpp b/src/client/component/ui_scripting.hpp index 3189c7b0..ad5792af 100644 --- a/src/client/component/ui_scripting.hpp +++ b/src/client/component/ui_scripting.hpp @@ -1,4 +1,5 @@ #pragma once +#include "game/ui_scripting/lua/value_conversion.hpp" #include "game/ui_scripting/menu.hpp" #include "game/ui_scripting/event.hpp" @@ -7,6 +8,10 @@ namespace ui_scripting extern std::unordered_map functions; extern std::unordered_map methods; + int main_function_handler(game::hks::lua_State* state); + void add_converted_function(game::hks::cclosure* closure, const sol::protected_function& function); + void clear_converted_functions(); + void enable_error_hook(); void disable_error_hook(); diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 1a5e5958..939784dc 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -160,5 +160,7 @@ namespace game WEAK symbol hksi_lua_pushvalue{0x2DE040}; WEAK symbol Hashtable_Create{0x2C8290}; WEAK symbol Hashtable_getNextHash{0x2D5150}; + WEAK symbol cclosure_Create{0x2C84B0}; } } \ No newline at end of file diff --git a/src/client/game/ui_scripting/execution.hpp b/src/client/game/ui_scripting/execution.hpp index a2880942..3a85ff2b 100644 --- a/src/client/game/ui_scripting/execution.hpp +++ b/src/client/game/ui_scripting/execution.hpp @@ -7,6 +7,7 @@ namespace ui_scripting { void push_value(const value& value); value get_return_value(int offset); + arguments get_return_values(int count); arguments call_script_function(const function& function, const arguments& arguments); diff --git a/src/client/game/ui_scripting/lua/engine.cpp b/src/client/game/ui_scripting/lua/engine.cpp index dd21ba87..da4b2107 100644 --- a/src/client/game/ui_scripting/lua/engine.cpp +++ b/src/client/game/ui_scripting/lua/engine.cpp @@ -3,6 +3,7 @@ #include "context.hpp" #include "../../../component/scheduler.hpp" +#include "../../../component/ui_scripting.hpp" #include #include @@ -200,7 +201,7 @@ namespace ui_scripting::lua::engine : "keyup"; event.arguments = {key}; - notify(event); + engine::notify(event); break; } @@ -346,7 +347,7 @@ namespace ui_scripting::lua::engine event event; event.element = &menu.second; event.name = "close"; - notify(event); + engine::notify(event); menu.second.close(); } @@ -377,7 +378,7 @@ namespace ui_scripting::lua::engine event event; event.element = menu; event.name = "open"; - notify(event); + engine::notify(event); menu->open(); } @@ -394,13 +395,14 @@ namespace ui_scripting::lua::engine event event; event.element = menu; event.name = "close"; - notify(event); + engine::notify(event); menu->close(); } void start() { + clear_converted_functions(); close_all_menus(); get_scripts().clear(); clear_menus(); @@ -409,6 +411,7 @@ namespace ui_scripting::lua::engine void stop() { + clear_converted_functions(); close_all_menus(); get_scripts().clear(); clear_menus(); diff --git a/src/client/game/ui_scripting/lua/value_conversion.cpp b/src/client/game/ui_scripting/lua/value_conversion.cpp index 51bbdbef..ce9d9d6b 100644 --- a/src/client/game/ui_scripting/lua/value_conversion.cpp +++ b/src/client/game/ui_scripting/lua/value_conversion.cpp @@ -1,6 +1,8 @@ #include #include "value_conversion.hpp" #include "../execution.hpp" +#include "../stack_isolation.hpp" +#include "../../../component/ui_scripting.hpp" namespace ui_scripting::lua { @@ -17,6 +19,18 @@ namespace ui_scripting::lua return res; } + + value convert_function(const sol::protected_function& function) + { + const auto closure = game::hks::cclosure_Create(*game::hks::lua_state, main_function_handler, 0, 0, 0); + add_converted_function(closure, function); + + game::hks::HksObject value{}; + value.t = game::hks::TCFUNCTION; + value.v.cClosure = closure; + + return value; + } } value convert(const sol::lua_value& value) @@ -76,6 +90,11 @@ namespace ui_scripting::lua return {convert_table(value.as())}; } + if (value.is()) + { + return {convert_function(value.as())}; + } + return {}; }