diff --git a/Chat Commands.md b/Chat Commands.md index 81d19c1..7f6eeb0 100644 --- a/Chat Commands.md +++ b/Chat Commands.md @@ -235,20 +235,6 @@ Load nodes from "(world folder)/schems/.we" with position 1 of the current //load some random filename //load huge_base -### //metasave - -Save the current WorldEdit region including metadata to "(world folder)/schems/.wem". - - //metasave some random filename - //metasave huge_base - -### //metaload - -Load nodes and metadata from "(world folder)/schems/.wem" with position 1 of the current WorldEdit region as the origin. - - //metaload some random filename - //metaload huge_base - ### //lua Executes as a Lua chunk in the global namespace. diff --git a/WorldEdit API.md b/WorldEdit API.md index e033150..464a719 100644 --- a/WorldEdit API.md +++ b/WorldEdit API.md @@ -152,6 +152,12 @@ Serialization ------------- Contained in serialization.lua, this module allows regions of nodes to be serialized and deserialized to formats suitable for use outside MineTest. +### version = worldedit.valueversion(value) + +Determines the version of serialized data `value`. + +Returns the version as a positive integer or 0 for unknown versions. + ### data, count = worldedit.serialize(pos1, pos2) Converts the region defined by positions `pos1` and `pos2` into a single string. @@ -170,26 +176,6 @@ Loads the nodes represented by string `value` at position `originpos`. Returns the number of nodes deserialized. -### count = worldedit.deserialize_old(originpos, value) - -Loads the nodes represented by string `value` at position `originpos`, using the older table-based WorldEdit format. - -This function is deprecated, and should not be used unless there is a need to support legacy WorldEdit save files. - -Returns the number of nodes deserialized. - -### count = worldedit.metasave(pos1, pos2, file) - -Saves the nodes and meta defined by positions `pos1` and `pos2` into a file. - -Returns the number of nodes saved. - -### count = worldedit.metaload(pos1, file) - -Loads the nodes and meta from `file` to position `pos1`. - -Returns the number of nodes loaded. - Code ---- Contained in code.lua, this module allows arbitrary Lua code to be used with WorldEdit. diff --git a/worldedit/compatibility.lua b/worldedit/compatibility.lua new file mode 100644 index 0000000..3b9c889 --- /dev/null +++ b/worldedit/compatibility.lua @@ -0,0 +1,17 @@ +worldedit.allocate_old = worldedit.allocate +worldedit.deserialize_old = worldedit.deserialize +worldedit.metasave = function(pos1, pos2, filename) + local file, err = io.open(filename, "wb") + if err then return 0 end + local data, count = worldedit.serialize(pos1, pos2) + file:write(data) + file:close() + return count +end +worldedit.metaload = function(originpos, filename) + filename = minetest.get_worldpath() .. "/schems/" .. file .. ".wem" + local file, err = io.open(filename, "wb") + if err then return 0 end + local data = file:read("*a") + return worldedit.deserialize(originpos, data) +end \ No newline at end of file diff --git a/worldedit/serialization.lua b/worldedit/serialization.lua index cb65240..c876261 100644 --- a/worldedit/serialization.lua +++ b/worldedit/serialization.lua @@ -1,7 +1,5 @@ worldedit = worldedit or {} -dofile(minetest.get_modpath("worldedit") .. "/table_save.lua") --wip: remove dependency - --modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions worldedit.sort_pos = function(pos1, pos2) pos1 = {x=pos1.x, y=pos1.y, z=pos1.z} @@ -18,175 +16,23 @@ worldedit.sort_pos = function(pos1, pos2) return pos1, pos2 end +--determines the version of serialized data `value`, returning the version as a positive integer or 0 for unknown versions +worldedit.valueversion = function(value) + if value:find("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)") and not value:find("%{") then --previous list format + return 3 + elseif value:find("^[^\"']+%{%d+%}") then + if value:find("%[\"meta\"%]") then --previous meta flat table format + return 2 + end + return 1 --original flat table format + elseif value:find("%{") then --current nested table format + return 4 + end + return 0 --unknown format +end + --converts the region defined by positions `pos1` and `pos2` into a single string, returning the serialized data and the number of nodes serialized -worldedit.serialize = function(pos1, pos2) - local pos1, pos2 = worldedit.sort_pos(pos1, pos2) - local pos = {x=pos1.x, y=0, z=0} - local count = 0 - local result = {} - local env = minetest.env - while pos.x <= pos2.x do - pos.y = pos1.y - while pos.y <= pos2.y do - pos.z = pos1.z - while pos.z <= pos2.z do - local node = env:get_node(pos) - if node.name ~= "air" and node.name ~= "ignore" then - count = count + 1 - result[count] = pos.x - pos1.x .. " " .. pos.y - pos1.y .. " " .. pos.z - pos1.z .. " " .. node.name .. " " .. node.param1 .. " " .. node.param2 - end - pos.z = pos.z + 1 - end - pos.y = pos.y + 1 - end - pos.x = pos.x + 1 - end - result = table.concat(result, "\n") --join all node entries into single string - return result, count -end - ---determines the volume the nodes represented by string `value` would occupy if deserialized at `originpos`, returning the two corner positions and the number of nodes -worldedit.allocate = function(originpos, value) - local huge = math.huge - local pos1 = {x=huge, y=huge, z=huge} - local pos2 = {x=-huge, y=-huge, z=-huge} - local originx, originy, originz = originpos.x, originpos.y, originpos.z - local count = 0 - for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries - x, y, z = originx + tonumber(x), originy + tonumber(y), originz + tonumber(z) - if x < pos1.x then - pos1.x = x - end - if y < pos1.y then - pos1.y = y - end - if z < pos1.z then - pos1.z = z - end - if x > pos2.x then - pos2.x = x - end - if y > pos2.y then - pos2.y = y - end - if z > pos2.z then - pos2.z = z - end - count = count + 1 - end - return pos1, pos2, count -end - ---loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized -worldedit.deserialize = function(originpos, value) - local pos = {x=0, y=0, z=0} - local node = {name="", param1=0, param2=0} - local originx, originy, originz = originpos.x, originpos.y, originpos.z - local count = 0 - local env = minetest.env - for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries - pos.x = originx + tonumber(x) - pos.y = originy + tonumber(y) - pos.z = originz + tonumber(z) - node.name = name - node.param1 = param1 - node.param2 = param2 - env:add_node(pos, node) - count = count + 1 - end - return count -end - ---determines the volume the nodes represented by string `value` would occupy if deserialized at `originpos`, returning the two corner positions and the number of nodes ---based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible) -worldedit.allocate_old = function(originpos, value) - --obtain the node table - local count = 0 - local get_tables = loadstring(value) - if get_tables == nil then --error loading value - return count - end - local tables = get_tables() - - --transform the node table into an array of nodes - for i = 1, #tables do - for j, v in pairs(tables[i]) do - if type(v) == "table" then - tables[i][j] = tables[v[1]] - end - end - end - - local huge = math.huge - local pos1 = {x=huge, y=huge, z=huge} - local pos2 = {x=-huge, y=-huge, z=-huge} - local originx, originy, originz = originpos.x, originpos.y, originpos.z - - --load the node array - for i, v in ipairs(tables[1]) do - local pos = v[1] - local x, y, z = originx - pos.x, originy - pos.y, originz - pos.z - if x < pos1.x then - pos1.x = x - end - if y < pos1.y then - pos1.y = y - end - if z < pos1.z then - pos1.z = z - end - if x > pos2.x then - pos2.x = x - end - if y > pos2.y then - pos2.y = y - end - if z > pos2.z then - pos2.z = z - end - count = count + 1 - end - return pos1, pos2, count -end - ---loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized ---based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible) -worldedit.deserialize_old = function(originpos, value) - --obtain the node table - local count = 0 - local get_tables = loadstring(value) - if get_tables == nil then --error loading value - return count - end - local tables = get_tables() - - --transform the node table into an array of nodes - for i = 1, #tables do - for j, v in pairs(tables[i]) do - if type(v) == "table" then - tables[i][j] = tables[v[1]] - end - end - end - - --load the node array - local env = minetest.env - local originx, originy, originz = originpos.x, originpos.y, originpos.z - for i, v in ipairs(tables[1]) do - local pos = v[1] - pos.x, pos.y, pos.z = originx - pos.x, originy - pos.y, originz - pos.z - env:add_node(pos, v[2]) - count = count + 1 - end - return count -end - ---saves the nodes and meta defined by positions `pos1` and `pos2` into a file, returning the number of nodes saved -worldedit.metasave = function(pos1, pos2, file) --wip: simply work with strings instead of doing IO - local path = minetest.get_worldpath() .. "/schems" - local filename = path .. "/" .. file .. ".wem" - os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist - local rows = {} +worldedit.serialize = function(pos1, pos2) --wip: check for ItemStacks and whether they can be serialized local pos1, pos2 = worldedit.sort_pos(pos1, pos2) local pos = {x=pos1.x, y=0, z=0} local count = 0 @@ -201,23 +47,15 @@ worldedit.metasave = function(pos1, pos2, file) --wip: simply work with strings if node.name ~= "air" and node.name ~= "ignore" then count = count + 1 local meta = env:get_meta(pos):to_table() - - --convert metadata itemstacks to itemstrings - for i, v in pairs(meta.inventory) do - for index, items in ipairs(v) do - v[index] = items:to_string() - end - end - - table.insert(rows, { - x = pos.x-pos1.x, - y = pos.y-pos1.y, - z = pos.z-pos1.z, + result[count] = { + x = pos.x - pos1.x, + y = pos.y - pos1.y, + z = pos.z - pos1.z, name = node.name, param1 = node.param1, param2 = node.param2, meta = meta, - }) + } end pos.z = pos.z + 1 end @@ -225,30 +63,157 @@ worldedit.metasave = function(pos1, pos2, file) --wip: simply work with strings end pos.x = pos.x + 1 end - local err = table.save(rows, filename) - if err then return _, err end - return count + result = minetest.serialize(result) --convert entries to a string + return result, count end ---loads the nodes and meta from `file` to position `pos1`, returning the number of nodes loaded -worldedit.metaload = function(pos1, file) --wip: simply work with strings instead of doing IO - local filename = minetest.get_worldpath() .. "/schems/" .. file .. ".wem" - local rows, err = table.load(filename) - if err then return _,err end - local pos = {x=0, y=0, z=0} - local node = {name="", param1=0, param2=0} +--determines the volume the nodes represented by string `value` would occupy if deserialized at `originpos`, returning the two corner positions and the number of nodes +--contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible) +worldedit.allocate = function(originpos, value) + local huge = math.huge + local pos1x, pos1y, pos1z = huge, huge, huge + local pos2x, pos2y, pos2z = -huge, -huge, -huge + local originx, originy, originz = originpos.x, originpos.y, originpos.z + local count = 0 + local version = worldedit.valueversion(value) + if version == 1 or version == 2 then --flat table format + --obtain the node table + local get_tables = loadstring(value) + if get_tables then --error loading value + return originpos, originpos, count + end + local tables = get_tables() + + --transform the node table into an array of nodes + for i = 1, #tables do + for j, v in pairs(tables[i]) do + if type(v) == "table" then + tables[i][j] = tables[v[1]] + end + end + end + local nodes = tables[1] + + --check the node array + count = #nodes + if version == 1 then --original flat table format + for index = 1, count do + local entry = nodes[index] + local pos = entry[1] + local x, y, z = originx - pos.x, originy - pos.y, originz - pos.z + if x < pos1x then pos1x = x end + if y < pos1y then pos1y = y end + if z < pos1z then pos1z = z end + if x > pos2x then pos2x = x end + if y > pos2y then pos2y = y end + if z > pos2z then pos2z = z end + end + else --previous meta flat table format + for index = 1, count do + local entry = nodes[index] + local x, y, z = originx - entry.x, originy - entry.y, originz - entry.z + if x < pos1x then pos1x = x end + if y < pos1y then pos1y = y end + if z < pos1z then pos1z = z end + if x > pos2x then pos2x = x end + if y > pos2y then pos2y = y end + if z > pos2z then pos2z = z end + end + end + elseif version == 3 then --previous list format + for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries + x, y, z = originx + tonumber(x), originy + tonumber(y), originz + tonumber(z) + if x < pos1x then pos1x = x end + if y < pos1y then pos1y = y end + if z < pos1z then pos1z = z end + if x > pos2x then pos2x = x end + if y > pos2y then pos2y = y end + if z > pos2z then pos2z = z end + count = count + 1 + end + elseif version == 4 then --current nested table format + local nodes = minetest.deserialize(value) + count = #nodes + for index = 1, count do + local entry = nodes[index] + x, y, z = originx + entry.x, originy + entry.y, originz + entry.z + if x < pos1x then pos1x = x end + if y < pos1y then pos1y = y end + if z < pos1z then pos1z = z end + if x > pos2x then pos2x = x end + if y > pos2y then pos2y = y end + if z > pos2z then pos2z = z end + end + end + local pos1 = {x=pos1x, y=pos1y, z=pos1z} + local pos2 = {x=pos2x, y=pos2y, z=pos2z} + return pos1, pos2, count +end + +--loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized +--contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible) +worldedit.deserialize = function(originpos, value) + local originx, originy, originz = originpos.x, originpos.y, originpos.z local count = 0 local env = minetest.env - for i,row in pairs(rows) do - pos.x = pos1.x + tonumber(row.x) - pos.y = pos1.y + tonumber(row.y) - pos.z = pos1.z + tonumber(row.z) - node.name = row.name - node.param1 = row.param1 - node.param2 = row.param2 - env:add_node(pos, node) - env:get_meta(pos):from_table(row.meta) - count = count + 1 + local version = worldedit.valueversion(value) + if version == 1 or version == 2 then --original flat table format + --obtain the node table + local get_tables = loadstring(value) + if not get_tables then --error loading value + return count + end + local tables = get_tables() + + --transform the node table into an array of nodes + for i = 1, #tables do + for j, v in pairs(tables[i]) do + if type(v) == "table" then + tables[i][j] = tables[v[1]] + end + end + end + local nodes = tables[1] + + --load the node array + count = #nodes + if version == 1 then --original flat table format + for index = 1, count do + local entry = nodes[index] + local pos = entry[1] + pos.x, pos.y, pos.z = originx - pos.x, originy - pos.y, originz - pos.z + env:add_node(pos, entry[2]) + end + else --previous meta flat table format + for index = 1, #nodes do + local entry = nodes[index] + entry.x, entry.y, entry.z = originx + entry.x, originy + entry.y, originz + entry.z + env:add_node(entry, entry) --entry acts both as position and as node + env:get_meta(entry):from_table(entry.meta) + end + end + elseif version == 3 then --previous list format + local pos = {x=0, y=0, z=0} + local node = {name="", param1=0, param2=0} + for x, y, z, name, param1, param2 in value:gmatch("([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)%s+([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do --match node entries + pos.x = originx + tonumber(x) + pos.y = originy + tonumber(y) + pos.z = originz + tonumber(z) + node.name = name + node.param1 = param1 + node.param2 = param2 + env:add_node(pos, node) + count = count + 1 + end + elseif version == 4 then --current nested table format + local nodes = minetest.deserialize(value) + count = #nodes + for index = 1, count do + local entry = nodes[index] + entry.x, entry.y, entry.z = originx + entry.x, originy + entry.y, originz + entry.z + env:add_node(entry, entry) --entry acts both as position and as node + env:get_meta(entry):from_table(entry.meta) + end end return count end \ No newline at end of file diff --git a/worldedit/table serialize (WIP).lua b/worldedit/table serialize (WIP).lua deleted file mode 100644 index 6947c0b..0000000 --- a/worldedit/table serialize (WIP).lua +++ /dev/null @@ -1,15 +0,0 @@ -serialize_meta = function(pos) - local insert, format, concat = table.insert, string.format, table.concat - --wip: do recursive serialize - - local meta = env:get_meta(pos):to_table() - local fields = {} - for key, value in pairs(meta.fields) do - insert(fields, format("%q", key) .. format("%q", value)) - end - return concat(meta.inventory, ",") .. concat(fields) -end - -deserialize_meta = function(value) - --wip -end \ No newline at end of file diff --git a/worldedit/table_save.lua b/worldedit/table_save.lua deleted file mode 100644 index cbc18ae..0000000 --- a/worldedit/table_save.lua +++ /dev/null @@ -1,133 +0,0 @@ ---[[ - Save Table to File - Load Table from File - v 1.0 - - Lua 5.2 compatible - - Only Saves Tables, Numbers and Strings - Insides Table References are saved - Does not save Userdata, Metatables, Functions and indices of these - ---------------------------------------------------- - table.save( table , filename ) - - on failure: returns an error msg - - ---------------------------------------------------- - table.load( filename or stringtable ) - - Loads a table that has been saved via the table.save function - - on success: returns a previously saved table - on failure: returns as second argument an error msg - ---------------------------------------------------- - - Licensed under the same terms as Lua itself. -]]-- -do - -- declare local variables - --// exportstring( string ) - --// returns a "Lua" portable version of the string - local function exportstring( s ) - return string.format("%q", s) - end - - --// The Save Function - function table.save( tbl,filename ) - local charS,charE = " ","\n" - local file,err = io.open( filename, "wb" ) - if err then return err end - - -- initiate variables for save procedure - local tables,lookup = { tbl },{ [tbl] = 1 } - file:write( "return {"..charE ) - - for idx,t in ipairs( tables ) do - file:write( "-- Table: {"..idx.."}"..charE ) - file:write( "{"..charE ) - local thandled = {} - - for i,v in ipairs( t ) do - thandled[i] = true - local stype = type( v ) - -- only handle value - if stype == "table" then - if not lookup[v] then - table.insert( tables, v ) - lookup[v] = #tables - end - file:write( charS.."{"..lookup[v].."},"..charE ) - elseif stype == "string" then - file:write( charS..exportstring( v )..","..charE ) - elseif stype == "number" then - file:write( charS..tostring( v )..","..charE ) - end - end - - for i,v in pairs( t ) do - -- escape handled values - if (not thandled[i]) then - - local str = "" - local stype = type( i ) - -- handle index - if stype == "table" then - if not lookup[i] then - table.insert( tables,i ) - lookup[i] = #tables - end - str = charS.."[{"..lookup[i].."}]=" - elseif stype == "string" then - str = charS.."["..exportstring( i ).."]=" - elseif stype == "number" then - str = charS.."["..tostring( i ).."]=" - end - - if str ~= "" then - stype = type( v ) - -- handle value - if stype == "table" then - if not lookup[v] then - table.insert( tables,v ) - lookup[v] = #tables - end - file:write( str.."{"..lookup[v].."},"..charE ) - elseif stype == "string" then - file:write( str..exportstring( v )..","..charE ) - elseif stype == "number" then - file:write( str..tostring( v )..","..charE ) - end - end - end - end - file:write( "},"..charE ) - end - file:write( "}" ) - file:close() - end - - --// The Load Function - function table.load( sfile ) - local ftables,err = loadfile( sfile ) - if err then return _,err end - local tables = ftables() - for idx = 1,#tables do - local tolinki = {} - for i,v in pairs( tables[idx] ) do - if type( v ) == "table" then - tables[idx][i] = tables[v[1]] - end - if type( i ) == "table" and tables[i[1]] then - table.insert( tolinki,{ i,tables[i[1]] } ) - end - end - -- link indices - for _,v in ipairs( tolinki ) do - tables[idx][v[2]],tables[idx][v[1]] = tables[idx][v[1]],nil - end - end - return tables[1] - end --- close do -end --- ChillCode \ No newline at end of file diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 67f50e3..208eb5d 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -750,12 +750,11 @@ minetest.register_chatcommand("/allocate", { local value = file:read("*a") file:close() - local nodepos1, nodepos2, count - if value:find("{") then --old WorldEdit format - nodepos1, nodepos2, count = worldedit.allocate_old(pos1, value) - else --new WorldEdit format - nodepos1, nodepos2, count = worldedit.allocate(pos1, value) + if worldedit.valueversion(value) == 0 then --unknown version + minetest.chat_send_player(name, "Invalid file: file is invalid or created with newer version of WorldEdit") + return end + local nodepos1, nodepos2, count = worldedit.allocate(pos1, value) worldedit.pos1[name] = nodepos1 worldedit.mark_pos1(name) @@ -768,7 +767,7 @@ minetest.register_chatcommand("/allocate", { minetest.register_chatcommand("/load", { params = "", - description = "Load nodes from \"(world folder)/schems/.we\" with position 1 of the current WorldEdit region as the origin", + description = "Load nodes from \"(world folder)/schems/[.we[m]]\" with position 1 of the current WorldEdit region as the origin", privs = {worldedit=true}, func = function(name, param) local pos1 = worldedit.pos1[name] @@ -782,72 +781,36 @@ minetest.register_chatcommand("/load", { return end - local filename = minetest.get_worldpath() .. "/schems/" .. param .. ".we" - local file, err = io.open(filename, "rb") - if err ~= nil then - minetest.chat_send_player(name, "Could not open file \"" .. filename .. "\"") + --find the file in the world path + local testpaths = { + minetest.get_worldpath() .. "/schems/" .. param, + minetest.get_worldpath() .. "/schems/" .. param .. ".we", + minetest.get_worldpath() .. "/schems/" .. param .. ".wem", + } + local file, err + for index, path in ipairs(testpaths) do + file, err = io.open(path, "rb") + if not err then + break + end + end + if err then + minetest.chat_send_player(name, "Could not open file \"" .. param .. "\"") return end local value = file:read("*a") file:close() - local count - if value:find("{") then --old WorldEdit format - count = worldedit.deserialize_old(pos1, value) - else --new WorldEdit format - count = worldedit.deserialize(pos1, value) + if worldedit.valueversion(value) == 0 then --unknown version + minetest.chat_send_player(name, "Invalid file: file is invalid or created with newer version of WorldEdit") + return end + local count = worldedit.deserialize(pos1, value) minetest.chat_send_player(name, count .. " nodes loaded") end, }) -minetest.register_chatcommand("/metasave", { - params = "", - description = "Save the current WorldEdit region to \"(world folder)/schems/.wem\"", - privs = {worldedit=true}, - func = function(name, param) - local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] - if pos1 == nil or pos2 == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") - return - end - if param == "" then - minetest.chat_send_player(name, "Invalid usage: " .. param) - return - end - local count, err = worldedit.metasave(pos1, pos2, param) - if err then - minetest.chat_send_player(name, "error loading file: " .. err) - else - minetest.chat_send_player(name, count .. " nodes saved") - end - end, -}) - -minetest.register_chatcommand("/metaload", { - params = "", - description = "Load nodes from \"(world folder)/schems/.wem\" with position 1 of the current WorldEdit region as the origin", - privs = {worldedit=true}, - func = function(name, param) - local pos1 = worldedit.pos1[name] - if pos1 == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") - return - end - if param == "" then - minetest.chat_send_player(name, "Invalid usage: " .. param) - return - end - local count, err = worldedit.metaload(pos1, param) - if err then - minetest.chat_send_player(name, "Error loading file: " .. err) - else - minetest.chat_send_player(name, count .. " nodes loaded") - end - end, -}) - minetest.register_chatcommand("/lua", { params = "", description = "Executes as a Lua chunk in the global namespace",