X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=worldedit_commands%2Finit.lua;h=99776740baaf6edb55e56c40fab7a417696cee3b;hb=d5ec1bcefc128b3de7b7f9cfdc99a1bf146d0a6b;hp=3931df0695de9eeef30c1c6fcb34ace28c90703d;hpb=aa4a70d237db22b587d46a50a21d1a71a445874e;p=worldedit.git diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 3931df0..9977674 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -1,21 +1,44 @@ minetest.register_privilege("worldedit", "Can use WorldEdit commands") worldedit.set_pos = {} +worldedit.inspect = {} worldedit.pos1 = {} worldedit.pos2 = {} +if minetest.place_schematic then + worldedit.prob_pos = {} + worldedit.prob_list = {} +end dofile(minetest.get_modpath("worldedit_commands") .. "/mark.lua") +worldedit.player_notify = function(name, message) + minetest.chat_send_player(name, "WorldEdit -!- " .. message, false) +end + --determines whether `nodename` is a valid node name, returning a boolean -worldedit.node_is_valid = function(nodename) - return minetest.registered_nodes[nodename] ~= nil - or minetest.registered_nodes["default:" .. nodename] ~= nil +worldedit.normalize_nodename = function(nodename) + local fullname = ItemStack({name=nodename}):get_name() --resolve aliases of node names to full names + if minetest.registered_nodes[fullname] then --directly found node name or alias of nodename + return fullname + end + for key, value in pairs(minetest.registered_nodes) do + if key:find(":" .. nodename, 1, true) then --found in mod + return key + end + end + nodename = nodename:lower() --lowercase both for case insensitive comparison + for key, value in pairs(minetest.registered_nodes) do + if value.description:lower() == nodename then --found in description + return key + end + end + return nil end --determines the axis in which a player is facing, returning an axis ("x", "y", or "z") and the sign (1 or -1) worldedit.player_axis = function(name) - local dir = minetest.env:get_player_by_name(name):get_look_dir() + local dir = minetest.get_player_by_name(name):get_look_dir() local x, y, z = math.abs(dir.x), math.abs(dir.y), math.abs(dir.z) if x > y then if x > z then @@ -27,6 +50,43 @@ worldedit.player_axis = function(name) return "z", dir.z > 0 and 1 or -1 end +minetest.register_chatcommand("/about", { + params = "", + description = "Get information about the mod", + func = function(name, param) + worldedit.player_notify(name, "WorldEdit 1.0 is available on this server. Type /help to get a list of commands, or get more information at https://github.com/Uberi/MineTest-WorldEdit/") + end, +}) + +minetest.register_chatcommand("/inspect", { + params = "on/off/1/0/true/false/yes/no/enable/disable", + description = "Enable or disable node inspection", + privs = {worldedit=true}, + func = function(name, param) + if param == "on" or param == "1" or param == "true" or param == "yes" or param == "enable" then + worldedit.inspect[name] = true + worldedit.player_notify(name, "node inspection enabled") + elseif param == "off" or param == "0" or param == "false" or param == "no" or param == "disable" then + worldedit.inspect[name] = nil + worldedit.player_notify(name, "node inspection disabled") + else + worldedit.player_notify(name, "invalid usage: " .. param) + end + end, +}) + +minetest.register_on_punchnode(function(pos, node, puncher) + local name = puncher:get_player_name() + if worldedit.inspect[name] then + if minetest.check_player_privs(name, {worldedit=true}) then + message = "inspector: " .. node.name .. " at " .. minetest.pos_to_string(pos) .. " (param1=" .. node.param1 .. ", param2=" .. node.param2 .. ")" + else + message = "inspector: worldedit privileges required" + end + worldedit.player_notify(name, message) + end +end) + minetest.register_chatcommand("/reset", { params = "", description = "Reset the region so that it is empty", @@ -36,7 +96,8 @@ minetest.register_chatcommand("/reset", { worldedit.pos2[name] = nil worldedit.mark_pos1(name) worldedit.mark_pos2(name) - minetest.chat_send_player(name, "WorldEdit region reset") + worldedit.set_pos[name] = nil + worldedit.player_notify(name, "region reset") end, }) @@ -47,7 +108,23 @@ minetest.register_chatcommand("/mark", { func = function(name, param) worldedit.mark_pos1(name) worldedit.mark_pos2(name) - minetest.chat_send_player(name, "WorldEdit region marked") + worldedit.player_notify(name, "region marked") + end, +}) + +minetest.register_chatcommand("/unmark", { + params = "", + description = "Hide markers if currently shown", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + worldedit.pos1[name] = nil + worldedit.pos2[name] = nil + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.player_notify(name, "region unmarked") end, }) @@ -56,11 +133,11 @@ minetest.register_chatcommand("/pos1", { description = "Set WorldEdit region position 1 to the player's location", privs = {worldedit=true}, func = function(name, param) - local pos = minetest.env:get_player_by_name(name):getpos() - pos.x, pos.y, pos.z = math.floor(pos.x), math.floor(pos.y), math.floor(pos.z) + local pos = minetest.get_player_by_name(name):getpos() + pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5) worldedit.pos1[name] = pos worldedit.mark_pos1(name) - minetest.chat_send_player(name, "WorldEdit position 1 set to " .. minetest.pos_to_string(pos)) + worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) end, }) @@ -69,11 +146,11 @@ minetest.register_chatcommand("/pos2", { description = "Set WorldEdit region position 2 to the player's location", privs = {worldedit=true}, func = function(name, param) - local pos = minetest.env:get_player_by_name(name):getpos() - pos.x, pos.y, pos.z = math.floor(pos.x), math.floor(pos.y), math.floor(pos.z) + local pos = minetest.get_player_by_name(name):getpos() + pos.x, pos.y, pos.z = math.floor(pos.x + 0.5), math.floor(pos.y + 0.5), math.floor(pos.z + 0.5) worldedit.pos2[name] = pos worldedit.mark_pos2(name) - minetest.chat_send_player(name, "WorldEdit position 2 set to " .. minetest.pos_to_string(pos)) + worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos)) end, }) @@ -84,26 +161,49 @@ minetest.register_chatcommand("/p", { func = function(name, param) if param == "set" then --set both WorldEdit positions worldedit.set_pos[name] = "pos1" - minetest.chat_send_player(name, "Select positions by punching two nodes") + worldedit.player_notify(name, "select positions by punching two nodes") elseif param == "set1" then --set WorldEdit position 1 worldedit.set_pos[name] = "pos1only" - minetest.chat_send_player(name, "Select position 1 by punching a node") + worldedit.player_notify(name, "select position 1 by punching a node") elseif param == "set2" then --set WorldEdit position 2 worldedit.set_pos[name] = "pos2" - minetest.chat_send_player(name, "Select position 2 by punching a node") + worldedit.player_notify(name, "select position 2 by punching a node") elseif param == "get" then --display current WorldEdit positions if worldedit.pos1[name] ~= nil then - minetest.chat_send_player(name, "WorldEdit position 1: " .. minetest.pos_to_string(worldedit.pos1[name])) + worldedit.player_notify(name, "position 1: " .. minetest.pos_to_string(worldedit.pos1[name])) else - minetest.chat_send_player(name, "WorldEdit position 1 not set") + worldedit.player_notify(name, "position 1 not set") end if worldedit.pos2[name] ~= nil then - minetest.chat_send_player(name, "WorldEdit position 2: " .. minetest.pos_to_string(worldedit.pos2[name])) + worldedit.player_notify(name, "position 2: " .. minetest.pos_to_string(worldedit.pos2[name])) else - minetest.chat_send_player(name, "WorldEdit position 2 not set") + worldedit.player_notify(name, "position 2 not set") end else - minetest.chat_send_player(name, "Unknown subcommand: " .. param) + worldedit.player_notify(name, "unknown subcommand: " .. param) + end + end, +}) + +minetest.register_chatcommand("/fixedpos", { + params = "set1/set2 x y z", + description = "Set a WorldEdit region position to the position at (, , )", + privs = {worldedit=true}, + func = function(name, param) + local found, _, flag, x, y, z = param:find("^(set[12])%s+([+-]?%d+)%s+([+-]?%d+)%s+([+-]?%d+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local pos = {x=tonumber(x), y=tonumber(y), z=tonumber(z)} + if flag == "set1" then + worldedit.pos1[name] = pos + worldedit.mark_pos1(name) + worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) + else --flag == "set2" + worldedit.pos2[name] = pos + worldedit.mark_pos2(name) + worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos)) end end, }) @@ -115,17 +215,20 @@ minetest.register_on_punchnode(function(pos, node, puncher) worldedit.pos1[name] = pos worldedit.mark_pos1(name) worldedit.set_pos[name] = "pos2" --set position 2 on the next invocation - minetest.chat_send_player(name, "WorldEdit region position 1 set to " .. minetest.pos_to_string(pos)) + worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) elseif worldedit.set_pos[name] == "pos1only" then --setting position 1 only worldedit.pos1[name] = pos worldedit.mark_pos1(name) worldedit.set_pos[name] = nil --finished setting positions - minetest.chat_send_player(name, "WorldEdit region position 1 set to " .. minetest.pos_to_string(pos)) + worldedit.player_notify(name, "position 1 set to " .. minetest.pos_to_string(pos)) elseif worldedit.set_pos[name] == "pos2" then --setting position 2 worldedit.pos2[name] = pos worldedit.mark_pos2(name) worldedit.set_pos[name] = nil --finished setting positions - minetest.chat_send_player(name, "WorldEdit region position 2 set to " .. minetest.pos_to_string(pos)) + worldedit.player_notify(name, "position 2 set to " .. minetest.pos_to_string(pos)) + elseif worldedit.set_pos[name] == "prob" then --setting Minetest schematic node probabilities + worldedit.prob_pos[name] = pos + minetest.show_formspec(puncher:get_player_name(), "prob_val_enter", "field[text;;]") end end end) @@ -137,12 +240,16 @@ minetest.register_chatcommand("/volume", { 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") + worldedit.player_notify(name, "no region selected") return end local volume = worldedit.volume(pos1, pos2) - minetest.chat_send_player(name, "Current WorldEdit region has a volume of " .. volume .. " nodes (" .. pos2.x - pos1.x .. "*" .. pos2.y - pos1.y .. "*" .. pos2.z - pos1.z .. ")") + local abs = math.abs + worldedit.player_notify(name, "current region has a volume of " .. volume .. " nodes (" + .. abs(pos2.x - pos1.x) .. "*" + .. abs(pos2.y - pos1.y) .. "*" + .. abs(pos2.z - pos1.z) .. ")") end, }) @@ -153,99 +260,190 @@ minetest.register_chatcommand("/set", { 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") + worldedit.player_notify(name, "no region selected") return end - if param == "" or not worldedit.node_is_valid(param) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + local node = worldedit.normalize_nodename(param) + if param == "" or not node then + worldedit.player_notify(name, "invalid node name: " .. param) return end - local count = worldedit.set(pos1, pos2, param) - minetest.chat_send_player(name, count .. " nodes set") + local count = worldedit.set(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes set") end, }) minetest.register_chatcommand("/replace", { params = " ", - description = "Replace all instances of with in the current WorldEdit region", + description = "Replace all instances of with in the current WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local newsearchnode = worldedit.normalize_nodename(searchnode) + if not newsearchnode then + worldedit.player_notify(name, "invalid search node name: " .. searchnode) + return + end + local newreplacenode = worldedit.normalize_nodename(replacenode) + if not newreplacenode then + worldedit.player_notify(name, "invalid replace node name: " .. replacenode) + return + end + + local count = worldedit.replace(pos1, pos2, newsearchnode, newreplacenode) + worldedit.player_notify(name, count .. " nodes replaced") + end, +}) + +minetest.register_chatcommand("/replaceinverse", { + params = " ", + description = "Replace all nodes other than with in the current WorldEdit region", 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") + worldedit.player_notify(name, "no region selected") return end - local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+([^%s]+)$") + local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end - if not worldedit.node_is_valid(searchnode) then - minetest.chat_send_player(name, "Invalid search node name: " .. searchnode) + local newsearchnode = worldedit.normalize_nodename(searchnode) + if not newsearchnode then + worldedit.player_notify(name, "invalid search node name: " .. searchnode) return end - if not worldedit.node_is_valid(replacenode) then - minetest.chat_send_player(name, "Invalid replace node name: " .. replacenode) + local newreplacenode = worldedit.normalize_nodename(replacenode) + if not newreplacenode then + worldedit.player_notify(name, "invalid replace node name: " .. replacenode) return end - local count = worldedit.replace(pos1, pos2, searchnode, replacenode) - minetest.chat_send_player(name, count .. " nodes replaced") + local count = worldedit.replaceinverse(pos1, pos2, searchnode, replacenode) + worldedit.player_notify(name, count .. " nodes replaced") end, }) minetest.register_chatcommand("/hollowsphere", { params = " ", - description = "Add hollow sphere at WorldEdit position 1 with radius , composed of ", + description = "Add hollow sphere centered at WorldEdit position 1 with radius , composed of ", privs = {worldedit=true}, func = function(name, param) local pos = worldedit.pos1[name] if pos == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") + worldedit.player_notify(name, "no region selected") return end - local found, _, radius, nodename = param:find("^(%d+)%s+([^%s]+)$") + local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end - if not worldedit.node_is_valid(nodename) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) return end - local count = worldedit.hollow_sphere(pos, tonumber(radius), nodename) - minetest.chat_send_player(name, count .. " nodes added") + local count = worldedit.hollow_sphere(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") end, }) minetest.register_chatcommand("/sphere", { params = " ", - description = "Add sphere at WorldEdit position 1 with radius , composed of ", + description = "Add sphere centered at WorldEdit position 1 with radius , composed of ", privs = {worldedit=true}, func = function(name, param) local pos = worldedit.pos1[name] if pos == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") + worldedit.player_notify(name, "no region selected") return end - local found, _, radius, nodename = param:find("^(%d+)%s+([^%s]+)$") + local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end - if not worldedit.node_is_valid(nodename) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) return end - local count = worldedit.sphere(pos, tonumber(radius), nodename) - minetest.chat_send_player(name, count .. " nodes added") + local count = worldedit.sphere(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/hollowdome", { + params = " ", + description = "Add hollow dome centered at WorldEdit position 1 with radius , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, radius, nodename = param:find("^([+-]?%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.hollow_dome(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") + end, +}) + +minetest.register_chatcommand("/dome", { + params = " ", + description = "Add dome centered at WorldEdit position 1 with radius , composed of ", + privs = {worldedit=true}, + func = function(name, param) + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, radius, nodename = param:find("^([+-]?%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) + return + end + + local count = worldedit.dome(pos, tonumber(radius), node) + worldedit.player_notify(name, count .. " nodes added") end, }) @@ -256,26 +454,28 @@ minetest.register_chatcommand("/hollowcylinder", { func = function(name, param) local pos = worldedit.pos1[name] if pos == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") + worldedit.player_notify(name, "no region selected") return end - local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+([^%s]+)$") + local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end + length, radius = tonumber(length), tonumber(radius) if axis == "?" then axis, sign = worldedit.player_axis(name) length = length * sign end - if not worldedit.node_is_valid(nodename) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) return end - local count = worldedit.hollow_cylinder(pos, axis, tonumber(length), tonumber(radius), nodename) - minetest.chat_send_player(name, count .. " nodes added") + local count = worldedit.hollow_cylinder(pos, axis, length, radius, node) + worldedit.player_notify(name, count .. " nodes added") end, }) @@ -286,78 +486,87 @@ minetest.register_chatcommand("/cylinder", { func = function(name, param) local pos = worldedit.pos1[name] if pos == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") + worldedit.player_notify(name, "no region selected") return end - local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+([^%s]+)$") + local found, _, axis, length, radius, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(%d+)%s+(.+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end + length, radius = tonumber(length), tonumber(radius) if axis == "?" then axis, sign = worldedit.player_axis(name) length = length * sign end - if not worldedit.node_is_valid(nodename) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) return end - local count = worldedit.cylinder(pos, axis, tonumber(length), tonumber(radius), nodename) - minetest.chat_send_player(name, count .. " nodes added") + local count = worldedit.cylinder(pos, axis, length, radius, node) + worldedit.player_notify(name, count .. " nodes added") end, }) minetest.register_chatcommand("/pyramid", { - params = " ", - description = "Add pyramid at WorldEdit position 1 with height , composed of ", + params = "x/y/z/? ", + description = "Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height , composed of ", privs = {worldedit=true}, func = function(name, param) local pos = worldedit.pos1[name] if pos == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") + worldedit.player_notify(name, "no region selected") return end - local found, _, size, nodename = param:find("(%d+)%s+([^%s]+)$") + local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end - if not worldedit.node_is_valid(nodename) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + height = tonumber(height) + if axis == "?" then + axis, sign = worldedit.player_axis(name) + height = height * sign + end + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) return end - local count = worldedit.pyramid(pos, tonumber(size), nodename) - minetest.chat_send_player(name, count .. " nodes added") + local count = worldedit.pyramid(pos, axis, height, node) + worldedit.player_notify(name, count .. " nodes added") end, }) minetest.register_chatcommand("/spiral", { - params = " ", - description = "Add spiral at WorldEdit position 1 with width , height , space between walls , composed of ", + params = " ", + description = "Add spiral centered at WorldEdit position 1 with side length , height , space between walls , composed of ", privs = {worldedit=true}, func = function(name, param) local pos = worldedit.pos1[name] if pos == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") + worldedit.player_notify(name, "no region selected") return end - local found, _, width, height, space, nodename = param:find("(%d+)%s+(%d+)%s+(%d+)%s+([^%s]+)$") + local found, _, length, height, space, nodename = param:find("^(%d+)%s+(%d+)%s+(%d+)%s+(.+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end - if not worldedit.node_is_valid(nodename) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + local node = worldedit.normalize_nodename(nodename) + if not node then + worldedit.player_notify(name, "invalid node name: " .. nodename) return end - local count = worldedit.spiral(pos, tonumber(width), tonumber(height), tonumber(space), nodename) - minetest.chat_send_player(name, count .. " nodes changed") + local count = worldedit.spiral(pos, tonumber(length), tonumber(height), tonumber(space), node) + worldedit.player_notify(name, count .. " nodes added") end, }) @@ -368,22 +577,23 @@ minetest.register_chatcommand("/copy", { 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") + worldedit.player_notify(name, "no region selected") return end local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end + amount = tonumber(amount) if axis == "?" then axis, sign = worldedit.player_axis(name) amount = amount * sign end - local count = worldedit.copy(pos1, pos2, axis, tonumber(amount)) - minetest.chat_send_player(name, count .. " nodes copied") + local count = worldedit.copy(pos1, pos2, axis, amount) + worldedit.player_notify(name, count .. " nodes copied") end, }) @@ -394,28 +604,28 @@ minetest.register_chatcommand("/move", { 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") + worldedit.player_notify(name, "no region selected") return end local found, _, axis, amount = param:find("^([xyz%?])%s+([+-]?%d+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end + amount = tonumber(amount) if axis == "?" then axis, sign = worldedit.player_axis(name) amount = amount * sign end - local count = worldedit.move(pos1, pos2, axis, tonumber(amount)) + local count = worldedit.move(pos1, pos2, axis, amount) pos1[axis] = pos1[axis] + amount pos2[axis] = pos2[axis] + amount worldedit.mark_pos1(name) worldedit.mark_pos2(name) - - minetest.chat_send_player(name, count .. " nodes moved") + worldedit.player_notify(name, count .. " nodes moved") end, }) @@ -426,22 +636,51 @@ minetest.register_chatcommand("/stack", { 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") + worldedit.player_notify(name, "no region selected") return end local found, _, axis, count = param:find("^([xyz%?])%s+([+-]?%d+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end + count = tonumber(count) if axis == "?" then axis, sign = worldedit.player_axis(name) count = count * sign end - local count = worldedit.stack(pos1, pos2, axis, tonumber(count)) - minetest.chat_send_player(name, count .. " nodes stacked") + local count = worldedit.stack(pos1, pos2, axis, count) + worldedit.player_notify(name, count .. " nodes stacked") + end, +}) + +minetest.register_chatcommand("/scale", { + params = "", + description = "Scale the current WorldEdit positions and region by a factor of positive integer with position 1 as the origin", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local factor = tonumber(param) + if not factor or factor ~= math.floor(factor) or factor <= 0 then + worldedit.player_notify(name, "invalid scaling factor: " .. param) + end + + local count, pos1, pos2 = worldedit.scale(pos1, pos2, factor) + + --reset markers to scaled positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + + worldedit.player_notify(name, count .. " nodes scaled") end, }) @@ -452,13 +691,13 @@ minetest.register_chatcommand("/transpose", { 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") + worldedit.player_notify(name, "no region selected") return end local found, _, axis1, axis2 = param:find("^([xyz%?])%s+([xyz%?])$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end if axis1 == "?" then @@ -468,12 +707,19 @@ minetest.register_chatcommand("/transpose", { axis2 = worldedit.player_axis(name) end if axis1 == axis2 then - minetest.chat_send_player(name, "Invalid usage: axes are the same") + worldedit.player_notify(name, "invalid usage: axes must be different") return end - local count = worldedit.transpose(pos1, pos2, axis1, axis2) - minetest.chat_send_player(name, count .. " nodes transposed") + local count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2) + + --reset markers to transposed positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + + worldedit.player_notify(name, count .. " nodes transposed") end, }) @@ -484,7 +730,7 @@ minetest.register_chatcommand("/flip", { 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") + worldedit.player_notify(name, "no region selected") return end @@ -492,12 +738,12 @@ minetest.register_chatcommand("/flip", { param = worldedit.player_axis(name) end if param ~= "x" and param ~= "y" and param ~= "z" then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end local count = worldedit.flip(pos1, pos2, param) - minetest.chat_send_player(name, count .. " nodes flipped") + worldedit.player_notify(name, count .. " nodes flipped") end, }) @@ -508,62 +754,113 @@ minetest.register_chatcommand("/rotate", { 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") + worldedit.player_notify(name, "no region selected") return end local found, _, axis, angle = param:find("^([xyz%?])%s+([+-]?%d+)$") if found == nil then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end if axis == "?" then axis = worldedit.player_axis(name) end if angle % 90 ~= 0 then - minetest.chat_send_player(name, "Invalid usage: angle must be multiple of 90") + worldedit.player_notify(name, "invalid usage: angle must be multiple of 90") return end - local count = worldedit.rotate(pos1, pos2, axis, angle) - minetest.chat_send_player(name, count .. " nodes rotated") + local count, pos1, pos2 = worldedit.rotate(pos1, pos2, axis, angle) + + --reset markers to rotated positions + worldedit.pos1[name] = pos1 + worldedit.pos2[name] = pos2 + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + + worldedit.player_notify(name, count .. " nodes rotated") end, }) -minetest.register_chatcommand("/dig", { +minetest.register_chatcommand("/orient", { + params = "", + description = "Rotate oriented nodes in the current WorldEdit region around the Y axis by angle (90 degree increment)", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local found, _, angle = param:find("^([+-]?%d+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + if angle % 90 ~= 0 then + worldedit.player_notify(name, "invalid usage: angle must be multiple of 90") + return + end + + local count = worldedit.orient(pos1, pos2, angle) + + worldedit.player_notify(name, count .. " nodes oriented") + end, +}) + +minetest.register_chatcommand("/fixlight", { params = "", - description = "Dig the current WorldEdit region", + description = "Fix the lighting in the current WorldEdit region", 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") + worldedit.player_notify(name, "no region selected") return end - local count = worldedit.dig(pos1, pos2) - minetest.chat_send_player(name, count .. " nodes dug") + local count = worldedit.fixlight(pos1, pos2) + worldedit.player_notify(name, count .. " nodes updated") end, }) minetest.register_chatcommand("/hide", { + params = "", + description = "Hide all nodes in the current WorldEdit region non-destructively", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local count = worldedit.hide(pos1, pos2) + worldedit.player_notify(name, count .. " nodes hidden") + end, +}) + +minetest.register_chatcommand("/suppress", { params = "", - description = "Hide all in the current WorldEdit region non-destructively", + description = "Suppress all in the current WorldEdit region non-destructively", 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") + worldedit.player_notify(name, "no region selected") return end - if param == "" or not worldedit.node_is_valid(param) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + local node = worldedit.normalize_nodename(param) + if param == "" or not node then + worldedit.player_notify(name, "invalid node name: " .. param) return end - local count = worldedit.hide(pos1, pos2, param) - minetest.chat_send_player(name, count .. " nodes hidden") + local count = worldedit.suppress(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes suppressed") end, }) @@ -574,17 +871,18 @@ minetest.register_chatcommand("/highlight", { 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") + worldedit.player_notify(name, "no region selected") return end - if param == "" or not worldedit.node_is_valid(param) then - minetest.chat_send_player(name, "Invalid node name: " .. param) + local node = worldedit.normalize_nodename(param) + if param == "" or not node then + worldedit.player_notify(name, "invalid node name: " .. param) return end - local count = worldedit.highlight(pos1, pos2, param) - minetest.chat_send_player(name, count .. " nodes highlighted") + local count = worldedit.highlight(pos1, pos2, node) + worldedit.player_notify(name, count .. " nodes highlighted") end, }) @@ -595,12 +893,12 @@ minetest.register_chatcommand("/restore", { 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") + worldedit.player_notify(name, "no region selected") return end local count = worldedit.restore(pos1, pos2) - minetest.chat_send_player(name, count .. " nodes restored") + worldedit.player_notify(name, count .. " nodes restored") end, }) @@ -611,12 +909,12 @@ minetest.register_chatcommand("/save", { 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") + worldedit.player_notify(name, "no region selected") return end if param == "" then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) return end @@ -627,14 +925,14 @@ minetest.register_chatcommand("/save", { os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist local file, err = io.open(filename, "wb") if err ~= nil then - minetest.chat_send_player(name, "Could not save file to \"" .. filename .. "\"") + worldedit.player_notify(name, "could not save file to \"" .. filename .. "\"") return end file:write(result) file:flush() file:close() - minetest.chat_send_player(name, count .. " nodes saved") + worldedit.player_notify(name, count .. " nodes saved") end, }) @@ -645,24 +943,28 @@ minetest.register_chatcommand("/allocate", { func = function(name, param) local pos1 = worldedit.pos1[name] if pos1 == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") + worldedit.player_notify(name, "no region selected") return end if param == "" then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) 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 .. "\"") + worldedit.player_notify(name, "could not open file \"" .. filename .. "\"") return end local value = file:read("*a") file:close() + if worldedit.valueversion(value) == 0 then --unknown version + worldedit.player_notify(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 @@ -670,88 +972,200 @@ minetest.register_chatcommand("/allocate", { worldedit.pos2[name] = nodepos2 worldedit.mark_pos2(name) - minetest.chat_send_player(name, count .. " nodes allocated") + worldedit.player_notify(name, count .. " nodes allocated") end, }) 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] if pos1 == nil then - minetest.chat_send_player(name, "No WorldEdit region selected") + worldedit.player_notify(name, "no region selected") return end if param == "" then - minetest.chat_send_player(name, "Invalid usage: " .. param) + worldedit.player_notify(name, "invalid usage: " .. param) 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 + worldedit.player_notify(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 + worldedit.player_notify(name, "invalid file: file is invalid or created with newer version of WorldEdit") + return end - minetest.chat_send_player(name, count .. " nodes loaded") + local count = worldedit.deserialize(pos1, value) + + worldedit.player_notify(name, count .. " nodes loaded") end, }) -minetest.register_chatcommand("/metasave", { +minetest.register_chatcommand("/lua", { + params = "", + description = "Executes as a Lua chunk in the global namespace", + privs = {worldedit=true, server=true}, + func = function(name, param) + local err = worldedit.lua(param) + if err then + worldedit.player_notify(name, "code error: " .. err) + else + worldedit.player_notify(name, "code successfully executed", false) + end + end, +}) + +minetest.register_chatcommand("/luatransform", { + params = "", + description = "Executes as a Lua chunk in the global namespace with the variable pos available, for each node in the current WorldEdit region", + privs = {worldedit=true, server=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return + end + + local err = worldedit.luatransform(pos1, pos2, param) + if err then + worldedit.player_notify(name, "code error: " .. err, false) + else + worldedit.player_notify(name, "code successfully executed", false) + end + end, +}) + +if minetest.place_schematic then +minetest.register_chatcommand("/mtschemcreate", { params = "", - description = "Save the current WorldEdit region to \"(world folder)/schems/.wem\"", + description = "Save the current WorldEdit region using the Minetest Schematic format to \"(world folder)/schems/.mts\"", 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") + worldedit.player_notify(name, "No region selected") return end - if param == "" then - minetest.chat_send_player(name, "Invalid usage: " .. param) + if param == nil then + worldedit.player_notify(name, "No filename specified") return end - local count, err = worldedit.metasave(pos1, pos2, param) - if err then - minetest.chat_send_player(name, "error loading file: " .. err) + + local path = minetest.get_worldpath() .. "/schems" + local filename = path .. "/" .. param .. ".mts" + os.execute("mkdir \"" .. path .. "\"") --create directory if it does not already exist + + local ret = minetest.create_schematic(pos1, pos2, worldedit.prob_list[name], filename) + if ret == nil then + worldedit.player_notify(name, "Failed to create Minetest schematic", false) else - minetest.chat_send_player(name, count .. " nodes saved") + worldedit.player_notify(name, "Saved Minetest schematic to " .. param, false) end + worldedit.prob_list[name] = {} end, }) -minetest.register_chatcommand("/metaload", { +minetest.register_chatcommand("/mtschemplace", { params = "", - description = "Load nodes from \"(world folder)/schems/.wem\" with position 1 of the current WorldEdit region as the origin", + description = "Load nodes from \"(world folder)/schems/.mts\" 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") + local pos = worldedit.pos1[name] + if pos == nil then + worldedit.player_notify(name, "No position selected") return end - if param == "" then - minetest.chat_send_player(name, "Invalid usage: " .. param) + if param == nil then + worldedit.player_notify(name, "No filename specified") return end - local count, err = worldedit.metaload(pos1, param) - if err then - minetest.chat_send_player(name, "error loading file: " .. err) + + local path = minetest.get_worldpath() .. "/schems/" .. param .. ".mts" + if minetest.place_schematic(pos, path) == nil then + worldedit.player_notify(name, "Failed to place Minetest schematic", false) + else + worldedit.player_notify(name, "Placed Minetest schematic " .. param .. + " at " .. minetest.pos_to_string(pos), false) + end + end, +}) + +minetest.register_chatcommand("/mtschemprob", { + params = "start/finish/get", + description = "Begins node probability entry for Minetest schematics, gets the nodes that have probabilities set, or ends node probability entry", + privs = {worldedit=true}, + func = function(name, param) + if param == "start" then --start probability setting + worldedit.set_pos[name] = "prob" + worldedit.prob_list[name] = {} + worldedit.player_notify(name, "select Minetest schematic probability values by punching nodes") + elseif param == "finish" then --finish probability setting + worldedit.set_pos[name] = nil + worldedit.player_notify(name, "finished Minetest schematic probability selection") + elseif param == "get" then --get all nodes that had probabilities set on them + local text = "" + local problist = worldedit.prob_list[name] + if problist == nil then + return + end + for k,v in pairs(problist) do + local prob = math.floor(((v["prob"] / 256) * 100) * 100 + 0.5) / 100 + text = text .. minetest.pos_to_string(v["pos"]) .. ": " .. prob .. "% | " + end + worldedit.player_notify(name, "Currently set node probabilities:") + worldedit.player_notify(name, text) else - minetest.chat_send_player(name, count .. " nodes loaded") + worldedit.player_notify(name, "unknown subcommand: " .. param) + end + end, +}) + +minetest.register_on_player_receive_fields( + function(player, formname, fields) + if (formname == "prob_val_enter") and (fields.text ~= "") then + local name = player:get_player_name() + local prob_entry = {pos=worldedit.prob_pos[name], prob=tonumber(fields.text)} + local index = table.getn(worldedit.prob_list[name]) + 1 + worldedit.prob_list[name][index] = prob_entry + end + end +) +end + +minetest.register_chatcommand("/clearobjects", { + params = "", + description = "Clears all objects within the WorldEdit region", + privs = {worldedit=true}, + func = function(name, param) + local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, "no region selected") + return end + + local count = worldedit.clearobjects(pos1, pos2) + worldedit.player_notify(name, count .. " objects cleared") end, })