fix: lua coroutines support
This commit is contained in:
@@ -21,11 +21,11 @@ namespace scripting {
|
||||
luaerror::luaerror(const std::string& message) : std::runtime_error(message) {
|
||||
}
|
||||
|
||||
void LuaState::removeLibFuncs(const char* libname, const char* funcs[]) {
|
||||
if (getglobal(libname)) {
|
||||
void LuaState::removeLibFuncs(lua_State* L, const char* libname, const char* funcs[]) {
|
||||
if (getglobal(L, libname)) {
|
||||
for (uint i = 0; funcs[i]; i++) {
|
||||
pushnil();
|
||||
setfield(funcs[i], -2);
|
||||
lua_pushnil(L);
|
||||
setfield(L, funcs[i], -2);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -34,10 +34,11 @@ LuaState::LuaState() {
|
||||
logger.info() << LUA_VERSION;
|
||||
logger.info() << LUAJIT_VERSION;
|
||||
|
||||
L = luaL_newstate();
|
||||
auto L = luaL_newstate();
|
||||
if (L == nullptr) {
|
||||
throw luaerror("could not to initialize Lua");
|
||||
}
|
||||
mainThread = L;
|
||||
// Allowed standard libraries
|
||||
luaopen_base(L);
|
||||
luaopen_math(L);
|
||||
@@ -57,15 +58,15 @@ LuaState::LuaState() {
|
||||
"tmpname",
|
||||
nullptr
|
||||
};
|
||||
removeLibFuncs("os", removed_os);
|
||||
removeLibFuncs(L, "os", removed_os);
|
||||
|
||||
createLibs();
|
||||
createLibs(L);
|
||||
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
setglobal(envName(0));
|
||||
pushglobals(L);
|
||||
setglobal(L, envName(0));
|
||||
|
||||
lua_createtable(L, 0, 0);
|
||||
setglobal(LAMBDAS_TABLE);
|
||||
setglobal(L, LAMBDAS_TABLE);
|
||||
}
|
||||
|
||||
std::string LuaState::envName(int env) {
|
||||
@@ -73,42 +74,15 @@ std::string LuaState::envName(int env) {
|
||||
}
|
||||
|
||||
LuaState::~LuaState() {
|
||||
lua_close(L);
|
||||
lua_close(mainThread);
|
||||
}
|
||||
|
||||
void LuaState::logError(const std::string& text) {
|
||||
logger.error() << text;
|
||||
}
|
||||
|
||||
void LuaState::addfunc(const std::string& name, lua_CFunction func) {
|
||||
void LuaState::addfunc(lua_State* L, const std::string& name, lua_CFunction func) {
|
||||
lua_pushcfunction(L, func);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
bool LuaState::getglobal(const std::string& name) {
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LuaState::hasglobal(const std::string& name) {
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return false;
|
||||
}
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return true;
|
||||
}
|
||||
|
||||
void LuaState::setglobal(const std::string& name) {
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
bool LuaState::rename(const std::string& from, const std::string& to) {
|
||||
bool LuaState::rename(lua_State* L, const std::string& from, const std::string& to) {
|
||||
const char* src = from.c_str();
|
||||
lua_getglobal(L, src);
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
@@ -123,262 +97,65 @@ bool LuaState::rename(const std::string& from, const std::string& to) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void LuaState::remove(const std::string& name) {
|
||||
void LuaState::remove(lua_State* L, const std::string& name) {
|
||||
lua_pushnil(L);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
void LuaState::createLibs() {
|
||||
openlib("audio", audiolib);
|
||||
openlib("block", blocklib);
|
||||
openlib("console", consolelib);
|
||||
openlib("core", corelib);
|
||||
openlib("file", filelib);
|
||||
openlib("gui", guilib);
|
||||
openlib("input", inputlib);
|
||||
openlib("inventory", inventorylib);
|
||||
openlib("item", itemlib);
|
||||
openlib("json", jsonlib);
|
||||
openlib("pack", packlib);
|
||||
openlib("player", playerlib);
|
||||
openlib("time", timelib);
|
||||
openlib("toml", tomllib);
|
||||
openlib("world", worldlib);
|
||||
void LuaState::createLibs(lua_State* L) {
|
||||
openlib(L, "audio", audiolib);
|
||||
openlib(L, "block", blocklib);
|
||||
openlib(L, "console", consolelib);
|
||||
openlib(L, "core", corelib);
|
||||
openlib(L, "file", filelib);
|
||||
openlib(L, "gui", guilib);
|
||||
openlib(L, "input", inputlib);
|
||||
openlib(L, "inventory", inventorylib);
|
||||
openlib(L, "item", itemlib);
|
||||
openlib(L, "json", jsonlib);
|
||||
openlib(L, "pack", packlib);
|
||||
openlib(L, "player", playerlib);
|
||||
openlib(L, "time", timelib);
|
||||
openlib(L, "toml", tomllib);
|
||||
openlib(L, "world", worldlib);
|
||||
|
||||
addfunc("print", lua_wrap_errors<l_print>);
|
||||
addfunc(L, "print", lua_wrap_errors<l_print>);
|
||||
}
|
||||
|
||||
void LuaState::loadbuffer(int env, const std::string& src, const std::string& file) {
|
||||
void LuaState::loadbuffer(lua_State* L, int env, const std::string& src, const std::string& file) {
|
||||
if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
|
||||
throw luaerror(lua_tostring(L, -1));
|
||||
}
|
||||
if (env && getglobal(envName(env))) {
|
||||
if (env && getglobal(L, envName(env))) {
|
||||
lua_setfenv(L, -2);
|
||||
}
|
||||
}
|
||||
|
||||
int LuaState::call(int argc, int nresults) {
|
||||
if (lua_pcall(L, argc, nresults, 0)) {
|
||||
throw luaerror(lua_tostring(L, -1));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::callNoThrow(int argc) {
|
||||
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
|
||||
logError(lua_tostring(L, -1));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::eval(int env, const std::string& src, const std::string& file) {
|
||||
int LuaState::eval(lua_State* L, int env, const std::string& src, const std::string& file) {
|
||||
auto srcText = "return "+src;
|
||||
loadbuffer(env, srcText, file);
|
||||
return call(0);
|
||||
loadbuffer(L, env, srcText, file);
|
||||
return call(L, 0);
|
||||
}
|
||||
|
||||
int LuaState::execute(int env, const std::string& src, const std::string& file) {
|
||||
loadbuffer(env, src, file);
|
||||
return callNoThrow(0);
|
||||
int LuaState::execute(lua_State* L, int env, const std::string& src, const std::string& file) {
|
||||
loadbuffer(L, env, src, file);
|
||||
return callNoThrow(L, 0);
|
||||
}
|
||||
|
||||
int LuaState::gettop() const {
|
||||
return lua_gettop(L);
|
||||
}
|
||||
|
||||
int LuaState::pushinteger(lua_Integer x) {
|
||||
lua_pushinteger(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::pushnumber(lua_Number x) {
|
||||
lua_pushnumber(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::pushboolean(bool x) {
|
||||
lua_pushboolean(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::pushivec3(lua_Integer x, lua_Integer y, lua_Integer z) {
|
||||
lua::pushivec3(L, x, y, z);
|
||||
return 3;
|
||||
}
|
||||
|
||||
int LuaState::pushstring(const std::string& str) {
|
||||
lua_pushstring(L, str.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::pushenv(int env) {
|
||||
if (getglobal(envName(env))) {
|
||||
int LuaState::pushenv(lua_State* L, int env) {
|
||||
if (getglobal(L, envName(env))) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LuaState::pushvalue(int idx) {
|
||||
lua_pushvalue(L, idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::pushvalue(const dynamic::Value& value) {
|
||||
using namespace dynamic;
|
||||
|
||||
if (auto* flag = std::get_if<bool>(&value)) {
|
||||
pushboolean(*flag);
|
||||
} else if (auto* num = std::get_if<integer_t>(&value)) {
|
||||
pushinteger(*num);
|
||||
} else if (auto* num = std::get_if<number_t>(&value)) {
|
||||
pushnumber(*num);
|
||||
} else if (auto* str = std::get_if<std::string>(&value)) {
|
||||
pushstring(str->c_str());
|
||||
} else if (auto listptr = std::get_if<List_sptr>(&value)) {
|
||||
auto list = *listptr;
|
||||
lua_createtable(L, list->size(), 0);
|
||||
for (size_t i = 0; i < list->size(); i++) {
|
||||
pushvalue(list->get(i));
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
} else if (auto mapptr = std::get_if<Map_sptr>(&value)) {
|
||||
auto map = *mapptr;
|
||||
lua_createtable(L, 0, map->size());
|
||||
for (auto& entry : map->values) {
|
||||
pushvalue(entry.second);
|
||||
lua_setfield(L, -2, entry.first.c_str());
|
||||
}
|
||||
} else {
|
||||
pushnil();
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::pushglobals() {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int LuaState::pushcfunction(lua_CFunction function) {
|
||||
lua_pushcfunction(L, function);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void LuaState::pop(int n) {
|
||||
lua_pop(L, n);
|
||||
}
|
||||
|
||||
int LuaState::pushnil() {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool LuaState::getfield(const std::string& name, int idx) {
|
||||
lua_getfield(L, idx, name.c_str());
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, -1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LuaState::setfield(const std::string& name, int idx) {
|
||||
lua_setfield(L, idx, name.c_str());
|
||||
}
|
||||
|
||||
bool LuaState::toboolean(int idx) {
|
||||
return lua_toboolean(L, idx);
|
||||
}
|
||||
|
||||
lua_Integer LuaState::tointeger(int idx) {
|
||||
return lua_tointeger(L, idx);
|
||||
}
|
||||
|
||||
lua_Number LuaState::tonumber(int idx) {
|
||||
return lua_tonumber(L, idx);
|
||||
}
|
||||
|
||||
glm::vec2 LuaState::tovec2(int idx) {
|
||||
return lua::tovec2(L, idx);
|
||||
}
|
||||
|
||||
glm::vec4 LuaState::tocolor(int idx) {
|
||||
return lua::tocolor(L, idx);
|
||||
}
|
||||
|
||||
const char* LuaState::tostring(int idx) {
|
||||
return lua_tostring(L, idx);
|
||||
}
|
||||
|
||||
dynamic::Value LuaState::tovalue(int idx) {
|
||||
using namespace dynamic;
|
||||
auto type = lua_type(L, idx);
|
||||
switch (type) {
|
||||
case LUA_TNIL:
|
||||
case LUA_TNONE:
|
||||
return dynamic::NONE;
|
||||
case LUA_TBOOLEAN:
|
||||
return lua_toboolean(L, idx) == 1;
|
||||
case LUA_TNUMBER: {
|
||||
auto number = lua_tonumber(L, idx);
|
||||
auto integer = lua_tointeger(L, idx);
|
||||
if (number == (lua_Number)integer) {
|
||||
return integer;
|
||||
} else {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
case LUA_TSTRING:
|
||||
return std::string(lua_tostring(L, idx));
|
||||
case LUA_TTABLE: {
|
||||
int len = lua_objlen(L, idx);
|
||||
if (len) {
|
||||
// array
|
||||
auto list = create_list();
|
||||
for (int i = 1; i <= len; i++) {
|
||||
lua_rawgeti(L, idx, i);
|
||||
list->put(tovalue(-1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return list;
|
||||
} else {
|
||||
// table
|
||||
auto map = create_map();
|
||||
lua_pushvalue(L, idx);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
lua_pushvalue(L, -2);
|
||||
auto key = lua_tostring(L, -1);
|
||||
map->put(key, tovalue(-2));
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error(
|
||||
"lua type "+std::string(luaL_typename(L, type))+" is not supported"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
bool LuaState::isstring(int idx) {
|
||||
return lua_isstring(L, idx);
|
||||
}
|
||||
|
||||
bool LuaState::isfunction(int idx) {
|
||||
return lua_isfunction(L, idx);
|
||||
}
|
||||
|
||||
void LuaState::openlib(const std::string& name, const luaL_Reg* libfuncs) {
|
||||
void LuaState::openlib(lua_State* L, const std::string& name, const luaL_Reg* libfuncs) {
|
||||
lua_newtable(L);
|
||||
luaL_setfuncs(L, libfuncs, 0);
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
std::shared_ptr<std::string> LuaState::createLambdaHandler() {
|
||||
std::shared_ptr<std::string> LuaState::createLambdaHandler(lua_State* L) {
|
||||
auto ptr = reinterpret_cast<ptrdiff_t>(lua_topointer(L, -1));
|
||||
auto name = util::mangleid(ptr);
|
||||
lua_getglobal(L, LAMBDAS_TABLE.c_str());
|
||||
@@ -395,40 +172,33 @@ std::shared_ptr<std::string> LuaState::createLambdaHandler() {
|
||||
});
|
||||
}
|
||||
|
||||
runnable LuaState::createRunnable() {
|
||||
auto funcptr = createLambdaHandler();
|
||||
runnable LuaState::createRunnable(lua_State* L) {
|
||||
auto funcptr = createLambdaHandler(L);
|
||||
return [=]() {
|
||||
lua_getglobal(L, LAMBDAS_TABLE.c_str());
|
||||
lua_getfield(L, -1, funcptr->c_str());
|
||||
callNoThrow(0);
|
||||
callNoThrow(L, 0);
|
||||
};
|
||||
}
|
||||
|
||||
scripting::common_func LuaState::createLambda() {
|
||||
auto funcptr = createLambdaHandler();
|
||||
scripting::common_func LuaState::createLambda(lua_State* L) {
|
||||
auto funcptr = createLambdaHandler(L);
|
||||
return [=](const std::vector<dynamic::Value>& args) {
|
||||
lua_getglobal(L, LAMBDAS_TABLE.c_str());
|
||||
lua_getfield(L, -1, funcptr->c_str());
|
||||
for (const auto& arg : args) {
|
||||
pushvalue(arg);
|
||||
pushvalue(L, arg);
|
||||
}
|
||||
if (call(args.size(), 1)) {
|
||||
auto result = tovalue(-1);
|
||||
pop(1);
|
||||
if (call(L, args.size(), 1)) {
|
||||
auto result = tovalue(L, -1);
|
||||
lua_pop(L, 1);
|
||||
return result;
|
||||
}
|
||||
return dynamic::Value(dynamic::NONE);
|
||||
};
|
||||
}
|
||||
|
||||
const char* LuaState::requireString(int idx) {
|
||||
if (!lua_isstring(L, idx)) {
|
||||
throw luaerror("string expected at "+std::to_string(idx));
|
||||
}
|
||||
return lua_tostring(L, idx);
|
||||
}
|
||||
|
||||
int LuaState::createEnvironment(int parent) {
|
||||
int LuaState::createEnvironment(lua_State* L, int parent) {
|
||||
int id = nextEnvironment++;
|
||||
|
||||
// local env = {}
|
||||
@@ -439,7 +209,7 @@ int LuaState::createEnvironment(int parent) {
|
||||
if (parent == 0) {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
} else {
|
||||
if (pushenv(parent) == 0) {
|
||||
if (pushenv(L, parent) == 0) {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
}
|
||||
}
|
||||
@@ -447,43 +217,43 @@ int LuaState::createEnvironment(int parent) {
|
||||
lua_setmetatable(L, -2);
|
||||
|
||||
// envname = env
|
||||
setglobal(envName(id));
|
||||
setglobal(L, envName(id));
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
void LuaState::removeEnvironment(int id) {
|
||||
void LuaState::removeEnvironment(lua_State* L, int id) {
|
||||
if (id == 0) {
|
||||
return;
|
||||
}
|
||||
lua_pushnil(L);
|
||||
setglobal(envName(id));
|
||||
setglobal(L, envName(id));
|
||||
}
|
||||
|
||||
bool LuaState::emit_event(const std::string &name, std::function<int(LuaState *)> args) {
|
||||
getglobal("events");
|
||||
getfield("emit");
|
||||
pushstring(name);
|
||||
callNoThrow(args(this) + 1);
|
||||
bool result = toboolean(-1);
|
||||
pop(2);
|
||||
bool LuaState::emitEvent(lua_State* L, const std::string &name, std::function<int(lua_State*)> args) {
|
||||
getglobal(L, "events");
|
||||
getfield(L, "emit");
|
||||
lua::pushstring(L, name);
|
||||
callNoThrow(L, args(L) + 1);
|
||||
bool result = lua_toboolean(L, -1);
|
||||
lua_pop(L, 2);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void LuaState::dumpStack() {
|
||||
int top = gettop();
|
||||
void LuaState::dumpStack(lua_State* L) {
|
||||
int top = lua_gettop(L);
|
||||
for (int i = 1; i <= top; i++) {
|
||||
std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30);
|
||||
switch (lua_type(L, i)) {
|
||||
case LUA_TNUMBER:
|
||||
std::cout << tonumber(i);
|
||||
std::cout << lua_tonumber(L, i);
|
||||
break;
|
||||
case LUA_TSTRING:
|
||||
std::cout << tostring(i);
|
||||
std::cout << lua_tostring(L, i);
|
||||
break;
|
||||
case LUA_TBOOLEAN:
|
||||
std::cout << (toboolean(i) ? "true" : "false");
|
||||
std::cout << (lua_toboolean(L, i) ? "true" : "false");
|
||||
break;
|
||||
case LUA_TNIL:
|
||||
std::cout << "nil";
|
||||
@@ -496,6 +266,6 @@ void LuaState::dumpStack() {
|
||||
}
|
||||
}
|
||||
|
||||
lua_State* LuaState::getLua() const {
|
||||
return L;
|
||||
lua_State* LuaState::getMainThread() const {
|
||||
return mainThread;
|
||||
}
|
||||
|
||||
@@ -17,65 +17,35 @@ namespace lua {
|
||||
};
|
||||
|
||||
class LuaState {
|
||||
lua_State* L;
|
||||
lua_State* mainThread;
|
||||
|
||||
int nextEnvironment = 1;
|
||||
|
||||
void logError(const std::string& text);
|
||||
void removeLibFuncs(const char* libname, const char* funcs[]);
|
||||
void createLibs();
|
||||
void removeLibFuncs(lua_State*, const char* libname, const char* funcs[]);
|
||||
void createLibs(lua_State* L);
|
||||
|
||||
std::shared_ptr<std::string> createLambdaHandler();
|
||||
std::shared_ptr<std::string> createLambdaHandler(lua_State*);
|
||||
public:
|
||||
LuaState();
|
||||
~LuaState();
|
||||
|
||||
static std::string envName(int env);
|
||||
void loadbuffer(int env, const std::string& src, const std::string& file);
|
||||
int gettop() const;
|
||||
int pushivec3(lua_Integer x, lua_Integer y, lua_Integer z);
|
||||
int pushinteger(lua_Integer x);
|
||||
int pushnumber(lua_Number x);
|
||||
int pushboolean(bool x);
|
||||
int pushstring(const std::string& str);
|
||||
int pushenv(int env);
|
||||
int pushvalue(int idx);
|
||||
int pushvalue(const dynamic::Value& value);
|
||||
int pushnil();
|
||||
int pushglobals();
|
||||
int pushcfunction(lua_CFunction function);
|
||||
void pop(int n=1);
|
||||
bool getfield(const std::string& name, int idx = -1);
|
||||
void setfield(const std::string& name, int idx = -2);
|
||||
bool toboolean(int idx);
|
||||
lua_Integer tointeger(int idx);
|
||||
lua_Number tonumber(int idx);
|
||||
glm::vec2 tovec2(int idx);
|
||||
glm::vec4 tocolor(int idx);
|
||||
dynamic::Value tovalue(int idx);
|
||||
const char* tostring(int idx);
|
||||
bool isstring(int idx);
|
||||
bool isfunction(int idx);
|
||||
int call(int argc, int nresults=-1);
|
||||
int callNoThrow(int argc);
|
||||
int execute(int env, const std::string& src, const std::string& file="<string>");
|
||||
int eval(int env, const std::string& src, const std::string& file="<eval>");
|
||||
void openlib(const std::string& name, const luaL_Reg* libfuncs);
|
||||
void addfunc(const std::string& name, lua_CFunction func);
|
||||
bool getglobal(const std::string& name);
|
||||
void setglobal(const std::string& name);
|
||||
bool hasglobal(const std::string& name);
|
||||
bool rename(const std::string& from, const std::string& to);
|
||||
void remove(const std::string& name);;
|
||||
runnable createRunnable();
|
||||
scripting::common_func createLambda();
|
||||
void loadbuffer(lua_State*, int env, const std::string& src, const std::string& file);
|
||||
int pushenv(lua_State*, int env);
|
||||
int execute(lua_State*, int env, const std::string& src, const std::string& file="<string>");
|
||||
int eval(lua_State*, int env, const std::string& src, const std::string& file="<eval>");
|
||||
void openlib(lua_State*, const std::string& name, const luaL_Reg* libfuncs);
|
||||
void addfunc(lua_State*, const std::string& name, lua_CFunction func);
|
||||
bool rename(lua_State*, const std::string& from, const std::string& to);
|
||||
void remove(lua_State*, const std::string& name);;
|
||||
runnable createRunnable(lua_State*);
|
||||
scripting::common_func createLambda(lua_State*);
|
||||
|
||||
const char* requireString(int idx);
|
||||
|
||||
int createEnvironment(int parent);
|
||||
void removeEnvironment(int id);
|
||||
bool emit_event(const std::string& name, std::function<int(lua::LuaState*)> args=[](auto*){return 0;});
|
||||
void dumpStack();
|
||||
lua_State* getLua() const;
|
||||
int createEnvironment(lua_State*, int parent);
|
||||
void removeEnvironment(lua_State*, int id);
|
||||
bool emitEvent(lua_State*, const std::string& name, std::function<int(lua_State*)> args=[](auto*){return 0;});
|
||||
void dumpStack(lua_State*);
|
||||
lua_State* getMainThread() const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "api_lua.hpp"
|
||||
#include "lua_commons.hpp"
|
||||
#include "lua_util.hpp"
|
||||
#include "LuaState.hpp"
|
||||
|
||||
#include "../scripting.hpp"
|
||||
@@ -17,10 +18,10 @@ static int l_add_command(lua_State* L) {
|
||||
if (!lua_isfunction(L, 3)) {
|
||||
throw std::runtime_error("invalid callback");
|
||||
}
|
||||
auto scheme = state->requireString(1);
|
||||
auto description = state->requireString(2);
|
||||
auto scheme = lua::require_string(L, 1);
|
||||
auto description = lua::require_string(L, 2);
|
||||
lua_pushvalue(L, 3);
|
||||
auto func = state->createLambda();
|
||||
auto func = state->createLambda(L);
|
||||
try {
|
||||
engine->getCommandsInterpreter()->getRepository()->add(
|
||||
scheme, description, [func](auto, auto args, auto kwargs) {
|
||||
@@ -33,16 +34,16 @@ static int l_add_command(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_execute(lua_State*) {
|
||||
auto prompt = state->requireString(1);
|
||||
static int l_execute(lua_State* L) {
|
||||
auto prompt = lua::require_string(L, 1);
|
||||
auto result = engine->getCommandsInterpreter()->execute(prompt);
|
||||
state->pushvalue(result);
|
||||
lua::pushvalue(L, result);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set(lua_State*) {
|
||||
auto name = state->requireString(1);
|
||||
auto value = state->tovalue(2);
|
||||
static int l_set(lua_State* L) {
|
||||
auto name = lua::require_string(L, 1);
|
||||
auto value = lua::tovalue(L, 2);
|
||||
(*engine->getCommandsInterpreter())[name] = value;
|
||||
return 0;
|
||||
}
|
||||
@@ -62,7 +63,7 @@ static int l_get_commands_list(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_get_command_info(lua_State* L) {
|
||||
auto name = state->requireString(1);
|
||||
auto name = lua::require_string(L, 1);
|
||||
auto interpreter = engine->getCommandsInterpreter();
|
||||
auto repo = interpreter->getRepository();
|
||||
auto command = repo->get(name);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lua_commons.hpp"
|
||||
#include "lua_util.hpp"
|
||||
#include "api_lua.hpp"
|
||||
#include "LuaState.hpp"
|
||||
|
||||
@@ -21,48 +22,49 @@
|
||||
namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
}
|
||||
using namespace scripting;
|
||||
|
||||
static int l_new_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto seed = lua_tostring(L, 2);
|
||||
auto generator = lua_tostring(L, 3);
|
||||
auto controller = scripting::engine->getController();
|
||||
auto name = lua::require_string(L, 1);
|
||||
auto seed = lua::require_string(L, 2);
|
||||
auto generator = lua::require_string(L, 3);
|
||||
auto controller = engine->getController();
|
||||
controller->createWorld(name, seed, generator);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_open_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto name = lua::require_string(L, 1);
|
||||
|
||||
auto controller = scripting::engine->getController();
|
||||
auto controller = engine->getController();
|
||||
controller->openWorld(name, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_reopen_world(lua_State*) {
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->reopenWorld(scripting::level->getWorld());
|
||||
auto controller = engine->getController();
|
||||
controller->reopenWorld(level->getWorld());
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_close_world(lua_State* L) {
|
||||
if (scripting::controller == nullptr) {
|
||||
if (controller == nullptr) {
|
||||
throw std::runtime_error("no world open");
|
||||
}
|
||||
bool save_world = lua_toboolean(L, 1);
|
||||
if (save_world) {
|
||||
scripting::controller->saveWorld();
|
||||
controller->saveWorld();
|
||||
}
|
||||
// destroy LevelScreen and run quit callbacks
|
||||
scripting::engine->setScreen(nullptr);
|
||||
engine->setScreen(nullptr);
|
||||
// create and go to menu screen
|
||||
scripting::engine->setScreen(std::make_shared<MenuScreen>(scripting::engine));
|
||||
engine->setScreen(std::make_shared<MenuScreen>(engine));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_delete_world(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto controller = scripting::engine->getController();
|
||||
auto name = lua::require_string(L, 1);
|
||||
auto controller = engine->getController();
|
||||
controller->deleteWorld(name);
|
||||
return 0;
|
||||
}
|
||||
@@ -95,35 +97,35 @@ static int l_reconfig_packs(lua_State* L) {
|
||||
remPacks.emplace_back(lua_tostring(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
auto controller = scripting::engine->getController();
|
||||
controller->reconfigPacks(scripting::controller, addPacks, remPacks);
|
||||
auto engine_controller = engine->getController();
|
||||
engine_controller->reconfigPacks(controller, addPacks, remPacks);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_get_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto value = scripting::engine->getSettingsHandler().getValue(name);
|
||||
scripting::state->pushvalue(value);
|
||||
auto name = lua::require_string(L, 1);
|
||||
const auto value = engine->getSettingsHandler().getValue(name);
|
||||
lua::pushvalue(L, value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_set_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto value = scripting::state->tovalue(2);
|
||||
scripting::engine->getSettingsHandler().setValue(name, value);
|
||||
auto name = lua::require_string(L, 1);
|
||||
const auto value = lua::tovalue(L, 2);
|
||||
engine->getSettingsHandler().setValue(name, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_str_setting(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
const auto string = scripting::engine->getSettingsHandler().toString(name);
|
||||
scripting::state->pushstring(string);
|
||||
auto name = lua::require_string(L, 1);
|
||||
const auto string = engine->getSettingsHandler().toString(name);
|
||||
lua::pushstring(L, string);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_get_setting_info(lua_State* L) {
|
||||
auto name = lua_tostring(L, 1);
|
||||
auto setting = scripting::engine->getSettingsHandler().getSetting(name);
|
||||
auto name = lua::require_string(L, 1);
|
||||
auto setting = engine->getSettingsHandler().getSetting(name);
|
||||
lua_createtable(L, 0, 1);
|
||||
if (auto number = dynamic_cast<NumberSetting*>(setting)) {
|
||||
lua_pushnumber(L, number->getMin());
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lua_commons.hpp"
|
||||
#include "lua_util.hpp"
|
||||
#include "api_lua.hpp"
|
||||
#include "LuaState.hpp"
|
||||
#include "../scripting.hpp"
|
||||
@@ -31,7 +32,7 @@ static fs::path resolve_path_soft(const std::string& path) {
|
||||
}
|
||||
|
||||
static int l_file_find(lua_State* L) {
|
||||
std::string path = state->requireString(1);
|
||||
auto path = lua::require_string(L, 1);
|
||||
try {
|
||||
lua_pushstring(L, engine->getResPaths()->findRaw(path).c_str());
|
||||
return 1;
|
||||
@@ -41,13 +42,13 @@ static int l_file_find(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_file_resolve(lua_State* L) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
lua_pushstring(L, path.u8string().c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_read(lua_State* L) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
if (fs::is_regular_file(path)) {
|
||||
lua_pushstring(L, files::read_string(path).c_str());
|
||||
return 1;
|
||||
@@ -55,50 +56,50 @@ static int l_file_read(lua_State* L) {
|
||||
throw std::runtime_error("file does not exists "+util::quote(path.u8string()));
|
||||
}
|
||||
|
||||
static int l_file_write(lua_State*) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
auto text = state->requireString(2);
|
||||
static int l_file_write(lua_State* L) {
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
std::string text = lua::require_string(L, 2);
|
||||
files::write_string(path, text);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_file_remove(lua_State*) {
|
||||
std::string rawpath = state->requireString(1);
|
||||
static int l_file_remove(lua_State* L) {
|
||||
std::string rawpath = lua::require_string(L, 1);
|
||||
fs::path path = resolve_path(rawpath);
|
||||
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
||||
if (entryPoint != "world") {
|
||||
throw std::runtime_error("access denied");
|
||||
}
|
||||
return state->pushboolean(fs::remove(path));
|
||||
return lua::pushboolean(L, fs::remove(path));
|
||||
}
|
||||
|
||||
static int l_file_remove_tree(lua_State*) {
|
||||
std::string rawpath = state->requireString(1);
|
||||
static int l_file_remove_tree(lua_State* L) {
|
||||
std::string rawpath = lua::require_string(L, 1);
|
||||
fs::path path = resolve_path(rawpath);
|
||||
auto entryPoint = rawpath.substr(0, rawpath.find(':'));
|
||||
if (entryPoint != "world") {
|
||||
throw std::runtime_error("access denied");
|
||||
}
|
||||
return state->pushinteger(fs::remove_all(path));
|
||||
return lua::pushinteger(L, fs::remove_all(path));
|
||||
}
|
||||
|
||||
static int l_file_exists(lua_State*) {
|
||||
fs::path path = resolve_path_soft(state->requireString(1));
|
||||
return state->pushboolean(fs::exists(path));
|
||||
static int l_file_exists(lua_State* L) {
|
||||
fs::path path = resolve_path_soft(lua::require_string(L, 1));
|
||||
return lua::pushboolean(L, fs::exists(path));
|
||||
}
|
||||
|
||||
static int l_file_isfile(lua_State*) {
|
||||
fs::path path = resolve_path_soft(state->requireString(1));
|
||||
return state->pushboolean(fs::is_regular_file(path));
|
||||
static int l_file_isfile(lua_State* L) {
|
||||
fs::path path = resolve_path_soft(lua::require_string(L, 1));
|
||||
return lua::pushboolean(L, fs::is_regular_file(path));
|
||||
}
|
||||
|
||||
static int l_file_isdir(lua_State*) {
|
||||
fs::path path = resolve_path_soft(state->requireString(1));
|
||||
return state->pushboolean(fs::is_directory(path));
|
||||
static int l_file_isdir(lua_State* L) {
|
||||
fs::path path = resolve_path_soft(lua::require_string(L, 1));
|
||||
return lua::pushboolean(L, fs::is_directory(path));
|
||||
}
|
||||
|
||||
static int l_file_length(lua_State* L) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
if (fs::exists(path)){
|
||||
lua_pushinteger(L, fs::file_size(path));
|
||||
} else {
|
||||
@@ -108,19 +109,17 @@ static int l_file_length(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_file_mkdir(lua_State* L) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
lua_pushboolean(L, fs::create_directory(path));
|
||||
return 1;
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
return lua::pushboolean(L, fs::create_directory(path));
|
||||
}
|
||||
|
||||
static int l_file_mkdirs(lua_State* L) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
lua_pushboolean(L, fs::create_directories(path));
|
||||
return 1;
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
return lua::pushboolean(L, fs::create_directories(path));
|
||||
}
|
||||
|
||||
static int l_file_read_bytes(lua_State* L) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
if (fs::is_regular_file(path)) {
|
||||
size_t length = static_cast<size_t>(fs::file_size(path));
|
||||
|
||||
@@ -162,7 +161,7 @@ static int l_file_write_bytes(lua_State* L) {
|
||||
throw std::runtime_error("string expected");
|
||||
}
|
||||
|
||||
fs::path path = resolve_path(state->requireString(pathIndex));
|
||||
fs::path path = resolve_path(lua::require_string(L, pathIndex));
|
||||
|
||||
std::vector<ubyte> bytes;
|
||||
|
||||
@@ -171,8 +170,7 @@ static int l_file_write_bytes(lua_State* L) {
|
||||
if(result != 1) {
|
||||
return result;
|
||||
} else {
|
||||
lua_pushboolean(L, files::write_bytes(path, bytes.data(), bytes.size()));
|
||||
return 1;
|
||||
return lua::pushboolean(L, files::write_bytes(path, bytes.data(), bytes.size()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,7 +185,7 @@ static int l_file_list_all_res(lua_State* L, const std::string& path) {
|
||||
}
|
||||
|
||||
static int l_file_list(lua_State* L) {
|
||||
std::string dirname = state->requireString(1);
|
||||
std::string dirname = lua::require_string(L, 1);
|
||||
if (dirname.find(':') == std::string::npos) {
|
||||
return l_file_list_all_res(L, dirname);
|
||||
}
|
||||
@@ -208,7 +206,7 @@ static int l_file_list(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_file_gzip_compress(lua_State* L) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
if (fs::is_regular_file(path)) {
|
||||
size_t length = static_cast<size_t>(fs::file_size(path));
|
||||
|
||||
@@ -221,7 +219,7 @@ static int l_file_gzip_compress(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_file_gzip_decompress(lua_State* L) {
|
||||
fs::path path = resolve_path(state->requireString(1));
|
||||
fs::path path = resolve_path(lua::require_string(L, 1));
|
||||
if (fs::is_regular_file(path)) {
|
||||
size_t length = static_cast<size_t>(fs::file_size(path));
|
||||
|
||||
|
||||
+151
-151
@@ -50,8 +50,8 @@ static DocumentNode getDocumentNode(lua_State*, const std::string& name, const s
|
||||
static DocumentNode getDocumentNode(lua_State* L, int idx=1) {
|
||||
lua_getfield(L, idx, "docname");
|
||||
lua_getfield(L, idx, "name");
|
||||
auto docname = state->requireString(-2);
|
||||
auto name = state->requireString(-1);
|
||||
auto docname = lua::require_string(L, -2);
|
||||
auto name = lua::require_string(L, -1);
|
||||
auto node = getDocumentNode(L, docname, name);
|
||||
lua_pop(L, 2);
|
||||
return node;
|
||||
@@ -74,7 +74,7 @@ static int l_menu_reset(lua_State* L) {
|
||||
static int l_textbox_paste(lua_State* L) {
|
||||
auto node = getDocumentNode(L);
|
||||
auto box = dynamic_cast<TextBox*>(node.node.get());
|
||||
auto text = state->requireString(2);
|
||||
auto text = lua::require_string(L, 2);
|
||||
box->paste(util::str2wstr_utf8(text));
|
||||
return 0;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ static int l_textbox_paste(lua_State* L) {
|
||||
static int l_container_add(lua_State* L) {
|
||||
auto docnode = getDocumentNode(L);
|
||||
auto node = dynamic_cast<Container*>(docnode.node.get());
|
||||
auto xmlsrc = state->requireString(2);
|
||||
auto xmlsrc = lua::require_string(L, 2);
|
||||
try {
|
||||
auto subnode = guiutil::create(xmlsrc, docnode.document->getEnvironment());
|
||||
node->add(subnode);
|
||||
@@ -115,10 +115,10 @@ static int l_container_clear(lua_State* L) {
|
||||
|
||||
static int l_container_set_interval(lua_State* L) {
|
||||
auto node = getDocumentNode(L, 1);
|
||||
auto interval = state->tointeger(2) / 1000.0f;
|
||||
auto interval = lua_tointeger(L, 2) / 1000.0f;
|
||||
if (auto container = std::dynamic_pointer_cast<Container>(node.node)) {
|
||||
state->pushvalue(3);
|
||||
auto runnable = state->createRunnable();
|
||||
lua_pushvalue(L, 3);
|
||||
auto runnable = state->createRunnable(L);
|
||||
container->listenInterval(interval, runnable);
|
||||
}
|
||||
return 0;
|
||||
@@ -131,212 +131,212 @@ static int l_move_into(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_inventory(UINode* node) {
|
||||
static int p_get_inventory(UINode* node, lua_State* L) {
|
||||
if (auto inventory = dynamic_cast<InventoryView*>(node)) {
|
||||
auto inv = inventory->getInventory();
|
||||
return state->pushinteger(inv ? inv->getId() : 0);
|
||||
return lua::pushinteger(L, inv ? inv->getId() : 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_reset(UINode* node) {
|
||||
static int p_get_reset(UINode* node, lua_State* L) {
|
||||
if (dynamic_cast<Menu*>(node)) {
|
||||
return state->pushcfunction(l_menu_reset);
|
||||
return lua::pushcfunction(L, l_menu_reset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_back(UINode* node) {
|
||||
static int p_get_back(UINode* node, lua_State* L) {
|
||||
if (dynamic_cast<Menu*>(node)) {
|
||||
return state->pushcfunction(l_menu_back);
|
||||
return lua::pushcfunction(L, l_menu_back);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_paste(UINode* node) {
|
||||
static int p_get_paste(UINode* node, lua_State* L) {
|
||||
if (dynamic_cast<TextBox*>(node)) {
|
||||
return state->pushcfunction(l_textbox_paste);
|
||||
return lua::pushcfunction(L, l_textbox_paste);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_page(UINode* node) {
|
||||
static int p_get_page(UINode* node, lua_State* L) {
|
||||
if (auto menu = dynamic_cast<Menu*>(node)) {
|
||||
return state->pushstring(menu->getCurrent().name);
|
||||
return lua::pushstring(L, menu->getCurrent().name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_is_checked(UINode* node) {
|
||||
static int p_is_checked(UINode* node, lua_State* L) {
|
||||
if (auto box = dynamic_cast<CheckBox*>(node)) {
|
||||
return state->pushboolean(box->isChecked());
|
||||
return lua::pushboolean(L, box->isChecked());
|
||||
} else if (auto box = dynamic_cast<FullCheckBox*>(node)) {
|
||||
return state->pushboolean(box->isChecked());
|
||||
return lua::pushboolean(L, box->isChecked());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_value(UINode* node) {
|
||||
static int p_get_value(UINode* node, lua_State* L) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
return state->pushnumber(bar->getValue());
|
||||
return lua::pushnumber(L, bar->getValue());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_min(UINode* node) {
|
||||
static int p_get_min(UINode* node, lua_State* L) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
return state->pushnumber(bar->getMin());
|
||||
return lua::pushnumber(L, bar->getMin());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_max(UINode* node) {
|
||||
static int p_get_max(UINode* node, lua_State* L) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
return state->pushnumber(bar->getMax());
|
||||
return lua::pushnumber(L, bar->getMax());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_step(UINode* node) {
|
||||
static int p_get_step(UINode* node, lua_State* L) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
return state->pushnumber(bar->getStep());
|
||||
return lua::pushnumber(L, bar->getStep());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_track_width(UINode* node) {
|
||||
static int p_get_track_width(UINode* node, lua_State* L) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
return state->pushnumber(bar->getTrackWidth());
|
||||
return lua::pushnumber(L, bar->getTrackWidth());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_track_color(UINode* node) {
|
||||
static int p_get_track_color(UINode* node, lua_State* L) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
return lua::pushcolor_arr(state->getLua(), bar->getTrackColor());
|
||||
return lua::pushcolor_arr(L, bar->getTrackColor());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_is_valid(UINode* node) {
|
||||
static int p_is_valid(UINode* node, lua_State* L) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
return state->pushboolean(box->validate());
|
||||
return lua::pushboolean(L, box->validate());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_caret(UINode* node) {
|
||||
static int p_get_caret(UINode* node, lua_State* L) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
return state->pushinteger(static_cast<integer_t>(box->getCaret()));
|
||||
return lua::pushinteger(L, static_cast<integer_t>(box->getCaret()));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_placeholder(UINode* node) {
|
||||
static int p_get_placeholder(UINode* node, lua_State* L) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
return state->pushstring(util::wstr2str_utf8(box->getPlaceholder()));
|
||||
return lua::pushwstring(L, box->getPlaceholder());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_text(UINode* node) {
|
||||
static int p_get_text(UINode* node, lua_State* L) {
|
||||
if (auto button = dynamic_cast<Button*>(node)) {
|
||||
return state->pushstring(util::wstr2str_utf8(button->getText()));
|
||||
return lua::pushwstring(L, button->getText());
|
||||
} else if (auto label = dynamic_cast<Label*>(node)) {
|
||||
return state->pushstring(util::wstr2str_utf8(label->getText()));
|
||||
return lua::pushwstring(L, label->getText());
|
||||
} else if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
return state->pushstring(util::wstr2str_utf8(box->getText()));
|
||||
return lua::pushwstring(L, box->getText());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_editable(UINode* node) {
|
||||
static int p_get_editable(UINode* node, lua_State* L) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
return state->pushboolean(box->isEditable());
|
||||
return lua::pushboolean(L, box->isEditable());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_src(UINode* node) {
|
||||
static int p_get_src(UINode* node, lua_State* L) {
|
||||
if (auto image = dynamic_cast<Image*>(node)) {
|
||||
return state->pushstring(image->getTexture());
|
||||
return lua::pushstring(L, image->getTexture());
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_add(UINode* node) {
|
||||
static int p_get_add(UINode* node, lua_State* L) {
|
||||
if (dynamic_cast<Container*>(node)) {
|
||||
return state->pushcfunction(lua_wrap_errors<l_container_add>);
|
||||
return lua::pushcfunction(L, lua_wrap_errors<l_container_add>);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_destruct(UINode*) {
|
||||
return state->pushcfunction(lua_wrap_errors<l_node_destruct>);
|
||||
static int p_get_destruct(UINode*, lua_State* L) {
|
||||
return lua::pushcfunction(L, lua_wrap_errors<l_node_destruct>);
|
||||
}
|
||||
|
||||
static int p_get_clear(UINode* node) {
|
||||
static int p_get_clear(UINode* node, lua_State* L) {
|
||||
if (dynamic_cast<Container*>(node)) {
|
||||
return state->pushcfunction(lua_wrap_errors<l_container_clear>);
|
||||
return lua::pushcfunction(L, lua_wrap_errors<l_container_clear>);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_set_interval(UINode* node) {
|
||||
static int p_set_interval(UINode* node, lua_State* L) {
|
||||
if (dynamic_cast<Container*>(node)) {
|
||||
return state->pushcfunction(lua_wrap_errors<l_container_set_interval>);
|
||||
return lua::pushcfunction(L, lua_wrap_errors<l_container_set_interval>);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int p_get_color(UINode* node) {
|
||||
return lua::pushcolor_arr(state->getLua(), node->getColor());
|
||||
static int p_get_color(UINode* node, lua_State* L) {
|
||||
return lua::pushcolor_arr(L, node->getColor());
|
||||
}
|
||||
static int p_get_hover_color(UINode* node) {
|
||||
return lua::pushcolor_arr(state->getLua(), node->getHoverColor());
|
||||
static int p_get_hover_color(UINode* node, lua_State* L) {
|
||||
return lua::pushcolor_arr(L, node->getHoverColor());
|
||||
}
|
||||
static int p_get_pressed_color(UINode* node) {
|
||||
return lua::pushcolor_arr(state->getLua(), node->getPressedColor());
|
||||
static int p_get_pressed_color(UINode* node, lua_State* L) {
|
||||
return lua::pushcolor_arr(L, node->getPressedColor());
|
||||
}
|
||||
static int p_get_tooltip(UINode* node) {
|
||||
return state->pushstring(util::wstr2str_utf8(node->getTooltip()));
|
||||
static int p_get_tooltip(UINode* node, lua_State* L) {
|
||||
return lua::pushwstring(L, node->getTooltip());
|
||||
}
|
||||
static int p_get_tooltip_delay(UINode* node) {
|
||||
return state->pushnumber(node->getTooltipDelay());
|
||||
static int p_get_tooltip_delay(UINode* node, lua_State* L) {
|
||||
return lua::pushnumber(L, node->getTooltipDelay());
|
||||
}
|
||||
static int p_get_pos(UINode* node) {
|
||||
return lua::pushvec2_arr(state->getLua(), node->getPos());
|
||||
static int p_get_pos(UINode* node, lua_State* L) {
|
||||
return lua::pushvec2_arr(L, node->getPos());
|
||||
}
|
||||
static int p_get_wpos(UINode* node) {
|
||||
return lua::pushvec2_arr(state->getLua(), node->calcPos());
|
||||
static int p_get_wpos(UINode* node, lua_State* L) {
|
||||
return lua::pushvec2_arr(L, node->calcPos());
|
||||
}
|
||||
static int p_get_size(UINode* node) {
|
||||
return lua::pushvec2_arr(state->getLua(), node->getSize());
|
||||
static int p_get_size(UINode* node, lua_State* L) {
|
||||
return lua::pushvec2_arr(L, node->getSize());
|
||||
}
|
||||
static int p_is_interactive(UINode* node) {
|
||||
return state->pushboolean(node->isInteractive());
|
||||
static int p_is_interactive(UINode* node, lua_State* L) {
|
||||
return lua::pushboolean(L, node->isInteractive());
|
||||
}
|
||||
static int p_is_visible(UINode* node) {
|
||||
return state->pushboolean(node->isVisible());
|
||||
static int p_is_visible(UINode* node, lua_State* L) {
|
||||
return lua::pushboolean(L, node->isVisible());
|
||||
}
|
||||
static int p_is_enabled(UINode* node) {
|
||||
return state->pushboolean(node->isEnabled());
|
||||
static int p_is_enabled(UINode* node, lua_State* L) {
|
||||
return lua::pushboolean(L, node->isEnabled());
|
||||
}
|
||||
static int p_move_into(UINode*) {
|
||||
return state->pushcfunction(l_move_into);
|
||||
static int p_move_into(UINode*, lua_State* L) {
|
||||
return lua::pushcfunction(L, l_move_into);
|
||||
}
|
||||
static int p_get_focused(UINode* node) {
|
||||
return state->pushboolean(node->isFocused());
|
||||
static int p_get_focused(UINode* node, lua_State* L) {
|
||||
return lua::pushboolean(L, node->isFocused());
|
||||
}
|
||||
|
||||
static int l_gui_getattr(lua_State* L) {
|
||||
auto docname = state->requireString(1);
|
||||
auto element = state->requireString(2);
|
||||
auto attr = state->requireString(3);
|
||||
auto docname = lua::require_string(L, 1);
|
||||
auto element = lua::require_string(L, 2);
|
||||
auto attr = lua::require_string(L, 3);
|
||||
auto docnode = getDocumentNode(L, docname, element);
|
||||
auto node = docnode.node;
|
||||
|
||||
static const std::unordered_map<std::string_view, std::function<int(UINode*)>> getters {
|
||||
static const std::unordered_map<std::string_view, std::function<int(UINode*,lua_State*)>> getters {
|
||||
{"color", p_get_color},
|
||||
{"hoverColor", p_get_hover_color},
|
||||
{"pressedColor", p_get_pressed_color},
|
||||
@@ -375,118 +375,118 @@ static int l_gui_getattr(lua_State* L) {
|
||||
};
|
||||
auto func = getters.find(attr);
|
||||
if (func != getters.end()) {
|
||||
return func->second(node.get());
|
||||
return func->second(node.get(), L);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void p_set_color(UINode* node, int idx) {
|
||||
node->setColor(state->tocolor(idx));
|
||||
static void p_set_color(UINode* node, lua_State* L, int idx) {
|
||||
node->setColor(lua::tocolor(L, idx));
|
||||
}
|
||||
static void p_set_hover_color(UINode* node, int idx) {
|
||||
node->setHoverColor(state->tocolor(idx));
|
||||
static void p_set_hover_color(UINode* node, lua_State* L, int idx) {
|
||||
node->setHoverColor(lua::tocolor(L, idx));
|
||||
}
|
||||
static void p_set_pressed_color(UINode* node, int idx) {
|
||||
node->setPressedColor(state->tocolor(idx));
|
||||
static void p_set_pressed_color(UINode* node, lua_State* L, int idx) {
|
||||
node->setPressedColor(lua::tocolor(L, idx));
|
||||
}
|
||||
static void p_set_tooltip(UINode* node, int idx) {
|
||||
node->setTooltip(util::str2wstr_utf8(state->requireString(idx)));
|
||||
static void p_set_tooltip(UINode* node, lua_State* L, int idx) {
|
||||
node->setTooltip(lua::require_wstring(L, idx));
|
||||
}
|
||||
static void p_set_tooltip_delay(UINode* node, int idx) {
|
||||
node->setTooltipDelay(state->tonumber(idx));
|
||||
static void p_set_tooltip_delay(UINode* node, lua_State* L, int idx) {
|
||||
node->setTooltipDelay(lua_tonumber(L, idx));
|
||||
}
|
||||
static void p_set_pos(UINode* node, int idx) {
|
||||
node->setPos(state->tovec2(idx));
|
||||
static void p_set_pos(UINode* node, lua_State* L, int idx) {
|
||||
node->setPos(lua::tovec2(L, idx));
|
||||
}
|
||||
static void p_set_wpos(UINode* node, int idx) {
|
||||
node->setPos(state->tovec2(idx)-node->calcPos());
|
||||
static void p_set_wpos(UINode* node, lua_State* L, int idx) {
|
||||
node->setPos(lua::tovec2(L, idx)-node->calcPos());
|
||||
}
|
||||
static void p_set_size(UINode* node, int idx) {
|
||||
node->setSize(state->tovec2(idx));
|
||||
static void p_set_size(UINode* node, lua_State* L, int idx) {
|
||||
node->setSize(lua::tovec2(L, idx));
|
||||
}
|
||||
static void p_set_interactive(UINode* node, int idx) {
|
||||
node->setInteractive(state->toboolean(idx));
|
||||
static void p_set_interactive(UINode* node, lua_State* L, int idx) {
|
||||
node->setInteractive(lua_toboolean(L, idx));
|
||||
}
|
||||
static void p_set_visible(UINode* node, int idx) {
|
||||
node->setVisible(state->toboolean(idx));
|
||||
static void p_set_visible(UINode* node, lua_State* L, int idx) {
|
||||
node->setVisible(lua_toboolean(L, idx));
|
||||
}
|
||||
static void p_set_enabled(UINode* node, int idx) {
|
||||
node->setEnabled(state->toboolean(idx));
|
||||
static void p_set_enabled(UINode* node, lua_State* L, int idx) {
|
||||
node->setEnabled(lua_toboolean(L, idx));
|
||||
}
|
||||
static void p_set_placeholder(UINode* node, int idx) {
|
||||
static void p_set_placeholder(UINode* node, lua_State* L, int idx) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
box->setPlaceholder(util::str2wstr_utf8(state->requireString(idx)));
|
||||
box->setPlaceholder(lua::require_wstring(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_text(UINode* node, int idx) {
|
||||
static void p_set_text(UINode* node, lua_State* L, int idx) {
|
||||
if (auto label = dynamic_cast<Label*>(node)) {
|
||||
label->setText(util::str2wstr_utf8(state->requireString(idx)));
|
||||
label->setText(lua::require_wstring(L, idx));
|
||||
} else if (auto button = dynamic_cast<Button*>(node)) {
|
||||
button->setText(util::str2wstr_utf8(state->requireString(idx)));
|
||||
button->setText(lua::require_wstring(L, idx));
|
||||
} else if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
box->setText(util::str2wstr_utf8(state->requireString(idx)));
|
||||
box->setText(lua::require_wstring(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_caret(UINode* node, int idx) {
|
||||
static void p_set_caret(UINode* node, lua_State* L, int idx) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
box->setCaret(static_cast<ptrdiff_t>(state->tointeger(idx)));
|
||||
box->setCaret(static_cast<ptrdiff_t>(lua_tointeger(L, idx)));
|
||||
}
|
||||
}
|
||||
static void p_set_editable(UINode* node, int idx) {
|
||||
static void p_set_editable(UINode* node, lua_State* L, int idx) {
|
||||
if (auto box = dynamic_cast<TextBox*>(node)) {
|
||||
box->setEditable(state->toboolean(idx));
|
||||
box->setEditable(lua_toboolean(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_src(UINode* node, int idx) {
|
||||
static void p_set_src(UINode* node, lua_State* L, int idx) {
|
||||
if (auto image = dynamic_cast<Image*>(node)) {
|
||||
image->setTexture(state->requireString(idx));
|
||||
image->setTexture(lua::require_string(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_value(UINode* node, int idx) {
|
||||
static void p_set_value(UINode* node, lua_State* L, int idx) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
bar->setValue(state->tonumber(idx));
|
||||
bar->setValue(lua_tonumber(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_min(UINode* node, int idx) {
|
||||
static void p_set_min(UINode* node, lua_State* L, int idx) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
bar->setMin(state->tonumber(idx));
|
||||
bar->setMin(lua_tonumber(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_max(UINode* node, int idx) {
|
||||
static void p_set_max(UINode* node, lua_State* L, int idx) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
bar->setMax(state->tonumber(idx));
|
||||
bar->setMax(lua_tonumber(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_step(UINode* node, int idx) {
|
||||
static void p_set_step(UINode* node, lua_State* L, int idx) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
bar->setStep(state->tonumber(idx));
|
||||
bar->setStep(lua_tonumber(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_track_width(UINode* node, int idx) {
|
||||
static void p_set_track_width(UINode* node, lua_State* L, int idx) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
bar->setTrackWidth(state->tointeger(idx));
|
||||
bar->setTrackWidth(lua_tointeger(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_track_color(UINode* node, int idx) {
|
||||
static void p_set_track_color(UINode* node, lua_State* L, int idx) {
|
||||
if (auto bar = dynamic_cast<TrackBar*>(node)) {
|
||||
bar->setTrackColor(state->tocolor(idx));
|
||||
bar->setTrackColor(lua::tocolor(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_checked(UINode* node, int idx) {
|
||||
static void p_set_checked(UINode* node, lua_State* L, int idx) {
|
||||
if (auto box = dynamic_cast<CheckBox*>(node)) {
|
||||
box->setChecked(state->toboolean(idx));
|
||||
box->setChecked(lua_toboolean(L, idx));
|
||||
} else if (auto box = dynamic_cast<FullCheckBox*>(node)) {
|
||||
box->setChecked(state->toboolean(idx));
|
||||
box->setChecked(lua_toboolean(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_page(UINode* node, int idx) {
|
||||
static void p_set_page(UINode* node, lua_State* L, int idx) {
|
||||
if (auto menu = dynamic_cast<Menu*>(node)) {
|
||||
menu->setPage(state->requireString(idx));
|
||||
menu->setPage(lua::require_string(L, idx));
|
||||
}
|
||||
}
|
||||
static void p_set_inventory(UINode* node, int idx) {
|
||||
static void p_set_inventory(UINode* node, lua_State* L, int idx) {
|
||||
if (auto view = dynamic_cast<InventoryView*>(node)) {
|
||||
auto inventory = level->inventories->get(state->tointeger(idx));
|
||||
auto inventory = level->inventories->get(lua_tointeger(L, idx));
|
||||
if (inventory == nullptr) {
|
||||
view->unbind();
|
||||
} else {
|
||||
@@ -494,8 +494,8 @@ static void p_set_inventory(UINode* node, int idx) {
|
||||
}
|
||||
}
|
||||
}
|
||||
static void p_set_focused(const std::shared_ptr<UINode> &node, int idx) {
|
||||
if (state->toboolean(idx) && !node->isFocused()) {
|
||||
static void p_set_focused(const std::shared_ptr<UINode> &node, lua_State* L, int idx) {
|
||||
if (lua_toboolean(L, idx) && !node->isFocused()) {
|
||||
scripting::engine->getGUI()->setFocus(node);
|
||||
} else if (node->isFocused()){
|
||||
node->defocus();
|
||||
@@ -503,14 +503,14 @@ static void p_set_focused(const std::shared_ptr<UINode> &node, int idx) {
|
||||
}
|
||||
|
||||
static int l_gui_setattr(lua_State* L) {
|
||||
auto docname = state->requireString(1);
|
||||
auto element = state->requireString(2);
|
||||
auto attr = state->requireString(3);
|
||||
auto docname = lua::require_string(L, 1);
|
||||
auto element = lua::require_string(L, 2);
|
||||
auto attr = lua::require_string(L, 3);
|
||||
|
||||
auto docnode = getDocumentNode(L, docname, element);
|
||||
auto node = docnode.node;
|
||||
|
||||
static const std::unordered_map<std::string_view, std::function<void(UINode*,int)>> setters {
|
||||
static const std::unordered_map<std::string_view, std::function<void(UINode*,lua_State*,int)>> setters {
|
||||
{"color", p_set_color},
|
||||
{"hoverColor", p_set_hover_color},
|
||||
{"pressedColor", p_set_pressed_color},
|
||||
@@ -539,20 +539,20 @@ static int l_gui_setattr(lua_State* L) {
|
||||
};
|
||||
auto func = setters.find(attr);
|
||||
if (func != setters.end()) {
|
||||
func->second(node.get(), 4);
|
||||
func->second(node.get(), L, 4);
|
||||
}
|
||||
static const std::unordered_map<std::string_view, std::function<void(std::shared_ptr<UINode>,int)>> setters2 {
|
||||
static const std::unordered_map<std::string_view, std::function<void(std::shared_ptr<UINode>,lua_State*,int)>> setters2 {
|
||||
{"focused", p_set_focused},
|
||||
};
|
||||
auto func2 = setters2.find(attr);
|
||||
if (func2 != setters2.end()) {
|
||||
func2->second(node, 4);
|
||||
func2->second(node, L, 4);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int l_gui_get_env(lua_State* L) {
|
||||
auto name = state->requireString(1);
|
||||
auto name = lua::require_string(L, 1);
|
||||
auto doc = scripting::engine->getAssets()->getLayout(name);
|
||||
if (doc == nullptr) {
|
||||
throw std::runtime_error("document '"+std::string(name)+"' not found");
|
||||
@@ -562,9 +562,9 @@ static int l_gui_get_env(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_gui_str(lua_State* L) {
|
||||
auto text = util::str2wstr_utf8(state->requireString(1));
|
||||
auto text = lua::require_wstring(L, 1);
|
||||
if (!lua_isnoneornil(L, 2)) {
|
||||
auto context = util::str2wstr_utf8(state->requireString(2));
|
||||
auto context = lua::require_wstring(L, 2);
|
||||
lua_pushstring(L, util::wstr2str_utf8(langs::get(text, context)).c_str());
|
||||
} else {
|
||||
lua_pushstring(L, util::wstr2str_utf8(langs::get(text)).c_str());
|
||||
@@ -573,7 +573,7 @@ static int l_gui_str(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_gui_reindex(lua_State* L) {
|
||||
auto name = state->requireString(1);
|
||||
auto name = lua::require_string(L, 1);
|
||||
auto doc = scripting::engine->getAssets()->getLayout(name);
|
||||
if (doc == nullptr) {
|
||||
throw std::runtime_error("document '"+std::string(name)+"' not found");
|
||||
|
||||
@@ -16,29 +16,28 @@ namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
extern Hud* hud;
|
||||
}
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static int l_keycode(lua_State* L) {
|
||||
const char* name = state->requireString(1);
|
||||
auto name = lua::require_string(L, 1);
|
||||
lua_pushinteger(L, static_cast<int>(input_util::keycode_from(name)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_mousecode(lua_State* L) {
|
||||
const char* name = state->requireString(1);
|
||||
auto name = lua::require_string(L, 1);
|
||||
lua_pushinteger(L, static_cast<int>(input_util::mousecode_from(name)));
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_add_callback(lua_State*) {
|
||||
auto bindname = state->requireString(1);
|
||||
static int l_add_callback(lua_State* L) {
|
||||
auto bindname = lua::require_string(L, 1);
|
||||
const auto& bind = Events::bindings.find(bindname);
|
||||
if (bind == Events::bindings.end()) {
|
||||
throw std::runtime_error("unknown binding "+util::quote(bindname));
|
||||
}
|
||||
state->pushvalue(2);
|
||||
runnable actual_callback = state->createRunnable();
|
||||
lua_pushvalue(L, 2);
|
||||
runnable actual_callback = state->createRunnable(L);
|
||||
runnable callback = [=]() {
|
||||
if (!scripting::engine->getGUI()->isFocusCaught()) {
|
||||
actual_callback();
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "lua_commons.hpp"
|
||||
#include "lua_util.hpp"
|
||||
#include "api_lua.hpp"
|
||||
#include "LuaState.hpp"
|
||||
#include "../scripting.hpp"
|
||||
@@ -8,12 +9,11 @@
|
||||
namespace scripting {
|
||||
extern lua::LuaState* state;
|
||||
}
|
||||
|
||||
using namespace scripting;
|
||||
|
||||
static int l_item_name(lua_State* L) {
|
||||
auto indices = scripting::content->getIndices();
|
||||
lua_Number id = lua_tointeger(L, 1);
|
||||
auto indices = content->getIndices();
|
||||
auto id = lua_tointeger(L, 1);
|
||||
if (static_cast<size_t>(id) >= indices->countItemDefs()) {
|
||||
return 0;
|
||||
}
|
||||
@@ -23,15 +23,15 @@ static int l_item_name(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_item_index(lua_State* L) {
|
||||
auto name = scripting::state->requireString(1);
|
||||
lua_pushinteger(L, scripting::content->requireItem(name).rt.id);
|
||||
auto name = lua::require_string(L, 1);
|
||||
lua_pushinteger(L, content->requireItem(name).rt.id);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int l_item_stack_size(lua_State* L) {
|
||||
auto indices = scripting::content->getIndices();
|
||||
lua_Integer id = lua_tointeger(L, 1);
|
||||
if (id < 0 || size_t(id) >= indices->countItemDefs()) {
|
||||
auto indices = content->getIndices();
|
||||
auto id = lua_tointeger(L, 1);
|
||||
if (static_cast<size_t>(id) >= indices->countItemDefs()) {
|
||||
return 0;
|
||||
}
|
||||
auto def = indices->getItemDef(id);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "api_lua.hpp"
|
||||
#include "lua_util.hpp"
|
||||
#include "lua_commons.hpp"
|
||||
#include "LuaState.hpp"
|
||||
|
||||
@@ -10,7 +11,7 @@ namespace scripting {
|
||||
}
|
||||
|
||||
static int l_json_stringify(lua_State* L) {
|
||||
auto value = scripting::state->tovalue(1);
|
||||
auto value = lua::tovalue(L, 1);
|
||||
|
||||
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) {
|
||||
bool nice = lua_toboolean(L, 2);
|
||||
@@ -23,9 +24,9 @@ static int l_json_stringify(lua_State* L) {
|
||||
}
|
||||
|
||||
static int l_json_parse(lua_State* L) {
|
||||
auto string = scripting::state->requireString(1);
|
||||
auto string = lua::require_string(L, 1);
|
||||
auto element = json::parse("<string>", string);
|
||||
scripting::state->pushvalue(element);
|
||||
lua::pushvalue(L, element);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "api_lua.hpp"
|
||||
#include "lua_util.hpp"
|
||||
#include "lua_commons.hpp"
|
||||
#include "LuaState.hpp"
|
||||
|
||||
@@ -11,7 +12,7 @@ namespace scripting {
|
||||
using namespace scripting;
|
||||
|
||||
static int l_toml_stringify(lua_State* L) {
|
||||
auto value = state->tovalue(1);
|
||||
auto value = lua::tovalue(L, 1);
|
||||
|
||||
if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) {
|
||||
auto string = toml::stringify(**mapptr);
|
||||
@@ -22,11 +23,11 @@ static int l_toml_stringify(lua_State* L) {
|
||||
}
|
||||
}
|
||||
|
||||
static int l_toml_parse(lua_State*) {
|
||||
auto string = state->requireString(1);
|
||||
static int l_toml_parse(lua_State* L) {
|
||||
auto string = lua::require_string(L, 1);
|
||||
auto element = toml::parse("<string>", string);
|
||||
auto value = std::make_unique<dynamic::Value>(element);
|
||||
state->pushvalue(*value);
|
||||
lua::pushvalue(L, *value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
#include "lua_util.hpp"
|
||||
|
||||
#include "../../../debug/Logger.hpp"
|
||||
#include "../../../util/stringutil.hpp"
|
||||
|
||||
static debug::Logger logger("lua");
|
||||
|
||||
int lua::pushvalue(lua_State* L, const dynamic::Value& value) {
|
||||
using namespace dynamic;
|
||||
|
||||
if (auto* flag = std::get_if<bool>(&value)) {
|
||||
lua_pushboolean(L, *flag);
|
||||
} else if (auto* num = std::get_if<integer_t>(&value)) {
|
||||
lua_pushinteger(L, *num);
|
||||
} else if (auto* num = std::get_if<number_t>(&value)) {
|
||||
lua_pushnumber(L, *num);
|
||||
} else if (auto* str = std::get_if<std::string>(&value)) {
|
||||
lua_pushstring(L, str->c_str());
|
||||
} else if (auto listptr = std::get_if<List_sptr>(&value)) {
|
||||
auto list = *listptr;
|
||||
lua_createtable(L, list->size(), 0);
|
||||
for (size_t i = 0; i < list->size(); i++) {
|
||||
pushvalue(L, list->get(i));
|
||||
lua_rawseti(L, -2, i+1);
|
||||
}
|
||||
} else if (auto mapptr = std::get_if<Map_sptr>(&value)) {
|
||||
auto map = *mapptr;
|
||||
lua_createtable(L, 0, map->size());
|
||||
for (auto& entry : map->values) {
|
||||
pushvalue(L, entry.second);
|
||||
lua_setfield(L, -2, entry.first.c_str());
|
||||
}
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::wstring lua::require_wstring(lua_State* L, int idx) {
|
||||
return util::str2wstr_utf8(lua::require_string(L, idx));
|
||||
}
|
||||
|
||||
int lua::pushwstring(lua_State* L, const std::wstring& str) {
|
||||
return lua::pushstring(L, util::wstr2str_utf8(str));
|
||||
}
|
||||
|
||||
dynamic::Value lua::tovalue(lua_State* L, int idx) {
|
||||
using namespace dynamic;
|
||||
auto type = lua_type(L, idx);
|
||||
switch (type) {
|
||||
case LUA_TNIL:
|
||||
case LUA_TNONE:
|
||||
return dynamic::NONE;
|
||||
case LUA_TBOOLEAN:
|
||||
return lua_toboolean(L, idx) == 1;
|
||||
case LUA_TNUMBER: {
|
||||
auto number = lua_tonumber(L, idx);
|
||||
auto integer = lua_tointeger(L, idx);
|
||||
if (number == (lua_Number)integer) {
|
||||
return integer;
|
||||
} else {
|
||||
return number;
|
||||
}
|
||||
}
|
||||
case LUA_TSTRING:
|
||||
return std::string(lua_tostring(L, idx));
|
||||
case LUA_TTABLE: {
|
||||
int len = lua_objlen(L, idx);
|
||||
if (len) {
|
||||
// array
|
||||
auto list = create_list();
|
||||
for (int i = 1; i <= len; i++) {
|
||||
lua_rawgeti(L, idx, i);
|
||||
list->put(tovalue(L, -1));
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
return list;
|
||||
} else {
|
||||
// table
|
||||
auto map = create_map();
|
||||
lua_pushvalue(L, idx);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2)) {
|
||||
lua_pushvalue(L, -2);
|
||||
auto key = lua_tostring(L, -1);
|
||||
map->put(key, tovalue(L, -2));
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
default:
|
||||
throw std::runtime_error(
|
||||
"lua type "+std::string(luaL_typename(L, type))+" is not supported"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void lua::logError(const std::string& text) {
|
||||
logger.error() << text;
|
||||
}
|
||||
|
||||
int lua::call(lua_State* L, int argc, int nresults) {
|
||||
if (lua_pcall(L, argc, nresults, 0)) {
|
||||
throw luaerror(lua_tostring(L, -1));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int lua::callNoThrow(lua_State* L, int argc) {
|
||||
if (lua_pcall(L, argc, LUA_MULTRET, 0)) {
|
||||
logError(lua_tostring(L, -1));
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -14,6 +14,23 @@
|
||||
#include <stdexcept>
|
||||
|
||||
namespace lua {
|
||||
// function wrappers with number of pushed values as return value
|
||||
|
||||
inline int pushnil(lua_State* L) {
|
||||
lua_pushnil(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int pushinteger(lua_State* L, lua_Integer x) {
|
||||
lua_pushinteger(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int pushnumber(lua_State* L, lua_Number x) {
|
||||
lua_pushnumber(L, x);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int pushivec3(lua_State* L, lua_Integer x, lua_Integer y, lua_Integer z) {
|
||||
lua_pushinteger(L, x);
|
||||
lua_pushinteger(L, y);
|
||||
@@ -84,7 +101,6 @@ namespace lua {
|
||||
lua_rawseti(L, -2, 4);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline int pushcolor_arr(lua_State* L, glm::vec4 vec) {
|
||||
lua_createtable(L, 4, 0);
|
||||
lua_getglobal(L, "color_mt");
|
||||
@@ -100,6 +116,33 @@ namespace lua {
|
||||
lua_rawseti(L, -2, 4);
|
||||
return 1;
|
||||
}
|
||||
inline int pushcfunction(lua_State* L, lua_CFunction func) {
|
||||
lua_pushcfunction(L, func);
|
||||
return 1;
|
||||
}
|
||||
inline int pushstring(lua_State* L, const std::string& str) {
|
||||
lua_pushstring(L, str.c_str());
|
||||
return 1;
|
||||
}
|
||||
|
||||
int pushwstring(lua_State* L, const std::wstring& str);
|
||||
|
||||
inline int pushboolean(lua_State* L, bool value) {
|
||||
lua_pushboolean(L, value);
|
||||
return 1;
|
||||
}
|
||||
inline int pushglobals(lua_State* L) {
|
||||
lua_pushvalue(L, LUA_GLOBALSINDEX);
|
||||
return 1;
|
||||
}
|
||||
inline int pushvalue(lua_State* L, int idx) {
|
||||
lua_pushvalue(L, idx);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inline bool toboolean(lua_State* L, int idx) {
|
||||
return lua_toboolean(L, idx);
|
||||
}
|
||||
|
||||
inline glm::vec2 tovec2(lua_State* L, int idx) {
|
||||
lua_pushvalue(L, idx);
|
||||
@@ -130,6 +173,61 @@ namespace lua {
|
||||
lua_pop(L, 1);
|
||||
return glm::vec4(r/255, g/255, b/255, a/255);
|
||||
}
|
||||
|
||||
inline const char* require_string(lua_State* L, int idx) {
|
||||
if (!lua_isstring(L, idx)) {
|
||||
throw luaerror("string expected at "+std::to_string(idx));
|
||||
}
|
||||
return lua_tostring(L, idx);
|
||||
}
|
||||
|
||||
std::wstring require_wstring(lua_State*, int idx);
|
||||
int pushvalue(lua_State*, const dynamic::Value& value);
|
||||
dynamic::Value tovalue(lua_State*, int idx);
|
||||
|
||||
inline void pop(lua_State* L, int n=1) {
|
||||
lua_pop(L, n);
|
||||
}
|
||||
|
||||
inline bool getfield(lua_State* L, const std::string& name, int idx=-1) {
|
||||
lua_getfield(L, idx, name.c_str());
|
||||
if (lua_isnil(L, -1)) {
|
||||
lua_pop(L, -1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void setfield(lua_State* L, const std::string& name, int idx=-2) {
|
||||
lua_setfield(L, idx, name.c_str());
|
||||
}
|
||||
|
||||
inline bool getglobal(lua_State* L, const std::string& name) {
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool hasglobal(lua_State* L, const std::string& name) {
|
||||
lua_getglobal(L, name.c_str());
|
||||
if (lua_isnil(L, lua_gettop(L))) {
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return false;
|
||||
}
|
||||
lua_pop(L, lua_gettop(L));
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void setglobal(lua_State* L, const std::string& name) {
|
||||
lua_setglobal(L, name.c_str());
|
||||
}
|
||||
|
||||
void logError(const std::string& text);
|
||||
int call(lua_State*, int argc, int nresults=-1);
|
||||
int callNoThrow(lua_State*, int argc);
|
||||
}
|
||||
|
||||
#endif // LOGIC_SCRIPTING_LUA_UTIL_HPP_
|
||||
|
||||
Reference in New Issue
Block a user