diff --git a/mods/WorldEdit/ChatCommands.md b/mods/WorldEdit/ChatCommands.md old mode 100755 new mode 100644 index 5b6820a..27952e4 --- a/mods/WorldEdit/ChatCommands.md +++ b/mods/WorldEdit/ChatCommands.md @@ -22,6 +22,9 @@ Many commands also have shorter names that can be typed faster. For example, if | `//hdo` | `//hollowdome` | | `//do` | `//dome` | | `//hcyl` | `//hollowcylinder` | +| `//cyl` | `//cylinder` | +| `//hpyr` | `//hollowpyramid` | +| `//pyr` | `//pyramid` | ### `//about` @@ -100,7 +103,7 @@ Display the volume of the current WorldEdit region. ### `//deleteblocks` -Delete the MapBlocks (16x16x16 units) that contain the selected region. This means that mapgen will be invoked for that area. As only whole MapBlocks get removed, the deleted area is usually larger than the selected one. Also, mapgen can trigger mechanisms like mud reflow or cavegen, which affects nodes (up to 112 nodes away) outside the MapBlock, so dont use this near buildings. +Delete the MapBlocks (16x16x16 units) that contain the selected region. This means that mapgen will be invoked for that area. As only whole MapBlocks get removed, the deleted area is usually larger than the selected one. Also, mapgen can trigger mechanisms like mud reflow or cavegen, which affects nodes (up to 112 nodes away) outside the MapBlock, so dont use this near buildings. Note that active entities are not part of a MapBlock and do not get deleted. //deleteblocks @@ -190,6 +193,15 @@ Add cylinder at WorldEdit position 1 along the x/y/z/? axis with length ` ` + +Add hollow pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height ``, composed of ``. + + //hollowpyramid x 8 Diamond Block + //hollowpyramid y -5 glass + //hollowpyramid z 2 mesecons:wire_00000000_off + //hollowpyramid ? 12 mesecons:wire_00000000_off + ### `//pyramid x/y/z? ` Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height ``, composed of ``. @@ -291,6 +303,12 @@ Fixes the lighting in the current WorldEdit region. //fixlight +### `//drain` + +Removes any fluid node within the current WorldEdit region. + + //drain + ### `//hide` Hide all nodes in the current WorldEdit region non-destructively. @@ -380,3 +398,38 @@ This mode can be left with `//mtschemprob finish`. `//mtschemprob get` will disp Clears all objects within the WorldEdit region. //clearobjects + +### `//shift x/y/z/?/up/down/left/right/front/back [+|-]` + +Shifts the selection area by `[+|-]` without touching its contents. The shifting axis can be absolute (`x/y/z`) or +relative (`up/down/left/right/front/back`). + + //shift left 5 + +### `//expand [+|-]x/y/z/?/up/down/left/right/front/back [reverse-amount]` + +Expands the selection by `` in the selected absolute or relative axis. If specified, the selection can be expanded in the +opposite direction over the same axis by `[reverse-amount]`. + + //expand right 7 5 + +### `//contract [+|-]x/y/z/?/up/down/left/right/front/back [reverse-amount]` + +Contracts the selection by `` in the selected absolute or relative axis. If specified, the selection can be contracted in the +opposite direction over the same axis by `[reverse-amount]`. + + //expand right 7 5 + +### `//outset [hv] ` + +Expands the selection in all directions by ``. If specified, the selection can be expanded horizontally in the x and z axes `[h]` +or vertically in the y axis `[v]`. + + //outset v 5 + +### `//inset [hv] ` + +Contracts the selection in all directions by ``. If specified, the selection can be contracted horizontally in the x and z axes `[h]` +or vertically in the y axis `[v]`. + + //outset v 5 \ No newline at end of file diff --git a/mods/WorldEdit/Tutorial.md b/mods/WorldEdit/Tutorial.md old mode 100755 new mode 100644 diff --git a/mods/WorldEdit/WorldEdit API.md b/mods/WorldEdit/WorldEdit API.md old mode 100755 new mode 100644 index 0b970f1..e81e549 --- a/mods/WorldEdit/WorldEdit API.md +++ b/mods/WorldEdit/WorldEdit API.md @@ -45,6 +45,12 @@ Copies the region defined by positions `pos1` and `pos2` along the `axis` axis ( Returns the number of nodes copied. +### count = worldedit.copy2(pos1, pos2, off) + +Copies the region defined by positions `pos1` and `pos2` by the offset vector `off`. + +Returns the number of nodes copied. + ### count = worldedit.move(pos1, pos2, axis, amount) Moves the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes. @@ -127,9 +133,9 @@ Adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length ` Returns the number of nodes added. -### count = worldedit.pyramid(pos, axis, height, node_name) +### count = worldedit.pyramid(pos, axis, height, node_name, hollow) -Adds a pyramid centered at `pos` along the `axis` axis ("x" or "y" or "z") with height `height`. +Adds a pyramid centered at `pos` along the `axis` axis ("x" or "y" or "z") with height `height`, composed of `node_name`. Returns the number of nodes added. diff --git a/mods/WorldEdit/worldedit/code.lua b/mods/WorldEdit/worldedit/code.lua old mode 100755 new mode 100644 diff --git a/mods/WorldEdit/worldedit/common.lua b/mods/WorldEdit/worldedit/common.lua old mode 100755 new mode 100644 diff --git a/mods/WorldEdit/worldedit/compatibility.lua b/mods/WorldEdit/worldedit/compatibility.lua old mode 100755 new mode 100644 diff --git a/mods/WorldEdit/worldedit/cuboid.lua b/mods/WorldEdit/worldedit/cuboid.lua new file mode 100644 index 0000000..ce20761 --- /dev/null +++ b/mods/WorldEdit/worldedit/cuboid.lua @@ -0,0 +1,258 @@ +-- Expands or contracts the cuboid in all axes by amount (positive or negative) +worldedit.cuboid_volumetric_expand = function(name, amount) + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, "Undefined cuboid" + end + + local delta1 = vector.new() + local delta2 = vector.new() + local delta_dir1 + local delta_dir2 + + delta1 = vector.add(delta1, amount) + delta2 = vector.add(delta2, amount) + delta_dir1, delta_dir2 = worldedit.get_expansion_directions(pos1, pos2) + delta1 = vector.multiply(delta1, delta_dir1) + delta2 = vector.multiply(delta2, delta_dir2) + worldedit.pos1[name] = vector.add(pos1, delta1) + worldedit.pos2[name] = vector.add(pos2, delta2) + + return true +end + + +-- Expands or contracts the cuboid in a single axis by amount (positive or negative) +worldedit.cuboid_linear_expand = function(name, axis, direction, amount) + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, "undefined cuboid" + end + + if direction ~= 1 and direction ~= -1 then + return false, "invalid marker" + end + + local marker = worldedit.marker_get_closest_to_axis(name, axis, direction) + local deltavect = vector.new() + + if axis == 'x' then + deltavect.x = amount * direction + elseif axis == 'y' then + deltavect.y = amount * direction + elseif axis == 'z' then + deltavect.z = amount * direction + else + return false, "invalid axis" + end + + worldedit.marker_move(name, marker, deltavect) + return true +end + + +-- Shifts the cuboid by '+-amount' in axis 'axis' +worldedit.cuboid_shift = function(name, axis, amount) + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, "undefined cuboid" + end + + if axis == 'x' then + worldedit.pos1[name].x = pos1.x + amount + worldedit.pos2[name].x = pos2.x + amount + elseif axis == 'y' then + worldedit.pos1[name].y = pos1.y + amount + worldedit.pos2[name].y = pos2.y + amount + elseif axis == 'z' then + worldedit.pos1[name].z = pos1.z + amount + worldedit.pos2[name].z = pos2.z + amount + else + return false, "invalid axis" + end + + return true +end + + +-- Moves the location of a single marker by adding deltavector +worldedit.marker_move = function(name, marker, deltavector) + if marker ~= 1 and marker ~= 2 then + return false + end + + if marker == 1 then + local pos = worldedit.pos1[name] + worldedit.pos1[name] = vector.add(deltavector, pos) + else + local pos = worldedit.pos2[name] + worldedit.pos2[name] = vector.add(deltavector, pos) + end + + return true +end + +-- Updates the location ingame of the markers +worldedit.marker_update = function(name, marker) + if marker == nil then + worldedit.mark_pos1(name) + worldedit.mark_pos2(name) + elseif marker == 1 then + worldedit.mark_pos1(name) + elseif marker == 2 then + worldedit.mark_pos2(name) + else + minetest.debug( + "worldedit: Invalid execution of function update_markers") + end +end + + +-- Returns two vectors with the directions for volumetric expansion +worldedit.get_expansion_directions = function(mark1, mark2) + if mark1 == nil or mark2 == nil then + return + end + local dir1 = vector.new() + local dir2 = vector.new() + + if mark1.x < mark2.x then + dir1.x = -1 + dir2.x = 1 + else + dir1.x = 1 + dir2.x = -1 + end + if mark1.y < mark2.y then + dir1.y = -1 + dir2.y = 1 + else + dir1.y = 1 + dir2.y = -1 + end + if mark1.z < mark2.z then + dir1.z = -1 + dir2.z = 1 + else + dir1.z = 1 + dir2.z = -1 + end + return dir1, dir2 +end + + +-- Return the marker that is closest to the player +worldedit.marker_get_closest_to_player = function(name) + local playerpos = minetest.get_player_by_name(name):getpos() + local dist1 = vector.distance(playerpos, worldedit.pos1[name]) + local dist2 = vector.distance(playerpos, worldedit.pos2[name]) + + if dist1 < dist2 then + return 1 + else + return 2 + end +end + + +-- Returns the closest marker to the specified axis and direction +worldedit.marker_get_closest_to_axis = function(name, axis, direction) + local pos1 = vector.new() + local pos2 = vector.new() + + if direction ~= 1 and direction ~= -1 then + return nil + end + + if axis == 'x' then + pos1.x = worldedit.pos1[name].x * direction + pos2.x = worldedit.pos2[name].x * direction + if pos1.x > pos2.x then + return 1 + else + return 2 + end + elseif axis == 'y' then + pos1.y = worldedit.pos1[name].y * direction + pos2.y = worldedit.pos2[name].y * direction + if pos1.y > pos2.y then + return 1 + else + return 2 + end + elseif axis == 'z' then + pos1.z = worldedit.pos1[name].z * direction + pos2.z = worldedit.pos2[name].z * direction + if pos1.z > pos2.z then + return 1 + else + return 2 + end + else + return nil + end +end + + +-- Translates up, down, left, right, front, back to their corresponding axes and +-- directions according to faced direction +worldedit.translate_direction = function(name, direction) + local axis, dir = worldedit.player_axis(name) + local resaxis, resdir + + if direction == "up" then + return 'y', 1 + end + + if direction == "down" then + return 'y', -1 + end + + if direction == "front" then + if axis == "y" then + resaxis = nil + resdir = nil + else + resaxis = axis + resdir = dir + end + end + + if direction == "back" then + if axis == "y" then + resaxis = nil + resdir = nil + else + resaxis = axis + resdir = -dir + end + end + + if direction == "left" then + if axis == 'x' then + resaxis = 'z' + resdir = dir + elseif axis == 'z' then + resaxis = 'x' + resdir = -dir + end + end + + if direction == "right" then + if axis == 'x' then + resaxis = 'z' + resdir = -dir + elseif axis == 'z' then + resaxis = 'x' + resdir = dir + end + end + + return resaxis, resdir +end \ No newline at end of file diff --git a/mods/WorldEdit/worldedit/init.lua b/mods/WorldEdit/worldedit/init.lua old mode 100755 new mode 100644 index 70a827d..37d52b2 --- a/mods/WorldEdit/worldedit/init.lua +++ b/mods/WorldEdit/worldedit/init.lua @@ -36,6 +36,7 @@ load_module(path .. "/visualization.lua") load_module(path .. "/serialization.lua") load_module(path .. "/code.lua") load_module(path .. "/compatibility.lua") +load_module(path .. "/cuboid.lua") if minetest.setting_getbool("log_mods") then diff --git a/mods/WorldEdit/worldedit/manipulations.lua b/mods/WorldEdit/worldedit/manipulations.lua old mode 100755 new mode 100644 index 2e7d33a..d48a172 --- a/mods/WorldEdit/worldedit/manipulations.lua +++ b/mods/WorldEdit/worldedit/manipulations.lua @@ -90,7 +90,7 @@ function worldedit.stack2(pos1, pos2, direction, amount, finished) translated.x = translated.x + direction.x translated.y = translated.y + direction.y translated.z = translated.z + direction.z - worldedit.copy2(pos1, pos2, translated, volume) + worldedit.copy2(pos1, pos2, translated) minetest.after(0, next_one) else if finished then @@ -164,6 +164,38 @@ function worldedit.copy(pos1, pos2, axis, amount) return worldedit.volume(pos1, pos2) end +--- Copies a region by offset vector `off`. +-- @param pos1 +-- @param pos2 +-- @param off +-- @return The number of nodes copied. +function worldedit.copy2(pos1, pos2, off) + local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + worldedit.keep_loaded(pos1, pos2) + + local get_node, get_meta, set_node = minetest.get_node, + minetest.get_meta, minetest.set_node + local pos = {} + pos.x = pos2.x + while pos.x >= pos1.x do + pos.y = pos2.y + while pos.y >= pos1.y do + pos.z = pos2.z + while pos.z >= pos1.z do + local node = get_node(pos) -- Obtain current node + local meta = get_meta(pos):to_table() -- Get meta of current node + local newpos = vector.add(pos, off) -- Calculate new position + set_node(newpos, node) -- Copy node to new position + get_meta(newpos):from_table(meta) -- Set metadata of new node + pos.z = pos.z - 1 + end + pos.y = pos.y - 1 + end + pos.x = pos.x - 1 + end + return worldedit.volume(pos1, pos2) +end --- Moves a region along `axis` by `amount` nodes. -- @return The number of nodes moved. @@ -543,14 +575,11 @@ end function worldedit.fixlight(pos1, pos2) local pos1, pos2 = worldedit.sort_pos(pos1, pos2) - worldedit.keep_loaded(pos1, pos2) + local vmanip = minetest.get_voxel_manip(pos1, pos2) + vmanip:write_to_map() + vmanip:update_map() -- this updates the lighting - local nodes = minetest.find_nodes_in_area(pos1, pos2, "air") - local dig_node = minetest.dig_node - for _, pos in ipairs(nodes) do - dig_node(pos) - end - return #nodes + return worldedit.volume(pos1, pos2) end diff --git a/mods/WorldEdit/worldedit/primitives.lua b/mods/WorldEdit/worldedit/primitives.lua old mode 100755 new mode 100644 index feeea2e..61c705d --- a/mods/WorldEdit/worldedit/primitives.lua +++ b/mods/WorldEdit/worldedit/primitives.lua @@ -150,14 +150,15 @@ end -- @param axis Axis ("x", "y", or "z") -- @param height Pyramid height. -- @param node_name Name of node to make pyramid of. +-- @param hollow Whether the pyramid should be hollow. -- @return The number of nodes added. -function worldedit.pyramid(pos, axis, height, node_name) +function worldedit.pyramid(pos, axis, height, node_name, hollow) local other1, other2 = worldedit.get_axis_others(axis) -- Set up voxel manipulator local manip, area = mh.init_axis_radius(pos, axis, height >= 0 and height or -height) - local data = mh.get_empty_data() + local data = mh.get_empty_data(area) -- Handle inverted pyramids local start_axis, end_axis, step @@ -177,7 +178,7 @@ function worldedit.pyramid(pos, axis, height, node_name) y = pos.y - area.MinEdge.y, z = pos.z - area.MinEdge.z, } - local size = height * step + local size = math.abs(height * step) local count = 0 -- For each level of the pyramid for index1 = 0, height, step do @@ -187,10 +188,12 @@ function worldedit.pyramid(pos, axis, height, node_name) local new_index2 = new_index1 + (index2 + offset[other1]) * stride[other1] for index3 = -size, size do local i = new_index2 + (index3 + offset[other2]) * stride[other2] - data[i] = node_id + if (not hollow or size - math.abs(index2) < 2 or size - math.abs(index3) < 2) then + data[i] = node_id + count = count + 1 + end end end - count = count + (size * 2 + 1) ^ 2 size = size - 1 end diff --git a/mods/WorldEdit/worldedit/serialization.lua b/mods/WorldEdit/worldedit/serialization.lua old mode 100755 new mode 100644 index 797a86e..8cff9b8 --- a/mods/WorldEdit/worldedit/serialization.lua +++ b/mods/WorldEdit/worldedit/serialization.lua @@ -144,9 +144,9 @@ local function load_schematic(value) "([^%s]+)%s+(%d+)%s+(%d+)[^\r\n]*[\r\n]*") do param1, param2 = tonumber(param1), tonumber(param2) table.insert(nodes, { - x = originx + tonumber(x), - y = originy + tonumber(y), - z = originz + tonumber(z), + x = tonumber(x), + y = tonumber(y), + z = tonumber(z), name = name, param1 = param1 ~= 0 and param1 or nil, param2 = param2 ~= 0 and param2 or nil, diff --git a/mods/WorldEdit/worldedit/textures/worldedit_wand.png b/mods/WorldEdit/worldedit/textures/worldedit_wand.png new file mode 100644 index 0000000..13eb121 Binary files /dev/null and b/mods/WorldEdit/worldedit/textures/worldedit_wand.png differ diff --git a/mods/WorldEdit/worldedit/visualization.lua b/mods/WorldEdit/worldedit/visualization.lua old mode 100755 new mode 100644 diff --git a/mods/WorldEdit/worldedit_commands/.gitignore b/mods/WorldEdit/worldedit_commands/.gitignore new file mode 100644 index 0000000..e4e5f6c --- /dev/null +++ b/mods/WorldEdit/worldedit_commands/.gitignore @@ -0,0 +1 @@ +*~ \ No newline at end of file diff --git a/mods/WorldEdit/worldedit_commands/cuboid.lua b/mods/WorldEdit/worldedit_commands/cuboid.lua new file mode 100644 index 0000000..88f0260 --- /dev/null +++ b/mods/WorldEdit/worldedit_commands/cuboid.lua @@ -0,0 +1,240 @@ +minetest.register_chatcommand("/outset", { + params = "[h|v] ", + description = "outset the selection", + privs = {worldedit=true}, + func = function(name, param) + local find, _, dir, amount = param:find("(%a*)%s*([+-]?%d+)") + + if find == nil then + return false, "invalid usage: " .. param + end + + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, + "Undefined region. Region must be defined beforehand." + end + + local hv_test = dir:find("[^hv]+") + + if hv_test ~= nil then + return false, "Invalid direction." + end + + if dir == "" or dir == "hv" or dir == "vh" then + assert(worldedit.cuboid_volumetric_expand(name, amount)) + elseif dir == "h" then + assert(worldedit.cuboid_linear_expand(name, 'x', 1, amount)) + assert(worldedit.cuboid_linear_expand(name, 'x', -1, amount)) + assert(worldedit.cuboid_linear_expand(name, 'z', 1, amount)) + assert(worldedit.cuboid_linear_expand(name, 'z', -1, amount)) + elseif dir == "v" then + assert(worldedit.cuboid_linear_expand(name, 'y', 1, amount)) + assert(worldedit.cuboid_linear_expand(name, 'y', -1, amount)) + else + return false, "Invalid number of arguments" + end + + worldedit.marker_update(name) + return true, "Region outset by " .. amount .. " blocks" + end, + } +) + + +minetest.register_chatcommand("/inset", { + params = "[h|v] ", + description = "inset the selection", + privs = {worldedit=true}, + func = function(name, param) + local find, _, dir, amount = param:find("(%a*)%s*([+-]?%d+)") + + if find == nil then + return false, "invalid usage: " .. param + end + + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + + if pos1 == nil or pos2 == nil then + return false, + "Undefined region. Region must be defined beforehand." + end + + local hv_test = dir:find("[^hv]+") + + if hv_test ~= nil then + return false, "Invalid direction." + end + + if dir == "" or dir == "vh" or dir == "hv" then + assert(worldedit.cuboid_volumetric_expand(name, -amount)) + elseif dir == "h" then + assert(worldedit.cuboid_linear_expand(name, 'x', 1, -amount)) + assert(worldedit.cuboid_linear_expand(name, 'x', -1, -amount)) + assert(worldedit.cuboid_linear_expand(name, 'z', 1, -amount)) + assert(worldedit.cuboid_linear_expand(name, 'z', -1, -amount)) + elseif dir == "v" then + assert(worldedit.cuboid_linear_expand(name, 'y', 1, -amount)) + assert(worldedit.cuboid_linear_expand(name, 'y', -1, -amount)) + else + return false, "Invalid number of arguments" + end + + worldedit.marker_update(name) + return true, "Region inset by " .. amount .. " blocks" + end, + } +) + + +minetest.register_chatcommand("/shift", { + params = "[x|y|z|?|up|down|left|right|front|back] [+|-]", + description = "Moves the selection region. Does not move contents.", + privs = {worldedit=true}, + func = function(name, param) + local pos1 = worldedit.pos1[name] + local pos2 = worldedit.pos2[name] + local find, _, direction, amount = param:find("([%?%l]+)%s*([+-]?%d+)") + + if find == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return + end + + if pos1 == nil or pos2 == nil then + worldedit.player_notify(name, + "Undefined region. Region must be defined beforehand.") + return + end + + local axis, dir + if direction == "x" or direction == "y" or direction == "z" then + axis, dir = direction, 1 + elseif direction == "?" then + axis, dir = worldedit.player_axis(name) + else + axis, dir = worldedit.translate_direction(name, direction) + end + + if axis == nil or dir == nil then + return false, "Invalid if looking straight up or down" + end + + assert(worldedit.cuboid_shift(name, axis, amount * dir)) + worldedit.marker_update(name) + + return true, "Region shifted by " .. amount .. " nodes" + end, + } +) + + +minetest.register_chatcommand("/expand", { + params = "[+|-] [reverse-amount]", + description = "expand the selection in one or two directions at once", + privs = {worldedit=true}, + func = function(name, param) + local find, _, sign, direction, amount, + rev_amount = param:find("([+-]?)([%?%l]+)%s*(%d+)%s*(%d*)") + + if find == nil then + worldedit.player_notify(name, "invalid use: " .. param) + return + end + + if worldedit.pos1[name] == nil or worldedit.pos2[name] == nil then + worldedit.player_notify(name, + "Undefined region. Region must be defined beforehand.") + return + end + + local absolute = direction:find("[xyz?]") + local dir, axis + + if rev_amount == "" then + rev_amount = 0 + end + + if absolute == nil then + axis, dir = worldedit.translate_direction(name, direction) + + if axis == nil or dir == nil then + return false, "Invalid if looking straight up or down" + end + else + if direction == "?" then + axis, dir = worldedit.player_axis(name) + else + axis = direction + dir = 1 + end + end + + if sign == "-" then + dir = -dir + end + + worldedit.cuboid_linear_expand(name, axis, dir, amount) + worldedit.cuboid_linear_expand(name, axis, -dir, rev_amount) + worldedit.marker_update(name) + return true, "Region expanded by " .. (amount + rev_amount) .. " nodes" + end, + } +) + + +minetest.register_chatcommand("/contract", { + params = "[+|-] [reverse-amount]", + description = "contract the selection in one or two directions at once", + privs = {worldedit=true}, + func = function(name, param) + local find, _, sign, direction, amount, + rev_amount = param:find("([+-]?)([%?%l]+)%s*(%d+)%s*(%d*)") + + if find == nil then + worldedit.player_notify(name, "invalid use: " .. param) + return + end + + if worldedit.pos1[name] == nil or worldedit.pos2[name] == nil then + worldedit.player_notify(name, + "Undefined region. Region must be defined beforehand.") + return + end + + local absolute = direction:find("[xyz?]") + local dir, axis + + if rev_amount == "" then + rev_amount = 0 + end + + if absolute == nil then + axis, dir = worldedit.translate_direction(name, direction) + + if axis == nil or dir == nil then + return false, "Invalid if looking straight up or down" + end + else + if direction == "?" then + axis, dir = worldedit.player_axis(name) + else + axis = direction + dir = 1 + end + end + + if sign == "-" then + dir = -dir + end + + worldedit.cuboid_linear_expand(name, axis, dir, -amount) + worldedit.cuboid_linear_expand(name, axis, -dir, -rev_amount) + worldedit.marker_update(name) + return true, "Region contracted by " .. (amount + rev_amount) .. " nodes" + end, + } +) diff --git a/mods/WorldEdit/worldedit_commands/depends.txt b/mods/WorldEdit/worldedit_commands/depends.txt old mode 100755 new mode 100644 diff --git a/mods/WorldEdit/worldedit_commands/init.lua b/mods/WorldEdit/worldedit_commands/init.lua old mode 100755 new mode 100644 index 9e8383c..f5837bf --- a/mods/WorldEdit/worldedit_commands/init.lua +++ b/mods/WorldEdit/worldedit_commands/init.lua @@ -10,8 +10,10 @@ if minetest.place_schematic then worldedit.prob_list = {} end +dofile(minetest.get_modpath("worldedit_commands") .. "/cuboid.lua") dofile(minetest.get_modpath("worldedit_commands") .. "/mark.lua") -local safe_region, check_region = dofile(minetest.get_modpath("worldedit_commands") .. "/safe.lua") +dofile(minetest.get_modpath("worldedit_commands") .. "/wand.lua") +local safe_region, check_region, reset_pending = dofile(minetest.get_modpath("worldedit_commands") .. "/safe.lua") local function get_position(name) --position 1 retrieval function for when not using `safe_region` local pos1 = worldedit.pos1[name] @@ -91,6 +93,56 @@ minetest.register_chatcommand("/about", { end, }) +-- mostly copied from builtin/chatcommands.lua with minor modifications +minetest.register_chatcommand("/help", { + privs = {}, + params = "[all/]", + description = "Get help for WorldEdit commands", + func = function(name, param) + local function is_we_command(cmd) + return cmd:sub(0, 1) == "/" + end + local function format_help_line(cmd, def) + local msg = minetest.colorize("#00ffff", "/"..cmd) + if def.params and def.params ~= "" then + msg = msg .. " " .. def.params + end + if def.description and def.description ~= "" then + msg = msg .. ": " .. def.description + end + return msg + end + + if not minetest.check_player_privs(name, "worldedit") then + return false, "You are not allowed to use any WorldEdit commands." + end + if param == "" then + local msg = "" + local cmds = {} + for cmd, def in pairs(minetest.chatcommands) do + if is_we_command(cmd) and minetest.check_player_privs(name, def.privs) then + cmds[#cmds + 1] = cmd:sub(2) -- strip the / + end + end + table.sort(cmds) + return true, "Available commands: " .. table.concat(cmds, " ") .. "\n" + .. "Use '//help ' to get more information," + .. " or '//help all' to list everything." + elseif param == "all" then + local cmds = {} + for cmd, def in pairs(minetest.chatcommands) do + if is_we_command(cmd) and minetest.check_player_privs(name, def.privs) then + cmds[#cmds + 1] = format_help_line(cmd, def) + end + end + table.sort(cmds) + return true, "Available commands:\n"..table.concat(cmds, "\n") + else + return minetest.chatcommands["help"].func(name, "/" .. param) + end + end, +}) + minetest.register_chatcommand("/inspect", { params = "on/off/1/0/true/false/yes/no/enable/disable/", description = "Enable or disable node inspection", @@ -110,16 +162,28 @@ minetest.register_chatcommand("/inspect", { end, }) +local function get_node_rlight(pos) + local vecs = { -- neighboring nodes + {x= 1, y= 0, z= 0}, + {x=-1, y= 0, z= 0}, + {x= 0, y= 1, z= 0}, + {x= 0, y=-1, z= 0}, + {x= 0, y= 0, z= 1}, + {x= 0, y= 0, z=-1}, + } + local ret = 0 + for _, v in ipairs(vecs) do + ret = math.max(ret, minetest.get_node_light(vector.add(pos, v))) + end + return ret +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 - local axis, sign = worldedit.player_axis(name) - message = string.format("inspector: %s at %s (param1=%d, param2=%d) punched by %s facing the %s axis", - node.name, minetest.pos_to_string(pos), node.param1, node.param2, name, axis .. (sign > 0 and "+" or "-")) - else - message = "inspector: worldedit privileges required" - end + local axis, sign = worldedit.player_axis(name) + message = string.format("inspector: %s at %s (param1=%d, param2=%d, received light=%d) punched facing the %s axis", + node.name, minetest.pos_to_string(pos), node.param1, node.param2, get_node_rlight(pos), axis .. (sign > 0 and "+" or "-")) worldedit.player_notify(name, message) end end) @@ -134,6 +198,8 @@ minetest.register_chatcommand("/reset", { worldedit.mark_pos1(name) worldedit.mark_pos2(name) worldedit.set_pos[name] = nil + --make sure the user does not try to confirm an operation after resetting pos: + reset_pending(name) worldedit.player_notify(name, "region reset") end, }) @@ -516,6 +582,39 @@ minetest.register_chatcommand("/cylinder", { end, check_cylinder), }) +local check_pyramid = function(name, param) + if worldedit.pos1[name] == nil then + worldedit.player_notify(name, "no position 1 selected") + return nil + end + local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$") + if found == nil then + worldedit.player_notify(name, "invalid usage: " .. param) + return nil + end + local node = get_node(name, nodename) + if not node then return nil end + height = tonumber(height) + return math.ceil(((height * 2 + 1) ^ 2) * height / 3) +end + +minetest.register_chatcommand("/hollowpyramid", { + params = "x/y/z/? ", + description = "Add hollow pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height , composed of ", + privs = {worldedit=true}, + func = safe_region(function(name, param) + local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$") + height = tonumber(height) + if axis == "?" then + axis, sign = worldedit.player_axis(name) + height = height * sign + end + local node = get_node(name, nodename) + local count = worldedit.pyramid(worldedit.pos1[name], axis, height, node, true) + worldedit.player_notify(name, count .. " nodes added") + end, check_pyramid), +}) + minetest.register_chatcommand("/pyramid", { params = "x/y/z/? ", description = "Add pyramid centered at WorldEdit position 1 along the x/y/z/? axis with height , composed of ", @@ -530,22 +629,7 @@ minetest.register_chatcommand("/pyramid", { local node = get_node(name, nodename) local count = worldedit.pyramid(worldedit.pos1[name], axis, height, node) worldedit.player_notify(name, count .. " nodes added") - end, - function(name, param) - if worldedit.pos1[name] == nil then - worldedit.player_notify(name, "no position 1 selected") - return nil - end - local found, _, axis, height, nodename = param:find("^([xyz%?])%s+([+-]?%d+)%s+(.+)$") - if found == nil then - worldedit.player_notify(name, "invalid usage: " .. param) - return nil - end - local node = get_node(name, nodename) - if not node then return nil end - height = tonumber(height) - return math.ceil(((height * 2 + 1) ^ 2) * height / 3) - end), + end, check_pyramid), }) minetest.register_chatcommand("/spiral", { @@ -570,7 +654,7 @@ minetest.register_chatcommand("/spiral", { end local node = get_node(name, nodename) if not node then return nil end - return check_region(name, param) + return 1 -- TODO: return an useful value end), }) @@ -838,6 +922,30 @@ minetest.register_chatcommand("/fixlight", { end), }) +minetest.register_chatcommand("/drain", { + params = "", + description = "Remove any fluid node within the current WorldEdit region", + privs = {worldedit=true}, + func = safe_region(function(name, param) + -- TODO: make an API function for this + local count = 0 + local pos1, pos2 = worldedit.sort_pos(worldedit.pos1[name], worldedit.pos2[name]) + for x = pos1.x, pos2.x do + for y = pos1.y, pos2.y do + for z = pos1.z, pos2.z do + local n = minetest.get_node({x=x, y=y, z=z}).name + local d = minetest.registered_nodes[n] + if d ~= nil and (d["drawtype"] == "liquid" or d["drawtype"] == "flowingliquid") then + minetest.remove_node({x=x, y=y, z=z}) + count = count + 1 + end + end + end + end + worldedit.player_notify(name, count .. " nodes updated") + end), +}) + minetest.register_chatcommand("/hide", { params = "", description = "Hide all nodes in the current WorldEdit region non-destructively", @@ -1015,11 +1123,6 @@ minetest.register_chatcommand("/lua", { description = "Executes as a Lua chunk in the global namespace", privs = {worldedit=true, server=true}, func = function(name, param) - local admin = minetest.setting_get("name") - if not admin or not name == admin then - worldedit.player_notify(name, "this command can only be run by the server administrator") - return - end local err = worldedit.lua(param) if err then worldedit.player_notify(name, "code error: " .. err) @@ -1034,12 +1137,6 @@ minetest.register_chatcommand("/luatransform", { 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 = safe_region(function(name, param) - local admin = minetest.setting_get("name") - if not admin or not name == admin then - worldedit.player_notify(name, "this command can only be run by the server administrator") - return - end - local err = worldedit.luatransform(worldedit.pos1[name], worldedit.pos2[name], param) if err then worldedit.player_notify(name, "code error: " .. err, false) @@ -1127,8 +1224,8 @@ minetest.register_chatcommand("/mtschemprob", { 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 .. "% | " + 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) @@ -1138,16 +1235,14 @@ minetest.register_chatcommand("/mtschemprob", { 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 +minetest.register_on_player_receive_fields(function(player, formname, fields) + if formname == "prob_val_enter" and not (fields.text == "" or fields.text == nil) 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) minetest.register_chatcommand("/clearobjects", { params = "", diff --git a/mods/WorldEdit/worldedit_commands/mark.lua b/mods/WorldEdit/worldedit_commands/mark.lua old mode 100755 new mode 100644 index ef4ed57..bc46a7f --- a/mods/WorldEdit/worldedit_commands/mark.lua +++ b/mods/WorldEdit/worldedit_commands/mark.lua @@ -58,8 +58,19 @@ worldedit.mark_region = function(name) end worldedit.marker_region[name] = nil end + if pos1 ~= nil and pos2 ~= nil then local pos1, pos2 = worldedit.sort_pos(pos1, pos2) + + local vec = vector.subtract(pos2, pos1) + local maxside = math.max(vec.x, math.max(vec.y, vec.z)) + local limit = tonumber(minetest.setting_get("active_object_send_range_blocks")) * 16 + if maxside > limit * 1.5 then + -- The client likely won't be able to see the plane markers as intended anyway, + -- thus don't place them and also don't load the area into memory + return + end + local thickness = 0.2 local sizex, sizey, sizez = (1 + pos2.x - pos1.x) / 2, (1 + pos2.y - pos1.y) / 2, (1 + pos2.z - pos1.z) / 2 @@ -72,24 +83,28 @@ worldedit.mark_region = function(name) --XY plane markers for _, z in ipairs({pos1.z - 0.5, pos2.z + 0.5}) do local marker = minetest.add_entity({x=pos1.x + sizex - 0.5, y=pos1.y + sizey - 0.5, z=z}, "worldedit:region_cube") - marker:set_properties({ - visual_size={x=sizex * 2, y=sizey * 2}, - collisionbox = {-sizex, -sizey, -thickness, sizex, sizey, thickness}, - }) - marker:get_luaentity().player_name = name - table.insert(markers, marker) + if marker ~= nil then + marker:set_properties({ + visual_size={x=sizex * 2, y=sizey * 2}, + collisionbox = {-sizex, -sizey, -thickness, sizex, sizey, thickness}, + }) + marker:get_luaentity().player_name = name + table.insert(markers, marker) + end end --YZ plane markers for _, x in ipairs({pos1.x - 0.5, pos2.x + 0.5}) do local marker = minetest.add_entity({x=x, y=pos1.y + sizey - 0.5, z=pos1.z + sizez - 0.5}, "worldedit:region_cube") - marker:set_properties({ - visual_size={x=sizez * 2, y=sizey * 2}, - collisionbox = {-thickness, -sizey, -sizez, thickness, sizey, sizez}, - }) - marker:setyaw(math.pi / 2) - marker:get_luaentity().player_name = name - table.insert(markers, marker) + if marker ~= nil then + marker:set_properties({ + visual_size={x=sizez * 2, y=sizey * 2}, + collisionbox = {-thickness, -sizey, -sizez, thickness, sizey, sizez}, + }) + marker:setyaw(math.pi / 2) + marker:get_luaentity().player_name = name + table.insert(markers, marker) + end end worldedit.marker_region[name] = markers @@ -153,7 +168,11 @@ minetest.register_entity(":worldedit:region_cube", { end end, on_punch = function(self, hitter) - for _, entity in ipairs(worldedit.marker_region[self.player_name]) do + local markers = worldedit.marker_region[self.player_name] + if not markers then + return + end + for _, entity in ipairs(markers) do entity:remove() end worldedit.marker_region[self.player_name] = nil diff --git a/mods/WorldEdit/worldedit_commands/safe.lua b/mods/WorldEdit/worldedit_commands/safe.lua old mode 100755 new mode 100644 index e52a6d2..3b2818d --- a/mods/WorldEdit/worldedit_commands/safe.lua +++ b/mods/WorldEdit/worldedit_commands/safe.lua @@ -30,6 +30,10 @@ local function safe_region(callback, nodes_needed) end end +local function reset_pending(name) + safe_region_callback[name], safe_region_param[name] = nil, nil +end + minetest.register_chatcommand("/y", { params = "", description = "Confirm a pending operation", @@ -40,15 +44,8 @@ minetest.register_chatcommand("/y", { return end - --obtain positions - 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 - safe_region_callback[name], safe_region_param[name] = nil, nil --reset pending operation - callback(name, param, pos1, pos2) + callback(name, param) end, }) @@ -64,5 +61,5 @@ minetest.register_chatcommand("/n", { end, }) -return safe_region, check_region +return safe_region, check_region, reset_pending diff --git a/mods/WorldEdit/worldedit_commands/textures/worldedit_cube.png b/mods/WorldEdit/worldedit_commands/textures/worldedit_cube.png old mode 100755 new mode 100644 index 075a9cb..fde36a8 Binary files a/mods/WorldEdit/worldedit_commands/textures/worldedit_cube.png and b/mods/WorldEdit/worldedit_commands/textures/worldedit_cube.png differ diff --git a/mods/WorldEdit/worldedit_commands/textures/worldedit_pos1.png b/mods/WorldEdit/worldedit_commands/textures/worldedit_pos1.png old mode 100755 new mode 100644 index cbd4337..4c304aa Binary files a/mods/WorldEdit/worldedit_commands/textures/worldedit_pos1.png and b/mods/WorldEdit/worldedit_commands/textures/worldedit_pos1.png differ diff --git a/mods/WorldEdit/worldedit_commands/textures/worldedit_pos2.png b/mods/WorldEdit/worldedit_commands/textures/worldedit_pos2.png old mode 100755 new mode 100644 index 5214780..1502f16 Binary files a/mods/WorldEdit/worldedit_commands/textures/worldedit_pos2.png and b/mods/WorldEdit/worldedit_commands/textures/worldedit_pos2.png differ diff --git a/mods/WorldEdit/worldedit_commands/wand.lua b/mods/WorldEdit/worldedit_commands/wand.lua new file mode 100644 index 0000000..0780801 --- /dev/null +++ b/mods/WorldEdit/worldedit_commands/wand.lua @@ -0,0 +1,24 @@ +minetest.register_tool(":worldedit:wand", { + description = "WorldEdit Wand tool, Left-click to set 1st position, right-click to set 2nd", + inventory_image = "worldedit_wand.png", + stack_max = 1, -- there is no need to have more than one + liquids_pointable = true, -- ground with only water on can be selected as well + + on_use = function(itemstack, placer, pointed_thing) + if placer ~= nil and pointed_thing ~= nil and pointed_thing.type == "node" then + local name = placer:get_player_name() + worldedit.pos1[name] = pointed_thing.under + worldedit.mark_pos1(name) + end + return itemstack -- nothing consumed, nothing changed + end, + + on_place = function(itemstack, placer, pointed_thing) -- Left Click + if placer ~= nil and pointed_thing ~= nil and pointed_thing.type == "node" then + local name = placer:get_player_name() + worldedit.pos2[name] = pointed_thing.under + worldedit.mark_pos2(name) + end + return itemstack -- nothing consumed, nothing changed + end, +}) diff --git a/mods/WorldEdit/worldedit_gui/depends.txt b/mods/WorldEdit/worldedit_gui/depends.txt old mode 100755 new mode 100644 index d603ac9..2558dce --- a/mods/WorldEdit/worldedit_gui/depends.txt +++ b/mods/WorldEdit/worldedit_gui/depends.txt @@ -2,4 +2,5 @@ worldedit worldedit_commands unified_inventory? inventory_plus? -creative? \ No newline at end of file +sfinv? +creative? diff --git a/mods/WorldEdit/worldedit_gui/functionality.lua b/mods/WorldEdit/worldedit_gui/functionality.lua old mode 100755 new mode 100644 index 3ba7c95..1fe14e5 --- a/mods/WorldEdit/worldedit_gui/functionality.lua +++ b/mods/WorldEdit/worldedit_gui/functionality.lua @@ -40,13 +40,13 @@ local angle_values = {90, 180, 270} setmetatable(angle_indices, {__index = function () return 1 end}) setmetatable(angle_values, {__index = function () return 90 end}) ---given multiple sets of privileges, produces a single set of privs that would have the same effect as requiring all of them at the same time +-- given multiple sets of privileges, produces a single set of privs that would have the same effect as requiring all of them at the same time local combine_privs = function(...) local result = {} for i, privs in ipairs({...}) do for name, value in pairs(privs) do if result[name] ~= nil and result[name] ~= value then --the priv must be both true and false, which can never happen - return {__fake_priv_that_nobody_has__=true} --priviledge table that can never be satisfied + return {__fake_priv_that_nobody_has__=true} --privilege table that can never be satisfied end result[name] = value end @@ -54,22 +54,44 @@ local combine_privs = function(...) return result end +-- display node (or unknown_node image otherwise) at specified pos in formspec +local formspec_node = function(pos, nodename) + return nodename and string.format("item_image[%s;1,1;%s]", pos, nodename) + or string.format("image[%s;1,1;worldedit_gui_unknown.png]", pos) +end + +-- two further priv helpers +local function we_privs(command) + return minetest.chatcommands["/" .. command].privs +end + +local function combine_we_privs(list) + local args = {} + for _, t in ipairs(list) do + table.insert(args, we_privs(t)) + end + return combine_privs(unpack(args)) +end + worldedit.register_gui_function("worldedit_gui_about", { - name = "About", privs = minetest.chatcommands["/about"].privs, + name = "About", + privs = {interact=true}, on_select = function(name) minetest.chatcommands["/about"].func(name, "") end, }) worldedit.register_gui_function("worldedit_gui_inspect", { - name = "Toggle Inspect", privs = minetest.chatcommands["/inspect"].privs, + name = "Toggle Inspect", + privs = we_privs("inspect"), on_select = function(name) minetest.chatcommands["/inspect"].func(name, worldedit.inspect[name] and "disable" or "enable") end, }) worldedit.register_gui_function("worldedit_gui_region", { - name = "Get/Set Region", privs = combine_privs(minetest.chatcommands["/p"].privs, minetest.chatcommands["/pos1"].privs, minetest.chatcommands["/pos2"].privs, minetest.chatcommands["/reset"].privs, minetest.chatcommands["/mark"].privs, minetest.chatcommands["/unmark"].privs, minetest.chatcommands["/volume"].privs, minetest.chatcommands["/fixedpos"].privs), + name = "Get/Set Region", + privs = combine_we_privs({"p", "pos1", "pos2", "reset", "mark", "unmark", "volume", "fixedpos"}), get_formspec = function(name) local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name] return "size[9,7]" .. worldedit.get_formspec_header("worldedit_gui_region") .. @@ -148,15 +170,15 @@ worldedit.register_gui_handler("worldedit_gui_region", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_set", { - name = "Set Nodes", privs = minetest.chatcommands["/set"].privs, + name = "Set Nodes", + privs = we_privs("set"), get_formspec = function(name) local node = gui_nodename1[name] local nodename = worldedit.normalize_nodename(node) return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_set") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_set_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_set_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. "button_exit[0,2.5;3,0.8;worldedit_gui_set_submit;Set Nodes]" end, }) @@ -166,7 +188,10 @@ worldedit.register_gui_handler("worldedit_gui_set", function(name, fields) gui_nodename1[name] = tostring(fields.worldedit_gui_set_node) worldedit.show_page(name, "worldedit_gui_set") if fields.worldedit_gui_set_submit then - minetest.chatcommands["/set"].func(name, gui_nodename1[name]) + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/set"].func(name, n) + end end return true end @@ -174,19 +199,18 @@ worldedit.register_gui_handler("worldedit_gui_set", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_replace", { - name = "Replace Nodes", privs = combine_privs(minetest.chatcommands["/replace"].privs, minetest.chatcommands["/replaceinverse"].privs), + name = "Replace Nodes", + privs = combine_we_privs({"replace", "replaceinverse"}), get_formspec = function(name) local search, replace = gui_nodename1[name], gui_nodename2[name] local search_nodename, replace_nodename = worldedit.normalize_nodename(search), worldedit.normalize_nodename(replace) return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_replace") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_replace_search;Name;%s]", minetest.formspec_escape(search)) .. "button[4,1.18;1.5,0.8;worldedit_gui_replace_search_search;Search]" .. - (search_nodename and string.format("item_image[5.5,1.1;1,1;%s]", search_nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", search_nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_replace_replace;Name;%s]", minetest.formspec_escape(replace)) .. "button[4,2.18;1.5,0.8;worldedit_gui_replace_replace_search;Search]" .. - (replace_nodename and string.format("item_image[5.5,2.1;1,1;%s]", replace_nodename) - or "image[5.5,2.1;1,1;unknown_node.png]") .. + formspec_node("5.5,2.1", replace_nodename) .. "button_exit[0,3.5;3,0.8;worldedit_gui_replace_submit;Replace Nodes]" .. "button_exit[3.5,3.5;3,0.8;worldedit_gui_replace_submit_inverse;Replace Inverse]" end, @@ -198,10 +222,19 @@ worldedit.register_gui_handler("worldedit_gui_replace", function(name, fields) gui_nodename1[name] = tostring(fields.worldedit_gui_replace_search) gui_nodename2[name] = tostring(fields.worldedit_gui_replace_replace) worldedit.show_page(name, "worldedit_gui_replace") + + local submit = nil if fields.worldedit_gui_replace_submit then - minetest.chatcommands["/replace"].func(name, string.format("%s %s", gui_nodename1[name], gui_nodename2[name])) + submit = "replace" elseif fields.worldedit_gui_replace_submit_inverse then - minetest.chatcommands["/replaceinverse"].func(name, string.format("%s %s", gui_nodename1[name], gui_nodename2[name])) + submit = "replaceinverse" + end + if submit then + local n1 = worldedit.normalize_nodename(gui_nodename1[name]) + local n2 = worldedit.normalize_nodename(gui_nodename2[name]) + if n1 and n2 then + minetest.chatcommands["/"..submit].func(name, string.format("%s %s", n1, n2)) + end end return true end @@ -209,15 +242,15 @@ worldedit.register_gui_handler("worldedit_gui_replace", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_sphere_dome", { - name = "Sphere/Dome", privs = combine_privs(minetest.chatcommands["/hollowsphere"].privs, minetest.chatcommands["/sphere"].privs, minetest.chatcommands["/hollowdome"].privs, minetest.chatcommands["/dome"].privs), + name = "Sphere/Dome", + privs = combine_we_privs({"hollowsphere", "sphere", "hollowdome", "dome"}), get_formspec = function(name) local node, radius = gui_nodename1[name], gui_distance2[name] local nodename = worldedit.normalize_nodename(node) return "size[6.5,5]" .. worldedit.get_formspec_header("worldedit_gui_sphere_dome") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_sphere_dome_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_sphere_dome_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_sphere_dome_radius;Radius;%s]", minetest.formspec_escape(radius)) .. "button_exit[0,3.5;3,0.8;worldedit_gui_sphere_dome_submit_hollow;Hollow Sphere]" .. "button_exit[3.5,3.5;3,0.8;worldedit_gui_sphere_dome_submit_solid;Solid Sphere]" .. @@ -233,14 +266,22 @@ worldedit.register_gui_handler("worldedit_gui_sphere_dome", function(name, field gui_nodename1[name] = tostring(fields.worldedit_gui_sphere_dome_node) gui_distance2[name] = tostring(fields.worldedit_gui_sphere_dome_radius) worldedit.show_page(name, "worldedit_gui_sphere_dome") + + local submit = nil if fields.worldedit_gui_sphere_dome_submit_hollow then - minetest.chatcommands["/hollowsphere"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name])) + submit = "hollowsphere" elseif fields.worldedit_gui_sphere_dome_submit_solid then - minetest.chatcommands["/sphere"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name])) + submit = "sphere" elseif fields.worldedit_gui_sphere_dome_submit_hollow_dome then - minetest.chatcommands["/hollowdome"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name])) + submit = "hollowdome" elseif fields.worldedit_gui_sphere_dome_submit_solid_dome then - minetest.chatcommands["/dome"].func(name, string.format("%s %s", gui_distance2[name], gui_nodename1[name])) + submit = "dome" + end + if submit then + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/"..submit].func(name, string.format("%s %s", gui_distance2[name], n)) + end end return true end @@ -248,15 +289,15 @@ worldedit.register_gui_handler("worldedit_gui_sphere_dome", function(name, field end) worldedit.register_gui_function("worldedit_gui_cylinder", { - name = "Cylinder", privs = combine_privs(minetest.chatcommands["/hollowcylinder"].privs, minetest.chatcommands["/cylinder"].privs), + name = "Cylinder", + privs = combine_we_privs({"hollowcylinder", "cylinder"}), get_formspec = function(name) local node, axis, length, radius = gui_nodename1[name], gui_axis1[name], gui_distance1[name], gui_distance2[name] local nodename = worldedit.normalize_nodename(node) return "size[6.5,5]" .. worldedit.get_formspec_header("worldedit_gui_cylinder") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_cylinder_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_cylinder_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_cylinder_length;Length;%s]", minetest.formspec_escape(length)) .. string.format("dropdown[4,2.18;2.5;worldedit_gui_cylinder_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) .. string.format("field[0.5,3.5;4,0.8;worldedit_gui_cylinder_radius;Radius;%s]", minetest.formspec_escape(radius)) .. @@ -273,56 +314,85 @@ worldedit.register_gui_handler("worldedit_gui_cylinder", function(name, fields) gui_distance1[name] = tostring(fields.worldedit_gui_cylinder_length) gui_distance2[name] = tostring(fields.worldedit_gui_cylinder_radius) worldedit.show_page(name, "worldedit_gui_cylinder") + + local submit = nil if fields.worldedit_gui_cylinder_submit_hollow then - minetest.chatcommands["/hollowcylinder"].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], gui_nodename1[name])) + submit = "hollowcylinder" elseif fields.worldedit_gui_cylinder_submit_solid then - minetest.chatcommands["/cylinder"].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], gui_nodename1[name])) + submit = "cylinder" end + if submit then + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/"..submit].func(name, string.format("%s %s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_distance2[name], n)) + end + end + return true + end + if fields.worldedit_gui_cylinder_axis then + gui_axis1[name] = axis_indices[fields.worldedit_gui_cylinder_axis] + worldedit.show_page(name, "worldedit_gui_cylinder") return true end return false end) worldedit.register_gui_function("worldedit_gui_pyramid", { - name = "Pyramid", privs = minetest.chatcommands["/pyramid"].privs, + name = "Pyramid", + privs = we_privs("pyramid"), get_formspec = function(name) local node, axis, length = gui_nodename1[name], gui_axis1[name], gui_distance1[name] local nodename = worldedit.normalize_nodename(node) return "size[6.5,4]" .. worldedit.get_formspec_header("worldedit_gui_pyramid") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_pyramid_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_pyramid_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_pyramid_length;Length;%s]", minetest.formspec_escape(length)) .. string.format("dropdown[4,2.18;2.5;worldedit_gui_pyramid_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) .. - "button_exit[0,3.5;3,0.8;worldedit_gui_pyramid_submit;Pyramid]" + "button_exit[0,3.5;3,0.8;worldedit_gui_pyramid_submit_hollow;Hollow Pyramid]" .. + "button_exit[3.5,3.5;3,0.8;worldedit_gui_pyramid_submit_solid;Solid Pyramid]" end, }) worldedit.register_gui_handler("worldedit_gui_pyramid", function(name, fields) - if fields.worldedit_gui_pyramid_search or fields.worldedit_gui_pyramid_submit then + if fields.worldedit_gui_pyramid_search or fields.worldedit_gui_pyramid_submit_solid or fields.worldedit_gui_pyramid_submit_hollow or fields.worldedit_gui_pyramid_axis then gui_nodename1[name] = tostring(fields.worldedit_gui_pyramid_node) gui_axis1[name] = axis_indices[fields.worldedit_gui_pyramid_axis] gui_distance1[name] = tostring(fields.worldedit_gui_pyramid_length) worldedit.show_page(name, "worldedit_gui_pyramid") - if fields.worldedit_gui_pyramid_submit then - minetest.chatcommands["/pyramid"].func(name, string.format("%s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], gui_nodename1[name])) + + local submit = nil + if fields.worldedit_gui_pyramid_submit_solid then + submit = "pyramid" + elseif fields.worldedit_gui_pyramid_submit_hollow then + submit = "hollowpyramid" end + if submit then + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/"..submit].func(name, string.format("%s %s %s", axis_values[gui_axis1[name]], gui_distance1[name], n)) + end + end + return true + end + if fields.worldedit_gui_pyramid_axis then + gui_axis1[name] = axis_indices[fields.worldedit_gui_pyramid_axis] + worldedit.show_page(name, "worldedit_gui_pyramid") return true end return false end) worldedit.register_gui_function("worldedit_gui_spiral", { - name = "Spiral", privs = minetest.chatcommands["/spiral"].privs, + name = "Spiral", + privs = we_privs("spiral"), get_formspec = function(name) local node, length, height, space = gui_nodename1[name], gui_distance1[name], gui_distance2[name], gui_distance3[name] local nodename = worldedit.normalize_nodename(node) return "size[6.5,6]" .. worldedit.get_formspec_header("worldedit_gui_spiral") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_spiral_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_spiral_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. string.format("field[0.5,2.5;4,0.8;worldedit_gui_spiral_length;Side Length;%s]", minetest.formspec_escape(length)) .. string.format("field[0.5,3.5;4,0.8;worldedit_gui_spiral_height;Height;%s]", minetest.formspec_escape(height)) .. string.format("field[0.5,4.5;4,0.8;worldedit_gui_spiral_space;Wall Spacing;%s]", minetest.formspec_escape(space)) .. @@ -338,7 +408,10 @@ worldedit.register_gui_handler("worldedit_gui_spiral", function(name, fields) gui_distance3[name] = tostring(fields.worldedit_gui_spiral_space) worldedit.show_page(name, "worldedit_gui_spiral") if fields.worldedit_gui_spiral_submit then - minetest.chatcommands["/spiral"].func(name, string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], gui_nodename1[name])) + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/spiral"].func(name, string.format("%s %s %s %s", gui_distance1[name], gui_distance2[name], gui_distance3[name], n)) + end end return true end @@ -346,7 +419,8 @@ worldedit.register_gui_handler("worldedit_gui_spiral", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_copy_move", { - name = "Copy/Move", privs = combine_privs(minetest.chatcommands["/copy"].privs, minetest.chatcommands["/move"].privs), + name = "Copy/Move", + privs = combine_we_privs({"copy", "move"}), get_formspec = function(name) local axis = gui_axis1[name] or 4 local amount = gui_distance1[name] or "10" @@ -370,11 +444,17 @@ worldedit.register_gui_handler("worldedit_gui_copy_move", function(name, fields) end return true end + if fields.worldedit_gui_copy_move_axis then + gui_axis1[name] = axis_indices[fields.worldedit_gui_copy_move_axis] or 4 + worldedit.show_page(name, "worldedit_gui_copy_move") + return true + end return false end) worldedit.register_gui_function("worldedit_gui_stack", { - name = "Stack", privs = minetest.chatcommands["/stack"].privs, + name = "Stack", + privs = we_privs("stack"), get_formspec = function(name) local axis, count = gui_axis1[name], gui_count1[name] return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_stack") .. @@ -392,11 +472,17 @@ worldedit.register_gui_handler("worldedit_gui_stack", function(name, fields) minetest.chatcommands["/stack"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], gui_count1[name])) return true end + if fields.worldedit_gui_stack_axis then + gui_axis1[name] = axis_indices[fields.worldedit_gui_stack_axis] + worldedit.show_page(name, "worldedit_gui_stack") + return true + end return false end) worldedit.register_gui_function("worldedit_gui_stretch", { - name = "Stretch", privs = minetest.chatcommands["/stretch"].privs, + name = "Stretch", + privs = we_privs("stretch"), get_formspec = function(name) local stretchx, stretchy, stretchz = gui_count1[name], gui_count2[name], gui_count3[name] return "size[5,5]" .. worldedit.get_formspec_header("worldedit_gui_stretch") .. @@ -420,7 +506,8 @@ worldedit.register_gui_handler("worldedit_gui_stretch", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_transpose", { - name = "Transpose", privs = minetest.chatcommands["/transpose"].privs, + name = "Transpose", + privs = we_privs("transpose"), get_formspec = function(name) local axis1, axis2 = gui_axis1[name], gui_axis2[name] return "size[5.5,3]" .. worldedit.get_formspec_header("worldedit_gui_transpose") .. @@ -433,18 +520,28 @@ worldedit.register_gui_function("worldedit_gui_transpose", { worldedit.register_gui_handler("worldedit_gui_transpose", function(name, fields) if fields.worldedit_gui_transpose_submit then gui_axis1[name] = axis_indices[fields.worldedit_gui_transpose_axis1] - gui_axis2[name] = axis_indices[fields.worldedit_gui_transpose_axis2] worldedit.show_page(name, "worldedit_gui_transpose") minetest.chatcommands["/transpose"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], axis_values[gui_axis2[name]])) return true end + if fields.worldedit_gui_transpose_axis1 then + gui_axis1[name] = axis_indices[fields.worldedit_gui_transpose_axis1] + worldedit.show_page(name, "worldedit_gui_transpose") + return true + end + if fields.worldedit_gui_transpose_axis2 then + gui_axis2[name] = axis_indices[fields.worldedit_gui_transpose_axis2] + worldedit.show_page(name, "worldedit_gui_transpose") + return true + end return false end) worldedit.register_gui_function("worldedit_gui_flip", { - name = "Flip", privs = minetest.chatcommands["/flip"].privs, + name = "Flip", + privs = we_privs("flip"), get_formspec = function(name) - local axis = gui_axis2[name] + local axis = gui_axis1[name] return "size[5,3]" .. worldedit.get_formspec_header("worldedit_gui_flip") .. string.format("dropdown[0,1;2.5;worldedit_gui_flip_axis;X axis,Y axis,Z axis,Look direction;%d]", axis) .. "button_exit[0,2.5;3,0.8;worldedit_gui_flip_submit;Flip]" @@ -453,16 +550,22 @@ worldedit.register_gui_function("worldedit_gui_flip", { worldedit.register_gui_handler("worldedit_gui_flip", function(name, fields) if fields.worldedit_gui_flip_submit then - gui_axis2[name] = axis_indices[fields.worldedit_gui_flip_axis] + gui_axis1[name] = axis_indices[fields.worldedit_gui_flip_axis] + worldedit.show_page(name, "worldedit_gui_flip") + minetest.chatcommands["/flip"].func(name, axis_values[gui_axis1[name]]) + return true + end + if fields.worldedit_gui_flip_axis then + gui_axis1[name] = axis_indices[fields.worldedit_gui_flip_axis] worldedit.show_page(name, "worldedit_gui_flip") - minetest.chatcommands["/flip"].func(name, axis_values[gui_axis2[name]]) return true end return false end) worldedit.register_gui_function("worldedit_gui_rotate", { - name = "Rotate", privs = minetest.chatcommands["/rotate"].privs, + name = "Rotate", + privs = we_privs("rotate"), get_formspec = function(name) local axis, angle = gui_axis1[name], gui_angle[name] return "size[5.5,3]" .. worldedit.get_formspec_header("worldedit_gui_rotate") .. @@ -480,11 +583,22 @@ worldedit.register_gui_handler("worldedit_gui_rotate", function(name, fields) minetest.chatcommands["/rotate"].func(name, string.format("%s %s", axis_values[gui_axis1[name]], angle_values[gui_angle[name]])) return true end + if fields.worldedit_gui_rotate_axis then + gui_axis1[name] = axis_indices[fields.worldedit_gui_rotate_axis] + worldedit.show_page(name, "worldedit_gui_rotate") + return true + end + if fields.worldedit_gui_rotate_angle then + gui_angle[name] = angle_indices[fields.worldedit_gui_rotate_angle] + worldedit.show_page(name, "worldedit_gui_rotate") + return true + end return false end) worldedit.register_gui_function("worldedit_gui_orient", { - name = "Orient", privs = minetest.chatcommands["/orient"].privs, + name = "Orient", + privs = we_privs("orient"), get_formspec = function(name) local angle = gui_angle[name] return "size[5,3]" .. worldedit.get_formspec_header("worldedit_gui_orient") .. @@ -497,36 +611,43 @@ worldedit.register_gui_handler("worldedit_gui_orient", function(name, fields) if fields.worldedit_gui_orient_submit then gui_angle[name] = angle_indices[fields.worldedit_gui_orient_angle] worldedit.show_page(name, "worldedit_gui_orient") - minetest.chatcommands["/orient"].func(name, angle_values[gui_angle[name]]) + minetest.chatcommands["/orient"].func(name, tostring(angle_values[gui_angle[name]])) + return true + end + if fields.worldedit_gui_orient_angle then + gui_angle[name] = angle_indices[fields.worldedit_gui_orient_angle] + worldedit.show_page(name, "worldedit_gui_orient") return true end return false end) worldedit.register_gui_function("worldedit_gui_fixlight", { - name = "Fix Lighting", privs = minetest.chatcommands["/fixlight"].privs, + name = "Fix Lighting", + privs = we_privs("fixlight"), on_select = function(name) minetest.chatcommands["/fixlight"].func(name, "") end, }) worldedit.register_gui_function("worldedit_gui_hide", { - name = "Hide Region", privs = minetest.chatcommands["/hide"].privs, + name = "Hide Region", + privs = we_privs("hide"), on_select = function(name) minetest.chatcommands["/hide"].func(name, "") end, }) worldedit.register_gui_function("worldedit_gui_suppress", { - name = "Suppress Nodes", privs = minetest.chatcommands["/suppress"].privs, + name = "Suppress Nodes", + privs = we_privs("suppress"), get_formspec = function(name) local node = gui_nodename1[name] local nodename = worldedit.normalize_nodename(node) return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_suppress") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_suppress_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_suppress_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. "button_exit[0,2.5;3,0.8;worldedit_gui_suppress_submit;Suppress Nodes]" end, }) @@ -536,7 +657,10 @@ worldedit.register_gui_handler("worldedit_gui_suppress", function(name, fields) gui_nodename1[name] = tostring(fields.worldedit_gui_suppress_node) worldedit.show_page(name, "worldedit_gui_suppress") if fields.worldedit_gui_suppress_submit then - minetest.chatcommands["/suppress"].func(name, gui_nodename1[name]) + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/suppress"].func(name, n) + end end return true end @@ -544,15 +668,15 @@ worldedit.register_gui_handler("worldedit_gui_suppress", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_highlight", { - name = "Highlight Nodes", privs = minetest.chatcommands["/highlight"].privs, + name = "Highlight Nodes", + privs = we_privs("highlight"), get_formspec = function(name) local node = gui_nodename1[name] local nodename = worldedit.normalize_nodename(node) return "size[6.5,3]" .. worldedit.get_formspec_header("worldedit_gui_highlight") .. string.format("field[0.5,1.5;4,0.8;worldedit_gui_highlight_node;Name;%s]", minetest.formspec_escape(node)) .. "button[4,1.18;1.5,0.8;worldedit_gui_highlight_search;Search]" .. - (nodename and string.format("item_image[5.5,1.1;1,1;%s]", nodename) - or "image[5.5,1.1;1,1;unknown_node.png]") .. + formspec_node("5.5,1.1", nodename) .. "button_exit[0,2.5;3,0.8;worldedit_gui_highlight_submit;Highlight Nodes]" end, }) @@ -562,7 +686,10 @@ worldedit.register_gui_handler("worldedit_gui_highlight", function(name, fields) gui_nodename1[name] = tostring(fields.worldedit_gui_highlight_node) worldedit.show_page(name, "worldedit_gui_highlight") if fields.worldedit_gui_highlight_submit then - minetest.chatcommands["/highlight"].func(name, gui_nodename1[name]) + local n = worldedit.normalize_nodename(gui_nodename1[name]) + if n then + minetest.chatcommands["/highlight"].func(name, n) + end end return true end @@ -570,14 +697,16 @@ worldedit.register_gui_handler("worldedit_gui_highlight", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_restore", { - name = "Restore Region", privs = minetest.chatcommands["/restore"].privs, + name = "Restore Region", + privs = we_privs("restore"), on_select = function(name) minetest.chatcommands["/restore"].func(name, "") end, }) worldedit.register_gui_function("worldedit_gui_save_load", { - name = "Save/Load", privs = combine_privs(minetest.chatcommands["/save"].privs, minetest.chatcommands["/allocate"].privs, minetest.chatcommands["/load"].privs), + name = "Save/Load", + privs = combine_we_privs({"save", "allocate", "load"}), get_formspec = function(name) local filename = gui_filename[name] return "size[6,4]" .. worldedit.get_formspec_header("worldedit_gui_save_load") .. @@ -588,9 +717,9 @@ worldedit.register_gui_function("worldedit_gui_save_load", { end, }) -worldedit.register_gui_handler("worldedit_gui_save", function(name, fields) - if fields.worldedit_gui_save_load_submit_save or worldedit_gui_save_load_submit_allocate or worldedit_gui_save_load_submit_load then - gui_filename[name] = tostring(fields.worldedit_gui_save_axis) +worldedit.register_gui_handler("worldedit_gui_save_load", function(name, fields) + if fields.worldedit_gui_save_load_submit_save or fields.worldedit_gui_save_load_submit_allocate or fields.worldedit_gui_save_load_submit_load then + gui_filename[name] = tostring(fields.worldedit_gui_save_filename) worldedit.show_page(name, "worldedit_gui_save_load") if fields.worldedit_gui_save_load_submit_save then minetest.chatcommands["/save"].func(name, gui_filename[name]) @@ -605,7 +734,8 @@ worldedit.register_gui_handler("worldedit_gui_save", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_lua", { - name = "Run Lua", + name = "Run Lua", privs = minetest.chatcommands["/clearobjects"].privs, + privs = we_privs("lua"), get_formspec = function(name) local code = gui_code[name] return "size[8,6.5]" .. worldedit.get_formspec_header("worldedit_gui_lua") .. @@ -617,7 +747,7 @@ worldedit.register_gui_function("worldedit_gui_lua", { worldedit.register_gui_handler("worldedit_gui_lua", function(name, fields) if fields.worldedit_gui_lua_run or fields.worldedit_gui_lua_transform then - gui_code[name] = fields.worldedit_gui_lua_value + gui_code[name] = fields.worldedit_gui_lua_code worldedit.show_page(name, "worldedit_gui_lua") if fields.worldedit_gui_lua_run then minetest.chatcommands["/lua"].func(name, gui_code[name]) @@ -630,28 +760,9 @@ worldedit.register_gui_handler("worldedit_gui_lua", function(name, fields) end) worldedit.register_gui_function("worldedit_gui_clearobjects", { - name = "Clear Objects", privs = minetest.chatcommands["/clearobjects"].privs, + name = "Clear Objects", + privs = we_privs("clearobjects"), on_select = function(name) minetest.chatcommands["/clearobjects"].func(name, "") end, }) - -worldedit.register_gui_function("worldedit_gui_formspec_tester", { - name = "Formspec Tester", - get_formspec = function(name) - local value = gui_formspec[name] - return "size[8,6.5]" .. worldedit.get_formspec_header("worldedit_gui_formspec_tester") .. - string.format("textarea[0.5,1;7.5,5.5;worldedit_gui_formspec_tester_value;Formspec Code;%s]", minetest.formspec_escape(value)) .. - "button_exit[0,6;3,0.8;worldedit_gui_formspec_tester_show;Show Formspec]" - end, -}) - -worldedit.register_gui_handler("worldedit_gui_formspec_tester", function(name, fields) - if fields.worldedit_gui_formspec_tester_show then - gui_formspec[name] = fields.worldedit_gui_formspec_tester_value or "" - worldedit.show_page(name, "worldedit_gui_formspec_tester") - minetest.show_formspec(name, "worldedit:formspec_tester", gui_formspec[name]) - return true - end - return false -end) diff --git a/mods/WorldEdit/worldedit_gui/init.lua b/mods/WorldEdit/worldedit_gui/init.lua index e545ae7..162cae0 100755 --- a/mods/WorldEdit/worldedit_gui/init.lua +++ b/mods/WorldEdit/worldedit_gui/init.lua @@ -14,7 +14,7 @@ Use `nil` for the `options` parameter to unregister the function associated with Use `nil` for the `get_formspec` field to denote that the function does not have its own screen. -Use `nil` for the `privs` field to denote that no special privileges are required to use the function. +The `privs` field may not be `nil`. If the identifier is already registered to another function, it will be replaced by the new one. @@ -24,6 +24,9 @@ The `on_select` function must not call `worldedit.show_page` worldedit.pages = {} --mapping of identifiers to options local identifiers = {} --ordered list of identifiers worldedit.register_gui_function = function(identifier, options) + if options.privs == nil or next(options.privs) == nil then + error("privs unset") + end worldedit.pages[identifier] = options table.insert(identifiers, identifier) end @@ -46,7 +49,7 @@ worldedit.register_gui_handler = function(identifier, handler) --ensure the player has permission to perform the action local entry = worldedit.pages[identifier] - if entry and minetest.check_player_privs(name, entry.privs or {}) then + if entry and minetest.check_player_privs(name, entry.privs) then return handler(name, fields) end return false @@ -67,7 +70,7 @@ local get_formspec = function(name, identifier) end --implement worldedit.show_page(name, page) in different ways depending on the available APIs -if unified_inventory then --unified inventory installed +if rawget(_G, "unified_inventory") then --unified inventory installed local old_func = worldedit.register_gui_function worldedit.register_gui_function = function(identifier, options) old_func(identifier, options) @@ -102,7 +105,7 @@ if unified_inventory then --unified inventory installed player:set_inventory_formspec(get_formspec(name, page)) end end -elseif inventory_plus then --inventory++ installed +elseif rawget(_G, "inventory_plus") then --inventory++ installed minetest.register_on_joinplayer(function(player) local can_worldedit = minetest.check_player_privs(player:get_player_name(), {worldedit=true}) if can_worldedit then @@ -120,7 +123,7 @@ elseif inventory_plus then --inventory++ installed return true elseif fields.worldedit_gui_exit then --return to original page if gui_player_formspecs[name] then - inventory_plus.set_inventory_formspec(player, gui_player_formspecs[name]) + inventory_plus.set_inventory_formspec(player, inventory_plus.get_formspec(player, "main")) end return true end @@ -133,7 +136,37 @@ elseif inventory_plus then --inventory++ installed inventory_plus.set_inventory_formspec(player, get_formspec(name, page)) end end +elseif rawget(_G, "sfinv") then --sfinv installed (part of minetest_game since 0.4.15) + assert(sfinv.enabled) + local orig_get = sfinv.pages["sfinv:crafting"].get + sfinv.override_page("sfinv:crafting", { + get = function(self, player, context) + local can_worldedit = minetest.check_player_privs(player, {worldedit=true}) + local fs = orig_get(self, player, context) + return fs .. (can_worldedit and "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" or "") + end + }) + + --show the form when the button is pressed and hide it when done + minetest.register_on_player_receive_fields(function(player, formname, fields) + if fields.worldedit_gui then --main page + worldedit.show_page(player:get_player_name(), "worldedit_gui") + return true + elseif fields.worldedit_gui_exit then --return to original page + sfinv.set_page(player, "sfinv:crafting") + return true + end + return false + end) + + worldedit.show_page = function(name, page) + local player = minetest.get_player_by_name(name) + if player then + player:set_inventory_formspec(get_formspec(name, page)) + end + end else --fallback button + -- FIXME: this is a huge clusterfuck and the back button is broken local player_formspecs = {} local update_main_formspec = function(name) @@ -145,8 +178,21 @@ else --fallback button if not player then --this is in case the player signs off while the media is loading return end - if (minetest.check_player_privs(name, {creative=true}) or minetest.setting_getbool("creative_mode")) and creative_inventory then --creative_inventory is active, add button to modified formspec - formspec = player:get_inventory_formspec() .. "image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" + if (minetest.check_player_privs(name, {creative=true}) or + minetest.setting_getbool("creative_mode")) and + creative then --creative is active, add button to modified formspec + local creative_formspec = player:get_inventory_formspec() + local tab_id = tonumber(creative_formspec:match("tabheader%[.-;(%d+)%;")) + + if tab_id == 1 then + formspec = creative_formspec .. + "image_button[0,1;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" + elseif not tab_id then + formspec = creative_formspec .. + "image_button[6,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" + else + return + end else formspec = formspec .. "image_button[0,0;1,1;inventory_plus_worldedit_gui.png;worldedit_gui;]" end @@ -199,6 +245,7 @@ end worldedit.register_gui_function("worldedit_gui", { name = "WorldEdit GUI", + privs = {interact=true}, get_formspec = function(name) --create a form with all the buttons arranged in a grid local buttons, x, y, index = {}, 0, 1, 0 @@ -231,7 +278,7 @@ worldedit.register_gui_handler("worldedit_gui", function(name, fields) for identifier, entry in pairs(worldedit.pages) do --check for WorldEdit GUI main formspec button selection if fields[identifier] and identifier ~= "worldedit_gui" then --ensure player has permission to perform action - local has_privs, missing_privs = minetest.check_player_privs(name, entry.privs or {}) + local has_privs, missing_privs = minetest.check_player_privs(name, entry.privs) if not has_privs then worldedit.player_notify(name, "you are not allowed to use this function (missing privileges: " .. table.concat(missing_privs, ", ") .. ")") return false diff --git a/mods/WorldEdit/worldedit_gui/textures/inventory_plus_worldedit_gui.png b/mods/WorldEdit/worldedit_gui/textures/inventory_plus_worldedit_gui.png old mode 100755 new mode 100644 index ff9404b..fbc1abc Binary files a/mods/WorldEdit/worldedit_gui/textures/inventory_plus_worldedit_gui.png and b/mods/WorldEdit/worldedit_gui/textures/inventory_plus_worldedit_gui.png differ diff --git a/mods/WorldEdit/worldedit_gui/textures/worldedit_gui_unknown.png b/mods/WorldEdit/worldedit_gui/textures/worldedit_gui_unknown.png new file mode 100644 index 0000000..f57436c Binary files /dev/null and b/mods/WorldEdit/worldedit_gui/textures/worldedit_gui_unknown.png differ diff --git a/mods/WorldEdit/worldedit_infinity/init.lua b/mods/WorldEdit/worldedit_infinity/init.lua old mode 100755 new mode 100644 diff --git a/mods/WorldEdit/worldedit_shortcommands/depends.txt b/mods/WorldEdit/worldedit_shortcommands/depends.txt old mode 100755 new mode 100644 diff --git a/mods/WorldEdit/worldedit_shortcommands/init.lua b/mods/WorldEdit/worldedit_shortcommands/init.lua old mode 100755 new mode 100644 index 8ef8d58..b8d8eb9 --- a/mods/WorldEdit/worldedit_shortcommands/init.lua +++ b/mods/WorldEdit/worldedit_shortcommands/init.lua @@ -31,6 +31,7 @@ worldedit.alias_chatcommand("/hdo", "/hollowdome") worldedit.alias_chatcommand("/do", "/dome") worldedit.alias_chatcommand("/hcyl", "/hollowcylinder") worldedit.alias_chatcommand("/cyl", "/cylinder") +worldedit.alias_chatcommand("/hpyr", "/hollowpyramid") worldedit.alias_chatcommand("/pyr", "/pyramid") worldedit.alias_chatcommand("/spl", "/spiral") worldedit.alias_chatcommand("/m", "/move") @@ -47,4 +48,4 @@ worldedit.alias_chatcommand("/hlt", "/highlight") worldedit.alias_chatcommand("/rsr", "/restore") worldedit.alias_chatcommand("/l", "/lua") worldedit.alias_chatcommand("/lt", "/luatransform") -worldedit.alias_chatcommand("/clro", "/clearobjects") \ No newline at end of file +worldedit.alias_chatcommand("/clro", "/clearobjects")