212 lines
4.7 KiB
C++
Raw Normal View History

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
}
}
}