Add lui key events + fixes
This commit is contained in:
parent
7e3976558a
commit
6452db033a
@ -4,6 +4,7 @@
|
||||
#include "game/game.hpp"
|
||||
|
||||
#include "game_console.hpp"
|
||||
#include "game/ui_scripting/execution.hpp"
|
||||
|
||||
#include <utils/hook.hpp>
|
||||
|
||||
@ -16,6 +17,12 @@ namespace input
|
||||
|
||||
void cl_char_event_stub(const int local_client_num, const int key)
|
||||
{
|
||||
ui_scripting::notify("keypress",
|
||||
{
|
||||
{"keynum", key},
|
||||
{"key", game::Key_KeynumToString(key, 0, 1)},
|
||||
});
|
||||
|
||||
if (!game_console::console_char_event(local_client_num, key))
|
||||
{
|
||||
return;
|
||||
@ -26,6 +33,12 @@ namespace input
|
||||
|
||||
void cl_key_event_stub(const int local_client_num, const int key, const int down)
|
||||
{
|
||||
ui_scripting::notify(down ? "keydown" : "keyup",
|
||||
{
|
||||
{"keynum", key},
|
||||
{"key", game::Key_KeynumToString(key, 0, 1)},
|
||||
});
|
||||
|
||||
if (!game_console::console_key_event(local_client_num, key, down))
|
||||
{
|
||||
return;
|
||||
|
@ -153,6 +153,8 @@ namespace game
|
||||
int a3, int a4, unsigned int a5)> LUI_OpenMenu{0x14039D5F0, 0x1404CD210};
|
||||
WEAK symbol<bool(int clientNum, const char* name, hks::lua_State* s)> LUI_BeginEvent{0x1400D27F0, 0x140161A00};
|
||||
WEAK symbol<void(hks::lua_State* s)> LUI_EndEvent{0x1400D3A80, 0x140162CD0};
|
||||
WEAK symbol<void()> LUI_EnterCriticalSection{0x1400D3B70, 0x140162DC0};
|
||||
WEAK symbol<void()> LUI_LeaveCriticalSection{0x1400D8DB0, 0x140168150};
|
||||
|
||||
WEAK symbol<bool(int clientNum, const char* menu)> Menu_IsMenuOpenAndVisible{0x1404709C0, 0x1404C7320};
|
||||
|
||||
@ -273,5 +275,6 @@ namespace game
|
||||
int internal_, int profilerTreatClosureAsFunc)> cclosure_Create{0x14008B5D0, 0x14011B540};
|
||||
WEAK symbol<int(lua_State* s, int t)> hksi_luaL_ref{0x1400A64D0, 0x140136D30};
|
||||
WEAK symbol<void(lua_State* s, int t, int ref)> hksi_luaL_unref{0x14009EF10, 0x14012F610};
|
||||
WEAK symbol<void(lua_State* s, HksObject* lfp)> closePendingUpvalues{0x14008EA00, 0x14011E970};
|
||||
}
|
||||
}
|
||||
|
@ -40,53 +40,53 @@ namespace ui_scripting
|
||||
bool notify(const std::string& name, const event_arguments& arguments)
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
if (!game::LUI_BeginEvent(0, name.data(), state))
|
||||
if (!state)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto _1 = gsl::finally(&disable_error_hook);
|
||||
enable_error_hook();
|
||||
|
||||
const auto top = state->m_apistack.top;
|
||||
const auto _1 = gsl::finally(game::LUI_LeaveCriticalSection);
|
||||
game::LUI_EnterCriticalSection();
|
||||
|
||||
try
|
||||
{
|
||||
const auto event = get_return_value(0).as<table>();
|
||||
const auto globals = table((*::game::hks::lua_state)->globals.v.table);
|
||||
const auto engine = globals.get("Engine").as<table>();
|
||||
const auto root = engine.get("GetLuiRoot").as<function>().call({})[0].as<userdata>();
|
||||
const auto process_event = root.get("processEvent").as<function>();
|
||||
|
||||
table event{};
|
||||
event.set("name", name);
|
||||
|
||||
for (const auto& arg : arguments)
|
||||
{
|
||||
event.set(arg.first, arg.second);
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
}
|
||||
|
||||
state->m_apistack.top = top;
|
||||
|
||||
try
|
||||
{
|
||||
game::LUI_EndEvent(state);
|
||||
process_event.call({root, event});
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
throw std::runtime_error(std::string("Error while processing event: ") + e.what());
|
||||
printf("Error processing event '%s' %s\n", name.data(), e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
arguments call_script_function(const function& function, const arguments& arguments)
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
state->m_apistack.top = state->m_apistack.base;
|
||||
|
||||
stack stack;
|
||||
push_value(function);
|
||||
for (auto i = arguments.begin(); i != arguments.end(); ++i)
|
||||
{
|
||||
push_value(*i);
|
||||
}
|
||||
|
||||
const auto num_args = static_cast<int>(arguments.size());
|
||||
stack.save(num_args + 1);
|
||||
|
||||
const auto _1 = gsl::finally(&disable_error_hook);
|
||||
enable_error_hook();
|
||||
|
||||
@ -98,6 +98,7 @@ namespace ui_scripting
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
stack.fix();
|
||||
throw std::runtime_error(std::string("Error executing script function: ") + e.what());
|
||||
}
|
||||
}
|
||||
@ -105,9 +106,10 @@ namespace ui_scripting
|
||||
script_value get_field(const userdata& self, const script_value& key)
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
state->m_apistack.top = state->m_apistack.base;
|
||||
|
||||
stack stack;
|
||||
push_value(key);
|
||||
stack.save(1);
|
||||
|
||||
const auto _1 = gsl::finally(&disable_error_hook);
|
||||
enable_error_hook();
|
||||
@ -124,16 +126,18 @@ namespace ui_scripting
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
throw std::runtime_error(std::string("Error getting userdata field: ") + e.what());
|
||||
stack.fix();
|
||||
throw std::runtime_error("Error getting userdata field: "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
script_value get_field(const table& self, const script_value& key)
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
state->m_apistack.top = state->m_apistack.base;
|
||||
|
||||
stack stack;
|
||||
push_value(key);
|
||||
stack.save(1);
|
||||
|
||||
const auto _1 = gsl::finally(&disable_error_hook);
|
||||
enable_error_hook();
|
||||
@ -150,14 +154,17 @@ namespace ui_scripting
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
throw std::runtime_error(std::string("Error getting table field: ") + e.what());
|
||||
stack.fix();
|
||||
throw std::runtime_error("Error getting table field: "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void set_field(const userdata& self, const script_value& key, const script_value& value)
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
state->m_apistack.top = state->m_apistack.base;
|
||||
|
||||
stack stack;
|
||||
stack.save(0);
|
||||
|
||||
const auto _1 = gsl::finally(&disable_error_hook);
|
||||
enable_error_hook();
|
||||
@ -172,14 +179,17 @@ namespace ui_scripting
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
throw std::runtime_error(std::string("Error setting userdata field: ") + e.what());
|
||||
stack.fix();
|
||||
throw std::runtime_error("Error setting userdata field: "s + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void set_field(const table& self, const script_value& key, const script_value& value)
|
||||
{
|
||||
const auto state = *game::hks::lua_state;
|
||||
state->m_apistack.top = state->m_apistack.base;
|
||||
|
||||
stack stack;
|
||||
stack.save(0);
|
||||
|
||||
const auto _1 = gsl::finally(&disable_error_hook);
|
||||
enable_error_hook();
|
||||
@ -194,7 +204,8 @@ namespace ui_scripting
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
throw std::runtime_error(std::string("Error setting table field: ") + e.what());
|
||||
stack.fix();
|
||||
throw std::runtime_error("Error setting table field: "s + e.what());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -273,4 +273,38 @@ namespace ui_scripting
|
||||
{
|
||||
return call_script_function(*this, arguments);
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
* Stack
|
||||
**************************************************************/
|
||||
|
||||
stack::stack()
|
||||
{
|
||||
this->state = *game::hks::lua_state;
|
||||
this->state->m_apistack.top = this->state->m_apistack.base;
|
||||
}
|
||||
|
||||
void stack::save(int num_args)
|
||||
{
|
||||
this->num_args_ = num_args;
|
||||
this->num_calls_ = state->m_numberOfCCalls;
|
||||
this->base_bottom_ = state->m_apistack.base - state->m_apistack.bottom;
|
||||
this->top_bottom_ = state->m_apistack.top - state->m_apistack.bottom;
|
||||
this->callstack_ = state->m_callStack.m_current - state->m_callStack.m_records;
|
||||
}
|
||||
|
||||
void stack::fix()
|
||||
{
|
||||
this->state->m_numberOfCCalls = this->num_calls_;
|
||||
|
||||
game::hks::closePendingUpvalues(this->state, &this->state->m_apistack.bottom[this->top_bottom_ - this->num_args_]);
|
||||
this->state->m_callStack.m_current = &this->state->m_callStack.m_records[this->callstack_];
|
||||
|
||||
this->state->m_apistack.base = &this->state->m_apistack.bottom[this->base_bottom_];
|
||||
this->state->m_apistack.top = &this->state->m_apistack.bottom[this->top_bottom_ - static_cast<uint64_t>(this->num_args_ + 1)];
|
||||
|
||||
this->state->m_apistack.bottom[this->top_bottom_].t = this->state->m_apistack.top[-1].t;
|
||||
this->state->m_apistack.bottom[this->top_bottom_].v.ptr = this->state->m_apistack.top[-1].v.ptr;
|
||||
this->state->m_apistack.top = &this->state->m_apistack.bottom[this->top_bottom_ + 1];
|
||||
}
|
||||
}
|
||||
|
@ -86,4 +86,28 @@ namespace ui_scripting
|
||||
|
||||
int ref{};
|
||||
};
|
||||
|
||||
class stack final
|
||||
{
|
||||
public:
|
||||
stack();
|
||||
|
||||
void save(int num_args);
|
||||
void fix();
|
||||
|
||||
stack(stack&&) = delete;
|
||||
stack(const stack&) = delete;
|
||||
stack& operator=(stack&&) = delete;
|
||||
stack& operator=(const stack&) = delete;
|
||||
|
||||
private:
|
||||
game::hks::lua_State* state;
|
||||
|
||||
int num_args_;
|
||||
int num_calls_;
|
||||
|
||||
uint64_t base_bottom_;
|
||||
uint64_t top_bottom_;
|
||||
uint64_t callstack_;
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user