diff --git a/src/logic/scripting/lua/LuaState.cpp b/src/logic/scripting/lua/LuaState.cpp index 524e3049..0d70a378 100644 --- a/src/logic/scripting/lua/LuaState.cpp +++ b/src/logic/scripting/lua/LuaState.cpp @@ -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); + addfunc(L, "print", lua_wrap_errors); } -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(&value)) { - pushboolean(*flag); - } else if (auto* num = std::get_if(&value)) { - pushinteger(*num); - } else if (auto* num = std::get_if(&value)) { - pushnumber(*num); - } else if (auto* str = std::get_if(&value)) { - pushstring(str->c_str()); - } else if (auto listptr = std::get_if(&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(&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 LuaState::createLambdaHandler() { +std::shared_ptr LuaState::createLambdaHandler(lua_State* L) { auto ptr = reinterpret_cast(lua_topointer(L, -1)); auto name = util::mangleid(ptr); lua_getglobal(L, LAMBDAS_TABLE.c_str()); @@ -395,40 +172,33 @@ std::shared_ptr 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& 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 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 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; } diff --git a/src/logic/scripting/lua/LuaState.hpp b/src/logic/scripting/lua/LuaState.hpp index 74c0257d..f8a925e5 100644 --- a/src/logic/scripting/lua/LuaState.hpp +++ b/src/logic/scripting/lua/LuaState.hpp @@ -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 createLambdaHandler(); + std::shared_ptr 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=""); - int eval(int env, const std::string& src, const std::string& file=""); - 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=""); + int eval(lua_State*, int env, const std::string& src, const std::string& file=""); + 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 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 args=[](auto*){return 0;}); + void dumpStack(lua_State*); + lua_State* getMainThread() const; }; } diff --git a/src/logic/scripting/lua/libconsole.cpp b/src/logic/scripting/lua/libconsole.cpp index 88238f65..0a27bcde 100644 --- a/src/logic/scripting/lua/libconsole.cpp +++ b/src/logic/scripting/lua/libconsole.cpp @@ -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); diff --git a/src/logic/scripting/lua/libcore.cpp b/src/logic/scripting/lua/libcore.cpp index 068c8824..48003a7d 100644 --- a/src/logic/scripting/lua/libcore.cpp +++ b/src/logic/scripting/lua/libcore.cpp @@ -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(scripting::engine)); + engine->setScreen(std::make_shared(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(setting)) { lua_pushnumber(L, number->getMin()); diff --git a/src/logic/scripting/lua/libfile.cpp b/src/logic/scripting/lua/libfile.cpp index ecea4c23..85336add 100644 --- a/src/logic/scripting/lua/libfile.cpp +++ b/src/logic/scripting/lua/libfile.cpp @@ -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(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 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(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(fs::file_size(path)); diff --git a/src/logic/scripting/lua/libgui.cpp b/src/logic/scripting/lua/libgui.cpp index 13e9102a..e89b1046 100644 --- a/src/logic/scripting/lua/libgui.cpp +++ b/src/logic/scripting/lua/libgui.cpp @@ -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(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(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(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(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(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(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(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(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(node)) { - return state->pushboolean(box->isChecked()); + return lua::pushboolean(L, box->isChecked()); } else if (auto box = dynamic_cast(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(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(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(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(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(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(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(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(node)) { - return state->pushinteger(static_cast(box->getCaret())); + return lua::pushinteger(L, static_cast(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(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(node)) { - return state->pushstring(util::wstr2str_utf8(button->getText())); + return lua::pushwstring(L, button->getText()); } else if (auto label = dynamic_cast(node)) { - return state->pushstring(util::wstr2str_utf8(label->getText())); + return lua::pushwstring(L, label->getText()); } else if (auto box = dynamic_cast(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(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(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(node)) { - return state->pushcfunction(lua_wrap_errors); + return lua::pushcfunction(L, lua_wrap_errors); } return 0; } -static int p_get_destruct(UINode*) { - return state->pushcfunction(lua_wrap_errors); +static int p_get_destruct(UINode*, lua_State* L) { + return lua::pushcfunction(L, lua_wrap_errors); } -static int p_get_clear(UINode* node) { +static int p_get_clear(UINode* node, lua_State* L) { if (dynamic_cast(node)) { - return state->pushcfunction(lua_wrap_errors); + return lua::pushcfunction(L, lua_wrap_errors); } return 0; } -static int p_set_interval(UINode* node) { +static int p_set_interval(UINode* node, lua_State* L) { if (dynamic_cast(node)) { - return state->pushcfunction(lua_wrap_errors); + return lua::pushcfunction(L, lua_wrap_errors); } 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> getters { + static const std::unordered_map> 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(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(node)) { - label->setText(util::str2wstr_utf8(state->requireString(idx))); + label->setText(lua::require_wstring(L, idx)); } else if (auto button = dynamic_cast(node)) { - button->setText(util::str2wstr_utf8(state->requireString(idx))); + button->setText(lua::require_wstring(L, idx)); } else if (auto box = dynamic_cast(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(node)) { - box->setCaret(static_cast(state->tointeger(idx))); + box->setCaret(static_cast(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(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(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(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(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(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(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(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(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(node)) { - box->setChecked(state->toboolean(idx)); + box->setChecked(lua_toboolean(L, idx)); } else if (auto box = dynamic_cast(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(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(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 &node, int idx) { - if (state->toboolean(idx) && !node->isFocused()) { +static void p_set_focused(const std::shared_ptr &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 &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> setters { + static const std::unordered_map> 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,int)>> setters2 { + static const std::unordered_map,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"); diff --git a/src/logic/scripting/lua/libinput.cpp b/src/logic/scripting/lua/libinput.cpp index 309cc26b..5e9413ea 100644 --- a/src/logic/scripting/lua/libinput.cpp +++ b/src/logic/scripting/lua/libinput.cpp @@ -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(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(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(); diff --git a/src/logic/scripting/lua/libitem.cpp b/src/logic/scripting/lua/libitem.cpp index c8d6c11a..16d8d877 100644 --- a/src/logic/scripting/lua/libitem.cpp +++ b/src/logic/scripting/lua/libitem.cpp @@ -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(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(id) >= indices->countItemDefs()) { return 0; } auto def = indices->getItemDef(id); diff --git a/src/logic/scripting/lua/libjson.cpp b/src/logic/scripting/lua/libjson.cpp index 7d3be119..9cb316b4 100644 --- a/src/logic/scripting/lua/libjson.cpp +++ b/src/logic/scripting/lua/libjson.cpp @@ -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(&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); - scripting::state->pushvalue(element); + lua::pushvalue(L, element); return 1; } diff --git a/src/logic/scripting/lua/libtoml.cpp b/src/logic/scripting/lua/libtoml.cpp index 86411d42..29348eeb 100644 --- a/src/logic/scripting/lua/libtoml.cpp +++ b/src/logic/scripting/lua/libtoml.cpp @@ -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(&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); auto value = std::make_unique(element); - state->pushvalue(*value); + lua::pushvalue(L, *value); return 1; } diff --git a/src/logic/scripting/lua/lua_util.cpp b/src/logic/scripting/lua/lua_util.cpp new file mode 100644 index 00000000..24cee222 --- /dev/null +++ b/src/logic/scripting/lua/lua_util.cpp @@ -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(&value)) { + lua_pushboolean(L, *flag); + } else if (auto* num = std::get_if(&value)) { + lua_pushinteger(L, *num); + } else if (auto* num = std::get_if(&value)) { + lua_pushnumber(L, *num); + } else if (auto* str = std::get_if(&value)) { + lua_pushstring(L, str->c_str()); + } else if (auto listptr = std::get_if(&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(&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; +} diff --git a/src/logic/scripting/lua/lua_util.hpp b/src/logic/scripting/lua/lua_util.hpp index 799bd3d4..e9833c79 100644 --- a/src/logic/scripting/lua/lua_util.hpp +++ b/src/logic/scripting/lua/lua_util.hpp @@ -14,6 +14,23 @@ #include 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_ diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 493b6f91..18185ac7 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -17,6 +17,7 @@ #include "../../voxels/Block.hpp" #include "../../world/Level.hpp" #include "lua/LuaState.hpp" +#include "lua/lua_util.hpp" #include #include @@ -37,12 +38,12 @@ const ContentIndices* scripting::indices = nullptr; BlocksController* scripting::blocks = nullptr; LevelController* scripting::controller = nullptr; -void load_script(const fs::path& name) { +static void load_script(const fs::path& name) { auto paths = scripting::engine->getPaths(); fs::path file = paths->getResources()/fs::path("scripts")/name; std::string src = files::read_string(file); - state->execute(0, src, file.u8string()); + state->execute(state->getMainThread(), 0, src, file.u8string()); } void scripting::initialize(Engine* engine) { @@ -59,46 +60,49 @@ scriptenv scripting::get_root_environment() { } scriptenv scripting::create_pack_environment(const ContentPack& pack) { - int id = state->createEnvironment(0); - state->pushenv(id); - state->pushvalue(-1); - state->setfield("PACK_ENV"); - state->pushstring(pack.id); - state->setfield("PACK_ID"); - state->pop(); + auto L = state->getMainThread(); + int id = state->createEnvironment(L, 0); + state->pushenv(L, id); + lua::pushvalue(L, -1); + lua::setfield(L, "PACK_ENV"); + lua::pushstring(L, pack.id); + lua::setfield(L, "PACK_ID"); + lua::pop(L); return std::shared_ptr(new int(id), [=](int* id) { - state->removeEnvironment(*id); + state->removeEnvironment(L, *id); delete id; }); } scriptenv scripting::create_doc_environment(const scriptenv& parent, const std::string& name) { - int id = state->createEnvironment(*parent); - state->pushenv(id); - state->pushvalue(-1); - state->setfield("DOC_ENV"); - state->pushstring(name.c_str()); - state->setfield("DOC_NAME"); + auto L = state->getMainThread(); + int id = state->createEnvironment(L, *parent); + state->pushenv(L, id); + lua_pushvalue(L, -1); + lua::setfield(L, "DOC_ENV"); + lua::pushstring(L, name); + lua::setfield(L, "DOC_NAME"); - if (state->getglobal("Document")) { - if (state->getfield("new")) { - state->pushstring(name.c_str()); - if (state->callNoThrow(1)) { - state->setfield("document", -3); + if (lua::getglobal(L, "Document")) { + if (lua::getfield(L, "new")) { + lua::pushstring(L, name); + if (lua::callNoThrow(L, 1)) { + lua::setfield(L, "document", -3); } } - state->pop(); + lua::pop(L); } - state->pop(); + lua::pop(L); return std::shared_ptr(new int(id), [=](int* id) { - state->removeEnvironment(*id); + state->removeEnvironment(L, *id); delete id; }); } void scripting::process_post_runnables() { - if (state->getglobal("__process_post_runnables")) { - state->callNoThrow(0); + auto L = state->getMainThread(); + if (lua::getglobal(L, "__process_post_runnables")) { + lua::callNoThrow(L, 0); } } @@ -110,38 +114,42 @@ void scripting::on_world_load(LevelController* controller) { scripting::controller = controller; load_script("world.lua"); + auto L = state->getMainThread(); for (auto& pack : scripting::engine->getContentPacks()) { - state->emit_event(pack.id + ".worldopen"); + state->emitEvent(L, pack.id + ".worldopen"); } } void scripting::on_world_tick() { + auto L = state->getMainThread(); for (auto& pack : scripting::engine->getContentPacks()) { - state->emit_event(pack.id + ".worldtick"); + state->emitEvent(L, pack.id + ".worldtick"); } } void scripting::on_world_save() { + auto L = state->getMainThread(); for (auto& pack : scripting::engine->getContentPacks()) { - state->emit_event(pack.id + ".worldsave"); + state->emitEvent(L, pack.id + ".worldsave"); } } void scripting::on_world_quit() { + auto L = state->getMainThread(); for (auto& pack : scripting::engine->getContentPacks()) { - state->emit_event(pack.id + ".worldquit"); + state->emitEvent(L, pack.id + ".worldquit"); } - state->getglobal("pack"); + lua::getglobal(L, "pack"); for (auto& pack : scripting::engine->getContentPacks()) { - state->getfield("unload"); - state->pushstring(pack.id); - state->callNoThrow(1); + lua::getfield(L, "unload"); + lua::pushstring(L, pack.id); + lua::callNoThrow(L, 1); } - state->pop(); + lua::pop(L); - if (state->getglobal("__scripts_cleanup")) { - state->callNoThrow(0); + if (lua::getglobal(L, "__scripts_cleanup")) { + lua::callNoThrow(L, 0); } scripting::level = nullptr; scripting::content = nullptr; @@ -152,77 +160,73 @@ void scripting::on_world_quit() { void scripting::on_blocks_tick(const Block* block, int tps) { std::string name = block->name + ".blockstick"; - state->emit_event(name, [tps] (lua::LuaState* state) { - state->pushinteger(tps); - return 1; + state->emitEvent(state->getMainThread(), name, [tps] (lua_State* L) { + return lua::pushinteger(L, tps); }); } void scripting::update_block(const Block* block, int x, int y, int z) { std::string name = block->name + ".update"; - state->emit_event(name, [x, y, z] (lua::LuaState* state) { - state->pushivec3(x, y, z); - return 3; + state->emitEvent(state->getMainThread(), name, [x, y, z] (lua_State* L) { + return lua::pushivec3(L, x, y, z); }); } void scripting::random_update_block(const Block* block, int x, int y, int z) { std::string name = block->name + ".randupdate"; - state->emit_event(name, [x, y, z] (lua::LuaState* state) { - state->pushivec3(x, y, z); - return 3; + state->emitEvent(state->getMainThread(), name, [x, y, z] (lua_State* L) { + return lua::pushivec3(L, x, y, z); }); } void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) { std::string name = block->name + ".placed"; - state->emit_event(name, [x, y, z, player] (lua::LuaState* state) { - state->pushivec3(x, y, z); - state->pushinteger(player->getId()); - return 4; + state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) { + lua::pushivec3(L, x, y, z); + lua::pushinteger(L, player->getId()); + return 4; }); } void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) { std::string name = block->name + ".broken"; - state->emit_event(name, [x, y, z, player] (lua::LuaState* state) { - state->pushivec3(x, y, z); - state->pushinteger(player->getId()); + state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) { + lua::pushivec3(L, x, y, z); + lua::pushinteger(L, player->getId()); return 4; }); } bool scripting::on_block_interact(Player* player, const Block* block, glm::ivec3 pos) { std::string name = block->name + ".interact"; - return state->emit_event(name, [pos, player] (lua::LuaState* state) { - state->pushivec3(pos.x, pos.y, pos.z); - state->pushinteger(player->getId()); + return state->emitEvent(state->getMainThread(), name, [pos, player] (lua_State* L) { + lua::pushivec3(L, pos.x, pos.y, pos.z); + lua::pushinteger(L, player->getId()); return 4; }); } bool scripting::on_item_use(Player* player, const ItemDef* item) { std::string name = item->name + ".use"; - return state->emit_event(name, [player] (lua::LuaState* state) { - state->pushinteger(player->getId()); - return 1; + return state->emitEvent(state->getMainThread(), name, [player] (lua_State* L) { + return lua::pushinteger(L, player->getId()); }); } bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) { std::string name = item->name + ".useon"; - return state->emit_event(name, [x, y, z, player] (lua::LuaState* state) { - state->pushivec3(x, y, z); - state->pushinteger(player->getId()); + return state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) { + lua::pushivec3(L, x, y, z); + lua::pushinteger(L, player->getId()); return 4; }); } bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) { std::string name = item->name + ".blockbreakby"; - return state->emit_event(name, [x, y, z, player] (lua::LuaState* state) { - state->pushivec3(x, y, z); - state->pushinteger(player->getId()); + return state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) { + lua::pushivec3(L, x, y, z); + lua::pushinteger(L, player->getId()); return 4; }); } @@ -233,9 +237,9 @@ void scripting::on_ui_open( ) { auto argsptr = std::make_shared>(std::move(args)); std::string name = layout->getId() + ".open"; - state->emit_event(name, [=] (lua::LuaState* state) { + state->emitEvent(state->getMainThread(), name, [=] (lua_State* L) { for (const auto& value : *argsptr) { - state->pushvalue(value); + lua::pushvalue(L, value); } return argsptr->size(); }); @@ -243,37 +247,37 @@ void scripting::on_ui_open( void scripting::on_ui_progress(UiDocument* layout, int workDone, int workTotal) { std::string name = layout->getId() + ".progress"; - state->emit_event(name, [=] (lua::LuaState* state) { - state->pushinteger(workDone); - state->pushinteger(workTotal); + state->emitEvent(state->getMainThread(), name, [=] (lua_State* L) { + lua::pushinteger(L, workDone); + lua::pushinteger(L, workTotal); return 2; }); } void scripting::on_ui_close(UiDocument* layout, Inventory* inventory) { std::string name = layout->getId() + ".close"; - state->emit_event(name, [inventory] (lua::LuaState* state) { - state->pushinteger(inventory == nullptr ? 0 : inventory->getId()); - return 1; + state->emitEvent(state->getMainThread(), name, [inventory] (lua_State* L) { + return lua::pushinteger(L, inventory ? inventory->getId() : 0); }); } bool scripting::register_event(int env, const std::string& name, const std::string& id) { - if (state->pushenv(env) == 0) { - state->pushglobals(); + auto L = state->getMainThread(); + if (state->pushenv(L, env) == 0) { + lua::pushglobals(L); } - if (state->getfield(name)) { - state->pop(); - state->getglobal("events"); - state->getfield("on"); - state->pushstring(id); - state->getfield(name, -4); - state->callNoThrow(2); - state->pop(); + if (lua::getfield(L, name)) { + lua::pop(L); + lua::getglobal(L, "events"); + lua::getfield(L, "on"); + lua::pushstring(L, id); + lua::getfield(L, name, -4); + lua::callNoThrow(L, 2); + lua::pop(L); // remove previous name - state->pushnil(); - state->setfield(name); + lua::pushnil(L); + lua::setfield(L, name); return true; } return false; @@ -283,7 +287,7 @@ void scripting::load_block_script(const scriptenv& senv, const std::string& pref int env = *senv; std::string src = files::read_string(file); logger.info() << "script (block) " << file.u8string(); - state->execute(env, src, file.u8string()); + state->execute(state->getMainThread(), env, src, file.u8string()); funcsset.init = register_event(env, "init", prefix+".init"); funcsset.update = register_event(env, "on_update", prefix+".update"); funcsset.randupdate = register_event(env, "on_random_update", prefix+".randupdate"); @@ -297,7 +301,7 @@ void scripting::load_item_script(const scriptenv& senv, const std::string& prefi int env = *senv; std::string src = files::read_string(file); logger.info() << "script (item) " << file.u8string(); - state->execute(env, src, file.u8string()); + state->execute(state->getMainThread(), env, src, file.u8string()); funcsset.init = register_event(env, "init", prefix+".init"); funcsset.on_use = register_event(env, "on_use", prefix+".use"); @@ -311,8 +315,7 @@ void scripting::load_world_script(const scriptenv& senv, const std::string& pref std::string src = files::read_string(file); logger.info() << "loading world script for " << prefix; - state->loadbuffer(env, src, file.u8string()); - state->callNoThrow(0); + state->execute(state->getMainThread(), env, src, file.u8string()); register_event(env, "init", prefix+".init"); register_event(env, "on_world_open", prefix+".worldopen"); @@ -327,8 +330,7 @@ void scripting::load_layout_script(const scriptenv& senv, const std::string& pre std::string src = files::read_string(file); logger.info() << "loading script " << file.u8string(); - state->loadbuffer(env, src, file.u8string()); - state->callNoThrow(0); + state->execute(state->getMainThread(), env, src, file.u8string()); script.onopen = register_event(env, "on_open", prefix+".open"); script.onprogress = register_event(env, "on_progress", prefix+".progress"); script.onclose = register_event(env, "on_close", prefix+".close"); diff --git a/src/logic/scripting/scripting_functional.cpp b/src/logic/scripting/scripting_functional.cpp index 644b2b95..c381dc35 100644 --- a/src/logic/scripting/scripting_functional.cpp +++ b/src/logic/scripting/scripting_functional.cpp @@ -1,5 +1,6 @@ #include "scripting_functional.hpp" +#include "lua/lua_util.hpp" #include "lua/LuaState.hpp" #include "../../debug/Logger.hpp" #include "../../util/stringutil.hpp" @@ -17,26 +18,30 @@ runnable scripting::create_runnable( const std::string& src, const std::string& file ) { + auto L = state->getMainThread(); try { - state->loadbuffer(*env, src, file); - return state->createRunnable(); + state->loadbuffer(L, *env, src, file); + return state->createRunnable(L); } catch (const lua::luaerror& err) { logger.error() << err.what(); return [](){}; } } -static bool processCallback( +static lua_State* processCallback( const scriptenv& env, const std::string& src, const std::string& file ) { + auto L = state->getMainThread(); try { - return state->eval(*env, src, file) != 0; + if (state->eval(L, *env, src, file) != 0) { + return L; + } } catch (lua::luaerror& err) { logger.error() << err.what(); - return false; } + return nullptr; } wstringconsumer scripting::create_wstring_consumer( @@ -45,9 +50,9 @@ wstringconsumer scripting::create_wstring_consumer( const std::string& file ) { return [=](const std::wstring& x){ - if (processCallback(env, src, file)) { - state->pushstring(util::wstr2str_utf8(x)); - state->callNoThrow(1); + if (auto L = processCallback(env, src, file)) { + lua::pushwstring(L, x); + lua::callNoThrow(L, 1); } }; } @@ -58,12 +63,12 @@ wstringsupplier scripting::create_wstring_supplier( const std::string& file ) { return [=](){ - if (processCallback(env, src, file)) { - if (state->isfunction(-1)) { - state->callNoThrow(0); + if (auto L = processCallback(env, src, file)) { + if (lua_isfunction(L, -1)) { + lua::callNoThrow(L, 0); } - auto str = state->tostring(-1); state->pop(); - return util::str2wstr_utf8(str); + auto str = lua::require_wstring(L, -1); lua_pop(L, 1); + return str; } return std::wstring(L""); }; @@ -75,10 +80,10 @@ wstringchecker scripting::create_wstring_validator( const std::string& file ) { return [=](const std::wstring& x){ - if (processCallback(env, src, file)) { - state->pushstring(util::wstr2str_utf8(x)); - if (state->callNoThrow(1)) - return state->toboolean(-1); + if (auto L = processCallback(env, src, file)) { + lua::pushwstring(L, x); + if (lua::callNoThrow(L, 1)) + return lua::toboolean(L, -1); } return false; }; @@ -90,9 +95,9 @@ boolconsumer scripting::create_bool_consumer( const std::string& file ) { return [=](bool x){ - if (processCallback(env, src, file)) { - state->pushboolean(x); - state->callNoThrow(1); + if (auto L = processCallback(env, src, file)) { + lua::pushboolean(L, x); + lua::callNoThrow(L, 1); } }; } @@ -103,11 +108,11 @@ boolsupplier scripting::create_bool_supplier( const std::string& file ) { return [=](){ - if (processCallback(env, src, file)) { - if (state->isfunction(-1)) { - state->callNoThrow(0); + if (auto L = processCallback(env, src, file)) { + if (lua_isfunction(L, -1)) { + lua::callNoThrow(L, 0); } - bool x = state->toboolean(-1); state->pop(); + bool x = lua::toboolean(L,-1); lua_pop(L, 1); return x; } return false; @@ -120,9 +125,9 @@ doubleconsumer scripting::create_number_consumer( const std::string& file ) { return [=](double x){ - if (processCallback(env, src, file)) { - state->pushnumber(x); - state->callNoThrow(1); + if (auto L = processCallback(env, src, file)) { + lua::pushnumber(L, x); + lua::callNoThrow(L, 1); } }; } @@ -133,12 +138,12 @@ doublesupplier scripting::create_number_supplier( const std::string& file ) { return [=](){ - if (processCallback(env, src, file)) { - if (state->isfunction(-1)) { - state->callNoThrow(0); + if (auto L = processCallback(env, src, file)) { + if (lua_isfunction(L, -1)) { + lua::callNoThrow(L, 0); } - auto x = state->tonumber(-1); - state->pop(); + auto x = lua_tonumber(L, -1); + lua::pop(L); return x; } return 0.0; @@ -150,12 +155,12 @@ int_array_consumer scripting::create_int_array_consumer( const std::string& src, const std::string& file ) { - return [=](const int arr[], size_t len){ - if (processCallback(env, src, file)) { + return [=](const int arr[], size_t len) { + if (auto L = processCallback(env, src, file)) { for (uint i = 0; i < len; i++) { - state->pushinteger(arr[i]); + lua::pushinteger(L, arr[i]); } - state->callNoThrow(len); + lua::callNoThrow(L, len); } }; } @@ -165,13 +170,13 @@ vec2supplier scripting::create_vec2_supplier( const std::string& src, const std::string& file ) { - return [=](){ - if (processCallback(env, src, file)) { - if (state->isfunction(-1)) { - state->callNoThrow(0); + return [=]() { + if (auto L = processCallback(env, src, file)) { + if (lua_isfunction(L, -1)) { + lua::callNoThrow(L, 0); } - auto y = state->tonumber(-1); state->pop(); - auto x = state->tonumber(-1); state->pop(); + auto y = lua_tonumber(L, -1); lua::pop(L); + auto x = lua_tonumber(L, -1); lua::pop(L); return glm::vec2(x, y); } return glm::vec2(0, 0); diff --git a/src/logic/scripting/scripting_hud.cpp b/src/logic/scripting/scripting_hud.cpp index 2c78973b..c1853dad 100644 --- a/src/logic/scripting/scripting_hud.cpp +++ b/src/logic/scripting/scripting_hud.cpp @@ -1,6 +1,7 @@ #include "scripting_hud.hpp" #include "scripting.hpp" +#include "lua/lua_util.hpp" #include "lua/api_lua.hpp" #include "lua/LuaState.hpp" @@ -13,6 +14,7 @@ namespace scripting { extern lua::LuaState* state; } +using namespace scripting; static debug::Logger logger("scripting-hud"); @@ -20,21 +22,21 @@ Hud* scripting::hud = nullptr; void scripting::on_frontend_init(Hud* hud) { scripting::hud = hud; - scripting::state->openlib("hud", hudlib); + state->openlib(state->getMainThread(), "hud", hudlib); for (auto& pack : scripting::engine->getContentPacks()) { - state->emit_event(pack.id + ".hudopen", [&] (lua::LuaState* state) { - state->pushinteger(hud->getPlayer()->getId()); - return 1; + state->emitEvent(state->getMainThread(), pack.id + ".hudopen", + [&] (lua_State* L) { + return lua::pushinteger(L, hud->getPlayer()->getId()); }); } } void scripting::on_frontend_close() { for (auto& pack : scripting::engine->getContentPacks()) { - state->emit_event(pack.id + ".hudclose", [&] (lua::LuaState* state) { - state->pushinteger(hud->getPlayer()->getId()); - return 1; + state->emitEvent(state->getMainThread(), pack.id + ".hudclose", + [&] (lua_State* L) { + return lua::pushinteger(L, hud->getPlayer()->getId()); }); } scripting::hud = nullptr; @@ -45,8 +47,9 @@ void scripting::load_hud_script(const scriptenv& senv, const std::string& packid std::string src = files::read_string(file); logger.info() << "loading script " << file.u8string(); - state->loadbuffer(env, src, file.u8string()); - state->callNoThrow(0); + auto L = state->getMainThread(); + state->loadbuffer(L, env, src, file.u8string()); + lua::callNoThrow(L, 0); register_event(env, "init", packid+".init"); register_event(env, "on_hud_open", packid+".hudopen");