From be5d909847ee3ce100df66fc7b1c69ec72de802a Mon Sep 17 00:00:00 2001 From: Federico Cecchetto Date: Tue, 28 Sep 2021 22:39:27 +0200 Subject: [PATCH] Some fixes --- src/client/component/ui_scripting.cpp | 53 ++++++++++++------- src/client/component/ui_scripting.hpp | 6 ++- src/client/game/symbols.hpp | 2 + src/client/game/ui_scripting/execution.cpp | 15 +++--- src/client/game/ui_scripting/lua/context.cpp | 26 +++------ src/client/game/ui_scripting/lua/context.hpp | 1 - .../game/ui_scripting/stack_isolation.cpp | 30 +++++++++++ .../game/ui_scripting/stack_isolation.hpp | 25 +++++++++ src/client/game/ui_scripting/value.hpp | 1 - 9 files changed, 110 insertions(+), 49 deletions(-) create mode 100644 src/client/game/ui_scripting/stack_isolation.cpp create mode 100644 src/client/game/ui_scripting/stack_isolation.hpp diff --git a/src/client/component/ui_scripting.cpp b/src/client/component/ui_scripting.cpp index e9cb60b6..9f7af16f 100644 --- a/src/client/component/ui_scripting.cpp +++ b/src/client/component/ui_scripting.cpp @@ -21,8 +21,6 @@ namespace ui_scripting { - std::unordered_map> libs; - namespace { utils::hook::detour hksi_open_lib_hook; @@ -33,15 +31,23 @@ namespace ui_scripting bool error_hook_enabled = false; + std::unordered_map functions; + std::unordered_map methods; + void* hksi_open_lib_stub(game::hks::lua_State* s, const char* libname, game::hks::luaL_Reg* l) { - if (libname) + for (auto i = l; i->name; ++i) { - libs[libname] = {}; - for (auto i = l; i->name; ++i) + if (i->name == "__gc"s) { - libs[libname][i->name] = i->function; + continue; } + + const auto lower = utils::string::to_lower(i->name); + + libname + ? functions[lower] = i->function + : methods[lower] = i->function; } return hksi_open_lib_hook.invoke(s, libname, l); @@ -75,7 +81,8 @@ namespace ui_scripting ui_scripting::lua::engine::start(); }); - libs = {}; + functions = {}; + methods = {}; return hks_start_hook.invoke(a1); } @@ -90,8 +97,8 @@ namespace ui_scripting if (name != "( lua_CFunction )LUI_CoD_LuaCall_UIExpression"s) { std::string name_ = name; - const auto sub = name_.substr(13, name_.size() - 14); - libs["Global"][sub] = f; + const auto sub = utils::string::to_lower(name_.substr(13, name_.size() - 14)); + functions[sub] = f; } hksi_add_function_hook.invoke(s, f, a3, name, a5); @@ -111,20 +118,26 @@ namespace ui_scripting game::hks::lua_function find_function(const std::string& name) { const auto lower = utils::string::to_lower(name); - - for (const auto lib : libs) + if (functions.find(lower) == functions.end()) { - for (const auto func : lib.second) - { - const auto lower_ = utils::string::to_lower(func.first); - if (lower == lower_) - { - return func.second; - } - } + return 0; } + return functions[lower]; + } - return 0; + game::hks::lua_function find_method(const std::string& name) + { + const auto lower = utils::string::to_lower(name); + if (methods.find(lower) == methods.end()) + { + return 0; + } + return methods[lower]; + } + + void notify(const event& e) + { + lua::engine::notify(e); } class component final : public component_interface diff --git a/src/client/component/ui_scripting.hpp b/src/client/component/ui_scripting.hpp index c61d9bd1..7b288380 100644 --- a/src/client/component/ui_scripting.hpp +++ b/src/client/component/ui_scripting.hpp @@ -1,12 +1,14 @@ #pragma once #include "game/ui_scripting/menu.hpp" +#include "game/ui_scripting/event.hpp" namespace ui_scripting { - extern std::unordered_map> libs; - void enable_error_hook(); void disable_error_hook(); game::hks::lua_function find_function(const std::string& name); + game::hks::lua_function find_method(const std::string& name); + + void notify(event e); } diff --git a/src/client/game/symbols.hpp b/src/client/game/symbols.hpp index 9bf7b483..658e3d1a 100644 --- a/src/client/game/symbols.hpp +++ b/src/client/game/symbols.hpp @@ -153,5 +153,7 @@ namespace game WEAK symbol lua_state{0x19D83E8}; WEAK symbol hksi_lua_pushlstring{0x287410}; WEAK symbol hks_obj_tolstring{0x287410}; + WEAK symbol hks_obj_getmetatable{0x2DA210}; + WEAK symbol hks_obj_getfield{0x2D9E20}; } } \ No newline at end of file diff --git a/src/client/game/ui_scripting/execution.cpp b/src/client/game/ui_scripting/execution.cpp index 9265605c..47dd551e 100644 --- a/src/client/game/ui_scripting/execution.cpp +++ b/src/client/game/ui_scripting/execution.cpp @@ -1,7 +1,7 @@ #include #include "value.hpp" #include "execution.hpp" - +#include "stack_isolation.hpp" #include "component/ui_scripting.hpp" #include @@ -59,7 +59,6 @@ namespace ui_scripting case 5: { const auto data = std::get(value_); - state->top->t = game::hks::HksObjectType::TLIGHTUSERDATA; state->top->v.ptr = data.ptr; state->top++; @@ -125,16 +124,15 @@ namespace ui_scripting throw std::runtime_error("Invalid lua state"); } - const auto state = *game::hks::lua_state; - state->top = state->base; - const auto function = ui_scripting::find_function(name); if (!function) { throw std::runtime_error("Function " + name + " not found"); } - const auto _ = gsl::finally([]() + stack_isolation _; + + const auto __ = gsl::finally([]() { disable_error_hook(); }); @@ -156,6 +154,11 @@ namespace ui_scripting values.push_back(get_return_value(i)); } + if (values.size() == 0) + { + values.push_back({}); + } + return values; } catch (const std::exception& e) diff --git a/src/client/game/ui_scripting/lua/context.cpp b/src/client/game/ui_scripting/lua/context.cpp index 20378d25..99f2c430 100644 --- a/src/client/game/ui_scripting/lua/context.cpp +++ b/src/client/game/ui_scripting/lua/context.cpp @@ -515,7 +515,7 @@ namespace ui_scripting::lua } } - lua::engine::notify(event); + notify(event); }; element_type["hidden"] = sol::property( @@ -589,7 +589,7 @@ namespace ui_scripting::lua } } - lua::engine::notify(event); + notify(event); }; menu_type["addchild"] = [](const sol::this_state s, menu& menu, element& element) @@ -640,7 +640,7 @@ namespace ui_scripting::lua event event; event.element = &menu; event.name = "close"; - handler.dispatch(event); + notify(event); menu.open(); }; @@ -650,7 +650,7 @@ namespace ui_scripting::lua event event; event.element = &menu; event.name = "close"; - handler.dispatch(event); + notify(event); menu.close(); }; @@ -809,7 +809,7 @@ namespace ui_scripting::lua event event; event.element = menu; event.name = "open"; - handler.dispatch(event); + notify(event); menu->open(); }; @@ -826,7 +826,7 @@ namespace ui_scripting::lua event event; event.element = menu; event.name = "close"; - handler.dispatch(event); + notify(event); menu->close(); }; @@ -953,11 +953,6 @@ namespace ui_scripting::lua ::game::Dvar_SetCommand(hash, "", string_value.data()); }; - game_type["playsound"] = [](const game&, const std::string& sound) - { - ::game::UI_PlayLocalSoundAlias(0, sound.data()); - }; - game_type["getwindowsize"] = [](const game&, const sol::this_state s) { const auto size = ::game::ScrPlace_GetViewPlacement()->realViewportSize; @@ -1001,14 +996,7 @@ namespace ui_scripting::lua } const auto values = call(name, arguments); - if (values.size() == 0) - { - return sol::lua_value{s, sol::lua_nil}; - } - else - { - return sol::lua_value{s, sol::as_returns(values)}; - } + return sol::as_returns(values); }; struct player diff --git a/src/client/game/ui_scripting/lua/context.hpp b/src/client/game/ui_scripting/lua/context.hpp index 99a196c2..70e2022d 100644 --- a/src/client/game/ui_scripting/lua/context.hpp +++ b/src/client/game/ui_scripting/lua/context.hpp @@ -10,7 +10,6 @@ #define SOL_PRINT_ERRORS 0 #include -#include "engine.hpp" #include "scheduler.hpp" #include "event_handler.hpp" diff --git a/src/client/game/ui_scripting/stack_isolation.cpp b/src/client/game/ui_scripting/stack_isolation.cpp new file mode 100644 index 00000000..dc51d08a --- /dev/null +++ b/src/client/game/ui_scripting/stack_isolation.cpp @@ -0,0 +1,30 @@ +#include +#include "stack_isolation.hpp" + +namespace ui_scripting +{ + stack_isolation::stack_isolation() + { + const auto state = *game::hks::lua_state; + + this->top_ = state->top; + this->base_ = state->base; + this->alloc_top_ = state->alloc_top; + this->bottom_ = state->bottom; + + state->top = this->stack_; + state->base = state->top; + state->alloc_top = &this->stack_[ARRAYSIZE(this->stack_) - 1]; + state->bottom = state->top; + } + + stack_isolation::~stack_isolation() + { + const auto state = *game::hks::lua_state; + + state->top = this->top_; + state->base = this->base_; + state->alloc_top = this->alloc_top_; + state->bottom = this->bottom_; + } +} diff --git a/src/client/game/ui_scripting/stack_isolation.hpp b/src/client/game/ui_scripting/stack_isolation.hpp new file mode 100644 index 00000000..035e8d54 --- /dev/null +++ b/src/client/game/ui_scripting/stack_isolation.hpp @@ -0,0 +1,25 @@ +#pragma once +#include "game/game.hpp" + +namespace ui_scripting +{ + class stack_isolation final + { + public: + stack_isolation(); + ~stack_isolation(); + + stack_isolation(stack_isolation&&) = delete; + stack_isolation(const stack_isolation&) = delete; + stack_isolation& operator=(stack_isolation&&) = delete; + stack_isolation& operator=(const stack_isolation&) = delete; + + private: + game::hks::HksObject stack_[512]{}; + + game::hks::HksObject* top_; + game::hks::HksObject* base_; + game::hks::HksObject* alloc_top_; + game::hks::HksObject* bottom_; + }; +} diff --git a/src/client/game/ui_scripting/value.hpp b/src/client/game/ui_scripting/value.hpp index f9cc7d67..ee684aaa 100644 --- a/src/client/game/ui_scripting/value.hpp +++ b/src/client/game/ui_scripting/value.hpp @@ -6,7 +6,6 @@ namespace ui_scripting struct lightuserdata { void* ptr; - bool operator==(const lightuserdata other) const noexcept { return this->ptr == other.ptr;