From ff7f18fa7b0615f5c8e8f69d7105f33ac99f4fb6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 22 Jan 2024 08:14:52 +0300 Subject: [PATCH] added stdlib.lua + lua errors handling update --- res/scripts/stdlib.lua | 51 +++++++++++++++++++++++++++++++ src/logic/scripting/scripting.cpp | 31 +++++++++++++------ 2 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 res/scripts/stdlib.lua diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua new file mode 100644 index 00000000..35927573 --- /dev/null +++ b/res/scripts/stdlib.lua @@ -0,0 +1,51 @@ +-- kit of standard functions + +-- Check if given table is an array +function is_array(x) + if #t > 0 then + return true + end + for k, v in pairs(x) do + return false + end + return true +end + +local __cached_scripts = {} +local __cached_results = {} + +-- Get entry-point and filename from `entry-point:filename` path +function parse_path(path) + local index = string.find(path, ':') + if index == nil then + error("invalid path syntax (':' missing)") + end + return string.sub(path, 1, index-1), string.sub(path, index+1, -1) +end + +-- Load script with caching +-- +-- path - script path `contentpack:filename`. +-- Example `base:scripts/tests.lua` +-- +-- nocache - ignore cached script, load anyway +function load_script(path, nocache) + local packname, filename = parse_path(path) + local packpath = pack.get_folder(packname) + local fullpath = packpath..filename + + -- __cached_scripts used in condition because cached result may be nil + if not nocache and __cached_scripts[fullpath] ~= nil then + return __cached_results[fullpath] + end + local script = loadfile(fullpath) + if script == nil then + error("script '"..filename.."' not found in '"..packname.."'") + end + local result = script() + if not nocache then + __cached_scripts[fullpath] = script + __cached_results[fullpath] = result + end + return result +end diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 4ab975f3..bddd54dd 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -26,6 +26,10 @@ Level* scripting::level = nullptr; const Content* scripting::content = nullptr; BlocksController* scripting::blocks = nullptr; +static void handleError(lua_State* L) { + std::cerr << "lua error: " << lua_tostring(L,-1) << std::endl; +} + inline int lua_pushivec3(lua_State* L, int x, int y, int z) { lua_pushinteger(L, x); lua_pushinteger(L, y); @@ -51,13 +55,24 @@ bool rename_global(lua_State* L, const char* src, const char* dst) { int call_func(lua_State* L, int argc, const std::string& name) { if (lua_pcall(L, argc, LUA_MULTRET, 0)) { - std::cerr << "Lua error in " << name << ": "; - std::cerr << lua_tostring(L,-1) << std::endl; + handleError(L); return 0; } return 1; } +void load_script(fs::path name) { + auto paths = scripting::engine->getPaths(); + fs::path file = paths->getResources()/fs::path("scripts")/name; + + std::string src = files::read_string(file); + if (luaL_loadbuffer(L, src.c_str(), src.length(), file.u8string().c_str())) { + handleError(L); + return; + } + call_func(L, 0, file.u8string()); +} + void scripting::initialize(Engine* engine) { scripting::engine = engine; @@ -81,17 +96,15 @@ void scripting::initialize(Engine* engine) { # endif // LUAJIT_VERSION apilua::create_funcs(L); + + load_script(fs::path("stdlib.lua")); } void scripting::on_world_load(Level* level, BlocksController* blocks) { scripting::level = level; scripting::content = level->content; scripting::blocks = blocks; - auto paths = scripting::engine->getPaths(); - fs::path file = paths->getResources()/fs::path("scripts/world.lua"); - std::string src = files::read_string(file); - luaL_loadbuffer(L, src.c_str(), src.length(), file.string().c_str()); - call_func(L, 0, "