From 6e0304248bb5690c5247c30e5ca141d74aa8b784 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 9 Oct 2024 05:30:02 +0300 Subject: [PATCH] add stdmin.lua --- .../base/generators/demo.files/biomes.json | 2 +- .../base/generators/demo.files/script.lua | 12 +- res/scripts/stdlib.lua | 230 +----------------- res/scripts/stdmin.lua | 224 +++++++++++++++++ src/logic/scripting/lua/lua_engine.cpp | 12 +- src/logic/scripting/lua/lua_engine.hpp | 6 +- src/logic/scripting/scripting.cpp | 2 +- .../scripting/scripting_world_generation.cpp | 3 +- 8 files changed, 245 insertions(+), 246 deletions(-) create mode 100644 res/scripts/stdmin.lua diff --git a/res/content/base/generators/demo.files/biomes.json b/res/content/base/generators/demo.files/biomes.json index 52b39eae..52bb9598 100644 --- a/res/content/base/generators/demo.files/biomes.json +++ b/res/content/base/generators/demo.files/biomes.json @@ -28,7 +28,7 @@ }, "desert": { "parameters": [ - {"weight": 0.1, "value": 0}, + {"weight": 0.3, "value": 0}, {"weight": 0.1, "value": 0} ], "layers": [ diff --git a/res/content/base/generators/demo.files/script.lua b/res/content/base/generators/demo.files/script.lua index 7c103090..4b87f041 100644 --- a/res/content/base/generators/demo.files/script.lua +++ b/res/content/base/generators/demo.files/script.lua @@ -1,13 +1,3 @@ --- Get entry-point and filename from `entry-point:filename` path --- // TODO: move to stdmin -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 - local _, dir = parse_path(__DIR__) ores = file.read_combined_list(dir.."/ores.json") @@ -45,7 +35,7 @@ function place_structures(x, z, w, d, seed, hmap, chunk_height) local sz = z + math.random() * 20 - 10 local ez = z + math.random() * 20 - 10 table.insert(placements, - {":line", 0, {sx - 10, sy, sz - 10}, {ex + 10, ey, ez + 10}, 3}) + {":line", 0, {sx - 10, sy, sz - 10}, {ex + 10, ey, ez + 10}, math.random()*2+2}) end return placements end diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 32dcc653..f6e2603a 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -1,24 +1,6 @@ --- 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 - --- 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 +------------------------------------------------ +------ Extended kit of standard functions ------ +------------------------------------------------ package = { loaded={} @@ -92,20 +74,6 @@ function sleep(timesec) end end -function pack.is_installed(packid) - return file.isfile(packid..":package.json") -end - -function pack.data_file(packid, name) - file.mkdirs("world:data/"..packid) - return "world:data/"..packid.."/"..name -end - -function pack.shared_file(packid, name) - file.mkdirs("config:"..packid) - return "config:"..packid.."/"..name -end - -- events events = { handlers = {} @@ -233,59 +201,6 @@ function session.reset_entry(name) session.entries[name] = nil end -function timeit(iters, func, ...) - local tm = time.uptime() - for i=1,iters do - func(...) - end - print("[time mcs]", (time.uptime()-tm) * 1000000) -end - -function table.has(t, x) - for i,v in ipairs(t) do - if v == x then - return true - end - end - return false -end - -function table.index(t, x) - for i,v in ipairs(t) do - if v == x then - return i - end - end - return -1 -end - -function table.remove_value(t, x) - local index = table.index(t, x) - if index ~= -1 then - table.remove(t, index) - end -end - -function table.tostring(t) - local s = '[' - for i,v in ipairs(t) do - s = s..tostring(v) - if i < #t then - s = s..', ' - end - end - return s..']' -end - -function file.readlines(path) - local str = file.read(path) - local lines = {} - for s in str:gmatch("[^\r\n]+") do - table.insert(lines, s) - end - return lines -end - stdcomp = require "core:internal/stdcomp" entities.get = stdcomp.get_Entity entities.get_all = function(uids) @@ -302,145 +217,6 @@ end math.randomseed(time.uptime() * 1536227939) ----------------------------------------------- - -function math.clamp(_in, low, high) - return math.min(math.max(_in, low), high) -end - -function math.rand(low, high) - return low + (high - low) * math.random() -end - ----------------------------------------------- - -function table.copy(t) - local copied = {} - - for k, v in pairs(t) do - copied[k] = v - end - - return copied -end - -function table.count_pairs(t) - local count = 0 - - for k, v in pairs(t) do - count = count + 1 - end - - return count -end - -function table.random(t) - return t[math.random(1, #t)] -end - ----------------------------------------------- - -local pattern_escape_replacements = { - ["("] = "%(", - [")"] = "%)", - ["."] = "%.", - ["%"] = "%%", - ["+"] = "%+", - ["-"] = "%-", - ["*"] = "%*", - ["?"] = "%?", - ["["] = "%[", - ["]"] = "%]", - ["^"] = "%^", - ["$"] = "%$", - ["\0"] = "%z" -} - -function string.pattern_safe(str) - return string.gsub(str, ".", pattern_escape_replacements) -end - ---local totable = string.ToTable -local string_sub = string.sub -local string_find = string.find -local string_len = string.len -function string.explode(separator, str, withpattern) - --if (separator == "") then return totable(str) end - if (withpattern == nil) then withpattern = false end - - local ret = {} - local current_pos = 1 - - for i = 1, string_len(str) do - local start_pos, end_pos = string_find(str, separator, current_pos, not withpattern) - if (not start_pos) then break end - ret[i] = string_sub(str, current_pos, start_pos - 1) - current_pos = end_pos + 1 - end - - ret[#ret + 1] = string_sub(str, current_pos) - - return ret -end - -function string.split(str, delimiter) - return string.explode(delimiter, str) -end - -function string.formatted_time(seconds, format) - if (not seconds) then seconds = 0 end - local hours = math.floor(seconds / 3600) - local minutes = math.floor((seconds / 60) % 60) - local millisecs = (seconds - math.floor(seconds)) * 1000 - seconds = math.floor(seconds % 60) - - if (format) then - return string.format(format, minutes, seconds, millisecs) - else - return { h = hours, m = minutes, s = seconds, ms = millisecs } - end -end - -function string.replace(str, tofind, toreplace) - local tbl = string.Explode(tofind, str) - if (tbl[1]) then return table.concat(tbl, toreplace) end - return str -end - -function string.trim(s, char) - if char then char = string.pattern_safe(char) else char = "%s" end - return string.match(s, "^" .. char .. "*(.-)" .. char .. "*$") or s -end - -function string.trim_right(s, char) - if char then char = string.pattern_safe(char) else char = "%s" end - return string.match(s, "^(.-)" .. char .. "*$") or s -end - -function string.trim_left(s, char) - if char then char = string.pattern_safe(char) else char = "%s" end - return string.match(s, "^" .. char .. "*(.+)$") or s -end - -local meta = getmetatable("") - -function meta:__index(key) - local val = string[key] - if (val ~= nil) then - return val - elseif (tonumber(key)) then - return string.sub(self, key, key) - end -end - -function string.starts_with(str, start) - return string.sub(str, 1, string.len(start)) == start -end - -function string.ends_with(str, endStr) - return endStr == "" or string.sub(str, -string.len(endStr)) == endStr -end - -- --------- Deprecated functions ------ -- local function wrap_deprecated(func, name, alternatives) return function (...) diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua new file mode 100644 index 00000000..9fd982bc --- /dev/null +++ b/res/scripts/stdmin.lua @@ -0,0 +1,224 @@ +-- 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 + +-- 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 + +function pack.is_installed(packid) + return file.isfile(packid..":package.json") +end + +function pack.data_file(packid, name) + file.mkdirs("world:data/"..packid) + return "world:data/"..packid.."/"..name +end + +function pack.shared_file(packid, name) + file.mkdirs("config:"..packid) + return "config:"..packid.."/"..name +end + + +function timeit(iters, func, ...) + local tm = time.uptime() + for i=1,iters do + func(...) + end + print("[time mcs]", (time.uptime()-tm) * 1000000) +end + +---------------------------------------------- + +function math.clamp(_in, low, high) + return math.min(math.max(_in, low), high) +end + +function math.rand(low, high) + return low + (high - low) * math.random() +end + +---------------------------------------------- + +function table.copy(t) + local copied = {} + + for k, v in pairs(t) do + copied[k] = v + end + + return copied +end + +function table.count_pairs(t) + local count = 0 + + for k, v in pairs(t) do + count = count + 1 + end + + return count +end + +function table.random(t) + return t[math.random(1, #t)] +end + +---------------------------------------------- + +local pattern_escape_replacements = { + ["("] = "%(", + [")"] = "%)", + ["."] = "%.", + ["%"] = "%%", + ["+"] = "%+", + ["-"] = "%-", + ["*"] = "%*", + ["?"] = "%?", + ["["] = "%[", + ["]"] = "%]", + ["^"] = "%^", + ["$"] = "%$", + ["\0"] = "%z" +} + +function string.pattern_safe(str) + return string.gsub(str, ".", pattern_escape_replacements) +end + +local string_sub = string.sub +local string_find = string.find +local string_len = string.len +function string.explode(separator, str, withpattern) + if (withpattern == nil) then withpattern = false end + + local ret = {} + local current_pos = 1 + + for i = 1, string_len(str) do + local start_pos, end_pos = string_find(str, separator, current_pos, not withpattern) + if (not start_pos) then break end + ret[i] = string_sub(str, current_pos, start_pos - 1) + current_pos = end_pos + 1 + end + + ret[#ret + 1] = string_sub(str, current_pos) + + return ret +end + +function string.split(str, delimiter) + return string.explode(delimiter, str) +end + +function string.formatted_time(seconds, format) + if (not seconds) then seconds = 0 end + local hours = math.floor(seconds / 3600) + local minutes = math.floor((seconds / 60) % 60) + local millisecs = (seconds - math.floor(seconds)) * 1000 + seconds = math.floor(seconds % 60) + + if (format) then + return string.format(format, minutes, seconds, millisecs) + else + return { h = hours, m = minutes, s = seconds, ms = millisecs } + end +end + +function string.replace(str, tofind, toreplace) + local tbl = string.Explode(tofind, str) + if (tbl[1]) then return table.concat(tbl, toreplace) end + return str +end + +function string.trim(s, char) + if char then char = string.pattern_safe(char) else char = "%s" end + return string.match(s, "^" .. char .. "*(.-)" .. char .. "*$") or s +end + +function string.trim_right(s, char) + if char then char = string.pattern_safe(char) else char = "%s" end + return string.match(s, "^(.-)" .. char .. "*$") or s +end + +function string.trim_left(s, char) + if char then char = string.pattern_safe(char) else char = "%s" end + return string.match(s, "^" .. char .. "*(.+)$") or s +end + +local meta = getmetatable("") + +function meta:__index(key) + local val = string[key] + if (val ~= nil) then + return val + elseif (tonumber(key)) then + return string.sub(self, key, key) + end +end + +function string.starts_with(str, start) + return string.sub(str, 1, string.len(start)) == start +end + +function string.ends_with(str, endStr) + return endStr == "" or string.sub(str, -string.len(endStr)) == endStr +end + +function table.has(t, x) + for i,v in ipairs(t) do + if v == x then + return true + end + end + return false +end + +function table.index(t, x) + for i,v in ipairs(t) do + if v == x then + return i + end + end + return -1 +end + +function table.remove_value(t, x) + local index = table.index(t, x) + if index ~= -1 then + table.remove(t, index) + end +end + +function table.tostring(t) + local s = '[' + for i,v in ipairs(t) do + s = s..tostring(v) + if i < #t then + s = s..', ' + end + end + return s..']' +end + +function file.readlines(path) + local str = file.read(path) + local lines = {} + for s in str:gmatch("[^\r\n]+") do + table.insert(lines, s) + end + return lines +end diff --git a/src/logic/scripting/lua/lua_engine.cpp b/src/logic/scripting/lua/lua_engine.cpp index b6cd8446..4c5e9856 100644 --- a/src/logic/scripting/lua/lua_engine.cpp +++ b/src/logic/scripting/lua/lua_engine.cpp @@ -3,6 +3,8 @@ #include #include +#include "files/files.hpp" +#include "files/engine_paths.hpp" #include "debug/Logger.hpp" #include "util/stringutil.hpp" #include "libs/api_lua.hpp" @@ -104,11 +106,11 @@ void lua::init_state(State* L, StateType stateType) { newusertype(L); } -void lua::initialize() { +void lua::initialize(const EnginePaths& paths) { logger.info() << LUA_VERSION; logger.info() << LUAJIT_VERSION; - main_thread = create_state(StateType::BASE); + main_thread = create_state(paths, StateType::BASE); } void lua::finalize() { @@ -131,11 +133,15 @@ State* lua::get_main_state() { return main_thread; } -State* lua::create_state(StateType stateType) { +State* lua::create_state(const EnginePaths& paths, StateType stateType) { auto L = luaL_newstate(); if (L == nullptr) { throw luaerror("could not initialize Lua state"); } init_state(L, stateType); + + auto resDir = paths.getResourcesFolder(); + auto src = files::read_string(resDir / fs::u8path("scripts/stdmin.lua")); + lua::pop(L, lua::execute(L, 0, src, "")); return L; } diff --git a/src/logic/scripting/lua/lua_engine.hpp b/src/logic/scripting/lua/lua_engine.hpp index 494de626..dd1e794d 100644 --- a/src/logic/scripting/lua/lua_engine.hpp +++ b/src/logic/scripting/lua/lua_engine.hpp @@ -7,13 +7,15 @@ #include "logic/scripting/scripting_functional.hpp" #include "lua_util.hpp" +class EnginePaths; + namespace lua { enum class StateType { BASE, GENERATOR, }; - void initialize(); + void initialize(const EnginePaths& paths); void finalize(); bool emit_event( @@ -22,7 +24,7 @@ namespace lua { std::function args = [](auto*) { return 0; } ); State* get_main_state(); - State* create_state(StateType stateType); + State* create_state(const EnginePaths& paths, StateType stateType); [[nodiscard]] scriptenv create_environment(State* L); void init_state(State* L, StateType stateType); diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index eaab27d3..42120534 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -62,7 +62,7 @@ int scripting::load_script( void scripting::initialize(Engine* engine) { scripting::engine = engine; - lua::initialize(); + lua::initialize(*engine->getPaths()); load_script(fs::path("stdlib.lua"), true); load_script(fs::path("stdcmd.lua"), true); diff --git a/src/logic/scripting/scripting_world_generation.cpp b/src/logic/scripting/scripting_world_generation.cpp index 7a872e18..43e041c1 100644 --- a/src/logic/scripting/scripting_world_generation.cpp +++ b/src/logic/scripting/scripting_world_generation.cpp @@ -14,6 +14,7 @@ #include "world/generator/GeneratorDef.hpp" #include "util/timeutil.hpp" #include "files/files.hpp" +#include "engine.hpp" #include "debug/Logger.hpp" using namespace lua; @@ -167,7 +168,7 @@ public: std::unique_ptr scripting::load_generator( const GeneratorDef& def, const fs::path& file, const std::string& dirPath ) { - auto L = create_state(StateType::GENERATOR); + auto L = create_state(*engine->getPaths(), StateType::GENERATOR); auto env = create_environment(L); stackguard _(L);