2022-03-02 05:26:55 -06:00
|
|
|
#include <std_include.hpp>
|
|
|
|
#include "execution.hpp"
|
|
|
|
#include "component/ui_scripting.hpp"
|
|
|
|
|
|
|
|
#include <utils/string.hpp>
|
|
|
|
|
|
|
|
namespace ui_scripting
|
|
|
|
{
|
|
|
|
void push_value(const script_value& value)
|
|
|
|
{
|
|
|
|
const auto state = *game::hks::lua_state;
|
|
|
|
const auto value_ = value.get_raw();
|
|
|
|
*state->m_apistack.top = value_;
|
|
|
|
state->m_apistack.top++;
|
|
|
|
}
|
|
|
|
|
|
|
|
script_value get_return_value(int offset)
|
|
|
|
{
|
|
|
|
const auto state = *game::hks::lua_state;
|
|
|
|
return state->m_apistack.top[-1 - offset];
|
|
|
|
}
|
|
|
|
|
|
|
|
arguments get_return_values(int count)
|
|
|
|
{
|
|
|
|
arguments values;
|
|
|
|
|
|
|
|
for (auto i = count - 1; i >= 0; i--)
|
|
|
|
{
|
|
|
|
values.push_back(get_return_value(i));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (values.size() == 0)
|
|
|
|
{
|
|
|
|
values.push_back({});
|
|
|
|
}
|
|
|
|
|
|
|
|
return values;
|
|
|
|
}
|
|
|
|
|
2022-03-17 20:58:26 +01:00
|
|
|
bool notify(const std::string& name, const event_arguments& arguments)
|
|
|
|
{
|
|
|
|
const auto state = *game::hks::lua_state;
|
2022-04-05 21:41:02 +02:00
|
|
|
if (!state)
|
2022-03-17 20:58:26 +01:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-04-05 21:41:02 +02:00
|
|
|
const auto _1 = gsl::finally(game::LUI_LeaveCriticalSection);
|
|
|
|
game::LUI_EnterCriticalSection();
|
|
|
|
|
2022-03-17 20:58:26 +01:00
|
|
|
try
|
|
|
|
{
|
2022-04-05 21:41:02 +02:00
|
|
|
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);
|
2022-03-17 20:58:26 +01:00
|
|
|
|
|
|
|
for (const auto& arg : arguments)
|
|
|
|
{
|
|
|
|
event.set(arg.first, arg.second);
|
|
|
|
}
|
|
|
|
|
2022-04-05 21:41:02 +02:00
|
|
|
process_event.call({root, event});
|
|
|
|
return true;
|
2022-03-17 20:58:26 +01:00
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
2022-04-05 21:41:02 +02:00
|
|
|
printf("Error processing event '%s' %s\n", name.data(), e.what());
|
|
|
|
return false;
|
2022-03-17 20:58:26 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-02 05:26:55 -06:00
|
|
|
arguments call_script_function(const function& function, const arguments& arguments)
|
|
|
|
{
|
|
|
|
const auto state = *game::hks::lua_state;
|
|
|
|
|
2022-04-05 21:41:02 +02:00
|
|
|
stack stack;
|
2022-03-02 05:26:55 -06:00
|
|
|
push_value(function);
|
|
|
|
for (auto i = arguments.begin(); i != arguments.end(); ++i)
|
|
|
|
{
|
|
|
|
push_value(*i);
|
|
|
|
}
|
|
|
|
|
2022-04-05 21:41:02 +02:00
|
|
|
const auto num_args = static_cast<int>(arguments.size());
|
|
|
|
stack.save(num_args + 1);
|
|
|
|
|
2022-03-02 05:26:55 -06:00
|
|
|
const auto _1 = gsl::finally(&disable_error_hook);
|
|
|
|
enable_error_hook();
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
game::hks::vm_call_internal(state, static_cast<int>(arguments.size()), -1, 0);
|
|
|
|
const auto count = static_cast<int>(state->m_apistack.top - state->m_apistack.base);
|
|
|
|
return get_return_values(count);
|
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
2022-04-05 21:41:02 +02:00
|
|
|
stack.fix();
|
2022-03-02 05:26:55 -06:00
|
|
|
throw std::runtime_error(std::string("Error executing script function: ") + e.what());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
script_value get_field(const userdata& self, const script_value& key)
|
|
|
|
{
|
|
|
|
const auto state = *game::hks::lua_state;
|
|
|
|
|
2022-04-05 21:41:02 +02:00
|
|
|
stack stack;
|
2022-03-02 05:26:55 -06:00
|
|
|
push_value(key);
|
2022-04-05 21:41:02 +02:00
|
|
|
stack.save(1);
|
2022-03-02 05:26:55 -06:00
|
|
|
|
|
|
|
const auto _1 = gsl::finally(&disable_error_hook);
|
|
|
|
enable_error_hook();
|
|
|
|
|
|
|
|
game::hks::HksObject value{};
|
|
|
|
game::hks::HksObject userdata{};
|
|
|
|
userdata.t = game::hks::TUSERDATA;
|
|
|
|
userdata.v.ptr = self.ptr;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
game::hks::hks_obj_gettable(&value, state, &userdata, &state->m_apistack.top[-1]);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
2022-04-05 21:41:02 +02:00
|
|
|
stack.fix();
|
|
|
|
throw std::runtime_error("Error getting userdata field: "s + e.what());
|
2022-03-02 05:26:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
script_value get_field(const table& self, const script_value& key)
|
|
|
|
{
|
|
|
|
const auto state = *game::hks::lua_state;
|
|
|
|
|
2022-04-05 21:41:02 +02:00
|
|
|
stack stack;
|
2022-03-02 05:26:55 -06:00
|
|
|
push_value(key);
|
2022-04-05 21:41:02 +02:00
|
|
|
stack.save(1);
|
2022-03-02 05:26:55 -06:00
|
|
|
|
|
|
|
const auto _1 = gsl::finally(&disable_error_hook);
|
|
|
|
enable_error_hook();
|
|
|
|
|
|
|
|
game::hks::HksObject value{};
|
|
|
|
game::hks::HksObject userdata{};
|
|
|
|
userdata.t = game::hks::TTABLE;
|
|
|
|
userdata.v.ptr = self.ptr;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
game::hks::hks_obj_gettable(&value, state, &userdata, &state->m_apistack.top[-1]);
|
|
|
|
return value;
|
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
2022-04-05 21:41:02 +02:00
|
|
|
stack.fix();
|
|
|
|
throw std::runtime_error("Error getting table field: "s + e.what());
|
2022-03-02 05:26:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_field(const userdata& self, const script_value& key, const script_value& value)
|
|
|
|
{
|
|
|
|
const auto state = *game::hks::lua_state;
|
2022-04-05 21:41:02 +02:00
|
|
|
|
|
|
|
stack stack;
|
|
|
|
stack.save(0);
|
2022-03-02 05:26:55 -06:00
|
|
|
|
|
|
|
const auto _1 = gsl::finally(&disable_error_hook);
|
|
|
|
enable_error_hook();
|
|
|
|
|
|
|
|
game::hks::HksObject userdata{};
|
|
|
|
userdata.t = game::hks::TUSERDATA;
|
|
|
|
userdata.v.ptr = self.ptr;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
game::hks::hks_obj_settable(state, &userdata, &key.get_raw(), &value.get_raw());
|
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
2022-04-05 21:41:02 +02:00
|
|
|
stack.fix();
|
|
|
|
throw std::runtime_error("Error setting userdata field: "s + e.what());
|
2022-03-02 05:26:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void set_field(const table& self, const script_value& key, const script_value& value)
|
|
|
|
{
|
|
|
|
const auto state = *game::hks::lua_state;
|
2022-04-05 21:41:02 +02:00
|
|
|
|
|
|
|
stack stack;
|
|
|
|
stack.save(0);
|
2022-03-02 05:26:55 -06:00
|
|
|
|
|
|
|
const auto _1 = gsl::finally(&disable_error_hook);
|
|
|
|
enable_error_hook();
|
|
|
|
|
|
|
|
game::hks::HksObject userdata{};
|
|
|
|
userdata.t = game::hks::TTABLE;
|
|
|
|
userdata.v.ptr = self.ptr;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
game::hks::hks_obj_settable(state, &userdata, &key.get_raw(), &value.get_raw());
|
|
|
|
}
|
|
|
|
catch (const std::exception& e)
|
|
|
|
{
|
2022-04-05 21:41:02 +02:00
|
|
|
stack.fix();
|
|
|
|
throw std::runtime_error("Error setting table field: "s + e.what());
|
2022-03-02 05:26:55 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|