fix: lua coroutines support

This commit is contained in:
MihailRis 2024-06-11 01:52:28 +03:00
parent 590f9757c0
commit 7973a9c32b
15 changed files with 707 additions and 740 deletions

View File

@ -21,11 +21,11 @@ namespace scripting {
luaerror::luaerror(const std::string& message) : std::runtime_error(message) { luaerror::luaerror(const std::string& message) : std::runtime_error(message) {
} }
void LuaState::removeLibFuncs(const char* libname, const char* funcs[]) { void LuaState::removeLibFuncs(lua_State* L, const char* libname, const char* funcs[]) {
if (getglobal(libname)) { if (getglobal(L, libname)) {
for (uint i = 0; funcs[i]; i++) { for (uint i = 0; funcs[i]; i++) {
pushnil(); lua_pushnil(L);
setfield(funcs[i], -2); setfield(L, funcs[i], -2);
} }
} }
} }
@ -34,10 +34,11 @@ LuaState::LuaState() {
logger.info() << LUA_VERSION; logger.info() << LUA_VERSION;
logger.info() << LUAJIT_VERSION; logger.info() << LUAJIT_VERSION;
L = luaL_newstate(); auto L = luaL_newstate();
if (L == nullptr) { if (L == nullptr) {
throw luaerror("could not to initialize Lua"); throw luaerror("could not to initialize Lua");
} }
mainThread = L;
// Allowed standard libraries // Allowed standard libraries
luaopen_base(L); luaopen_base(L);
luaopen_math(L); luaopen_math(L);
@ -57,15 +58,15 @@ LuaState::LuaState() {
"tmpname", "tmpname",
nullptr nullptr
}; };
removeLibFuncs("os", removed_os); removeLibFuncs(L, "os", removed_os);
createLibs(); createLibs(L);
lua_pushvalue(L, LUA_GLOBALSINDEX); pushglobals(L);
setglobal(envName(0)); setglobal(L, envName(0));
lua_createtable(L, 0, 0); lua_createtable(L, 0, 0);
setglobal(LAMBDAS_TABLE); setglobal(L, LAMBDAS_TABLE);
} }
std::string LuaState::envName(int env) { std::string LuaState::envName(int env) {
@ -73,42 +74,15 @@ std::string LuaState::envName(int env) {
} }
LuaState::~LuaState() { LuaState::~LuaState() {
lua_close(L); lua_close(mainThread);
} }
void LuaState::logError(const std::string& text) { void LuaState::addfunc(lua_State* L, const std::string& name, lua_CFunction func) {
logger.error() << text;
}
void LuaState::addfunc(const std::string& name, lua_CFunction func) {
lua_pushcfunction(L, func); lua_pushcfunction(L, func);
lua_setglobal(L, name.c_str()); lua_setglobal(L, name.c_str());
} }
bool LuaState::getglobal(const std::string& name) { bool LuaState::rename(lua_State* L, const std::string& from, const std::string& to) {
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) {
const char* src = from.c_str(); const char* src = from.c_str();
lua_getglobal(L, src); lua_getglobal(L, src);
if (lua_isnil(L, lua_gettop(L))) { if (lua_isnil(L, lua_gettop(L))) {
@ -123,262 +97,65 @@ bool LuaState::rename(const std::string& from, const std::string& to) {
return true; return true;
} }
void LuaState::remove(const std::string& name) { void LuaState::remove(lua_State* L, const std::string& name) {
lua_pushnil(L); lua_pushnil(L);
lua_setglobal(L, name.c_str()); lua_setglobal(L, name.c_str());
} }
void LuaState::createLibs() { void LuaState::createLibs(lua_State* L) {
openlib("audio", audiolib); openlib(L, "audio", audiolib);
openlib("block", blocklib); openlib(L, "block", blocklib);
openlib("console", consolelib); openlib(L, "console", consolelib);
openlib("core", corelib); openlib(L, "core", corelib);
openlib("file", filelib); openlib(L, "file", filelib);
openlib("gui", guilib); openlib(L, "gui", guilib);
openlib("input", inputlib); openlib(L, "input", inputlib);
openlib("inventory", inventorylib); openlib(L, "inventory", inventorylib);
openlib("item", itemlib); openlib(L, "item", itemlib);
openlib("json", jsonlib); openlib(L, "json", jsonlib);
openlib("pack", packlib); openlib(L, "pack", packlib);
openlib("player", playerlib); openlib(L, "player", playerlib);
openlib("time", timelib); openlib(L, "time", timelib);
openlib("toml", tomllib); openlib(L, "toml", tomllib);
openlib("world", worldlib); 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())) { if (luaL_loadbuffer(L, src.c_str(), src.length(), file.c_str())) {
throw luaerror(lua_tostring(L, -1)); throw luaerror(lua_tostring(L, -1));
} }
if (env && getglobal(envName(env))) { if (env && getglobal(L, envName(env))) {
lua_setfenv(L, -2); lua_setfenv(L, -2);
} }
} }
int LuaState::call(int argc, int nresults) { int LuaState::eval(lua_State* L, int env, const std::string& src, const std::string& file) {
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) {
auto srcText = "return "+src; auto srcText = "return "+src;
loadbuffer(env, srcText, file); loadbuffer(L, env, srcText, file);
return call(0); return call(L, 0);
} }
int LuaState::execute(int env, const std::string& src, const std::string& file) { int LuaState::execute(lua_State* L, int env, const std::string& src, const std::string& file) {
loadbuffer(env, src, file); loadbuffer(L, env, src, file);
return callNoThrow(0); return callNoThrow(L, 0);
} }
int LuaState::gettop() const { int LuaState::pushenv(lua_State* L, int env) {
return lua_gettop(L); if (getglobal(L, envName(env))) {
}
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))) {
return 1; return 1;
} }
return 0; return 0;
} }
int LuaState::pushvalue(int idx) { void LuaState::openlib(lua_State* L, const std::string& name, const luaL_Reg* libfuncs) {
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) {
lua_newtable(L); lua_newtable(L);
luaL_setfuncs(L, libfuncs, 0); luaL_setfuncs(L, libfuncs, 0);
lua_setglobal(L, name.c_str()); 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 ptr = reinterpret_cast<ptrdiff_t>(lua_topointer(L, -1));
auto name = util::mangleid(ptr); auto name = util::mangleid(ptr);
lua_getglobal(L, LAMBDAS_TABLE.c_str()); lua_getglobal(L, LAMBDAS_TABLE.c_str());
@ -395,40 +172,33 @@ std::shared_ptr<std::string> LuaState::createLambdaHandler() {
}); });
} }
runnable LuaState::createRunnable() { runnable LuaState::createRunnable(lua_State* L) {
auto funcptr = createLambdaHandler(); auto funcptr = createLambdaHandler(L);
return [=]() { return [=]() {
lua_getglobal(L, LAMBDAS_TABLE.c_str()); lua_getglobal(L, LAMBDAS_TABLE.c_str());
lua_getfield(L, -1, funcptr->c_str()); lua_getfield(L, -1, funcptr->c_str());
callNoThrow(0); callNoThrow(L, 0);
}; };
} }
scripting::common_func LuaState::createLambda() { scripting::common_func LuaState::createLambda(lua_State* L) {
auto funcptr = createLambdaHandler(); auto funcptr = createLambdaHandler(L);
return [=](const std::vector<dynamic::Value>& args) { return [=](const std::vector<dynamic::Value>& args) {
lua_getglobal(L, LAMBDAS_TABLE.c_str()); lua_getglobal(L, LAMBDAS_TABLE.c_str());
lua_getfield(L, -1, funcptr->c_str()); lua_getfield(L, -1, funcptr->c_str());
for (const auto& arg : args) { for (const auto& arg : args) {
pushvalue(arg); pushvalue(L, arg);
} }
if (call(args.size(), 1)) { if (call(L, args.size(), 1)) {
auto result = tovalue(-1); auto result = tovalue(L, -1);
pop(1); lua_pop(L, 1);
return result; return result;
} }
return dynamic::Value(dynamic::NONE); return dynamic::Value(dynamic::NONE);
}; };
} }
const char* LuaState::requireString(int idx) { int LuaState::createEnvironment(lua_State* L, int parent) {
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 id = nextEnvironment++; int id = nextEnvironment++;
// local env = {} // local env = {}
@ -439,7 +209,7 @@ int LuaState::createEnvironment(int parent) {
if (parent == 0) { if (parent == 0) {
lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushvalue(L, LUA_GLOBALSINDEX);
} else { } else {
if (pushenv(parent) == 0) { if (pushenv(L, parent) == 0) {
lua_pushvalue(L, LUA_GLOBALSINDEX); lua_pushvalue(L, LUA_GLOBALSINDEX);
} }
} }
@ -447,43 +217,43 @@ int LuaState::createEnvironment(int parent) {
lua_setmetatable(L, -2); lua_setmetatable(L, -2);
// envname = env // envname = env
setglobal(envName(id)); setglobal(L, envName(id));
return id; return id;
} }
void LuaState::removeEnvironment(int id) { void LuaState::removeEnvironment(lua_State* L, int id) {
if (id == 0) { if (id == 0) {
return; return;
} }
lua_pushnil(L); lua_pushnil(L);
setglobal(envName(id)); setglobal(L, envName(id));
} }
bool LuaState::emit_event(const std::string &name, std::function<int(LuaState *)> args) { bool LuaState::emitEvent(lua_State* L, const std::string &name, std::function<int(lua_State*)> args) {
getglobal("events"); getglobal(L, "events");
getfield("emit"); getfield(L, "emit");
pushstring(name); lua::pushstring(L, name);
callNoThrow(args(this) + 1); callNoThrow(L, args(L) + 1);
bool result = toboolean(-1); bool result = lua_toboolean(L, -1);
pop(2); lua_pop(L, 2);
return result; return result;
} }
void LuaState::dumpStack() { void LuaState::dumpStack(lua_State* L) {
int top = gettop(); int top = lua_gettop(L);
for (int i = 1; i <= top; i++) { for (int i = 1; i <= top; i++) {
std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30); std::cout << std::setw(3) << i << std::setw(20) << luaL_typename(L, i) << std::setw(30);
switch (lua_type(L, i)) { switch (lua_type(L, i)) {
case LUA_TNUMBER: case LUA_TNUMBER:
std::cout << tonumber(i); std::cout << lua_tonumber(L, i);
break; break;
case LUA_TSTRING: case LUA_TSTRING:
std::cout << tostring(i); std::cout << lua_tostring(L, i);
break; break;
case LUA_TBOOLEAN: case LUA_TBOOLEAN:
std::cout << (toboolean(i) ? "true" : "false"); std::cout << (lua_toboolean(L, i) ? "true" : "false");
break; break;
case LUA_TNIL: case LUA_TNIL:
std::cout << "nil"; std::cout << "nil";
@ -496,6 +266,6 @@ void LuaState::dumpStack() {
} }
} }
lua_State* LuaState::getLua() const { lua_State* LuaState::getMainThread() const {
return L; return mainThread;
} }

View File

@ -17,65 +17,35 @@ namespace lua {
}; };
class LuaState { class LuaState {
lua_State* L; lua_State* mainThread;
int nextEnvironment = 1; int nextEnvironment = 1;
void logError(const std::string& text); void removeLibFuncs(lua_State*, const char* libname, const char* funcs[]);
void removeLibFuncs(const char* libname, const char* funcs[]); void createLibs(lua_State* L);
void createLibs();
std::shared_ptr<std::string> createLambdaHandler(); std::shared_ptr<std::string> createLambdaHandler(lua_State*);
public: public:
LuaState(); LuaState();
~LuaState(); ~LuaState();
static std::string envName(int env); static std::string envName(int env);
void loadbuffer(int env, const std::string& src, const std::string& file); void loadbuffer(lua_State*, int env, const std::string& src, const std::string& file);
int gettop() const; int pushenv(lua_State*, int env);
int pushivec3(lua_Integer x, lua_Integer y, lua_Integer z); int execute(lua_State*, int env, const std::string& src, const std::string& file="<string>");
int pushinteger(lua_Integer x); int eval(lua_State*, int env, const std::string& src, const std::string& file="<eval>");
int pushnumber(lua_Number x); void openlib(lua_State*, const std::string& name, const luaL_Reg* libfuncs);
int pushboolean(bool x); void addfunc(lua_State*, const std::string& name, lua_CFunction func);
int pushstring(const std::string& str); bool rename(lua_State*, const std::string& from, const std::string& to);
int pushenv(int env); void remove(lua_State*, const std::string& name);;
int pushvalue(int idx); runnable createRunnable(lua_State*);
int pushvalue(const dynamic::Value& value); scripting::common_func createLambda(lua_State*);
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();
const char* requireString(int idx); int createEnvironment(lua_State*, int parent);
void removeEnvironment(lua_State*, int id);
int createEnvironment(int parent); bool emitEvent(lua_State*, const std::string& name, std::function<int(lua_State*)> args=[](auto*){return 0;});
void removeEnvironment(int id); void dumpStack(lua_State*);
bool emit_event(const std::string& name, std::function<int(lua::LuaState*)> args=[](auto*){return 0;}); lua_State* getMainThread() const;
void dumpStack();
lua_State* getLua() const;
}; };
} }

View File

@ -1,5 +1,6 @@
#include "api_lua.hpp" #include "api_lua.hpp"
#include "lua_commons.hpp" #include "lua_commons.hpp"
#include "lua_util.hpp"
#include "LuaState.hpp" #include "LuaState.hpp"
#include "../scripting.hpp" #include "../scripting.hpp"
@ -17,10 +18,10 @@ static int l_add_command(lua_State* L) {
if (!lua_isfunction(L, 3)) { if (!lua_isfunction(L, 3)) {
throw std::runtime_error("invalid callback"); throw std::runtime_error("invalid callback");
} }
auto scheme = state->requireString(1); auto scheme = lua::require_string(L, 1);
auto description = state->requireString(2); auto description = lua::require_string(L, 2);
lua_pushvalue(L, 3); lua_pushvalue(L, 3);
auto func = state->createLambda(); auto func = state->createLambda(L);
try { try {
engine->getCommandsInterpreter()->getRepository()->add( engine->getCommandsInterpreter()->getRepository()->add(
scheme, description, [func](auto, auto args, auto kwargs) { scheme, description, [func](auto, auto args, auto kwargs) {
@ -33,16 +34,16 @@ static int l_add_command(lua_State* L) {
return 0; return 0;
} }
static int l_execute(lua_State*) { static int l_execute(lua_State* L) {
auto prompt = state->requireString(1); auto prompt = lua::require_string(L, 1);
auto result = engine->getCommandsInterpreter()->execute(prompt); auto result = engine->getCommandsInterpreter()->execute(prompt);
state->pushvalue(result); lua::pushvalue(L, result);
return 1; return 1;
} }
static int l_set(lua_State*) { static int l_set(lua_State* L) {
auto name = state->requireString(1); auto name = lua::require_string(L, 1);
auto value = state->tovalue(2); auto value = lua::tovalue(L, 2);
(*engine->getCommandsInterpreter())[name] = value; (*engine->getCommandsInterpreter())[name] = value;
return 0; return 0;
} }
@ -62,7 +63,7 @@ static int l_get_commands_list(lua_State* L) {
} }
static int l_get_command_info(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 interpreter = engine->getCommandsInterpreter();
auto repo = interpreter->getRepository(); auto repo = interpreter->getRepository();
auto command = repo->get(name); auto command = repo->get(name);

View File

@ -1,4 +1,5 @@
#include "lua_commons.hpp" #include "lua_commons.hpp"
#include "lua_util.hpp"
#include "api_lua.hpp" #include "api_lua.hpp"
#include "LuaState.hpp" #include "LuaState.hpp"
@ -21,48 +22,49 @@
namespace scripting { namespace scripting {
extern lua::LuaState* state; extern lua::LuaState* state;
} }
using namespace scripting;
static int l_new_world(lua_State* L) { static int l_new_world(lua_State* L) {
auto name = lua_tostring(L, 1); auto name = lua::require_string(L, 1);
auto seed = lua_tostring(L, 2); auto seed = lua::require_string(L, 2);
auto generator = lua_tostring(L, 3); auto generator = lua::require_string(L, 3);
auto controller = scripting::engine->getController(); auto controller = engine->getController();
controller->createWorld(name, seed, generator); controller->createWorld(name, seed, generator);
return 0; return 0;
} }
static int l_open_world(lua_State* L) { 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); controller->openWorld(name, false);
return 0; return 0;
} }
static int l_reopen_world(lua_State*) { static int l_reopen_world(lua_State*) {
auto controller = scripting::engine->getController(); auto controller = engine->getController();
controller->reopenWorld(scripting::level->getWorld()); controller->reopenWorld(level->getWorld());
return 0; return 0;
} }
static int l_close_world(lua_State* L) { static int l_close_world(lua_State* L) {
if (scripting::controller == nullptr) { if (controller == nullptr) {
throw std::runtime_error("no world open"); throw std::runtime_error("no world open");
} }
bool save_world = lua_toboolean(L, 1); bool save_world = lua_toboolean(L, 1);
if (save_world) { if (save_world) {
scripting::controller->saveWorld(); controller->saveWorld();
} }
// destroy LevelScreen and run quit callbacks // destroy LevelScreen and run quit callbacks
scripting::engine->setScreen(nullptr); engine->setScreen(nullptr);
// create and go to menu screen // create and go to menu screen
scripting::engine->setScreen(std::make_shared<MenuScreen>(scripting::engine)); engine->setScreen(std::make_shared<MenuScreen>(engine));
return 0; return 0;
} }
static int l_delete_world(lua_State* L) { static int l_delete_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->deleteWorld(name); controller->deleteWorld(name);
return 0; return 0;
} }
@ -95,35 +97,35 @@ static int l_reconfig_packs(lua_State* L) {
remPacks.emplace_back(lua_tostring(L, -1)); remPacks.emplace_back(lua_tostring(L, -1));
lua_pop(L, 1); lua_pop(L, 1);
} }
auto controller = scripting::engine->getController(); auto engine_controller = engine->getController();
controller->reconfigPacks(scripting::controller, addPacks, remPacks); engine_controller->reconfigPacks(controller, addPacks, remPacks);
return 0; return 0;
} }
static int l_get_setting(lua_State* L) { static int l_get_setting(lua_State* L) {
auto name = lua_tostring(L, 1); auto name = lua::require_string(L, 1);
const auto value = scripting::engine->getSettingsHandler().getValue(name); const auto value = engine->getSettingsHandler().getValue(name);
scripting::state->pushvalue(value); lua::pushvalue(L, value);
return 1; return 1;
} }
static int l_set_setting(lua_State* L) { static int l_set_setting(lua_State* L) {
auto name = lua_tostring(L, 1); auto name = lua::require_string(L, 1);
const auto value = scripting::state->tovalue(2); const auto value = lua::tovalue(L, 2);
scripting::engine->getSettingsHandler().setValue(name, value); engine->getSettingsHandler().setValue(name, value);
return 0; return 0;
} }
static int l_str_setting(lua_State* L) { static int l_str_setting(lua_State* L) {
auto name = lua_tostring(L, 1); auto name = lua::require_string(L, 1);
const auto string = scripting::engine->getSettingsHandler().toString(name); const auto string = engine->getSettingsHandler().toString(name);
scripting::state->pushstring(string); lua::pushstring(L, string);
return 1; return 1;
} }
static int l_get_setting_info(lua_State* L) { static int l_get_setting_info(lua_State* L) {
auto name = lua_tostring(L, 1); auto name = lua::require_string(L, 1);
auto setting = scripting::engine->getSettingsHandler().getSetting(name); auto setting = engine->getSettingsHandler().getSetting(name);
lua_createtable(L, 0, 1); lua_createtable(L, 0, 1);
if (auto number = dynamic_cast<NumberSetting*>(setting)) { if (auto number = dynamic_cast<NumberSetting*>(setting)) {
lua_pushnumber(L, number->getMin()); lua_pushnumber(L, number->getMin());

View File

@ -1,4 +1,5 @@
#include "lua_commons.hpp" #include "lua_commons.hpp"
#include "lua_util.hpp"
#include "api_lua.hpp" #include "api_lua.hpp"
#include "LuaState.hpp" #include "LuaState.hpp"
#include "../scripting.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) { static int l_file_find(lua_State* L) {
std::string path = state->requireString(1); auto path = lua::require_string(L, 1);
try { try {
lua_pushstring(L, engine->getResPaths()->findRaw(path).c_str()); lua_pushstring(L, engine->getResPaths()->findRaw(path).c_str());
return 1; return 1;
@ -41,13 +42,13 @@ static int l_file_find(lua_State* L) {
} }
static int l_file_resolve(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()); lua_pushstring(L, path.u8string().c_str());
return 1; return 1;
} }
static int l_file_read(lua_State* L) { 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)) { if (fs::is_regular_file(path)) {
lua_pushstring(L, files::read_string(path).c_str()); lua_pushstring(L, files::read_string(path).c_str());
return 1; 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())); throw std::runtime_error("file does not exists "+util::quote(path.u8string()));
} }
static int l_file_write(lua_State*) { static int l_file_write(lua_State* L) {
fs::path path = resolve_path(state->requireString(1)); fs::path path = resolve_path(lua::require_string(L, 1));
auto text = state->requireString(2); std::string text = lua::require_string(L, 2);
files::write_string(path, text); files::write_string(path, text);
return 1; return 1;
} }
static int l_file_remove(lua_State*) { static int l_file_remove(lua_State* L) {
std::string rawpath = state->requireString(1); std::string rawpath = lua::require_string(L, 1);
fs::path path = resolve_path(rawpath); fs::path path = resolve_path(rawpath);
auto entryPoint = rawpath.substr(0, rawpath.find(':')); auto entryPoint = rawpath.substr(0, rawpath.find(':'));
if (entryPoint != "world") { if (entryPoint != "world") {
throw std::runtime_error("access denied"); 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*) { static int l_file_remove_tree(lua_State* L) {
std::string rawpath = state->requireString(1); std::string rawpath = lua::require_string(L, 1);
fs::path path = resolve_path(rawpath); fs::path path = resolve_path(rawpath);
auto entryPoint = rawpath.substr(0, rawpath.find(':')); auto entryPoint = rawpath.substr(0, rawpath.find(':'));
if (entryPoint != "world") { if (entryPoint != "world") {
throw std::runtime_error("access denied"); 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*) { static int l_file_exists(lua_State* L) {
fs::path path = resolve_path_soft(state->requireString(1)); fs::path path = resolve_path_soft(lua::require_string(L, 1));
return state->pushboolean(fs::exists(path)); return lua::pushboolean(L, fs::exists(path));
} }
static int l_file_isfile(lua_State*) { static int l_file_isfile(lua_State* L) {
fs::path path = resolve_path_soft(state->requireString(1)); fs::path path = resolve_path_soft(lua::require_string(L, 1));
return state->pushboolean(fs::is_regular_file(path)); return lua::pushboolean(L, fs::is_regular_file(path));
} }
static int l_file_isdir(lua_State*) { static int l_file_isdir(lua_State* L) {
fs::path path = resolve_path_soft(state->requireString(1)); fs::path path = resolve_path_soft(lua::require_string(L, 1));
return state->pushboolean(fs::is_directory(path)); return lua::pushboolean(L, fs::is_directory(path));
} }
static int l_file_length(lua_State* L) { 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)){ if (fs::exists(path)){
lua_pushinteger(L, fs::file_size(path)); lua_pushinteger(L, fs::file_size(path));
} else { } else {
@ -108,19 +109,17 @@ static int l_file_length(lua_State* L) {
} }
static int l_file_mkdir(lua_State* L) { static int l_file_mkdir(lua_State* L) {
fs::path path = resolve_path(state->requireString(1)); fs::path path = resolve_path(lua::require_string(L, 1));
lua_pushboolean(L, fs::create_directory(path)); return lua::pushboolean(L, fs::create_directory(path));
return 1;
} }
static int l_file_mkdirs(lua_State* L) { static int l_file_mkdirs(lua_State* L) {
fs::path path = resolve_path(state->requireString(1)); fs::path path = resolve_path(lua::require_string(L, 1));
lua_pushboolean(L, fs::create_directories(path)); return lua::pushboolean(L, fs::create_directories(path));
return 1;
} }
static int l_file_read_bytes(lua_State* L) { 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)) { if (fs::is_regular_file(path)) {
size_t length = static_cast<size_t>(fs::file_size(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"); 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; std::vector<ubyte> bytes;
@ -171,8 +170,7 @@ static int l_file_write_bytes(lua_State* L) {
if(result != 1) { if(result != 1) {
return result; return result;
} else { } else {
lua_pushboolean(L, files::write_bytes(path, bytes.data(), bytes.size())); return lua::pushboolean(L, files::write_bytes(path, bytes.data(), bytes.size()));
return 1;
} }
} }
@ -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) { 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) { if (dirname.find(':') == std::string::npos) {
return l_file_list_all_res(L, dirname); 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) { 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)) { if (fs::is_regular_file(path)) {
size_t length = static_cast<size_t>(fs::file_size(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) { 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)) { if (fs::is_regular_file(path)) {
size_t length = static_cast<size_t>(fs::file_size(path)); size_t length = static_cast<size_t>(fs::file_size(path));

View File

@ -50,8 +50,8 @@ static DocumentNode getDocumentNode(lua_State*, const std::string& name, const s
static DocumentNode getDocumentNode(lua_State* L, int idx=1) { static DocumentNode getDocumentNode(lua_State* L, int idx=1) {
lua_getfield(L, idx, "docname"); lua_getfield(L, idx, "docname");
lua_getfield(L, idx, "name"); lua_getfield(L, idx, "name");
auto docname = state->requireString(-2); auto docname = lua::require_string(L, -2);
auto name = state->requireString(-1); auto name = lua::require_string(L, -1);
auto node = getDocumentNode(L, docname, name); auto node = getDocumentNode(L, docname, name);
lua_pop(L, 2); lua_pop(L, 2);
return node; return node;
@ -74,7 +74,7 @@ static int l_menu_reset(lua_State* L) {
static int l_textbox_paste(lua_State* L) { static int l_textbox_paste(lua_State* L) {
auto node = getDocumentNode(L); auto node = getDocumentNode(L);
auto box = dynamic_cast<TextBox*>(node.node.get()); 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)); box->paste(util::str2wstr_utf8(text));
return 0; return 0;
} }
@ -82,7 +82,7 @@ static int l_textbox_paste(lua_State* L) {
static int l_container_add(lua_State* L) { static int l_container_add(lua_State* L) {
auto docnode = getDocumentNode(L); auto docnode = getDocumentNode(L);
auto node = dynamic_cast<Container*>(docnode.node.get()); auto node = dynamic_cast<Container*>(docnode.node.get());
auto xmlsrc = state->requireString(2); auto xmlsrc = lua::require_string(L, 2);
try { try {
auto subnode = guiutil::create(xmlsrc, docnode.document->getEnvironment()); auto subnode = guiutil::create(xmlsrc, docnode.document->getEnvironment());
node->add(subnode); node->add(subnode);
@ -115,10 +115,10 @@ static int l_container_clear(lua_State* L) {
static int l_container_set_interval(lua_State* L) { static int l_container_set_interval(lua_State* L) {
auto node = getDocumentNode(L, 1); 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)) { if (auto container = std::dynamic_pointer_cast<Container>(node.node)) {
state->pushvalue(3); lua_pushvalue(L, 3);
auto runnable = state->createRunnable(); auto runnable = state->createRunnable(L);
container->listenInterval(interval, runnable); container->listenInterval(interval, runnable);
} }
return 0; return 0;
@ -131,212 +131,212 @@ static int l_move_into(lua_State* L) {
return 0; 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)) { if (auto inventory = dynamic_cast<InventoryView*>(node)) {
auto inv = inventory->getInventory(); auto inv = inventory->getInventory();
return state->pushinteger(inv ? inv->getId() : 0); return lua::pushinteger(L, inv ? inv->getId() : 0);
} }
return 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)) { if (dynamic_cast<Menu*>(node)) {
return state->pushcfunction(l_menu_reset); return lua::pushcfunction(L, l_menu_reset);
} }
return 0; return 0;
} }
static int p_get_back(UINode* node) { static int p_get_back(UINode* node, lua_State* L) {
if (dynamic_cast<Menu*>(node)) { if (dynamic_cast<Menu*>(node)) {
return state->pushcfunction(l_menu_back); return lua::pushcfunction(L, l_menu_back);
} }
return 0; return 0;
} }
static int p_get_paste(UINode* node) { static int p_get_paste(UINode* node, lua_State* L) {
if (dynamic_cast<TextBox*>(node)) { if (dynamic_cast<TextBox*>(node)) {
return state->pushcfunction(l_textbox_paste); return lua::pushcfunction(L, l_textbox_paste);
} }
return 0; 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)) { if (auto menu = dynamic_cast<Menu*>(node)) {
return state->pushstring(menu->getCurrent().name); return lua::pushstring(L, menu->getCurrent().name);
} }
return 0; 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)) { 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)) { } else if (auto box = dynamic_cast<FullCheckBox*>(node)) {
return state->pushboolean(box->isChecked()); return lua::pushboolean(L, box->isChecked());
} }
return 0; 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)) { if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getValue()); return lua::pushnumber(L, bar->getValue());
} }
return 0; 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)) { if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getMin()); return lua::pushnumber(L, bar->getMin());
} }
return 0; 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)) { if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getMax()); return lua::pushnumber(L, bar->getMax());
} }
return 0; 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)) { if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getStep()); return lua::pushnumber(L, bar->getStep());
} }
return 0; 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)) { if (auto bar = dynamic_cast<TrackBar*>(node)) {
return state->pushnumber(bar->getTrackWidth()); return lua::pushnumber(L, bar->getTrackWidth());
} }
return 0; 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)) { if (auto bar = dynamic_cast<TrackBar*>(node)) {
return lua::pushcolor_arr(state->getLua(), bar->getTrackColor()); return lua::pushcolor_arr(L, bar->getTrackColor());
} }
return 0; 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)) { if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushboolean(box->validate()); return lua::pushboolean(L, box->validate());
} }
return 0; 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)) { 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; 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)) { if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushstring(util::wstr2str_utf8(box->getPlaceholder())); return lua::pushwstring(L, box->getPlaceholder());
} }
return 0; 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)) { 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)) { } 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)) { } else if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushstring(util::wstr2str_utf8(box->getText())); return lua::pushwstring(L, box->getText());
} }
return 0; 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)) { if (auto box = dynamic_cast<TextBox*>(node)) {
return state->pushboolean(box->isEditable()); return lua::pushboolean(L, box->isEditable());
} }
return 0; 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)) { if (auto image = dynamic_cast<Image*>(node)) {
return state->pushstring(image->getTexture()); return lua::pushstring(L, image->getTexture());
} }
return 0; return 0;
} }
static int p_get_add(UINode* node) { static int p_get_add(UINode* node, lua_State* L) {
if (dynamic_cast<Container*>(node)) { 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; return 0;
} }
static int p_get_destruct(UINode*) { static int p_get_destruct(UINode*, lua_State* L) {
return state->pushcfunction(lua_wrap_errors<l_node_destruct>); 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)) { 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; return 0;
} }
static int p_set_interval(UINode* node) { static int p_set_interval(UINode* node, lua_State* L) {
if (dynamic_cast<Container*>(node)) { 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; return 0;
} }
static int p_get_color(UINode* node) { static int p_get_color(UINode* node, lua_State* L) {
return lua::pushcolor_arr(state->getLua(), node->getColor()); return lua::pushcolor_arr(L, node->getColor());
} }
static int p_get_hover_color(UINode* node) { static int p_get_hover_color(UINode* node, lua_State* L) {
return lua::pushcolor_arr(state->getLua(), node->getHoverColor()); return lua::pushcolor_arr(L, node->getHoverColor());
} }
static int p_get_pressed_color(UINode* node) { static int p_get_pressed_color(UINode* node, lua_State* L) {
return lua::pushcolor_arr(state->getLua(), node->getPressedColor()); return lua::pushcolor_arr(L, node->getPressedColor());
} }
static int p_get_tooltip(UINode* node) { static int p_get_tooltip(UINode* node, lua_State* L) {
return state->pushstring(util::wstr2str_utf8(node->getTooltip())); return lua::pushwstring(L, node->getTooltip());
} }
static int p_get_tooltip_delay(UINode* node) { static int p_get_tooltip_delay(UINode* node, lua_State* L) {
return state->pushnumber(node->getTooltipDelay()); return lua::pushnumber(L, node->getTooltipDelay());
} }
static int p_get_pos(UINode* node) { static int p_get_pos(UINode* node, lua_State* L) {
return lua::pushvec2_arr(state->getLua(), node->getPos()); return lua::pushvec2_arr(L, node->getPos());
} }
static int p_get_wpos(UINode* node) { static int p_get_wpos(UINode* node, lua_State* L) {
return lua::pushvec2_arr(state->getLua(), node->calcPos()); return lua::pushvec2_arr(L, node->calcPos());
} }
static int p_get_size(UINode* node) { static int p_get_size(UINode* node, lua_State* L) {
return lua::pushvec2_arr(state->getLua(), node->getSize()); return lua::pushvec2_arr(L, node->getSize());
} }
static int p_is_interactive(UINode* node) { static int p_is_interactive(UINode* node, lua_State* L) {
return state->pushboolean(node->isInteractive()); return lua::pushboolean(L, node->isInteractive());
} }
static int p_is_visible(UINode* node) { static int p_is_visible(UINode* node, lua_State* L) {
return state->pushboolean(node->isVisible()); return lua::pushboolean(L, node->isVisible());
} }
static int p_is_enabled(UINode* node) { static int p_is_enabled(UINode* node, lua_State* L) {
return state->pushboolean(node->isEnabled()); return lua::pushboolean(L, node->isEnabled());
} }
static int p_move_into(UINode*) { static int p_move_into(UINode*, lua_State* L) {
return state->pushcfunction(l_move_into); return lua::pushcfunction(L, l_move_into);
} }
static int p_get_focused(UINode* node) { static int p_get_focused(UINode* node, lua_State* L) {
return state->pushboolean(node->isFocused()); return lua::pushboolean(L, node->isFocused());
} }
static int l_gui_getattr(lua_State* L) { static int l_gui_getattr(lua_State* L) {
auto docname = state->requireString(1); auto docname = lua::require_string(L, 1);
auto element = state->requireString(2); auto element = lua::require_string(L, 2);
auto attr = state->requireString(3); auto attr = lua::require_string(L, 3);
auto docnode = getDocumentNode(L, docname, element); auto docnode = getDocumentNode(L, docname, element);
auto node = docnode.node; 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}, {"color", p_get_color},
{"hoverColor", p_get_hover_color}, {"hoverColor", p_get_hover_color},
{"pressedColor", p_get_pressed_color}, {"pressedColor", p_get_pressed_color},
@ -375,118 +375,118 @@ static int l_gui_getattr(lua_State* L) {
}; };
auto func = getters.find(attr); auto func = getters.find(attr);
if (func != getters.end()) { if (func != getters.end()) {
return func->second(node.get()); return func->second(node.get(), L);
} }
return 0; return 0;
} }
static void p_set_color(UINode* node, int idx) { static void p_set_color(UINode* node, lua_State* L, int idx) {
node->setColor(state->tocolor(idx)); node->setColor(lua::tocolor(L, idx));
} }
static void p_set_hover_color(UINode* node, int idx) { static void p_set_hover_color(UINode* node, lua_State* L, int idx) {
node->setHoverColor(state->tocolor(idx)); node->setHoverColor(lua::tocolor(L, idx));
} }
static void p_set_pressed_color(UINode* node, int idx) { static void p_set_pressed_color(UINode* node, lua_State* L, int idx) {
node->setPressedColor(state->tocolor(idx)); node->setPressedColor(lua::tocolor(L, idx));
} }
static void p_set_tooltip(UINode* node, int idx) { static void p_set_tooltip(UINode* node, lua_State* L, int idx) {
node->setTooltip(util::str2wstr_utf8(state->requireString(idx))); node->setTooltip(lua::require_wstring(L, idx));
} }
static void p_set_tooltip_delay(UINode* node, int idx) { static void p_set_tooltip_delay(UINode* node, lua_State* L, int idx) {
node->setTooltipDelay(state->tonumber(idx)); node->setTooltipDelay(lua_tonumber(L, idx));
} }
static void p_set_pos(UINode* node, int idx) { static void p_set_pos(UINode* node, lua_State* L, int idx) {
node->setPos(state->tovec2(idx)); node->setPos(lua::tovec2(L, idx));
} }
static void p_set_wpos(UINode* node, int idx) { static void p_set_wpos(UINode* node, lua_State* L, int idx) {
node->setPos(state->tovec2(idx)-node->calcPos()); node->setPos(lua::tovec2(L, idx)-node->calcPos());
} }
static void p_set_size(UINode* node, int idx) { static void p_set_size(UINode* node, lua_State* L, int idx) {
node->setSize(state->tovec2(idx)); node->setSize(lua::tovec2(L, idx));
} }
static void p_set_interactive(UINode* node, int idx) { static void p_set_interactive(UINode* node, lua_State* L, int idx) {
node->setInteractive(state->toboolean(idx)); node->setInteractive(lua_toboolean(L, idx));
} }
static void p_set_visible(UINode* node, int idx) { static void p_set_visible(UINode* node, lua_State* L, int idx) {
node->setVisible(state->toboolean(idx)); node->setVisible(lua_toboolean(L, idx));
} }
static void p_set_enabled(UINode* node, int idx) { static void p_set_enabled(UINode* node, lua_State* L, int idx) {
node->setEnabled(state->toboolean(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)) { 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)) { 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)) { } 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)) { } 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { 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)) { } 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)) { 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)) { 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) { if (inventory == nullptr) {
view->unbind(); view->unbind();
} else { } 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) { static void p_set_focused(const std::shared_ptr<UINode> &node, lua_State* L, int idx) {
if (state->toboolean(idx) && !node->isFocused()) { if (lua_toboolean(L, idx) && !node->isFocused()) {
scripting::engine->getGUI()->setFocus(node); scripting::engine->getGUI()->setFocus(node);
} else if (node->isFocused()){ } else if (node->isFocused()){
node->defocus(); 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) { static int l_gui_setattr(lua_State* L) {
auto docname = state->requireString(1); auto docname = lua::require_string(L, 1);
auto element = state->requireString(2); auto element = lua::require_string(L, 2);
auto attr = state->requireString(3); auto attr = lua::require_string(L, 3);
auto docnode = getDocumentNode(L, docname, element); auto docnode = getDocumentNode(L, docname, element);
auto node = docnode.node; 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}, {"color", p_set_color},
{"hoverColor", p_set_hover_color}, {"hoverColor", p_set_hover_color},
{"pressedColor", p_set_pressed_color}, {"pressedColor", p_set_pressed_color},
@ -539,20 +539,20 @@ static int l_gui_setattr(lua_State* L) {
}; };
auto func = setters.find(attr); auto func = setters.find(attr);
if (func != setters.end()) { 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}, {"focused", p_set_focused},
}; };
auto func2 = setters2.find(attr); auto func2 = setters2.find(attr);
if (func2 != setters2.end()) { if (func2 != setters2.end()) {
func2->second(node, 4); func2->second(node, L, 4);
} }
return 0; return 0;
} }
static int l_gui_get_env(lua_State* L) { 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); auto doc = scripting::engine->getAssets()->getLayout(name);
if (doc == nullptr) { if (doc == nullptr) {
throw std::runtime_error("document '"+std::string(name)+"' not found"); 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) { 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)) { 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()); lua_pushstring(L, util::wstr2str_utf8(langs::get(text, context)).c_str());
} else { } else {
lua_pushstring(L, util::wstr2str_utf8(langs::get(text)).c_str()); 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) { 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); auto doc = scripting::engine->getAssets()->getLayout(name);
if (doc == nullptr) { if (doc == nullptr) {
throw std::runtime_error("document '"+std::string(name)+"' not found"); throw std::runtime_error("document '"+std::string(name)+"' not found");

View File

@ -16,29 +16,28 @@ namespace scripting {
extern lua::LuaState* state; extern lua::LuaState* state;
extern Hud* hud; extern Hud* hud;
} }
using namespace scripting; using namespace scripting;
static int l_keycode(lua_State* L) { 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))); lua_pushinteger(L, static_cast<int>(input_util::keycode_from(name)));
return 1; return 1;
} }
static int l_mousecode(lua_State* L) { 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))); lua_pushinteger(L, static_cast<int>(input_util::mousecode_from(name)));
return 1; return 1;
} }
static int l_add_callback(lua_State*) { static int l_add_callback(lua_State* L) {
auto bindname = state->requireString(1); auto bindname = lua::require_string(L, 1);
const auto& bind = Events::bindings.find(bindname); const auto& bind = Events::bindings.find(bindname);
if (bind == Events::bindings.end()) { if (bind == Events::bindings.end()) {
throw std::runtime_error("unknown binding "+util::quote(bindname)); throw std::runtime_error("unknown binding "+util::quote(bindname));
} }
state->pushvalue(2); lua_pushvalue(L, 2);
runnable actual_callback = state->createRunnable(); runnable actual_callback = state->createRunnable(L);
runnable callback = [=]() { runnable callback = [=]() {
if (!scripting::engine->getGUI()->isFocusCaught()) { if (!scripting::engine->getGUI()->isFocusCaught()) {
actual_callback(); actual_callback();

View File

@ -1,4 +1,5 @@
#include "lua_commons.hpp" #include "lua_commons.hpp"
#include "lua_util.hpp"
#include "api_lua.hpp" #include "api_lua.hpp"
#include "LuaState.hpp" #include "LuaState.hpp"
#include "../scripting.hpp" #include "../scripting.hpp"
@ -8,12 +9,11 @@
namespace scripting { namespace scripting {
extern lua::LuaState* state; extern lua::LuaState* state;
} }
using namespace scripting; using namespace scripting;
static int l_item_name(lua_State* L) { static int l_item_name(lua_State* L) {
auto indices = scripting::content->getIndices(); auto indices = content->getIndices();
lua_Number id = lua_tointeger(L, 1); auto id = lua_tointeger(L, 1);
if (static_cast<size_t>(id) >= indices->countItemDefs()) { if (static_cast<size_t>(id) >= indices->countItemDefs()) {
return 0; return 0;
} }
@ -23,15 +23,15 @@ static int l_item_name(lua_State* L) {
} }
static int l_item_index(lua_State* L) { static int l_item_index(lua_State* L) {
auto name = scripting::state->requireString(1); auto name = lua::require_string(L, 1);
lua_pushinteger(L, scripting::content->requireItem(name).rt.id); lua_pushinteger(L, content->requireItem(name).rt.id);
return 1; return 1;
} }
static int l_item_stack_size(lua_State* L) { static int l_item_stack_size(lua_State* L) {
auto indices = scripting::content->getIndices(); auto indices = content->getIndices();
lua_Integer id = lua_tointeger(L, 1); auto id = lua_tointeger(L, 1);
if (id < 0 || size_t(id) >= indices->countItemDefs()) { if (static_cast<size_t>(id) >= indices->countItemDefs()) {
return 0; return 0;
} }
auto def = indices->getItemDef(id); auto def = indices->getItemDef(id);

View File

@ -1,4 +1,5 @@
#include "api_lua.hpp" #include "api_lua.hpp"
#include "lua_util.hpp"
#include "lua_commons.hpp" #include "lua_commons.hpp"
#include "LuaState.hpp" #include "LuaState.hpp"
@ -10,7 +11,7 @@ namespace scripting {
} }
static int l_json_stringify(lua_State* L) { 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)) { if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) {
bool nice = lua_toboolean(L, 2); 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) { 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); auto element = json::parse("<string>", string);
scripting::state->pushvalue(element); lua::pushvalue(L, element);
return 1; return 1;
} }

View File

@ -1,4 +1,5 @@
#include "api_lua.hpp" #include "api_lua.hpp"
#include "lua_util.hpp"
#include "lua_commons.hpp" #include "lua_commons.hpp"
#include "LuaState.hpp" #include "LuaState.hpp"
@ -11,7 +12,7 @@ namespace scripting {
using namespace scripting; using namespace scripting;
static int l_toml_stringify(lua_State* L) { 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)) { if (auto mapptr = std::get_if<dynamic::Map_sptr>(&value)) {
auto string = toml::stringify(**mapptr); auto string = toml::stringify(**mapptr);
@ -22,11 +23,11 @@ static int l_toml_stringify(lua_State* L) {
} }
} }
static int l_toml_parse(lua_State*) { static int l_toml_parse(lua_State* L) {
auto string = state->requireString(1); auto string = lua::require_string(L, 1);
auto element = toml::parse("<string>", string); auto element = toml::parse("<string>", string);
auto value = std::make_unique<dynamic::Value>(element); auto value = std::make_unique<dynamic::Value>(element);
state->pushvalue(*value); lua::pushvalue(L, *value);
return 1; return 1;
} }

View File

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

View File

@ -14,6 +14,23 @@
#include <stdexcept> #include <stdexcept>
namespace lua { 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) { inline int pushivec3(lua_State* L, lua_Integer x, lua_Integer y, lua_Integer z) {
lua_pushinteger(L, x); lua_pushinteger(L, x);
lua_pushinteger(L, y); lua_pushinteger(L, y);
@ -84,7 +101,6 @@ namespace lua {
lua_rawseti(L, -2, 4); lua_rawseti(L, -2, 4);
return 1; return 1;
} }
inline int pushcolor_arr(lua_State* L, glm::vec4 vec) { inline int pushcolor_arr(lua_State* L, glm::vec4 vec) {
lua_createtable(L, 4, 0); lua_createtable(L, 4, 0);
lua_getglobal(L, "color_mt"); lua_getglobal(L, "color_mt");
@ -100,6 +116,33 @@ namespace lua {
lua_rawseti(L, -2, 4); lua_rawseti(L, -2, 4);
return 1; 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) { inline glm::vec2 tovec2(lua_State* L, int idx) {
lua_pushvalue(L, idx); lua_pushvalue(L, idx);
@ -130,6 +173,61 @@ namespace lua {
lua_pop(L, 1); lua_pop(L, 1);
return glm::vec4(r/255, g/255, b/255, a/255); 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_ #endif // LOGIC_SCRIPTING_LUA_UTIL_HPP_

View File

@ -17,6 +17,7 @@
#include "../../voxels/Block.hpp" #include "../../voxels/Block.hpp"
#include "../../world/Level.hpp" #include "../../world/Level.hpp"
#include "lua/LuaState.hpp" #include "lua/LuaState.hpp"
#include "lua/lua_util.hpp"
#include <iostream> #include <iostream>
#include <stdexcept> #include <stdexcept>
@ -37,12 +38,12 @@ const ContentIndices* scripting::indices = nullptr;
BlocksController* scripting::blocks = nullptr; BlocksController* scripting::blocks = nullptr;
LevelController* scripting::controller = 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(); auto paths = scripting::engine->getPaths();
fs::path file = paths->getResources()/fs::path("scripts")/name; fs::path file = paths->getResources()/fs::path("scripts")/name;
std::string src = files::read_string(file); 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) { void scripting::initialize(Engine* engine) {
@ -59,46 +60,49 @@ scriptenv scripting::get_root_environment() {
} }
scriptenv scripting::create_pack_environment(const ContentPack& pack) { scriptenv scripting::create_pack_environment(const ContentPack& pack) {
int id = state->createEnvironment(0); auto L = state->getMainThread();
state->pushenv(id); int id = state->createEnvironment(L, 0);
state->pushvalue(-1); state->pushenv(L, id);
state->setfield("PACK_ENV"); lua::pushvalue(L, -1);
state->pushstring(pack.id); lua::setfield(L, "PACK_ENV");
state->setfield("PACK_ID"); lua::pushstring(L, pack.id);
state->pop(); lua::setfield(L, "PACK_ID");
lua::pop(L);
return std::shared_ptr<int>(new int(id), [=](int* id) { return std::shared_ptr<int>(new int(id), [=](int* id) {
state->removeEnvironment(*id); state->removeEnvironment(L, *id);
delete id; delete id;
}); });
} }
scriptenv scripting::create_doc_environment(const scriptenv& parent, const std::string& name) { scriptenv scripting::create_doc_environment(const scriptenv& parent, const std::string& name) {
int id = state->createEnvironment(*parent); auto L = state->getMainThread();
state->pushenv(id); int id = state->createEnvironment(L, *parent);
state->pushvalue(-1); state->pushenv(L, id);
state->setfield("DOC_ENV"); lua_pushvalue(L, -1);
state->pushstring(name.c_str()); lua::setfield(L, "DOC_ENV");
state->setfield("DOC_NAME"); lua::pushstring(L, name);
lua::setfield(L, "DOC_NAME");
if (state->getglobal("Document")) { if (lua::getglobal(L, "Document")) {
if (state->getfield("new")) { if (lua::getfield(L, "new")) {
state->pushstring(name.c_str()); lua::pushstring(L, name);
if (state->callNoThrow(1)) { if (lua::callNoThrow(L, 1)) {
state->setfield("document", -3); lua::setfield(L, "document", -3);
} }
} }
state->pop(); lua::pop(L);
} }
state->pop(); lua::pop(L);
return std::shared_ptr<int>(new int(id), [=](int* id) { return std::shared_ptr<int>(new int(id), [=](int* id) {
state->removeEnvironment(*id); state->removeEnvironment(L, *id);
delete id; delete id;
}); });
} }
void scripting::process_post_runnables() { void scripting::process_post_runnables() {
if (state->getglobal("__process_post_runnables")) { auto L = state->getMainThread();
state->callNoThrow(0); 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; scripting::controller = controller;
load_script("world.lua"); load_script("world.lua");
auto L = state->getMainThread();
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".worldopen"); state->emitEvent(L, pack.id + ".worldopen");
} }
} }
void scripting::on_world_tick() { void scripting::on_world_tick() {
auto L = state->getMainThread();
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".worldtick"); state->emitEvent(L, pack.id + ".worldtick");
} }
} }
void scripting::on_world_save() { void scripting::on_world_save() {
auto L = state->getMainThread();
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".worldsave"); state->emitEvent(L, pack.id + ".worldsave");
} }
} }
void scripting::on_world_quit() { void scripting::on_world_quit() {
auto L = state->getMainThread();
for (auto& pack : scripting::engine->getContentPacks()) { 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()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->getfield("unload"); lua::getfield(L, "unload");
state->pushstring(pack.id); lua::pushstring(L, pack.id);
state->callNoThrow(1); lua::callNoThrow(L, 1);
} }
state->pop(); lua::pop(L);
if (state->getglobal("__scripts_cleanup")) { if (lua::getglobal(L, "__scripts_cleanup")) {
state->callNoThrow(0); lua::callNoThrow(L, 0);
} }
scripting::level = nullptr; scripting::level = nullptr;
scripting::content = nullptr; scripting::content = nullptr;
@ -152,77 +160,73 @@ void scripting::on_world_quit() {
void scripting::on_blocks_tick(const Block* block, int tps) { void scripting::on_blocks_tick(const Block* block, int tps) {
std::string name = block->name + ".blockstick"; std::string name = block->name + ".blockstick";
state->emit_event(name, [tps] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), name, [tps] (lua_State* L) {
state->pushinteger(tps); return lua::pushinteger(L, tps);
return 1;
}); });
} }
void scripting::update_block(const Block* block, int x, int y, int z) { void scripting::update_block(const Block* block, int x, int y, int z) {
std::string name = block->name + ".update"; std::string name = block->name + ".update";
state->emit_event(name, [x, y, z] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), name, [x, y, z] (lua_State* L) {
state->pushivec3(x, y, z); return lua::pushivec3(L, x, y, z);
return 3;
}); });
} }
void scripting::random_update_block(const Block* block, int x, int y, int z) { void scripting::random_update_block(const Block* block, int x, int y, int z) {
std::string name = block->name + ".randupdate"; std::string name = block->name + ".randupdate";
state->emit_event(name, [x, y, z] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), name, [x, y, z] (lua_State* L) {
state->pushivec3(x, y, z); return lua::pushivec3(L, x, y, z);
return 3;
}); });
} }
void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) { void scripting::on_block_placed(Player* player, const Block* block, int x, int y, int z) {
std::string name = block->name + ".placed"; std::string name = block->name + ".placed";
state->emit_event(name, [x, y, z, player] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) {
state->pushivec3(x, y, z); lua::pushivec3(L, x, y, z);
state->pushinteger(player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
}); });
} }
void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) { void scripting::on_block_broken(Player* player, const Block* block, int x, int y, int z) {
std::string name = block->name + ".broken"; std::string name = block->name + ".broken";
state->emit_event(name, [x, y, z, player] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) {
state->pushivec3(x, y, z); lua::pushivec3(L, x, y, z);
state->pushinteger(player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
}); });
} }
bool scripting::on_block_interact(Player* player, const Block* block, glm::ivec3 pos) { bool scripting::on_block_interact(Player* player, const Block* block, glm::ivec3 pos) {
std::string name = block->name + ".interact"; std::string name = block->name + ".interact";
return state->emit_event(name, [pos, player] (lua::LuaState* state) { return state->emitEvent(state->getMainThread(), name, [pos, player] (lua_State* L) {
state->pushivec3(pos.x, pos.y, pos.z); lua::pushivec3(L, pos.x, pos.y, pos.z);
state->pushinteger(player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
}); });
} }
bool scripting::on_item_use(Player* player, const ItemDef* item) { bool scripting::on_item_use(Player* player, const ItemDef* item) {
std::string name = item->name + ".use"; std::string name = item->name + ".use";
return state->emit_event(name, [player] (lua::LuaState* state) { return state->emitEvent(state->getMainThread(), name, [player] (lua_State* L) {
state->pushinteger(player->getId()); return lua::pushinteger(L, player->getId());
return 1;
}); });
} }
bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) { bool scripting::on_item_use_on_block(Player* player, const ItemDef* item, int x, int y, int z) {
std::string name = item->name + ".useon"; std::string name = item->name + ".useon";
return state->emit_event(name, [x, y, z, player] (lua::LuaState* state) { return state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) {
state->pushivec3(x, y, z); lua::pushivec3(L, x, y, z);
state->pushinteger(player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
}); });
} }
bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) { bool scripting::on_item_break_block(Player* player, const ItemDef* item, int x, int y, int z) {
std::string name = item->name + ".blockbreakby"; std::string name = item->name + ".blockbreakby";
return state->emit_event(name, [x, y, z, player] (lua::LuaState* state) { return state->emitEvent(state->getMainThread(), name, [x, y, z, player] (lua_State* L) {
state->pushivec3(x, y, z); lua::pushivec3(L, x, y, z);
state->pushinteger(player->getId()); lua::pushinteger(L, player->getId());
return 4; return 4;
}); });
} }
@ -233,9 +237,9 @@ void scripting::on_ui_open(
) { ) {
auto argsptr = std::make_shared<std::vector<dynamic::Value>>(std::move(args)); auto argsptr = std::make_shared<std::vector<dynamic::Value>>(std::move(args));
std::string name = layout->getId() + ".open"; 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) { for (const auto& value : *argsptr) {
state->pushvalue(value); lua::pushvalue(L, value);
} }
return argsptr->size(); return argsptr->size();
}); });
@ -243,37 +247,37 @@ void scripting::on_ui_open(
void scripting::on_ui_progress(UiDocument* layout, int workDone, int workTotal) { void scripting::on_ui_progress(UiDocument* layout, int workDone, int workTotal) {
std::string name = layout->getId() + ".progress"; std::string name = layout->getId() + ".progress";
state->emit_event(name, [=] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), name, [=] (lua_State* L) {
state->pushinteger(workDone); lua::pushinteger(L, workDone);
state->pushinteger(workTotal); lua::pushinteger(L, workTotal);
return 2; return 2;
}); });
} }
void scripting::on_ui_close(UiDocument* layout, Inventory* inventory) { void scripting::on_ui_close(UiDocument* layout, Inventory* inventory) {
std::string name = layout->getId() + ".close"; std::string name = layout->getId() + ".close";
state->emit_event(name, [inventory] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), name, [inventory] (lua_State* L) {
state->pushinteger(inventory == nullptr ? 0 : inventory->getId()); return lua::pushinteger(L, inventory ? inventory->getId() : 0);
return 1;
}); });
} }
bool scripting::register_event(int env, const std::string& name, const std::string& id) { bool scripting::register_event(int env, const std::string& name, const std::string& id) {
if (state->pushenv(env) == 0) { auto L = state->getMainThread();
state->pushglobals(); if (state->pushenv(L, env) == 0) {
lua::pushglobals(L);
} }
if (state->getfield(name)) { if (lua::getfield(L, name)) {
state->pop(); lua::pop(L);
state->getglobal("events"); lua::getglobal(L, "events");
state->getfield("on"); lua::getfield(L, "on");
state->pushstring(id); lua::pushstring(L, id);
state->getfield(name, -4); lua::getfield(L, name, -4);
state->callNoThrow(2); lua::callNoThrow(L, 2);
state->pop(); lua::pop(L);
// remove previous name // remove previous name
state->pushnil(); lua::pushnil(L);
state->setfield(name); lua::setfield(L, name);
return true; return true;
} }
return false; return false;
@ -283,7 +287,7 @@ void scripting::load_block_script(const scriptenv& senv, const std::string& pref
int env = *senv; int env = *senv;
std::string src = files::read_string(file); std::string src = files::read_string(file);
logger.info() << "script (block) " << file.u8string(); 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.init = register_event(env, "init", prefix+".init");
funcsset.update = register_event(env, "on_update", prefix+".update"); funcsset.update = register_event(env, "on_update", prefix+".update");
funcsset.randupdate = register_event(env, "on_random_update", prefix+".randupdate"); 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; int env = *senv;
std::string src = files::read_string(file); std::string src = files::read_string(file);
logger.info() << "script (item) " << file.u8string(); 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.init = register_event(env, "init", prefix+".init");
funcsset.on_use = register_event(env, "on_use", prefix+".use"); 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); std::string src = files::read_string(file);
logger.info() << "loading world script for " << prefix; logger.info() << "loading world script for " << prefix;
state->loadbuffer(env, src, file.u8string()); state->execute(state->getMainThread(), env, src, file.u8string());
state->callNoThrow(0);
register_event(env, "init", prefix+".init"); register_event(env, "init", prefix+".init");
register_event(env, "on_world_open", prefix+".worldopen"); 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); std::string src = files::read_string(file);
logger.info() << "loading script " << file.u8string(); logger.info() << "loading script " << file.u8string();
state->loadbuffer(env, src, file.u8string()); state->execute(state->getMainThread(), env, src, file.u8string());
state->callNoThrow(0);
script.onopen = register_event(env, "on_open", prefix+".open"); script.onopen = register_event(env, "on_open", prefix+".open");
script.onprogress = register_event(env, "on_progress", prefix+".progress"); script.onprogress = register_event(env, "on_progress", prefix+".progress");
script.onclose = register_event(env, "on_close", prefix+".close"); script.onclose = register_event(env, "on_close", prefix+".close");

View File

@ -1,5 +1,6 @@
#include "scripting_functional.hpp" #include "scripting_functional.hpp"
#include "lua/lua_util.hpp"
#include "lua/LuaState.hpp" #include "lua/LuaState.hpp"
#include "../../debug/Logger.hpp" #include "../../debug/Logger.hpp"
#include "../../util/stringutil.hpp" #include "../../util/stringutil.hpp"
@ -17,26 +18,30 @@ runnable scripting::create_runnable(
const std::string& src, const std::string& src,
const std::string& file const std::string& file
) { ) {
auto L = state->getMainThread();
try { try {
state->loadbuffer(*env, src, file); state->loadbuffer(L, *env, src, file);
return state->createRunnable(); return state->createRunnable(L);
} catch (const lua::luaerror& err) { } catch (const lua::luaerror& err) {
logger.error() << err.what(); logger.error() << err.what();
return [](){}; return [](){};
} }
} }
static bool processCallback( static lua_State* processCallback(
const scriptenv& env, const scriptenv& env,
const std::string& src, const std::string& src,
const std::string& file const std::string& file
) { ) {
auto L = state->getMainThread();
try { try {
return state->eval(*env, src, file) != 0; if (state->eval(L, *env, src, file) != 0) {
return L;
}
} catch (lua::luaerror& err) { } catch (lua::luaerror& err) {
logger.error() << err.what(); logger.error() << err.what();
return false;
} }
return nullptr;
} }
wstringconsumer scripting::create_wstring_consumer( wstringconsumer scripting::create_wstring_consumer(
@ -45,9 +50,9 @@ wstringconsumer scripting::create_wstring_consumer(
const std::string& file const std::string& file
) { ) {
return [=](const std::wstring& x){ return [=](const std::wstring& x){
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
state->pushstring(util::wstr2str_utf8(x)); lua::pushwstring(L, x);
state->callNoThrow(1); lua::callNoThrow(L, 1);
} }
}; };
} }
@ -58,12 +63,12 @@ wstringsupplier scripting::create_wstring_supplier(
const std::string& file const std::string& file
) { ) {
return [=](){ return [=](){
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
if (state->isfunction(-1)) { if (lua_isfunction(L, -1)) {
state->callNoThrow(0); lua::callNoThrow(L, 0);
} }
auto str = state->tostring(-1); state->pop(); auto str = lua::require_wstring(L, -1); lua_pop(L, 1);
return util::str2wstr_utf8(str); return str;
} }
return std::wstring(L""); return std::wstring(L"");
}; };
@ -75,10 +80,10 @@ wstringchecker scripting::create_wstring_validator(
const std::string& file const std::string& file
) { ) {
return [=](const std::wstring& x){ return [=](const std::wstring& x){
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
state->pushstring(util::wstr2str_utf8(x)); lua::pushwstring(L, x);
if (state->callNoThrow(1)) if (lua::callNoThrow(L, 1))
return state->toboolean(-1); return lua::toboolean(L, -1);
} }
return false; return false;
}; };
@ -90,9 +95,9 @@ boolconsumer scripting::create_bool_consumer(
const std::string& file const std::string& file
) { ) {
return [=](bool x){ return [=](bool x){
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
state->pushboolean(x); lua::pushboolean(L, x);
state->callNoThrow(1); lua::callNoThrow(L, 1);
} }
}; };
} }
@ -103,11 +108,11 @@ boolsupplier scripting::create_bool_supplier(
const std::string& file const std::string& file
) { ) {
return [=](){ return [=](){
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
if (state->isfunction(-1)) { if (lua_isfunction(L, -1)) {
state->callNoThrow(0); lua::callNoThrow(L, 0);
} }
bool x = state->toboolean(-1); state->pop(); bool x = lua::toboolean(L,-1); lua_pop(L, 1);
return x; return x;
} }
return false; return false;
@ -120,9 +125,9 @@ doubleconsumer scripting::create_number_consumer(
const std::string& file const std::string& file
) { ) {
return [=](double x){ return [=](double x){
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
state->pushnumber(x); lua::pushnumber(L, x);
state->callNoThrow(1); lua::callNoThrow(L, 1);
} }
}; };
} }
@ -133,12 +138,12 @@ doublesupplier scripting::create_number_supplier(
const std::string& file const std::string& file
) { ) {
return [=](){ return [=](){
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
if (state->isfunction(-1)) { if (lua_isfunction(L, -1)) {
state->callNoThrow(0); lua::callNoThrow(L, 0);
} }
auto x = state->tonumber(-1); auto x = lua_tonumber(L, -1);
state->pop(); lua::pop(L);
return x; return x;
} }
return 0.0; return 0.0;
@ -150,12 +155,12 @@ int_array_consumer scripting::create_int_array_consumer(
const std::string& src, const std::string& src,
const std::string& file const std::string& file
) { ) {
return [=](const int arr[], size_t len){ return [=](const int arr[], size_t len) {
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
for (uint i = 0; i < len; i++) { 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& src,
const std::string& file const std::string& file
) { ) {
return [=](){ return [=]() {
if (processCallback(env, src, file)) { if (auto L = processCallback(env, src, file)) {
if (state->isfunction(-1)) { if (lua_isfunction(L, -1)) {
state->callNoThrow(0); lua::callNoThrow(L, 0);
} }
auto y = state->tonumber(-1); state->pop(); auto y = lua_tonumber(L, -1); lua::pop(L);
auto x = state->tonumber(-1); state->pop(); auto x = lua_tonumber(L, -1); lua::pop(L);
return glm::vec2(x, y); return glm::vec2(x, y);
} }
return glm::vec2(0, 0); return glm::vec2(0, 0);

View File

@ -1,6 +1,7 @@
#include "scripting_hud.hpp" #include "scripting_hud.hpp"
#include "scripting.hpp" #include "scripting.hpp"
#include "lua/lua_util.hpp"
#include "lua/api_lua.hpp" #include "lua/api_lua.hpp"
#include "lua/LuaState.hpp" #include "lua/LuaState.hpp"
@ -13,6 +14,7 @@
namespace scripting { namespace scripting {
extern lua::LuaState* state; extern lua::LuaState* state;
} }
using namespace scripting;
static debug::Logger logger("scripting-hud"); static debug::Logger logger("scripting-hud");
@ -20,21 +22,21 @@ Hud* scripting::hud = nullptr;
void scripting::on_frontend_init(Hud* hud) { void scripting::on_frontend_init(Hud* hud) {
scripting::hud = hud; scripting::hud = hud;
scripting::state->openlib("hud", hudlib); state->openlib(state->getMainThread(), "hud", hudlib);
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".hudopen", [&] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), pack.id + ".hudopen",
state->pushinteger(hud->getPlayer()->getId()); [&] (lua_State* L) {
return 1; return lua::pushinteger(L, hud->getPlayer()->getId());
}); });
} }
} }
void scripting::on_frontend_close() { void scripting::on_frontend_close() {
for (auto& pack : scripting::engine->getContentPacks()) { for (auto& pack : scripting::engine->getContentPacks()) {
state->emit_event(pack.id + ".hudclose", [&] (lua::LuaState* state) { state->emitEvent(state->getMainThread(), pack.id + ".hudclose",
state->pushinteger(hud->getPlayer()->getId()); [&] (lua_State* L) {
return 1; return lua::pushinteger(L, hud->getPlayer()->getId());
}); });
} }
scripting::hud = nullptr; 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); std::string src = files::read_string(file);
logger.info() << "loading script " << file.u8string(); logger.info() << "loading script " << file.u8string();
state->loadbuffer(env, src, file.u8string()); auto L = state->getMainThread();
state->callNoThrow(0); state->loadbuffer(L, env, src, file.u8string());
lua::callNoThrow(L, 0);
register_event(env, "init", packid+".init"); register_event(env, "init", packid+".init");
register_event(env, "on_hud_open", packid+".hudopen"); register_event(env, "on_hud_open", packid+".hudopen");