--luarocks imports local lfs = minetest or require("lfs") --local luajson = minetest or require("json") --lua-json local dkjson = minetest or require("dkjson") --setup lib env --context is always -eq to the highest possible subfolder in the mods dir, this can be ether the mod or modpack root folder. local DIR_DELIM = debug.getinfo(1, "S").source:match("[\\/]") local context = debug and debug.getinfo(1, "S").source:match("mods[/\\][/\\]?([^/]*)") or "modpack" local modpath = minetest and core.get_modpath(core.get_current_modname()) or debug.getinfo(1, "S").source:match("^(.+)[/\\]"):sub(2) --declare stuff local namespace = {} --this file creates the context, tested using lua 5.1 and via mt's built-in virtual lua sandbox env namespace.mergeTables = function(firstTable, secondTable) if firstTable == nil then firstTable = {} end if secondTable == nil then return firstTable end for k,v in pairs(secondTable) do firstTable[k] = v end return firstTable end namespace.getCallerInfo = function(p1IntLookback) p1IntLookback = p1IntLookback or 0 local info = debug.getinfo(2 + p1IntLookback, "Sl") if info then return info end end namespace.parse = function(p1String, p2Default) if minetest then return core.parse_json(p1String) else return (dkjson.decode(p1String) or p2Default) end end namespace.stringify = function(p1Table, p2Pretty) p2Pretty = p2Pretty or true return minetest and core.write_json(p1Table, p2Pretty) or dkjson.encode(p1Table, { indent = p2Pretty }) end namespace.log = function(...) local info = namespace.getCallerInfo(1) --console: none, error --debug.txt:none, error, warning, action --never?info, verbose, trace --debug_log_level = action if core then core.log("action", table.concat({"logged from: ", info.short_src,"@", info.currentline,";"})) end for _, arg in ipairs({...}) do arg = tostring(arg) if type(arg) == "table" then local _ = minetest and core.debug(namespace.stringify(arg)) or _G["io"]["write"](namespace.stringify(arg)) else local _ = minetest and core.debug(arg) or _G["io"]["write"](arg) end end _G["print"]("") end local print = namespace.log --print("[", namespace.parse("[false]")) --print("{", namespace.stringify({false})) namespace.get_dir_list=minetest and core.get_dir_list or function (folder) local returns = {} for filePath in lfs.dir(folder) do if filePath~= "." and filePath ~= ".." then table.insert(returns, filePath) end end return returns end namespace.dofolder = function(folder, todoFunc) for _, filePath in ipairs(namespace.get_dir_list(folder..modpath:match("[\\/]"))) do if todoFunc ~= nil then todoFunc(filePath) end end end --add local to global context _G[context] = {} _G[context] = namespace.mergeTables(_G[context], namespace) -- do the thing dofile(table.concat({modpath,"string.lua"}, DIR_DELIM)) dofile(table.concat({modpath,"table.lua"}, DIR_DELIM)) -- DIR_DELIM 2345 < is 5 chars shorter, why must I be made to do things the hard way! namespace.dofolder(modpath .. modpath:match("[\\/]") .. "lua5_1", function(filePath) if filePath:match("^.+%.(.+)$") == "lua" then dofile(modpath .. modpath:match("[\\/]") .. "lua5_1"..modpath:match("[\\/]")..filePath) end end) if minetest or (core and luanti)then --This was written before the name charge to match lexicographic order, --I'm not renaming it cause you chose to have an internal vote --Editors Note: yeah, get em blood child! _G[context].dofolder(modpath .. modpath:match("[\\/]") .. "minetest", function(filePath) if filePath:match("^.+%.(.+)$") == "lua" then dofile(modpath .. modpath:match("[\\/]") .. "minetest"..modpath:match("[\\/]")..filePath) end end) end _G[context].dofolder(modpath .. modpath:match("[\\/]") .. "namespace", function(filePath) if filePath:match("^.+%.(.+)$") == "lua" then dofile(modpath .. modpath:match("[\\/]") .. "namespace"..modpath:match("[\\/]")..filePath) end end) --return so dofile works correctly return namespace