LUI scripting fixes

This commit is contained in:
Federico Cecchetto 2021-10-21 00:21:50 +02:00
parent 1e401f8b36
commit bdb6b7324e
16 changed files with 417 additions and 269 deletions

View File

@ -16,6 +16,7 @@
#include "game/ui_scripting/lua/engine.hpp" #include "game/ui_scripting/lua/engine.hpp"
#include "game/ui_scripting/execution.hpp" #include "game/ui_scripting/execution.hpp"
#include "game/ui_scripting/lua/error.hpp"
#include <utils/string.hpp> #include <utils/string.hpp>
#include <utils/hook.hpp> #include <utils/hook.hpp>
@ -136,6 +137,7 @@ namespace ui_scripting
} }
const auto results = function(sol::as_args(converted_args)); const auto results = function(sol::as_args(converted_args));
lua::handle_error(results);
for (const auto& result : results) for (const auto& result : results)
{ {
@ -206,10 +208,7 @@ namespace ui_scripting
command::add("reloadmenus", []() command::add("reloadmenus", []()
{ {
scheduler::once([]() scheduler::once(ui_scripting::lua::engine::start, scheduler::pipeline::renderer);
{
ui_scripting::lua::engine::start();
}, scheduler::pipeline::renderer);
}); });
command::add("openluamenu", [](const command::params& params) command::add("openluamenu", [](const command::params& params)

View File

@ -156,6 +156,7 @@ namespace game
WEAK symbol<int(lua_State* s, const HksObject* obj, HksObject* ret)> hks_obj_getmetatable{0x2DA210}; WEAK symbol<int(lua_State* s, const HksObject* obj, HksObject* ret)> hks_obj_getmetatable{0x2DA210};
WEAK symbol<HksObject*(HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)> hks_obj_getfield{0x2D9E20}; WEAK symbol<HksObject*(HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)> hks_obj_getfield{0x2D9E20};
WEAK symbol<void(lua_State* s, const HksObject* tbl, const HksObject* key, const HksObject* val)> hks_obj_settable{0x2DB040}; WEAK symbol<void(lua_State* s, const HksObject* tbl, const HksObject* key, const HksObject* val)> hks_obj_settable{0x2DB040};
WEAK symbol<HksObject* (HksObject* result, lua_State* s, const HksObject* table, const HksObject* key)> hks_obj_gettable{0x2DA300};
WEAK symbol<void(lua_State* s, int nargs, int nresults, const unsigned int* pc)> vm_call_internal{0x30AB60}; WEAK symbol<void(lua_State* s, int nargs, int nresults, const unsigned int* pc)> vm_call_internal{0x30AB60};
WEAK symbol<void(lua_State* s, int index)> hksi_lua_pushvalue{0x2DE040}; WEAK symbol<void(lua_State* s, int index)> hksi_lua_pushvalue{0x2DE040};
WEAK symbol<HashTable*(lua_State* s, unsigned int arraySize, unsigned int hashSize)> Hashtable_Create{0x2C8290}; WEAK symbol<HashTable*(lua_State* s, unsigned int arraySize, unsigned int hashSize)> Hashtable_Create{0x2C8290};
@ -163,5 +164,7 @@ namespace game
WEAK symbol<void(lua_State* s, const HksObject* tbl, HksObject* key, HksObject* retval)> hks_obj_next{0x2DA850}; WEAK symbol<void(lua_State* s, const HksObject* tbl, HksObject* key, HksObject* retval)> hks_obj_next{0x2DA850};
WEAK symbol<cclosure*(lua_State* s, lua_function function, int num_upvalues, WEAK symbol<cclosure*(lua_State* s, lua_function function, int num_upvalues,
int internal_, int profilerTreatClosureAsFunc)> cclosure_Create{0x2C84B0}; int internal_, int profilerTreatClosureAsFunc)> cclosure_Create{0x2C84B0};
WEAK symbol<int(lua_State* s, int t)> hksi_luaL_ref{0x2E4520};
WEAK symbol<void(lua_State* s, int t, int ref)> hksi_luaL_unref{0x2DCE50};
} }
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "game/game.hpp" #include "game/game.hpp"
#include "value.hpp" #include "script_value.hpp"
namespace ui_scripting namespace ui_scripting
{ {
@ -76,7 +76,7 @@ namespace ui_scripting
alignment horzalign = alignment::start; alignment horzalign = alignment::start;
alignment vertalign = alignment::start; alignment vertalign = alignment::start;
std::unordered_map<std::string, value> attributes = {}; std::unordered_map<std::string, script_value> attributes = {};
std::string font = "default"; std::string font = "default";
std::string material = "white"; std::string material = "white";
std::string border_material = "white"; std::string border_material = "white";

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "value.hpp" #include "script_value.hpp"
namespace ui_scripting namespace ui_scripting
{ {

View File

@ -7,7 +7,7 @@
namespace ui_scripting namespace ui_scripting
{ {
void push_value(const value& value) void push_value(const script_value& value)
{ {
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
const auto value_ = value.get_raw(); const auto value_ = value.get_raw();
@ -15,7 +15,7 @@ namespace ui_scripting
state->m_apistack.top++; state->m_apistack.top++;
} }
value get_return_value(int offset) script_value get_return_value(int offset)
{ {
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
return state->m_apistack.top[-1 - offset]; return state->m_apistack.top[-1 - offset];
@ -23,7 +23,7 @@ namespace ui_scripting
arguments get_return_values(int count) arguments get_return_values(int count)
{ {
std::vector<value> values; arguments values;
for (auto i = count - 1; i >= 0; i--) for (auto i = count - 1; i >= 0; i--)
{ {
@ -49,11 +49,8 @@ namespace ui_scripting
push_value(*i); push_value(*i);
} }
const auto _1 = gsl::finally(&disable_error_hook);
enable_error_hook(); enable_error_hook();
const auto __ = gsl::finally([]()
{
disable_error_hook();
});
try try
{ {
@ -67,18 +64,15 @@ namespace ui_scripting
} }
} }
value get_field(const userdata& self, const value& key) script_value get_field(const userdata& self, const script_value& key)
{ {
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
stack_isolation _; stack_isolation _;
push_value(key); push_value(key);
const auto _1 = gsl::finally(&disable_error_hook);
enable_error_hook(); enable_error_hook();
const auto __ = gsl::finally([]()
{
disable_error_hook();
});
game::hks::HksObject value{}; game::hks::HksObject value{};
game::hks::HksObject userdata{}; game::hks::HksObject userdata{};
@ -87,7 +81,7 @@ namespace ui_scripting
try try
{ {
game::hks::hks_obj_getfield(&value, state, &userdata, &state->m_apistack.top[-1]); game::hks::hks_obj_gettable(&value, state, &userdata, &state->m_apistack.top[-1]);
return value; return value;
} }
catch (const std::exception& e) catch (const std::exception& e)
@ -96,18 +90,15 @@ namespace ui_scripting
} }
} }
value get_field(const table& self, const value& key) script_value get_field(const table& self, const script_value& key)
{ {
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
stack_isolation _; stack_isolation _;
push_value(key); push_value(key);
const auto _1 = gsl::finally(&disable_error_hook);
enable_error_hook(); enable_error_hook();
const auto __ = gsl::finally([]()
{
disable_error_hook();
});
game::hks::HksObject value{}; game::hks::HksObject value{};
game::hks::HksObject userdata{}; game::hks::HksObject userdata{};
@ -116,7 +107,7 @@ namespace ui_scripting
try try
{ {
game::hks::hks_obj_getfield(&value, state, &userdata, &state->m_apistack.top[-1]); game::hks::hks_obj_gettable(&value, state, &userdata, &state->m_apistack.top[-1]);
return value; return value;
} }
catch (const std::exception& e) catch (const std::exception& e)
@ -125,17 +116,14 @@ namespace ui_scripting
} }
} }
void set_field(const userdata& self, const value& key, const value& value) void set_field(const userdata& self, const script_value& key, const script_value& value)
{ {
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
stack_isolation _; stack_isolation _;
const auto _1 = gsl::finally(&disable_error_hook);
enable_error_hook(); enable_error_hook();
const auto __ = gsl::finally([]()
{
disable_error_hook();
});
game::hks::HksObject userdata{}; game::hks::HksObject userdata{};
userdata.t = game::hks::TUSERDATA; userdata.t = game::hks::TUSERDATA;
@ -151,17 +139,14 @@ namespace ui_scripting
} }
} }
void set_field(const table& self, const value& key, const value& value) void set_field(const table& self, const script_value& key, const script_value& value)
{ {
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
stack_isolation _; stack_isolation _;
const auto _1 = gsl::finally(&disable_error_hook);
enable_error_hook(); enable_error_hook();
const auto __ = gsl::finally([]()
{
disable_error_hook();
});
game::hks::HksObject userdata{}; game::hks::HksObject userdata{};
userdata.t = game::hks::TTABLE; userdata.t = game::hks::TTABLE;

View File

@ -1,20 +1,20 @@
#pragma once #pragma once
#include "game/game.hpp" #include "game/game.hpp"
#include "types.hpp" #include "types.hpp"
#include "value.hpp" #include "script_value.hpp"
namespace ui_scripting namespace ui_scripting
{ {
void push_value(const value& value); void push_value(const script_value& value);
value get_return_value(int offset); script_value get_return_value(int offset);
arguments get_return_values(int count); arguments get_return_values(int count);
arguments call_script_function(const function& function, const arguments& arguments); arguments call_script_function(const function& function, const arguments& arguments);
value get_field(const userdata& self, const value& key); script_value get_field(const userdata& self, const script_value& key);
value get_field(const table& self, const value& key); script_value get_field(const table& self, const script_value& key);
void set_field(const userdata& self, const value& key, const value& value); void set_field(const userdata& self, const script_value& key, const script_value& value);
void set_field(const table& self, const value& key, const value& value); void set_field(const table& self, const script_value& key, const script_value& value);
arguments call_method(const userdata& self, const std::string& name, const arguments& arguments); arguments call_method(const userdata& self, const std::string& name, const arguments& arguments);
arguments call(const std::string& name, const arguments& arguments); arguments call(const std::string& name, const arguments& arguments);

View File

@ -3,7 +3,7 @@
#include "error.hpp" #include "error.hpp"
#include "value_conversion.hpp" #include "value_conversion.hpp"
#include "../../scripting/execution.hpp" #include "../../scripting/execution.hpp"
#include "../value.hpp" #include "../script_value.hpp"
#include "../execution.hpp" #include "../execution.hpp"
#include "../../../component/ui_scripting.hpp" #include "../../../component/ui_scripting.hpp"
@ -1008,6 +1008,17 @@ namespace ui_scripting::lua
auto userdata_type = state.new_usertype<userdata>("userdata_"); auto userdata_type = state.new_usertype<userdata>("userdata_");
userdata_type["new"] = sol::property(
[](const userdata& userdata, const sol::this_state s)
{
return convert(s, userdata.get("new"));
},
[](const userdata& userdata, const sol::this_state s, const sol::lua_value& value)
{
userdata.set("new", convert({s, value}));
}
);
for (const auto method : methods) for (const auto method : methods)
{ {
const auto name = method.first; const auto name = method.first;
@ -1047,6 +1058,17 @@ namespace ui_scripting::lua
auto table_type = state.new_usertype<table>("table_"); auto table_type = state.new_usertype<table>("table_");
table_type["new"] = sol::property(
[](const table& table, const sol::this_state s)
{
return convert(s, table.get("new"));
},
[](const table& table, const sol::this_state s, const sol::lua_value& value)
{
table.set("new", convert({s, value}));
}
);
table_type["get"] = [](const table& table, const sol::this_state s, table_type["get"] = [](const table& table, const sol::this_state s,
const std::string& name) const std::string& name)
{ {

View File

@ -20,7 +20,7 @@ namespace ui_scripting::lua
return res; return res;
} }
value convert_function(const sol::protected_function& function) script_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); const auto closure = game::hks::cclosure_Create(*game::hks::lua_state, main_function_handler, 0, 0, 0);
add_converted_function(closure, function); add_converted_function(closure, function);
@ -33,8 +33,13 @@ namespace ui_scripting::lua
} }
} }
value convert(const sol::lua_value& value) script_value convert(const sol::lua_value& value)
{ {
if (value.is<bool>())
{
return {value.as<bool>()};
}
if (value.is<int>()) if (value.is<int>())
{ {
return {value.as<int>()}; return {value.as<int>()};
@ -45,11 +50,6 @@ namespace ui_scripting::lua
return {value.as<unsigned int>()}; return {value.as<unsigned int>()};
} }
if (value.is<bool>())
{
return {value.as<bool>()};
}
if (value.is<double>()) if (value.is<double>())
{ {
return {value.as<double>()}; return {value.as<double>()};
@ -98,7 +98,7 @@ namespace ui_scripting::lua
return {}; return {};
} }
sol::lua_value convert(lua_State* state, const value& value) sol::lua_value convert(lua_State* state, const script_value& value)
{ {
if (value.is<int>()) if (value.is<int>())
{ {
@ -110,6 +110,11 @@ namespace ui_scripting::lua
return {state, value.as<float>()}; return {state, value.as<float>()};
} }
if (value.is<bool>())
{
return {state, value.as<bool>()};
}
if (value.is<std::string>()) if (value.is<std::string>())
{ {
return {state, value.as<std::string>()}; return {state, value.as<std::string>()};

View File

@ -1,9 +1,9 @@
#pragma once #pragma once
#include "context.hpp" #include "context.hpp"
#include "../script_value.hpp"
namespace ui_scripting::lua namespace ui_scripting::lua
{ {
value convert(const sol::lua_value& value); script_value convert(const sol::lua_value& value);
sol::lua_value convert(lua_State* state, const value& value); sol::lua_value convert(lua_State* state, const script_value& value);
} }

View File

@ -2,7 +2,7 @@
#include "execution.hpp" #include "execution.hpp"
#include "types.hpp" #include "types.hpp"
#include "stack_isolation.hpp" #include "stack_isolation.hpp"
#include "value.hpp" #include "script_value.hpp"
namespace ui_scripting namespace ui_scripting
{ {
@ -10,12 +10,12 @@ namespace ui_scripting
* Constructors * Constructors
**************************************************************/ **************************************************************/
value::value(const game::hks::HksObject& value) script_value::script_value(const game::hks::HksObject& value)
: value_(value) : value_(value)
{ {
} }
value::value(const int value) script_value::script_value(const int value)
{ {
game::hks::HksObject obj{}; game::hks::HksObject obj{};
obj.t = game::hks::TNUMBER; obj.t = game::hks::TNUMBER;
@ -24,7 +24,7 @@ namespace ui_scripting
this->value_ = obj; this->value_ = obj;
} }
value::value(const unsigned int value) script_value::script_value(const unsigned int value)
{ {
game::hks::HksObject obj{}; game::hks::HksObject obj{};
obj.t = game::hks::TNUMBER; obj.t = game::hks::TNUMBER;
@ -33,12 +33,16 @@ namespace ui_scripting
this->value_ = obj; this->value_ = obj;
} }
value::value(const bool value) script_value::script_value(const bool value)
: value(static_cast<unsigned>(value))
{ {
game::hks::HksObject obj{};
obj.t = game::hks::TBOOLEAN;
obj.v.boolean = value;
this->value_ = obj;
} }
value::value(const float value) script_value::script_value(const float value)
{ {
game::hks::HksObject obj{}; game::hks::HksObject obj{};
obj.t = game::hks::TNUMBER; obj.t = game::hks::TNUMBER;
@ -47,12 +51,12 @@ namespace ui_scripting
this->value_ = obj; this->value_ = obj;
} }
value::value(const double value) script_value::script_value(const double value)
: value(static_cast<float>(value)) : script_value(static_cast<float>(value))
{ {
} }
value::value(const char* value) script_value::script_value(const char* value)
{ {
game::hks::HksObject obj{}; game::hks::HksObject obj{};
stack_isolation _; stack_isolation _;
@ -64,30 +68,30 @@ namespace ui_scripting
this->value_ = obj; this->value_ = obj;
} }
value::value(const std::string& value) script_value::script_value(const std::string& value)
: value(value.data()) : script_value(value.data())
{ {
} }
value::value(const lightuserdata& value) script_value::script_value(const lightuserdata& value)
{ {
this->value_.t = game::hks::TLIGHTUSERDATA; this->value_.t = game::hks::TLIGHTUSERDATA;
this->value_.v.ptr = value.ptr; this->value_.v.ptr = value.ptr;
} }
value::value(const userdata& value) script_value::script_value(const userdata& value)
{ {
this->value_.t = game::hks::TUSERDATA; this->value_.t = game::hks::TUSERDATA;
this->value_.v.ptr = value.ptr; this->value_.v.ptr = value.ptr;
} }
value::value(const table& value) script_value::script_value(const table& value)
{ {
this->value_.t = game::hks::TTABLE; this->value_.t = game::hks::TTABLE;
this->value_.v.ptr = value.ptr; this->value_.v.ptr = value.ptr;
} }
value::value(const function& value) script_value::script_value(const function& value)
{ {
this->value_.t = value.type; this->value_.t = value.type;
this->value_.v.ptr = value.ptr; this->value_.v.ptr = value.ptr;
@ -98,39 +102,44 @@ namespace ui_scripting
**************************************************************/ **************************************************************/
template <> template <>
bool value::is<int>() const bool script_value::is<int>() const
{ {
return this->get_raw().t == game::hks::TNUMBER; const auto number = this->get_raw().v.number;
return this->get_raw().t == game::hks::TNUMBER && static_cast<int>(number) == number;
} }
template <> template <>
bool value::is<unsigned int>() const bool script_value::is<unsigned int>() const
{ {
return this->is<int>(); return this->is<int>();
} }
template <> template <>
bool value::is<bool>() const int script_value::get() const
{
return this->is<int>();
}
template <>
int value::get() const
{ {
return static_cast<int>(this->get_raw().v.number); return static_cast<int>(this->get_raw().v.number);
} }
template <> template <>
unsigned int value::get() const unsigned int script_value::get() const
{ {
return static_cast<unsigned int>(this->get_raw().v.number); return static_cast<unsigned int>(this->get_raw().v.number);
} }
/***************************************************************
* Boolean
**************************************************************/
template <> template <>
bool value::get() const bool script_value::is<bool>() const
{ {
return this->get_raw().v.native != 0; return this->get_raw().t == game::hks::TBOOLEAN;
}
template <>
bool script_value::get() const
{
return this->get_raw().v.boolean;
} }
/*************************************************************** /***************************************************************
@ -138,25 +147,25 @@ namespace ui_scripting
**************************************************************/ **************************************************************/
template <> template <>
bool value::is<float>() const bool script_value::is<float>() const
{ {
return this->get_raw().t == game::hks::TNUMBER; return this->get_raw().t == game::hks::TNUMBER;
} }
template <> template <>
bool value::is<double>() const bool script_value::is<double>() const
{ {
return this->is<float>(); return this->is<float>();
} }
template <> template <>
float value::get() const float script_value::get() const
{ {
return this->get_raw().v.number; return this->get_raw().v.number;
} }
template <> template <>
double value::get() const double script_value::get() const
{ {
return static_cast<double>(this->get_raw().v.number); return static_cast<double>(this->get_raw().v.number);
} }
@ -166,30 +175,104 @@ namespace ui_scripting
**************************************************************/ **************************************************************/
template <> template <>
bool value::is<const char*>() const bool script_value::is<const char*>() const
{ {
return this->get_raw().t == game::hks::TSTRING; return this->get_raw().t == game::hks::TSTRING;
} }
template <> template <>
bool value::is<std::string>() const bool script_value::is<std::string>() const
{ {
return this->is<const char*>(); return this->is<const char*>();
} }
template <> template <>
const char* value::get() const const char* script_value::get() const
{ {
return this->get_raw().v.str->m_data; return this->get_raw().v.str->m_data;
} }
template <> template <>
std::string value::get() const std::string script_value::get() const
{ {
return this->get<const char*>(); return this->get<const char*>();
} }
bool value::operator==(const value& other) /***************************************************************
* Lightuserdata
**************************************************************/
template <>
bool script_value::is<lightuserdata>() const
{
return this->get_raw().t == game::hks::TLIGHTUSERDATA;
}
template <>
lightuserdata script_value::get() const
{
return this->get_raw().v.ptr;
}
/***************************************************************
* Userdata
**************************************************************/
template <>
bool script_value::is<userdata>() const
{
return this->get_raw().t == game::hks::TUSERDATA;
}
template <>
userdata script_value::get() const
{
return this->get_raw().v.ptr;
}
/***************************************************************
* Table
**************************************************************/
template <>
bool script_value::is<table>() const
{
return this->get_raw().t == game::hks::TTABLE;
}
template <>
table script_value::get() const
{
return this->get_raw().v.table;
}
/***************************************************************
* Function
**************************************************************/
template <>
bool script_value::is<function>() const
{
return this->get_raw().t == game::hks::TIFUNCTION
|| this->get_raw().t == game::hks::TCFUNCTION;
}
template <>
function script_value::get() const
{
return { this->get_raw().v.cClosure, this->get_raw().t };
}
/***************************************************************
*
**************************************************************/
const game::hks::HksObject& script_value::get_raw() const
{
return this->value_;
}
bool script_value::operator==(const script_value& other)
{ {
if (this->get_raw().t != other.get_raw().t) if (this->get_raw().t != other.get_raw().t)
{ {
@ -203,78 +286,4 @@ namespace ui_scripting
return this->get_raw().v.native == other.get_raw().v.native; return this->get_raw().v.native == other.get_raw().v.native;
} }
/***************************************************************
* Lightuserdata
**************************************************************/
template <>
bool value::is<lightuserdata>() const
{
return this->get_raw().t == game::hks::TLIGHTUSERDATA;
}
template <>
lightuserdata value::get() const
{
return this->get_raw().v.ptr;
}
/***************************************************************
* Userdata
**************************************************************/
template <>
bool value::is<userdata>() const
{
return this->get_raw().t == game::hks::TUSERDATA;
}
template <>
userdata value::get() const
{
return this->get_raw().v.ptr;
}
/***************************************************************
* Table
**************************************************************/
template <>
bool value::is<table>() const
{
return this->get_raw().t == game::hks::TTABLE;
}
template <>
table value::get() const
{
return this->get_raw().v.table;
}
/***************************************************************
* Function
**************************************************************/
template <>
bool value::is<function>() const
{
return this->get_raw().t == game::hks::TIFUNCTION
|| this->get_raw().t == game::hks::TCFUNCTION;
}
template <>
function value::get() const
{
return {this->get_raw().v.cClosure, this->get_raw().t};
}
/***************************************************************
*
**************************************************************/
const game::hks::HksObject& value::get_raw() const
{
return this->value_;
}
} }

View File

@ -0,0 +1,58 @@
#pragma once
#include "game/game.hpp"
namespace ui_scripting
{
class lightuserdata;
class userdata;
class table;
class function;
class script_value
{
public:
script_value() = default;
script_value(const game::hks::HksObject& value);
script_value(int value);
script_value(unsigned int value);
script_value(bool value);
script_value(float value);
script_value(double value);
script_value(const char* value);
script_value(const std::string& value);
script_value(const lightuserdata& value);
script_value(const userdata& value);
script_value(const table& value);
script_value(const function& value);
bool operator==(const script_value& other);
template <typename T>
bool is() const;
template <typename T>
T as() const
{
if (!this->is<T>())
{
throw std::runtime_error("Invalid type");
}
return get<T>();
}
const game::hks::HksObject& get_raw() const;
private:
template <typename T>
T get() const;
game::hks::HksObject value_{};
};
using arguments = std::vector<script_value>;
}

View File

@ -6,25 +6,6 @@ namespace ui_scripting
stack_isolation::stack_isolation() stack_isolation::stack_isolation()
{ {
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
state->m_apistack.top = state->m_apistack.base;
this->top_ = state->m_apistack.top;
this->base_ = state->m_apistack.base;
this->alloc_top_ = state->m_apistack.alloc_top;
this->bottom_ = state->m_apistack.bottom;
state->m_apistack.top = this->stack_;
state->m_apistack.base = state->m_apistack.top;
state->m_apistack.alloc_top = &this->stack_[ARRAYSIZE(this->stack_) - 1];
state->m_apistack.bottom = state->m_apistack.top;
}
stack_isolation::~stack_isolation()
{
const auto state = *game::hks::lua_state;
state->m_apistack.top = this->top_;
state->m_apistack.base = this->base_;
state->m_apistack.alloc_top = this->alloc_top_;
state->m_apistack.bottom = this->bottom_;
} }
} }

View File

@ -7,19 +7,10 @@ namespace ui_scripting
{ {
public: public:
stack_isolation(); stack_isolation();
~stack_isolation();
stack_isolation(stack_isolation&&) = delete; stack_isolation(stack_isolation&&) = delete;
stack_isolation(const stack_isolation&) = delete; stack_isolation(const stack_isolation&) = delete;
stack_isolation& operator=(stack_isolation&&) = delete; stack_isolation& operator=(stack_isolation&&) = delete;
stack_isolation& operator=(const 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_;
}; };
} }

View File

@ -1,6 +1,7 @@
#include <std_include.hpp> #include <std_include.hpp>
#include "types.hpp" #include "types.hpp"
#include "execution.hpp" #include "execution.hpp"
#include "stack_isolation.hpp"
namespace ui_scripting namespace ui_scripting
{ {
@ -22,21 +23,16 @@ namespace ui_scripting
{ {
} }
void userdata::set(const value& key, const value& value) const void userdata::set(const script_value& key, const script_value& value) const
{ {
set_field(*this, key, value); set_field(*this, key, value);
} }
value userdata::get(const value& key) const script_value userdata::get(const script_value& key) const
{ {
return get_field(*this, key); return get_field(*this, key);
} }
arguments userdata::call(const std::string& name, const arguments& arguments) const
{
return call_method(this->ptr, name, arguments);
}
/*************************************************************** /***************************************************************
* Table * Table
**************************************************************/ **************************************************************/
@ -45,19 +41,83 @@ namespace ui_scripting
{ {
const auto state = *game::hks::lua_state; const auto state = *game::hks::lua_state;
this->ptr = game::hks::Hashtable_Create(state, 0, 0); this->ptr = game::hks::Hashtable_Create(state, 0, 0);
this->add();
} }
table::table(game::hks::HashTable* ptr_) table::table(game::hks::HashTable* ptr_)
: ptr(ptr_) : ptr(ptr_)
{ {
this->add();
} }
void table::set(const value& key, const value& value) const table::table(const table& other) : table(other.ptr)
{
}
table::table(table&& other) noexcept
{
this->ptr = other.ptr;
this->ref = other.ref;
other.ref = 0;
}
table::~table()
{
this->release();
}
table& table::operator=(const table& other)
{
if (&other != this)
{
this->release();
this->ptr = other.ptr;
this->ref = other.ref;
this->add();
}
return *this;
}
table& table::operator=(table&& other) noexcept
{
if (&other != this)
{
this->release();
this->ptr = other.ptr;
this->ref = other.ref;
other.ref = 0;
}
return *this;
}
void table::add()
{
game::hks::HksObject value{};
value.v.table = this->ptr;
value.t = game::hks::TTABLE;
stack_isolation _;
push_value(value);
this->ref = game::hks::hksi_luaL_ref(*game::hks::lua_state, -10000);
}
void table::release()
{
if (this->ref)
{
game::hks::hksi_luaL_unref(*game::hks::lua_state, -10000, this->ref);
}
}
void table::set(const script_value& key, const script_value& value) const
{ {
set_field(*this, key, value); set_field(*this, key, value);
} }
value table::get(const value& key) const script_value table::get(const script_value& key) const
{ {
return get_field(*this, key); return get_field(*this, key);
} }
@ -70,6 +130,72 @@ namespace ui_scripting
: ptr(ptr_) : ptr(ptr_)
, type(type_) , type(type_)
{ {
this->add();
}
function::function(const function& other) : function(other.ptr, other.type)
{
}
function::function(function&& other) noexcept
{
this->ptr = other.ptr;
this->type = other.type;
this->ref = other.ref;
other.ref = 0;
}
function::~function()
{
this->release();
}
function& function::operator=(const function& other)
{
if (&other != this)
{
this->release();
this->ptr = other.ptr;
this->type = other.type;
this->ref = other.ref;
this->add();
}
return *this;
}
function& function::operator=(function&& other) noexcept
{
if (&other != this)
{
this->release();
this->ptr = other.ptr;
this->type = other.type;
this->ref = other.ref;
other.ref = 0;
}
return *this;
}
void function::add()
{
game::hks::HksObject value{};
value.v.cClosure = this->ptr;
value.t = this->type;
stack_isolation _;
push_value(value);
this->ref = game::hks::hksi_luaL_ref(*game::hks::lua_state, -10000);
}
void function::release()
{
if (this->ref)
{
game::hks::hksi_luaL_unref(*game::hks::lua_state, -10000, this->ref);
}
} }
arguments function::call(const arguments& arguments) const arguments function::call(const arguments& arguments) const

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "game/game.hpp" #include "game/game.hpp"
#include "value.hpp" #include "script_value.hpp"
namespace ui_scripting namespace ui_scripting
{ {
@ -16,9 +16,8 @@ namespace ui_scripting
public: public:
userdata(void*); userdata(void*);
value get(const value& key) const; script_value get(const script_value& key) const;
void set(const value& key, const value& value) const; void set(const script_value& key, const script_value& value) const;
arguments call(const std::string& name, const arguments& arguments) const;
void* ptr; void* ptr;
}; };
@ -29,10 +28,24 @@ namespace ui_scripting
table(); table();
table(game::hks::HashTable* ptr_); table(game::hks::HashTable* ptr_);
value get(const value& key) const; table(const table& other);
void set(const value& key, const value& value) const; table(table&& other) noexcept;
~table();
table& operator=(const table& other);
table& operator=(table&& other) noexcept;
script_value get(const script_value& key) const;
void set(const script_value& key, const script_value& value) const;
game::hks::HashTable* ptr; game::hks::HashTable* ptr;
private:
void add();
void release();
int ref;
}; };
class function class function
@ -40,9 +53,23 @@ namespace ui_scripting
public: public:
function(game::hks::cclosure*, game::hks::HksObjectType); function(game::hks::cclosure*, game::hks::HksObjectType);
function(const function& other);
function(function&& other) noexcept;
~function();
function& operator=(const function& other);
function& operator=(function&& other) noexcept;
arguments call(const arguments& arguments) const; arguments call(const arguments& arguments) const;
game::hks::cclosure* ptr; game::hks::cclosure* ptr;
game::hks::HksObjectType type; game::hks::HksObjectType type;
private:
void add();
void release();
int ref;
}; };
} }

View File

@ -1,58 +0,0 @@
#pragma once
#include "game/game.hpp"
namespace ui_scripting
{
class lightuserdata;
class userdata;
class table;
class function;
class value
{
public:
value() = default;
value(const game::hks::HksObject& value);
value(int value);
value(unsigned int value);
value(bool value);
value(float value);
value(double value);
value(const char* value);
value(const std::string& value);
value(const lightuserdata& value);
value(const userdata& value);
value(const table& value);
value(const function& value);
bool operator==(const value& other);
template <typename T>
bool is() const;
template <typename T>
T as() const
{
if (!this->is<T>())
{
throw std::runtime_error("Invalid type");
}
return get<T>();
}
const game::hks::HksObject& get_raw() const;
private:
template <typename T>
T get() const;
game::hks::HksObject value_{};
};
using arguments = std::vector<value>;
}