From 9ca809ff9485a21464720a539a544d35b6d86c1b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 22 Aug 2026 00:10:30 +0300 Subject: [PATCH] add loaders (WIP) --- res/scripts/post_content.lua | 35 +++++++++++++++++- res/scripts/stdlib.lua | 1 + res/scripts/stdmin.lua | 50 ++++++++++++++++++++++---- src/assets/AssetsLoader.cpp | 1 - src/logic/scripting/lua/lua_engine.cpp | 5 +++ src/logic/scripting/scripting.cpp | 18 +++++++++- 6 files changed, 100 insertions(+), 10 deletions(-) diff --git a/res/scripts/post_content.lua b/res/scripts/post_content.lua index d6d48fbd1..97b2e93b6 100644 --- a/res/scripts/post_content.lua +++ b/res/scripts/post_content.lua @@ -1,3 +1,6 @@ +local app = __vc_app +local internals = __vc_internals + local user_props = file.read_combined_object("config/user-props.toml") local names = { "parent", "caption", "texture", "texture-faces", "model", "model-name", @@ -42,7 +45,7 @@ local function make_read_only(t) __newindex = function() error("table is read-only") end - }) + }) end make_read_only(block.properties) @@ -85,3 +88,33 @@ cache_names(block) cache_names(item) __vc_scripts_registry.build_registry() + +local packs = app.get_content() +table.insert(packs, 1, "core") + +for i, packid in ipairs(packs) do + local loaders_dir = packid..":scripts/loaders" + if not file.isdir(loaders_dir) then + goto continue + end + local files = file.list(loaders_dir) + for _, path in ipairs(files) do + if file.ext(path) == "json" then + debug.log("registering loader "..path) + local dto = json.parse(file.read(path)) + local module = setmetatable({}, {__index=internals.get_pack_env(packid)}) + local module_path = file.join(file.parent(path), file.stem(path)..".lua") + if not file.exists(module_path) then + error("loader "..path.." missing module "..module_path) + end + load(file.read(module_path), module_path, "t", module)() + if rawget(module, "execute") == nil then + error("loader "..path.." missing function 'execute'") + end + if dto.type == "compiler" then + internals.register_compiler(packid, dto.extensions, module) + end + end + end + ::continue:: +end diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 2869bba1c..56d86bf8f 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -392,6 +392,7 @@ end ffi = nil __vc_app = nil +__vc_internals = nil __vc_lock_internal_modules() __vc_lock_internal_modules = nil __vc_update_coroutines = nil diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 03de8cbaa..e1b735478 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -154,6 +154,20 @@ package = { } local __cached_scripts = {} local __warnings_hidden = {} +local __compilers = {} + +function __vc_internals.register_compiler(sourcepack, extensions, module) + local compiler = { + packid = sourcepack, + extensions = extensions, + module = module, + } + for i, ext in ipairs(extensions) do + if not __compilers[ext] then + __compilers[ext] = compiler + end + end +end function on_deprecated_call(name, alternatives) if __warnings_hidden[name] then @@ -200,6 +214,21 @@ end local __internal_locked = false +local default_compiler = { + module = { + execute = function(code, path, env) + local script, err = load(code, path) + if script == nil then + error(err) + end + if env then + script = setfenv(script, env) + end + return script + end + } +} + -- Load script with caching -- -- path - script path `contentpack:filename`. @@ -211,6 +240,9 @@ function __load_script(path, nocache, env) local is_internal = (packname == "res" or packname == "core") and filename:find("modules/internal") == 1 + local ext = path:match("%.([^:/\\]+)$") + local compiler = __compilers[ext] or default_compiler + nocache = nocache or is_internal if is_internal and __internal_locked then @@ -225,13 +257,7 @@ function __load_script(path, nocache, env) error("script '"..filename.."' not found in '"..packname.."'") end - local script, err = load(file.read(path), path) - if script == nil then - error(err) - end - if env then - script = setfenv(script, env) - end + local script = compiler.module.execute(file.read(path), path, env) local result = script() if not nocache then __cached_scripts[path] = script @@ -245,6 +271,9 @@ function __vc_lock_internal_modules() end local __pack_envs = __vc__pack_envs +function __vc_internals.get_pack_env(packid) + return __pack_envs[packid] +end __vc__pack_envs = nil function require(path) @@ -277,6 +306,13 @@ function __scripts_cleanup(non_reset_packs) __pack_envs[packname] = nil ::continue:: end + for ext, compiler in pairs(__compilers) do + if table.has(non_reset_packs, compiler.packid) then + goto continue + end + __compilers[ext] = nil + ::continue:: + end end function __vc__error(msg, frame, n, lastn) diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 5f339af29..581e6e109 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -220,7 +220,6 @@ void AssetsLoader::processPreloadList(AssetType tag, const dv::value& list) { } void AssetsLoader::processPreloadConfig(const io::path& file) { - logger.debug() << "===== PRELOAD FILE: " << file.string(); auto root = io::read_json(file); processPreloadList(AssetType::ATLAS, root["atlases"]); processPreloadList(AssetType::FONT, root["fonts"]); diff --git a/src/logic/scripting/lua/lua_engine.cpp b/src/logic/scripting/lua/lua_engine.cpp index 78708deca..850b34109 100644 --- a/src/logic/scripting/lua/lua_engine.cpp +++ b/src/logic/scripting/lua/lua_engine.cpp @@ -74,6 +74,11 @@ static void create_libs(State* L, StateType stateType) { getglobal(L, "__vc_app"); setregistry(L, "app"); + createtable(L, 0, 0); + pushvalue(L, -1); + setglobal(L, "__vc_internals"); + setregistry(L, "internals"); + if (stateType == StateType::SCRIPT) { getregistry(L, "app"); setglobal(L, "app"); diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index d448a8421..15da3697e 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -288,7 +288,23 @@ void scripting::on_content_load(Content* content) { lua::setfield(L, "properties"); lua::pop(L); } - load_script("post_content.lua", true); + + lua::getregistry(L, "app"); + lua::setglobal(L, "__vc_app"); + lua::getregistry(L, "internals"); + lua::setglobal(L, "__vc_internals"); + try { + load_script("post_content.lua", true); + } catch (const std::exception&) { + lua::pushnil(L); + lua::setglobal(L, "__vc_app"); + throw; + } + lua::pushnil(L); + lua::setglobal(L, "__vc_app"); + lua::pushnil(L); + lua::setglobal(L, "__vc_internals"); + load_script("stdcmd.lua", true); }