summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--ChatCommands.md (renamed from Chat Commands.md)0
-rw-r--r--README.md6
-rw-r--r--Tutorial.md4
-rw-r--r--WorldEdit API.md48
-rw-r--r--config.ld12
-rw-r--r--worldedit/code.lua40
-rw-r--r--worldedit/common.lua114
-rw-r--r--worldedit/compatibility.lua50
-rw-r--r--worldedit/init.lua49
-rw-r--r--worldedit/manipulations.lua720
-rw-r--r--worldedit/primitives.lua503
-rw-r--r--worldedit/serialization.lua27
-rw-r--r--worldedit/visualization.lua145
-rw-r--r--worldedit_commands/init.lua28
-rw-r--r--worldedit_commands/mark.lua25
16 files changed, 789 insertions, 984 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5236e1e
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*~
+
diff --git a/Chat Commands.md b/ChatCommands.md
index 07bcfd6..07bcfd6 100644
--- a/Chat Commands.md
+++ b/ChatCommands.md
diff --git a/README.md b/README.md
index 7d3077b..22dd7c7 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-WorldEdit v1.0 for Minetest 0.4.8+
+WorldEdit v1.1 for Minetest 0.4.8+
==================================
The ultimate in-game world editing tool for [Minetest](http://minetest.net/)! Tons of functionality to help with building, fixing, and more.
@@ -41,9 +41,9 @@ Interface
---------
WorldEdit is accessed in-game in two main ways.
-The GUI adds a screen to each player's inventory that gives access to various WorldEdit functions. The [tutorial](Tutorial.md) and the [Chat Commands Reference](Chat Commands.md) may be helpful in learning to use it.
+The GUI adds a screen to each player's inventory that gives access to various WorldEdit functions. The [tutorial](Tutorial.md) and the [Chat Commands Reference](ChatCommands.md) may be helpful in learning to use it.
-The chat interface adds many chat commands that perform various WorldEdit powered tasks. It is documented in the [Chat Commands Reference](Chat Commands.md).
+The chat interface adds many chat commands that perform various WorldEdit powered tasks. It is documented in the [Chat Commands Reference](ChatCommands.md).
Compatibility
-------------
diff --git a/Tutorial.md b/Tutorial.md
index abe554a..1ed3998 100644
--- a/Tutorial.md
+++ b/Tutorial.md
@@ -107,7 +107,7 @@ Step 4: Other commands
----------------------
### Chat Commands
-There are many more commands than what is shown here. See the [Chat Commands Reference](Chat Commands.md) for a detailed list of them, along with descriptions and examples for every single one.
+There are many more commands than what is shown here. See the [Chat Commands Reference](ChatCommands.md) for a detailed list of them, along with descriptions and examples for every single one.
If you're in-game and forgot how a command works, just use the `/help <command name>` command, without the first forward slash. For example, to see some information about the `//set <node>` command mentioned earlier, simply use `/help /set`.
@@ -115,6 +115,6 @@ A very useful command to check out is the `//save <schematic>` command, which ca
### WorldEdit GUI
-This only scratches the surface of what WorldEdit is capable of. Most of the functions in the WorldEdit GUI correspond to chat commands, and so the [Chat Commands Reference](Chat Commands.md) may be useful if you get stuck.
+This only scratches the surface of what WorldEdit is capable of. Most of the functions in the WorldEdit GUI correspond to chat commands, and so the [Chat Commands Reference](ChatCommands.md) may be useful if you get stuck.
It is helpful to explore the various buttons in the interface and check out what they do. Learning the chat command interface is also useful if you use WorldEdit intensively - an experienced chat command user can usually work faster than an experienced WorldEdit GUI user. \ No newline at end of file
diff --git a/WorldEdit API.md b/WorldEdit API.md
index af7138b..f50b506 100644
--- a/WorldEdit API.md
+++ b/WorldEdit API.md
@@ -21,9 +21,9 @@ Manipulations
-------------
Contained in manipulations.lua, this module allows several node operations to be applied over a region.
-### count = worldedit.set(pos1, pos2, nodename)
+### count = worldedit.set(pos1, pos2, node_name)
-Sets a region defined by positions `pos1` and `pos2` to `nodename`. To clear a region, use "air" as the value of `nodename`.
+Sets a region defined by positions `pos1` and `pos2` to `node_name`. To clear a region, use "air" as the value of `node_name`.
Returns the number of nodes set.
@@ -109,51 +109,33 @@ Primitives
----------
Contained in primitives.lua, this module allows the creation of several geometric primitives.
-### count = worldedit.hollow_sphere(pos, radius, nodename)
+### count = worldedit.sphere(pos, radius, node_name, hollow)
-Adds a hollow sphere centered at `pos` with radius `radius`, composed of `nodename`.
+Adds a sphere centered at `pos` with radius `radius`, composed of `node_name`.
Returns the number of nodes added.
-### count = worldedit.sphere(pos, radius, nodename)
+### count = worldedit.dome(pos, radius, node_name, hollow)
-Adds a sphere centered at `pos` with radius `radius`, composed of `nodename`.
+Adds a dome centered at `pos` with radius `radius`, composed of `node_name`.
Returns the number of nodes added.
-### count = worldedit.hollow_dome(pos, radius, nodename)
+### count = worldedit.cylinder(pos, axis, length, radius, node_name, hollow)
-Adds a hollow dome centered at `pos` with radius `radius`, composed of `nodename`.
+Adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `node_name`.
Returns the number of nodes added.
-### count = worldedit.dome(pos, radius, nodename)
-
-Adds a dome centered at `pos` with radius `radius`, composed of `nodename`.
-
-Returns the number of nodes added.
-
-### count = worldedit.hollow_cylinder(pos, axis, length, radius, nodename)
-
-Adds a hollow cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`.
-
-Returns the number of nodes added.
-
-### count = worldedit.cylinder(pos, axis, length, radius, nodename)
-
-Adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`.
-
-Returns the number of nodes added.
-
-### count = worldedit.pyramid(pos, axis, height, nodename)
+### count = worldedit.pyramid(pos, axis, height, node_name)
Adds a pyramid centered at `pos` along the `axis` axis ("x" or "y" or "z") with height `height`.
Returns the number of nodes added.
-### count = worldedit.spiral(pos, length, height, spacer, nodename)
+### count = worldedit.spiral(pos, length, height, spacer, node_name)
-Adds a spiral centered at `pos` with side length `length`, height `height`, space between walls `spacer`, composed of `nodename`.
+Adds a spiral centered at `pos` with side length `length`, height `height`, space between walls `spacer`, composed of `node_name`.
Returns the number of nodes added.
@@ -173,15 +155,15 @@ Hides all nodes in a region defined by positions `pos1` and `pos2` by non-destru
Returns the number of nodes hidden.
-### count = worldedit.suppress(pos1, pos2, nodename)
+### count = worldedit.suppress(pos1, pos2, node_name)
-Suppresses all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes.
+Suppresses all instances of `node_name` in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes.
Returns the number of nodes suppressed.
-### count = worldedit.highlight(pos1, pos2, nodename)
+### count = worldedit.highlight(pos1, pos2, node_name)
-Highlights all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively hiding all other nodes.
+Highlights all instances of `node_name` in a region defined by positions `pos1` and `pos2` by non-destructively hiding all other nodes.
Returns the number of nodes found.
diff --git a/config.ld b/config.ld
new file mode 100644
index 0000000..69be224
--- /dev/null
+++ b/config.ld
@@ -0,0 +1,12 @@
+project = "WorldEdit"
+title = "WorldEdit API Documentation"
+description = "Minetest mod to mass-modify nodes"
+format = "markdown"
+file = {"worldedit"}
+topics = {
+ "README.md",
+ "Tutorial.md",
+ "ChatCommands.md",
+ "LICENSE.txt"
+}
+
diff --git a/worldedit/code.lua b/worldedit/code.lua
index 2959bf8..a939deb 100644
--- a/worldedit/code.lua
+++ b/worldedit/code.lua
@@ -1,27 +1,9 @@
-worldedit = worldedit or {}
-local minetest = minetest -- local copy of global
+--- Lua code execution functions.
+-- @module worldedit.code
--- Copies and modifies positions `pos1` and `pos2` so that each component of
--- `pos1` is less than or equal to the corresponding component of `pos2`.
--- Returns the new positions.
-worldedit.sort_pos = function(pos1, pos2)
- pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
- pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
- if pos1.x > pos2.x then
- pos2.x, pos1.x = pos1.x, pos2.x
- end
- if pos1.y > pos2.y then
- pos2.y, pos1.y = pos1.y, pos2.y
- end
- if pos1.z > pos2.z then
- pos2.z, pos1.z = pos1.z, pos2.z
- end
- return pos1, pos2
-end
-
--- Executes `code` as a Lua chunk in the global namespace,
--- returning an error if the code fails, or nil otherwise.
-worldedit.lua = function(code)
+--- Executes `code` as a Lua chunk in the global namespace.
+-- @return An error message if the code fails, or nil on success.
+function worldedit.lua(code)
local func, err = loadstring(code)
if not func then -- Syntax error
return err
@@ -33,10 +15,12 @@ worldedit.lua = function(code)
return nil
end
--- Executes `code` as a Lua chunk in the global namespace with the variable
+
+--- Executes `code` as a Lua chunk in the global namespace with the variable
-- pos available, for each node in a region defined by positions `pos1` and
--- `pos2`, returning an error if the code fails, or nil otherwise
-worldedit.luatransform = function(pos1, pos2, code)
+-- `pos2`.
+-- @return An error message if the code fails, or nil on success.
+function worldedit.luatransform(pos1, pos2, code)
pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local factory, err = loadstring("return function(pos) " .. code .. " end")
@@ -45,9 +29,7 @@ worldedit.luatransform = function(pos1, pos2, code)
end
local func = factory()
- -- Keep area loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ worldedit.keep_loaded(pos1, pos2)
local pos = {x=pos1.x, y=0, z=0}
while pos.x <= pos2.x do
diff --git a/worldedit/common.lua b/worldedit/common.lua
new file mode 100644
index 0000000..be9a2c9
--- /dev/null
+++ b/worldedit/common.lua
@@ -0,0 +1,114 @@
+--- Common functions [INTERNAL]. All of these functions are internal!
+-- @module worldedit.common
+
+--- Copies and modifies positions `pos1` and `pos2` so that each component of
+-- `pos1` is less than or equal to the corresponding component of `pos2`.
+-- Returns the new positions.
+function worldedit.sort_pos(pos1, pos2)
+ pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
+ pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
+ if pos1.x > pos2.x then
+ pos2.x, pos1.x = pos1.x, pos2.x
+ end
+ if pos1.y > pos2.y then
+ pos2.y, pos1.y = pos1.y, pos2.y
+ end
+ if pos1.z > pos2.z then
+ pos2.z, pos1.z = pos1.z, pos2.z
+ end
+ return pos1, pos2
+end
+
+
+--- Determines the volume of the region defined by positions `pos1` and `pos2`.
+-- @return The volume.
+function worldedit.volume(pos1, pos2)
+ local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
+ return (pos2.x - pos1.x + 1) *
+ (pos2.y - pos1.y + 1) *
+ (pos2.z - pos1.z + 1)
+end
+
+
+--- Gets other axes given an axis.
+-- @raise Axis must be x, y, or z!
+function worldedit.get_axis_others(axis)
+ if axis == "x" then
+ return "y", "z"
+ elseif axis == "y" then
+ return "x", "z"
+ elseif axis == "z" then
+ return "x", "y"
+ else
+ error("Axis must be x, y, or z!")
+ end
+end
+
+
+function worldedit.keep_loaded(pos1, pos2)
+ local manip = minetest.get_voxel_manip()
+ manip:read_from_map(pos1, pos2)
+end
+
+
+local mh = {}
+worldedit.manip_helpers = mh
+
+
+--- Generates an empty VoxelManip data table for an area.
+-- @return The empty data table.
+function mh.get_empty_data(area)
+ -- Fill emerged area with ignore so that blocks in the area that are
+ -- only partially modified aren't overwriten.
+ local data = {}
+ local c_ignore = minetest.get_content_id("ignore")
+ for i = 1, worldedit.volume(area.MinEdge, area.MaxEdge) do
+ data[i] = c_ignore
+ end
+ return data
+end
+
+
+function mh.init(pos1, pos2)
+ local manip = minetest.get_voxel_manip()
+ local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
+ local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
+ return manip, area
+end
+
+
+function mh.init_radius(pos, radius)
+ local pos1 = vector.subtract(pos, radius)
+ local pos2 = vector.add(pos, radius)
+ return mh.init(pos1, pos2)
+end
+
+
+function mh.init_axis_radius(base_pos, axis, radius)
+ return mh.init_axis_radius_length(base_pos, axis, radius, radius)
+end
+
+
+function mh.init_axis_radius_length(base_pos, axis, radius, length)
+ local other1, other2 = worldedit.get_axis_others(axis)
+ local pos1 = {
+ [axis] = base_pos[axis],
+ [other1] = base_pos[other1] - radius,
+ [other2] = base_pos[other2] - radius
+ }
+ local pos2 = {
+ [axis] = base_pos[axis] + length,
+ [other1] = base_pos[other1] + radius,
+ [other2] = base_pos[other2] + radius
+ }
+ return mh.init(pos1, pos2)
+end
+
+
+function mh.finish(manip, data)
+ -- Update map
+ manip:set_data(data)
+ manip:write_to_map()
+ manip:update_map()
+end
+
diff --git a/worldedit/compatibility.lua b/worldedit/compatibility.lua
index e44e43b..c989a05 100644
--- a/worldedit/compatibility.lua
+++ b/worldedit/compatibility.lua
@@ -1,11 +1,21 @@
-worldedit = worldedit or {}
-local minetest = minetest --local copy of global
+--- Compatibility functions.
+-- @module worldedit.compatibility
+
+local function deprecated(new_func)
+ local info = debug.getinfo(1, "n")
+ local msg = "worldedit." .. info.name .. "() is deprecated."
+ if new_func then
+ msg = msg .. " Use worldedit." .. new_func .. "() instead."
+ end
+ minetest.log("deprecated", msg)
+end
worldedit.allocate_old = worldedit.allocate
worldedit.deserialize_old = worldedit.deserialize
-worldedit.metasave = function(pos1, pos2, filename)
+function worldedit.metasave(pos1, pos2, filename)
+ deprecated("save")
local file, err = io.open(filename, "wb")
if err then return 0 end
local data, count = worldedit.serialize(pos1, pos2)
@@ -14,7 +24,8 @@ worldedit.metasave = function(pos1, pos2, filename)
return count
end
-worldedit.metaload = function(originpos, filename)
+function worldedit.metaload(originpos, filename)
+ deprecated("load")
filename = minetest.get_worldpath() .. "/schems/" .. file .. ".wem"
local file, err = io.open(filename, "wb")
if err then return 0 end
@@ -22,11 +33,13 @@ worldedit.metaload = function(originpos, filename)
return worldedit.deserialize(originpos, data)
end
-worldedit.scale = function(pos1, pos2, factor)
+function worldedit.scale(pos1, pos2, factor)
+ deprecated("stretch")
return worldedit.stretch(pos1, pos2, factor, factor, factor)
end
-worldedit.valueversion = function(value)
+function worldedit.valueversion(value)
+ deprecated("read_header")
local version = worldedit.read_header(value)
if not version or version > worldedit.LATEST_SERIALIZATION_VERSION then
return 0
@@ -34,3 +47,28 @@ worldedit.valueversion = function(value)
return version
end
+function worldedit.replaceinverse(pos1, pos2, search_node, replace_node)
+ deprecated("replace")
+ return worldedit.replace(pos1, pos2, search_node, replace_node, true)
+end
+
+function worldedit.clearobjects(...)
+ deprecated("clear_objects")
+ return worldedit.clear_objects(...)
+end
+
+function worldedit.hollow_sphere(pos, radius, node_name)
+ deprecated("sphere")
+ return worldedit.sphere(pos, radius, node_name, true)
+end
+
+function worldedit.hollow_dome(pos, radius, node_name)
+ deprecated("dome")
+ return worldedit.dome(pos, radius, node_name, true)
+end
+
+function worldedit.hollow_cylinder(pos, axis, length, radius, node_name)
+ deprecated("cylinder")
+ return worldedit.cylinder(pos, axis, length, radius, node_name, true)
+end
+
diff --git a/worldedit/init.lua b/worldedit/init.lua
index a6361b5..34c9820 100644
--- a/worldedit/init.lua
+++ b/worldedit/init.lua
@@ -1,25 +1,44 @@
-worldedit = worldedit or {}
-worldedit.version = {major=1, minor=0}
-worldedit.version_string = "1.0"
+--- Worldedit.
+-- @module worldedit
+-- @release 1.1
+-- @copyright 2013 sfan5, Anthony Zhang (Uberi/Temperest), and Brett O'Donnell (cornernote).
+-- @license GNU Affero General Public License version 3 (AGPLv3)
+-- @author sfan5
+-- @author Anthony Zang (Uberi/Temperest)
+-- @author Bret O'Donnel (cornernote)
+-- @author ShadowNinja
-assert(minetest.get_voxel_manip, string.rep(">", 300) .. "HEY YOU! YES, YOU OVER THERE. THIS VERSION OF WORLDEDIT REQUIRES MINETEST 0.4.8 OR LATER! YOU HAVE AN OLD VERSION." .. string.rep("<", 300))
+worldedit = {}
+worldedit.version = {1, 1, major=1, minor=1}
+worldedit.version_string = table.concat(worldedit.version, ".")
+
+if not minetest.get_voxel_manip then
+ local err_msg = "This version of WorldEdit requires Minetest 0.4.8 or later! You have an old version."
+ minetest.log("error", string.rep("#", 128))
+ minetest.log("error", err_msg)
+ minetest.log("error", string.rep("#", 128))
+ error(err_msg)
+end
local path = minetest.get_modpath(minetest.get_current_modname())
-local loadmodule = function(path)
+local function load_module(path)
local file = io.open(path)
- if not file then
- return
- end
+ if not file then return end
file:close()
return dofile(path)
end
-loadmodule(path .. "/manipulations.lua")
-loadmodule(path .. "/primitives.lua")
-loadmodule(path .. "/visualization.lua")
-loadmodule(path .. "/serialization.lua")
-loadmodule(path .. "/code.lua")
-loadmodule(path .. "/compatibility.lua")
+dofile(path .. "/common.lua")
+load_module(path .. "/manipulations.lua")
+load_module(path .. "/primitives.lua")
+load_module(path .. "/visualization.lua")
+load_module(path .. "/serialization.lua")
+load_module(path .. "/code.lua")
+load_module(path .. "/compatibility.lua")
+
+
+if minetest.setting_getbool("log_mods") then
+ print("[WorldEdit] Loaded!")
+end
-print("[MOD] WorldEdit loaded!")
diff --git a/worldedit/manipulations.lua b/worldedit/manipulations.lua
index 2b16c32..e76cf70 100644
--- a/worldedit/manipulations.lua
+++ b/worldedit/manipulations.lua
@@ -1,331 +1,138 @@
-worldedit = worldedit or {}
-local minetest = minetest --local copy of global
-
--- Copies and modifies positions `pos1` and `pos2` so that each component of
--- `pos1` is less than or equal to the corresponding component of `pos2`.
--- Returns the new positions.
-worldedit.sort_pos = function(pos1, pos2)
- pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
- pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
- if pos1.x > pos2.x then
- pos2.x, pos1.x = pos1.x, pos2.x
- end
- if pos1.y > pos2.y then
- pos2.y, pos1.y = pos1.y, pos2.y
- end
- if pos1.z > pos2.z then
- pos2.z, pos1.z = pos1.z, pos2.z
- end
- return pos1, pos2
-end
+--- Generic node manipulations.
+-- @module worldedit.manipulations
---determines the volume of the region defined by positions `pos1` and `pos2`, returning the volume
-worldedit.volume = function(pos1, pos2)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- return (pos2.x - pos1.x + 1) * (pos2.y - pos1.y + 1) * (pos2.z - pos1.z + 1)
-end
+local mh = worldedit.manip_helpers
---sets a region defined by positions `pos1` and `pos2` to `nodename`, returning the number of nodes filled
-worldedit.set = function(pos1, pos2, nodenames)
- if type(nodenames) == "string" then
- nodenames = {nodenames}
- end
-
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
+--- Sets a region to `node_names`.
+-- @param pos1
+-- @param pos2
+-- @param node_names Node name or list of node names.
+-- @return The number of nodes set.
+function worldedit.set(pos1, pos2, node_names)
+ pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
- end
+ local manip, area = mh.init(pos1, pos2)
+ local data = mh.get_empty_data(area)
- --fill selected area with node
- local node_ids = {}
- for i,v in ipairs(nodenames) do
- node_ids[i] = minetest.get_content_id(nodenames[i])
- end
- if #node_ids == 1 then --only one type of node
- local id = node_ids[1]
- for i in area:iterp(pos1, pos2) do nodes[i] = id end --fill area with node
- else --several types of nodes specified
+ if type(node_names) == "string" then -- Only one type of node
+ local id = minetest.get_content_id(node_names)
+ -- Fill area with node
+ for i in area:iterp(pos1, pos2) do
+ data[i] = id
+ end
+ else -- Several types of nodes specified
+ local node_ids = {}
+ for i, v in ipairs(node_names) do
+ node_ids[i] = minetest.get_content_id(v)
+ end
+ -- Fill area randomly with nodes
local id_count, rand = #node_ids, math.random
- for i in area:iterp(pos1, pos2) do nodes[i] = node_ids[rand(id_count)] end --fill randomly with all types of specified nodes
- end
-
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
-
- return worldedit.volume(pos1, pos2)
-end
-
---replaces all instances of `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`, returning the number of nodes replaced
-worldedit.replace = function(pos1, pos2, searchnode, replacenode)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
-
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- local nodes = manip:get_data()
- local searchnode_id = minetest.get_content_id(searchnode)
- local replacenode_id = minetest.get_content_id(replacenode)
- local count = 0
- for i in area:iterp(pos1, pos2) do --replace searchnode with replacenode
- if nodes[i] == searchnode_id then
- nodes[i] = replacenode_id
- count = count + 1
+ for i in area:iterp(pos1, pos2) do
+ data[i] = node_ids[rand(id_count)]
end
end
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
+ mh.finish(manip, data)
- return count
+ return worldedit.volume(pos1, pos2)
end
---replaces all nodes other than `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`, returning the number of nodes replaced
-worldedit.replaceinverse = function(pos1, pos2, searchnode, replacenode)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
-
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- local nodes = manip:get_data()
- local searchnode_id = minetest.get_content_id(searchnode)
- local replacenode_id = minetest.get_content_id(replacenode)
- local count = 0
- for i in area:iterp(pos1, pos2) do --replace anything that is not searchnode with replacenode
- if nodes[i] ~= searchnode_id then
- nodes[i] = replacenode_id
- count = count + 1
- end
- end
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
-
- return count
-end
-
---copies the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes, returning the number of nodes copied
-worldedit.copy = function(pos1, pos2, axis, amount) --wip: replace the old version below
+--- Replaces all instances of `search_node` with `replace_node` in a region.
+-- When `inverse` is `true`, replaces all instances that are NOT `search_node`.
+-- @return The number of nodes replaced.
+function worldedit.replace(pos1, pos2, search_node, replace_node, inverse)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- if amount == 0 then
- return
- end
+ local manip, area = mh.init(pos1, pos2)
+ local data = manip:get_data()
- local other1, other2
- if axis == "x" then
- other1, other2 = "y", "z"
- elseif axis == "y" then
- other1, other2 = "x", "z"
- else --axis == "z"
- other1, other2 = "x", "y"
- end
+ local search_id = minetest.get_content_id(search_node)
+ local replace_id = minetest.get_content_id(replace_node)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ local count = 0
- --prepare slice along axis
- local extent = {
- [axis] = 1,
- [other1]=pos2[other1] - pos1[other1] + 1,
- [other2]=pos2[other2] - pos1[other2] + 1,
- }
- local nodes = {}
- local schematic = {size=extent, data=nodes}
-
- local currentpos = {x=pos1.x, y=pos1.y, z=pos1.z}
- local stride = {x=1, y=extent.x, z=extent.x * extent.y}
- local get_node = minetest.get_node
- for index1 = 1, extent[axis] do --go through each slice
- --copy slice into schematic
- local newindex1 = (index1 + offset[axis]) * stride[axis] + 1 --offset contributed by axis plus 1 to make it 1-indexed
- for index2 = 1, extent[other1] do
- local newindex2 = newindex1 + (index2 + offset[other1]) * stride[other1]
- for index3 = 1, extent[other2] do
- local i = newindex2 + (index3 + offset[other2]) * stride[other2]
- local node = get_node(pos)
- node.param1 = 255 --node will always appear
- nodes[i] = node
+ --- TODO: This could be shortened by checking `inverse` in the loop,
+ -- but that would have a speed penalty. Is the penalty big enough
+ -- to matter?
+ if not inverse then
+ for i in area:iterp(pos1, pos2) do
+ if data[i] == search_id then
+ data[i] = replace_id
+ count = count + 1
end
end
-
- --copy schematic to target
- currentpos[axis] = currentpos[axis] + amount
- place_schematic(currentpos, schematic)
-
- --wip: copy meta
-
- currentpos[axis] = currentpos[axis] + 1
- end
- return worldedit.volume(pos1, pos2)
-end
-
-worldedit.copy2 = function(pos1, pos2, direction, volume)
- -- the overlap shouldn't matter as long as we
- -- 1) start at the furthest separated corner
- -- 2) complete an edge before moving inward, either edge works
- -- 3) complete a face before moving inward, similarly
- --
- -- to do this I
- -- 1) find the furthest destination in the direction, of each axis
- -- 2) call those the furthest separated corner
- -- 3) make sure to iterate inward from there
- -- 4) nested loop to make sure complete edge, complete face, then complete cube.
-
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
- local somemeta = get_meta(pos1) -- hax lol
- local to_table = somemeta.to_table
- local from_table = somemeta.from_table
- somemeta = nil
-
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
-
- local sx, sy, sz -- direction sign
- local ix, iy, iz -- initial destination
- local ex, ey, ez -- final destination
- local originalx, originaly, originalz -- source
- -- vim -> :'<,'>s/\<\([ioes]\?\)x\>/\1y/g
- if direction.x > 0 then
- originalx = pos2.x
- ix = originalx + direction.x
- ex = pos1.x + direction.x
- sx = -1
- elseif direction.x < 0 then
- originalx = pos1.x
- ix = originalx + direction.x
- ex = pos2.x + direction.x
- sx = 1
else
- originalx = pos1.x
- ix = originalx -- whatever
- ex = pos2.x
- sx = 1
- end
-
- if direction.y > 0 then
- originaly = pos2.y
- iy = originaly + direction.y
- ey = pos1.y + direction.y
- sy = -1
- elseif direction.y < 0 then
- originaly = pos1.y
- iy = originaly + direction.y
- ey = pos2.y + direction.y
- sy = 1
- else
- originaly = pos1.y
- iy = originaly -- whatever
- ey = pos2.y
- sy = 1
- end
-
- if direction.z > 0 then
- originalz = pos2.z
- iz = originalz + direction.z
- ez = pos1.z + direction.z
- sz = -1
- elseif direction.z < 0 then
- originalz = pos1.z
- iz = originalz + direction.z
- ez = pos2.z + direction.z
- sz = 1
- else
- originalz = pos1.z
- iz = originalz -- whatever
- ez = pos2.z
- sz = 1
- end
- -- print('copy',originalx,ix,ex,sx,originaly,iy,ey,sy,originalz,iz,ez,sz)
-
- local ox,oy,oz
-
- ox = originalx
- for x = ix, ex, sx do
- oy = originaly
- for y = iy, ey, sy do
- oz = originalz
- for z = iz, ez, sz do
- -- reusing pos1/pos2 as source/dest here
- pos1.x, pos1.y, pos1.z = ox, oy, oz
- pos2.x, pos2.y, pos2.z = x, y, z
- local node = get_node(pos1)
- local meta = to_table(get_meta(pos1)) --get meta of current node
- add_node(pos2,node)
- from_table(get_meta(pos2),meta)
- oz = oz + sz
+ for i in area:iterp(pos1, pos2) do
+ if data[i] ~= search_id then
+ data[i] = replace_id
+ count = count + 1
end
- oy = oy + sy
end
- ox = ox + sx
end
+
+ mh.finish(manip, data)
+
+ return count
end
---duplicates the region defined by positions `pos1` and `pos2` `amount` times with offset vector `direction`, returning the number of nodes stacked
-worldedit.stack2 = function(pos1, pos2, direction, amount, finished)
+
+--- Duplicates a region `amount` times with offset vector `direction`.
+-- Stacking is spread across server steps, one copy per step.
+-- @return The number of nodes stacked.
+function worldedit.stack2(pos1, pos2, direction, amount, finished)
local i = 0
- local translated = {x=0,y=0,z=0}
- local function nextone()
+ local translated = {x=0, y=0, z=0}
+ local function next_one()
if i < amount then
i = i + 1
translated.x = translated.x + direction.x
translated.y = translated.y + direction.y
translated.z = translated.z + direction.z
worldedit.copy2(pos1, pos2, translated, volume)
- minetest.after(0, nextone)
+ minetest.after(0, next_one)
else
if finished then
finished()
end
end
end
- nextone()
+ next_one()
return worldedit.volume(pos1, pos2) * amount
end
---copies the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes, returning the number of nodes copied
-worldedit.copy = function(pos1, pos2, axis, amount)
+
+--- Copies a region along `axis` by `amount` nodes.
+-- @param pos1
+-- @param pos2
+-- @param axis Axis ("x", "y", or "z")
+-- @param amount
+-- @return The number of nodes copied.
+function worldedit.copy(pos1, pos2, axis, amount)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ worldedit.keep_loaded(pos1, pos2)
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
+ local get_node, get_meta, set_node = minetest.get_node,
+ minetest.get_meta, minetest.set_node
+ -- Copy things backwards when negative to avoid corruption.
+ -- FIXME: Lots of code duplication here.
if amount < 0 then
- local pos = {x=pos1.x, y=0, z=0}
+ local pos = {}
+ pos.x = pos1.x
while pos.x <= pos2.x do
pos.y = pos1.y
while pos.y <= pos2.y do
pos.z = pos1.z
while pos.z <= pos2.z do
- local node = get_node(pos) --obtain current node
- local meta = get_meta(pos):to_table() --get meta of current node
- local value = pos[axis] --store current position
- pos[axis] = value + amount --move along axis
- add_node(pos, node) --copy node to new position
- get_meta(pos):from_table(meta) --set metadata of new node
- pos[axis] = value --restore old position
+ local node = get_node(pos) -- Obtain current node
+ local meta = get_meta(pos):to_table() -- Get meta of current node
+ local value = pos[axis] -- Store current position
+ pos[axis] = value + amount -- Move along axis
+ set_node(pos, node) -- Copy node to new position
+ get_meta(pos):from_table(meta) -- Set metadata of new node
+ pos[axis] = value -- Restore old position
pos.z = pos.z + 1
end
pos.y = pos.y + 1
@@ -333,19 +140,20 @@ worldedit.copy = function(pos1, pos2, axis, amount)
pos.x = pos.x + 1
end
else
- local pos = {x=pos2.x, y=0, z=0}
+ 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 value = pos[axis] --store current position
- pos[axis] = value + amount --move along axis
- add_node(pos, node) --copy node to new position
- get_meta(pos):from_table(meta) --set metadata of new node
- pos[axis] = value --restore old position
+ local node = get_node(pos) -- Obtain current node
+ local meta = get_meta(pos):to_table() -- Get meta of current node
+ local value = pos[axis] -- Store current position
+ pos[axis] = value + amount -- Move along axis
+ set_node(pos, node) -- Copy node to new position
+ get_meta(pos):from_table(meta) -- Set metadata of new node
+ pos[axis] = value -- Restore old position
pos.z = pos.z - 1
end
pos.y = pos.y - 1
@@ -356,31 +164,38 @@ worldedit.copy = function(pos1, pos2, axis, amount)
return worldedit.volume(pos1, pos2)
end
---moves the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") by `amount` nodes, returning the number of nodes moved
-worldedit.move = function(pos1, pos2, axis, amount)
+
+--- Moves a region along `axis` by `amount` nodes.
+-- @return The number of nodes moved.
+function worldedit.move(pos1, pos2, axis, amount)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ worldedit.keep_loaded(pos1, pos2)
- --wip: move slice by slice using schematic method in the move axis and transfer metadata in separate loop (and if the amount is greater than the length in the axis, copy whole thing at a time and erase original after, using schematic method)
- local get_node, get_meta, add_node, remove_node = minetest.get_node, minetest.get_meta, minetest.add_node, minetest.remove_node
+ --- TODO: Move slice by slice using schematic method in the move axis
+ -- and transfer metadata in separate loop (and if the amount is
+ -- greater than the length in the axis, copy whole thing at a time and
+ -- erase original after, using schematic method).
+ local get_node, get_meta, set_node, remove_node = minetest.get_node,
+ minetest.get_meta, minetest.set_node, minetest.remove_node
+ -- Copy things backwards when negative to avoid corruption.
+ --- FIXME: Lots of code duplication here.
if amount < 0 then
- local pos = {x=pos1.x, y=0, z=0}
+ local pos = {}
+ pos.x = pos1.x
while pos.x <= pos2.x do
pos.y = pos1.y
while pos.y <= pos2.y do
pos.z = pos1.z
while pos.z <= pos2.z do
- local node = get_node(pos) --obtain current node
- local meta = get_meta(pos):to_table() --get metadata of current node
- remove_node(pos)
- local value = pos[axis] --store current position
- pos[axis] = value + amount --move along axis
- add_node(pos, node) --move node to new position
- get_meta(pos):from_table(meta) --set metadata of new node
- pos[axis] = value --restore old position
+ local node = get_node(pos) -- Obtain current node
+ local meta = get_meta(pos):to_table() -- Get metadata of current node
+ remove_node(pos) -- Remove current node
+ local value = pos[axis] -- Store current position
+ pos[axis] = value + amount -- Move along axis
+ set_node(pos, node) -- Move node to new position
+ get_meta(pos):from_table(meta) -- Set metadata of new node
+ pos[axis] = value -- Restore old position
pos.z = pos.z + 1
end
pos.y = pos.y + 1
@@ -388,20 +203,21 @@ worldedit.move = function(pos1, pos2, axis, amount)
pos.x = pos.x + 1
end
else
- local pos = {x=pos2.x, y=0, z=0}
+ 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 metadata of current node
- remove_node(pos)
- local value = pos[axis] --store current position
- pos[axis] = value + amount --move along axis
- add_node(pos, node) --move node to new position
- get_meta(pos):from_table(meta) --set metadata of new node
- pos[axis] = value --restore old position
+ local node = get_node(pos) -- Obtain current node
+ local meta = get_meta(pos):to_table() -- Get metadata of current node
+ remove_node(pos) -- Remove current node
+ local value = pos[axis] -- Store current position
+ pos[axis] = value + amount -- Move along axis
+ set_node(pos, node) -- Move node to new position
+ get_meta(pos):from_table(meta) -- Set metadata of new node
+ pos[axis] = value -- Restore old position
pos.z = pos.z - 1
end
pos.y = pos.y - 1
@@ -412,8 +228,15 @@ worldedit.move = function(pos1, pos2, axis, amount)
return worldedit.volume(pos1, pos2)
end
---duplicates the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") `count` times, returning the number of nodes stacked
-worldedit.stack = function(pos1, pos2, axis, count)
+
+--- Duplicates a region along `axis` `amount` times.
+-- Stacking is spread across server steps, one copy per step.
+-- @param pos1
+-- @param pos2
+-- @param axis Axis direction, "x", "y", or "z".
+-- @param count
+-- @return The number of nodes stacked.
+function worldedit.stack(pos1, pos2, axis, count)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local length = pos2[axis] - pos1[axis] + 1
if count < 0 then
@@ -423,72 +246,85 @@ worldedit.stack = function(pos1, pos2, axis, count)
local amount = 0
local copy = worldedit.copy
local i = 1
- function nextone()
+ function next_one()
if i <= count then
i = i + 1
amount = amount + length
copy(pos1, pos2, axis, amount)
- minetest.after(0, nextone)
+ minetest.after(0, next_one)
end
end
- nextone()
+ next_one()
return worldedit.volume(pos1, pos2) * count
end
---stretches the region defined by positions `pos1` and `pos2` by an factor of positive integers `stretchx`, `stretchy`. and `stretchz` along the X, Y, and Z axes, respectively, with `pos1` as the origin, returning the number of nodes scaled, the new scaled position 1, and the new scaled position 2
-worldedit.stretch = function(pos1, pos2, stretchx, stretchy, stretchz) --wip: test this
+
+--- Stretches a region by a factor of positive integers along the X, Y, and Z
+-- axes, respectively, with `pos1` as the origin.
+-- @param pos1
+-- @param pos2
+-- @param stretch_x Amount to stretch along X axis.
+-- @param stretch_y Amount to stretch along Y axis.
+-- @param stretch_z Amount to stretch along Z axis.
+-- @return The number of nodes scaled.
+-- @return The new scaled position 1.
+-- @return The new scaled position 2.
+function worldedit.stretch(pos1, pos2, stretch_x, stretch_y, stretch_z)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- --prepare schematic of large node
- local get_node, get_meta, place_schematic = minetest.get_node, minetest.get_meta, minetest.place_schematic
+ -- Prepare schematic of large node
+ local get_node, get_meta, place_schematic = minetest.get_node,
+ minetest.get_meta, minetest.place_schematic
local placeholder_node = {name="", param1=255, param2=0}
local nodes = {}
- for i = 1, stretchx * stretchy * stretchz do
+ for i = 1, stretch_x * stretch_y * stretch_z do
nodes[i] = placeholder_node
end
- local schematic = {size={x=stretchx, y=stretchy, z=stretchz}, data=nodes}
+ local schematic = {size={x=stretch_x, y=stretch_y, z=stretch_z}, data=nodes}
- local sizex, sizey, sizez = stretchx - 1, stretchy - 1, stretchz - 1
+ local size_x, size_y, size_z = stretch_x - 1, stretch_y - 1, stretch_z - 1
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
local new_pos2 = {
- x=pos1.x + (pos2.x - pos1.x) * stretchx + sizex,
- y=pos1.y + (pos2.y - pos1.y) * stretchy + sizey,
- z=pos1.z + (pos2.z - pos1.z) * stretchz + sizez,
+ x = pos1.x + (pos2.x - pos1.x) * stretch_x + size_x,
+ y = pos1.y + (pos2.y - pos1.y) * stretch_y + size_y,
+ z = pos1.z + (pos2.z - pos1.z) * stretch_z + size_z,
}
- manip:read_from_map(pos1, new_pos2)
+ worldedit.keep_loaded(pos1, new_pos2)
local pos = {x=pos2.x, y=0, z=0}
- local bigpos = {x=0, y=0, z=0}
+ local big_pos = {x=0, y=0, z=0}
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 node = get_node(pos) -- Get current node
+ local meta = get_meta(pos):to_table() -- Get meta of current node
- --calculate far corner of the big node
- local posx = pos1.x + (pos.x - pos1.x) * stretchx
- local posy = pos1.y + (pos.y - pos1.y) * stretchy
- local posz = pos1.z + (pos.z - pos1.z) * stretchz
+ -- Calculate far corner of the big node
+ local pos_x = pos1.x + (pos.x - pos1.x) * stretch_x
+ local pos_y = pos1.y + (pos.y - pos1.y) * stretch_y
+ local pos_z = pos1.z + (pos.z - pos1.z) * stretch_z
- --create large node
+ -- Create large node
placeholder_node.name = node.name
placeholder_node.param2 = node.param2
- bigpos.x, bigpos.y, bigpos.z = posx, posy, posz
- place_schematic(bigpos, schematic)
-
- --fill in large node meta
- if next(meta.fields) ~= nil or next(meta.inventory) ~= nil then --node has meta fields
- for x = 0, sizex do
- for y = 0, sizey do
- for z = 0, sizez do
- bigpos.x, bigpos.y, bigpos.z = posx + x, posy + y, posz + z
- get_meta(bigpos):from_table(meta) --set metadata of new node
- end
- end
+ big_pos.x, big_pos.y, big_pos.z = pos_x, pos_y, pos_z
+ place_schematic(big_pos, schematic)
+
+ -- Fill in large node meta
+ if next(meta.fields) ~= nil or next(meta.inventory) ~= nil then
+ -- Node has meta fields
+ for x = 0, size_x do
+ for y = 0, size_y do
+ for z = 0, size_z do
+ big_pos.x = pos_x + x
+ big_pos.y = pos_y + y
+ big_pos.z = pos_z + z
+ -- Set metadata of new node
+ get_meta(big_pos):from_table(meta)
+ end
+ end
end
end
pos.z = pos.z - 1
@@ -497,11 +333,15 @@ worldedit.stretch = function(pos1, pos2, stretchx, stretchy, stretchz) --wip: te
end
pos.x = pos.x - 1
end
- return worldedit.volume(pos1, pos2) * stretchx * stretchy * stretchz, pos1, new_pos2
+ return worldedit.volume(pos1, pos2) * stretch_x * stretch_y * stretch_z, pos1, new_pos2
end
---transposes a region defined by the positions `pos1` and `pos2` between the `axis1` and `axis2` axes, returning the number of nodes transposed, the new transposed position 1, and the new transposed position 2
-worldedit.transpose = function(pos1, pos2, axis1, axis2)
+
+--- Transposes a region between two axes.
+-- @return The number of nodes transposed.
+-- @return The new transposed position 1.
+-- @return The new transposed position 2.
+function worldedit.transpose(pos1, pos2, axis1, axis2)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local compare
@@ -517,37 +357,36 @@ worldedit.transpose = function(pos1, pos2, axis1, axis2)
end
end
- --calculate the new position 2 after transposition
+ -- Calculate the new position 2 after transposition
local new_pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
new_pos2[axis1] = pos1[axis1] + extent2
new_pos2[axis2] = pos1[axis2] + extent1
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- local upperbound = {x=pos2.x, y=pos2.y, z=pos2.z}
- if upperbound[axis1] < new_pos2[axis1] then upperbound[axis1] = new_pos2[axis1] end
- if upperbound[axis2] < new_pos2[axis2] then upperbound[axis2] = new_pos2[axis2] end
- manip:read_from_map(pos1, upperbound)
+ local upper_bound = {x=pos2.x, y=pos2.y, z=pos2.z}
+ if upper_bound[axis1] < new_pos2[axis1] then upper_bound[axis1] = new_pos2[axis1] end
+ if upper_bound[axis2] < new_pos2[axis2] then upper_bound[axis2] = new_pos2[axis2] end
+ worldedit.keep_loaded(pos1, upper_bound)
local pos = {x=pos1.x, y=0, z=0}
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
+ local get_node, get_meta, set_node = minetest.get_node,
+ minetest.get_meta, minetest.set_node
while pos.x <= pos2.x do
pos.y = pos1.y
while pos.y <= pos2.y do
pos.z = pos1.z
while pos.z <= pos2.z do
local extent1, extent2 = pos[axis1] - pos1[axis1], pos[axis2] - pos1[axis2]
- if compare(extent1, extent2) then --transpose only if below the diagonal
+ if compare(extent1, extent2) then -- Transpose only if below the diagonal
local node1 = get_node(pos)
local meta1 = get_meta(pos):to_table()
- local value1, value2 = pos[axis1], pos[axis2] --save position values
- pos[axis1], pos[axis2] = pos1[axis1] + extent2, pos1[axis2] + extent1 --swap axis extents
+ local value1, value2 = pos[axis1], pos[axis2] -- Save position values
+ pos[axis1], pos[axis2] = pos1[axis1] + extent2, pos1[axis2] + extent1 -- Swap axis extents
local node2 = get_node(pos)
local meta2 = get_meta(pos):to_table()
- add_node(pos, node1)
+ set_node(pos, node1)
get_meta(pos):from_table(meta1)
- pos[axis1], pos[axis2] = value1, value2 --restore position values
- add_node(pos, node2)
+ pos[axis1], pos[axis2] = value1, value2 -- Restore position values
+ set_node(pos, node2)
get_meta(pos):from_table(meta2)
end
pos.z = pos.z + 1
@@ -559,19 +398,20 @@ worldedit.transpose = function(pos1, pos2, axis1, axis2)
return worldedit.volume(pos1, pos2), pos1, new_pos2
end
---flips a region defined by the positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z"), returning the number of nodes flipped
-worldedit.flip = function(pos1, pos2, axis)
+
+--- Flips a region along `axis`.
+-- @return The number of nodes flipped.
+function worldedit.flip(pos1, pos2, axis)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ worldedit.keep_loaded(pos1, pos2)
- --wip: flip the region slice by slice along the flip axis using schematic method
+ --- TODO: Flip the region slice by slice along the flip axis using schematic method.
local pos = {x=pos1.x, y=0, z=0}
local start = pos1[axis] + pos2[axis]
pos2[axis] = pos1[axis] + math.floor((pos2[axis] - pos1[axis]) / 2)
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
+ local get_node, get_meta, set_node = minetest.get_node,
+ minetest.get_meta, minetest.set_node
while pos.x <= pos2.x do
pos.y = pos1.y
while pos.y <= pos2.y do
@@ -579,14 +419,14 @@ worldedit.flip = function(pos1, pos2, axis)
while pos.z <= pos2.z do
local node1 = get_node(pos)
local meta1 = get_meta(pos):to_table()
- local value = pos[axis]
- pos[axis] = start - value
+ local value = pos[axis] -- Save position
+ pos[axis] = start - value -- Shift position
local node2 = get_node(pos)
local meta2 = get_meta(pos):to_table()
- add_node(pos, node1)
+ set_node(pos, node1)
get_meta(pos):from_table(meta1)
- pos[axis] = value
- add_node(pos, node2)
+ pos[axis] = value -- Restore position
+ set_node(pos, node2)
get_meta(pos):from_table(meta2)
pos.z = pos.z + 1
end
@@ -597,63 +437,74 @@ worldedit.flip = function(pos1, pos2, axis)
return worldedit.volume(pos1, pos2)
end
---rotates a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise around axis `axis` (90 degree increment), returning the number of nodes rotated
-worldedit.rotate = function(pos1, pos2, axis, angle)
+
+--- Rotates a region clockwise around an axis.
+-- @param pos1
+-- @param pos2
+-- @param axis Axis ("x", "y", or "z").
+-- @param angle Angle in degrees (90 degree increments only).
+-- @return The number of nodes rotated.
+-- @return The new first position.
+-- @return The new second position.
+function worldedit.rotate(pos1, pos2, axis, angle)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- local axis1, axis2
- if axis == "x" then
- axis1, axis2 = "z", "y"
- elseif axis == "y" then
- axis1, axis2 = "x", "z"
- else --axis == "z"
- axis1, axis2 = "y", "x"
- end
+ local other1, other2 = worldedit.get_axis_others(axis)
angle = angle % 360
local count
if angle == 90 then
- worldedit.flip(pos1, pos2, axis1)
- count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2)
+ worldedit.flip(pos1, pos2, other1)
+ count, pos1, pos2 = worldedit.transpose(pos1, pos2, other1, other2)
elseif angle == 180 then
- worldedit.flip(pos1, pos2, axis1)
- count = worldedit.flip(pos1, pos2, axis2)
+ worldedit.flip(pos1, pos2, other1)
+ count = worldedit.flip(pos1, pos2, other2)
elseif angle == 270 then
- worldedit.flip(pos1, pos2, axis2)
- count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2)
+ worldedit.flip(pos1, pos2, other2)
+ count, pos1, pos2 = worldedit.transpose(pos1, pos2, other1, other2)
+ else
+ error("Only 90 degree increments are supported!")
end
return count, pos1, pos2
end
---rotates all oriented nodes in a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise (90 degree increment) around the Y axis, returning the number of nodes oriented
-worldedit.orient = function(pos1, pos2, angle) --wip: support 6D facedir rotation along arbitrary axis
+
+--- Rotates all oriented nodes in a region clockwise around the Y axis.
+-- @param pos1
+-- @param pos2
+-- @param angle Angle in degrees (90 degree increments only).
+-- @return The number of nodes oriented.
+-- TODO: Support 6D facedir rotation along arbitrary axis.
+function worldedit.orient(pos1, pos2, angle)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local registered_nodes = minetest.registered_nodes
local wallmounted = {
- [90]={[0]=0, [1]=1, [2]=5, [3]=4, [4]=2, [5]=3},
- [180]={[0]=0, [1]=1, [2]=3, [3]=2, [4]=5, [5]=4},
- [270]={[0]=0, [1]=1, [2]=4, [3]=5, [4]=3, [5]=2}
+ [90] = {[0]=0, 1, 5, 4, 2, 3},
+ [180] = {[0]=0, 1, 3, 2, 5, 4},
+ [270] = {[0]=0, 1, 4, 5, 3, 2}
}
local facedir = {
- [90]={[0]=1, [1]=2, [2]=3, [3]=0},
- [180]={[0]=2, [1]=3, [2]=0, [3]=1},
- [270]={[0]=3, [1]=0, [2]=1, [3]=2}
+ [90] = {[0]=1, 2, 3, 0},
+ [180] = {[0]=2, 3, 0, 1},
+ [270] = {[0]=3, 0, 1, 2}
}
angle = angle % 360
if angle == 0 then
return 0
end
+ if angle % 90 ~= 0 then
+ error("Only 90 degree increments are supported!")
+ end
local wallmounted_substitution = wallmounted[angle]
local facedir_substitution = facedir[angle]
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ worldedit.keep_loaded(pos1, pos2)
local count = 0
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
+ local get_node, get_meta, swap_node = minetest.get_node,
+ minetest.get_meta, minetest.swap_node
local pos = {x=pos1.x, y=0, z=0}
while pos.x <= pos2.x do
pos.y = pos1.y
@@ -666,13 +517,13 @@ worldedit.orient = function(pos1, pos2, angle) --wip: support 6D facedir rotatio
if def.paramtype2 == "wallmounted" then
node.param2 = wallmounted_substitution[node.param2]
local meta = get_meta(pos):to_table()
- add_node(pos, node)
+ set_node(pos, node)
get_meta(pos):from_table(meta)
count = count + 1
elseif def.paramtype2 == "facedir" then
node.param2 = facedir_substitution[node.param2]
local meta = get_meta(pos):to_table()
- add_node(pos, node)
+ set_node(pos, node)
get_meta(pos):from_table(meta)
count = count + 1
end
@@ -686,13 +537,13 @@ worldedit.orient = function(pos1, pos2, angle) --wip: support 6D facedir rotatio
return count
end
---fixes the lighting in a region defined by positions `pos1` and `pos2`, returning the number of nodes updated
-worldedit.fixlight = function(pos1, pos2)
+
+--- Attempts to fix the lighting in a region.
+-- @return The number of nodes updated.
+function worldedit.fixlight(pos1, pos2)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ worldedit.keep_loaded(pos1, pos2)
local nodes = minetest.find_nodes_in_area(pos1, pos2, "air")
local dig_node = minetest.dig_node
@@ -702,26 +553,40 @@ worldedit.fixlight = function(pos1, pos2)
return #nodes
end
---clears all objects in a region defined by the positions `pos1` and `pos2`, returning the number of objects cleared
-worldedit.clearobjects = function(pos1, pos2)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+--- Clears all objects in a region.
+-- @return The number of objects cleared.
+function worldedit.clear_objects(pos1, pos2)
+ pos1, pos2 = worldedit.sort_pos(pos1, pos2)
+
+ worldedit.keep_loaded(pos1, pos2)
+
+ -- Offset positions to include full nodes (positions are in the center of nodes)
+ local pos1x, pos1y, pos1z = pos1.x - 0.5, pos1.y - 0.5, pos1.z - 0.5
+ local pos2x, pos2y, pos2z = pos2.x + 0.5, pos2.y + 0.5, pos2.z + 0.5
- local pos1x, pos1y, pos1z = pos1.x, pos1.y, pos1.z
- local pos2x, pos2y, pos2z = pos2.x + 1, pos2.y + 1, pos2.z + 1
- local center = {x=(pos1x + pos2x) / 2, y=(pos1y + pos2y) / 2, z=(pos1z + pos2z) / 2} --center of region
- local radius = ((center.x - pos1x + 0.5) + (center.y - pos1y + 0.5) + (center.z - pos1z + 0.5)) ^ 0.5 --bounding sphere radius
+ -- Center of region
+ local center = {
+ x = pos1x + ((pos2x - pos1x) / 2),
+ y = pos1y + ((pos2y - pos1y) / 2),
+ z = pos1z + ((pos2z - pos1z) / 2)
+ }
+ -- Bounding sphere radius
+ local radius = math.sqrt(
+ (center.x - pos1x) ^ 2 +
+ (center.y - pos1y) ^ 2 +
+ (center.z - pos1z) ^ 2)
local count = 0
- for _, obj in pairs(minetest.get_objects_inside_radius(center, radius)) do --all objects in bounding sphere
+ for _, obj in pairs(minetest.get_objects_inside_radius(center, radius)) do
local entity = obj:get_luaentity()
- if not (entity and entity.name:find("^worldedit:")) then --avoid WorldEdit entities
+ -- Avoid players and WorldEdit entities
+ if not obj:is_player() and (not entity or
+ not entity.name:find("^worldedit:")) then
local pos = obj:getpos()
- if pos.x >= pos1x and pos.x <= pos2x
- and pos.y >= pos1y and pos.y <= pos2y
- and pos.z >= pos1z and pos.z <= pos2z then --inside region
+ if pos.x >= pos1x and pos.x <= pos2x and
+ pos.y >= pos1y and pos.y <= pos2y and
+ pos.z >= pos1z and pos.z <= pos2z then
+ -- Inside region
obj:remove()
count = count + 1
end
@@ -729,3 +594,4 @@ worldedit.clearobjects = function(pos1, pos2)
end
return count
end
+
diff --git a/worldedit/primitives.lua b/worldedit/primitives.lua
index 1baa29e..6d3b026 100644
--- a/worldedit/primitives.lua
+++ b/worldedit/primitives.lua
@@ -1,470 +1,273 @@
-worldedit = worldedit or {}
-local minetest = minetest --local copy of global
-
---adds a hollow sphere centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
-worldedit.hollow_sphere = function(pos, radius, nodename)
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local pos1 = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius}
- local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
- end
+--- Functions for creating primitive shapes.
+-- @module worldedit.primitives
- --fill selected area with node
- local node_id = minetest.get_content_id(nodename)
- local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
- local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
- local zstride, ystride = area.zstride, area.ystride
- local count = 0
- for z = -radius, radius do
- local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
- for y = -radius, radius do
- local newy = newz + (y + offsety) * ystride
- for x = -radius, radius do
- local squared = x * x + y * y + z * z
- if squared >= min_radius and squared <= max_radius then --position is on surface of sphere
- local i = newy + (x + offsetx)
- nodes[i] = node_id
- count = count + 1
- end
- end
- end
- end
+local mh = worldedit.manip_helpers
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
- return count
-end
+--- Adds a sphere of `node_name` centered at `pos`.
+-- @param pos Position to center sphere at.
+-- @param radius Sphere radius.
+-- @param node_name Name of node to make shere of.
+-- @param hollow Whether the sphere should be hollow.
+-- @return The number of nodes added.
+function worldedit.sphere(pos, radius, node_name, hollow)
+ local manip, area = mh.init_radius(pos, radius)
---adds a sphere centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
-worldedit.sphere = function(pos, radius, nodename)
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local pos1 = {x=pos.x - radius, y=pos.y - radius, z=pos.z - radius}
- local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
- end
+ local data = mh.get_empty_data(area)
- --fill selected area with node
- local node_id = minetest.get_content_id(nodename)
- local max_radius = radius * (radius + 1)
- local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
- local zstride, ystride = area.zstride, area.ystride
+ -- Fill selected area with node
+ local node_id = minetest.get_content_id(node_name)
+ local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
+ local offset_x, offset_y, offset_z = pos.x - area.MinEdge.x, pos.y - area.MinEdge.y, pos.z - area.MinEdge.z
+ local stride_z, stride_y = area.zstride, area.ystride
local count = 0
for z = -radius, radius do
- local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
+ -- Offset contributed by z plus 1 to make it 1-indexed
+ local new_z = (z + offset_z) * stride_z + 1
for y = -radius, radius do
- local newy = newz + (y + offsety) * ystride
+ local new_y = new_z + (y + offset_y) * stride_y
for x = -radius, radius do
- if x * x + y * y + z * z <= max_radius then --position is inside sphere
- local i = newy + (x + offsetx)
- nodes[i] = node_id
+ local squared = x * x + y * y + z * z
+ if squared <= max_radius and (not hollow or squared >= min_radius) then
+ -- Position is on surface of sphere
+ local i = new_y + (x + offset_x)
+ data[i] = node_id
count = count + 1
end
end
end
end
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
+ mh.finish(manip, data)
return count
end
---adds a hollow dome centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
-worldedit.hollow_dome = function(pos, radius, nodename)
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local pos1 = {x=pos.x - radius, y=pos.y, z=pos.z - radius}
- local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
- end
- local miny, maxy = 0, radius
+--- Adds a dome.
+-- @param pos Position to center dome at.
+-- @param radius Dome radius. Negative for concave domes.
+-- @param node_name Name of node to make dome of.
+-- @param hollow Whether the dome should be hollow.
+-- @return The number of nodes added.
+-- TODO: Add axis option.
+function worldedit.dome(pos, radius, node_name, hollow)
+ local min_y, max_y = 0, radius
if radius < 0 then
radius = -radius
- miny, maxy = -radius, 0
+ min_y, max_y = -radius, 0
end
- --fill selected area with node
- local node_id = minetest.get_content_id(nodename)
+ local manip, area = mh.init_axis_radius(pos, "y", radius)
+ local data = mh.get_empty_data(area)
+
+ -- Add dome
+ local node_id = minetest.get_content_id(node_name)
local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
- local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
- local zstride, ystride = area.zstride, area.ystride
+ local offset_x, offset_y, offset_z = pos.x - area.MinEdge.x, pos.y - area.MinEdge.y, pos.z - area.MinEdge.z
+ local stride_z, stride_y = area.zstride, area.ystride
local count = 0
for z = -radius, radius do
- local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
- for y = miny, maxy do
- local newy = newz + (y + offsety) * ystride
+ local new_z = (z + offset_z) * stride_z + 1 --offset contributed by z plus 1 to make it 1-indexed
+ for y = min_y, max_y do
+ local new_y = new_z + (y + offset_y) * stride_y
for x = -radius, radius do
local squared = x * x + y * y + z * z
- if squared >= min_radius and squared <= max_radius then --position is on surface of sphere
- local i = newy + (x + offsetx)
- nodes[i] = node_id
- count = count + 1
- end
- end
- end
- end
-
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
-
- return count
-end
-
---adds a dome centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
-worldedit.dome = function(pos, radius, nodename)
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local pos1 = {x=pos.x - radius, y=pos.y, z=pos.z - radius}
- local pos2 = {x=pos.x + radius, y=pos.y + radius, z=pos.z + radius}
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
- end
-
- local miny, maxy = 0, radius
- if radius < 0 then
- radius = -radius
- miny, maxy = -radius, 0
- end
-
- --fill selected area with node
- local node_id = minetest.get_content_id(nodename)
- local max_radius = radius * (radius + 1)
- local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
- local zstride, ystride = area.zstride, area.ystride
- local count = 0
- for z = -radius, radius do
- local newz = (z + offsetz) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
- for y = miny, maxy do
- local newy = newz + (y + offsety) * ystride
- for x = -radius, radius do
- if x * x + y * y + z * z <= max_radius then --position is inside sphere
- local i = newy + (x + offsetx)
- nodes[i] = node_id
+ if squared <= max_radius and (not hollow or squared >= min_radius) then
+ -- Position is in dome
+ local i = new_y + (x + offset_x)
+ data[i] = node_id
count = count + 1
end
end
end
end
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
+ mh.finish(manip, data)
return count
end
---adds a hollow cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`, returning the number of nodes added
-worldedit.hollow_cylinder = function(pos, axis, length, radius, nodename)
- local other1, other2
- if axis == "x" then
- other1, other2 = "y", "z"
- elseif axis == "y" then
- other1, other2 = "x", "z"
- else --axis == "z"
- other1, other2 = "x", "y"
- end
-
- --handle negative lengths
- local currentpos = {x=pos.x, y=pos.y, z=pos.z}
+--- Adds a cylinder.
+-- @param pos Position to center base of cylinder at.
+-- @param axis Axis ("x", "y", or "z")
+-- @param length Cylinder length.
+-- @param radius Cylinder radius.
+-- @param node_name Name of node to make cylinder of.
+-- @param hollow Whether the cylinder should be hollow.
+-- @return The number of nodes added.
+function worldedit.cylinder(pos, axis, length, radius, node_name, hollow)
+ local other1, other2 = worldedit.get_axis_others(axis)
+
+ -- Handle negative lengths
+ local current_pos = {x=pos.x, y=pos.y, z=pos.z}
if length < 0 then
length = -length
- currentpos[axis] = currentpos[axis] - length
+ current_pos[axis] = current_pos[axis] - length
end
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local pos1 = {
- [axis]=currentpos[axis],
- [other1]=currentpos[other1] - radius,
- [other2]=currentpos[other2] - radius
- }
- local pos2 = {
- [axis]=currentpos[axis] + length - 1,
- [other1]=currentpos[other1] + radius,
- [other2]=currentpos[other2] + radius
- }
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
- end
+ -- Set up voxel manipulator
+ local manip, area = mh.init_axis_radius_length(current_pos, axis, radius, length)
+ local data = mh.get_empty_data(area)
- --fill selected area with node
- local node_id = minetest.get_content_id(nodename)
+ -- Add cylinder
+ local node_id = minetest.get_content_id(node_name)
local min_radius, max_radius = radius * (radius - 1), radius * (radius + 1)
local stride = {x=1, y=area.ystride, z=area.zstride}
- local offset = {x=currentpos.x - emerged_pos1.x, y=currentpos.y - emerged_pos1.y, z=currentpos.z - emerged_pos1.z}
+ local offset = {
+ x = current_pos.x - area.MinEdge.x,
+ y = current_pos.y - area.MinEdge.y,
+ z = current_pos.z - area.MinEdge.z,
+ }
local min_slice, max_slice = offset[axis], offset[axis] + length - 1
local count = 0
for index2 = -radius, radius do
- local newindex2 = (index2 + offset[other1]) * stride[other1] + 1 --offset contributed by other axis 1 plus 1 to make it 1-indexed
+ -- Offset contributed by other axis 1 plus 1 to make it 1-indexed
+ local new_index2 = (index2 + offset[other1]) * stride[other1] + 1
for index3 = -radius, radius do
- local newindex3 = newindex2 + (index3 + offset[other2]) * stride[other2]
+ local new_index3 = new_index2 + (index3 + offset[other2]) * stride[other2]
local squared = index2 * index2 + index3 * index3
- if squared >= min_radius and squared <= max_radius then --position is on surface of cylinder
- for index1 = min_slice, max_slice do --add column along axis
- local i = newindex3 + index1 * stride[axis]
- nodes[i] = node_id
+ if squared <= max_radius and (not hollow or squared >= min_radius) then
+ -- Position is in cylinder
+ -- Add column along axis
+ for index1 = min_slice, max_slice do
+ local vi = new_index3 + index1 * stride[axis]
+ data[vi] = node_id
end
count = count + length
end
end
end
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
+ mh.finish(manip, data)
return count
end
---adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`, returning the number of nodes added
-worldedit.cylinder = function(pos, axis, length, radius, nodename)
- local other1, other2
- if axis == "x" then
- other1, other2 = "y", "z"
- elseif axis == "y" then
- other1, other2 = "x", "z"
- else --axis == "z"
- other1, other2 = "x", "y"
- end
-
- --handle negative lengths
- local currentpos = {x=pos.x, y=pos.y, z=pos.z}
- if length < 0 then
- length = -length
- currentpos[axis] = currentpos[axis] - length
- end
-
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local pos1 = {
- [axis]=currentpos[axis],
- [other1]=currentpos[other1] - radius,
- [other2]=currentpos[other2] - radius
- }
- local pos2 = {
- [axis]=currentpos[axis] + length - 1,
- [other1]=currentpos[other1] + radius,
- [other2]=currentpos[other2] + radius
- }
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
- end
-
- --fill selected area with node
- local node_id = minetest.get_content_id(nodename)
- local max_radius = radius * (radius + 1)
- local stride = {x=1, y=area.ystride, z=area.zstride}
- local offset = {x=currentpos.x - emerged_pos1.x, y=currentpos.y - emerged_pos1.y, z=currentpos.z - emerged_pos1.z}
- local min_slice, max_slice = offset[axis], offset[axis] + length - 1
- local count = 0
- for index2 = -radius, radius do
- local newindex2 = (index2 + offset[other1]) * stride[other1] + 1 --offset contributed by other axis 1 plus 1 to make it 1-indexed
- for index3 = -radius, radius do
- local newindex3 = newindex2 + (index3 + offset[other2]) * stride[other2]
- if index2 * index2 + index3 * index3 <= max_radius then --position is within cylinder
- for index1 = min_slice, max_slice do --add column along axis
- local i = newindex3 + index1 * stride[axis]
- nodes[i] = node_id
- end
- count = count + length
- end
- end
- end
-
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
- return count
-end
+--- Adds a pyramid.
+-- @param pos Position to center base of pyramid at.
+-- @param axis Axis ("x", "y", or "z")
+-- @param height Pyramid height.
+-- @param node_name Name of node to make pyramid of.
+-- @return The number of nodes added.
+function worldedit.pyramid(pos, axis, height, node_name)
+ local other1, other2 = worldedit.get_axis_others(axis)
---adds a pyramid centered at `pos` with height `height`, composed of `nodename`, returning the number of nodes added
-worldedit.pyramid = function(pos, axis, height, nodename)
- local other1, other2
- if axis == "x" then
- other1, other2 = "y", "z"
- elseif axis == "y" then
- other1, other2 = "x", "z"
- else --axis == "z"
- other1, other2 = "x", "y"
- end
-
- local pos1 = {x=pos.x - height, y=pos.y - height, z=pos.z - height}
- local pos2 = {x=pos.x + height, y=pos.y + height, z=pos.z + height}
+ -- 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()
- --handle inverted pyramids
- local startaxis, endaxis, step
+ -- Handle inverted pyramids
+ local start_axis, end_axis, step
if height > 0 then
height = height - 1
step = 1
- pos1[axis] = pos[axis] --upper half of box
else
height = height + 1
step = -1
- pos2[axis] = pos[axis] --lower half of box
- end
-
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
end
- --fill selected area with node
- local node_id = minetest.get_content_id(nodename)
+ -- Add pyramid
+ local node_id = minetest.get_content_id(node_name)
local stride = {x=1, y=area.ystride, z=area.zstride}
- local offset = {x=pos.x - emerged_pos1.x, y=pos.y - emerged_pos1.y, z=pos.z - emerged_pos1.z}
+ local offset = {
+ x = pos.x - area.MinEdge.x,
+ y = pos.y - area.MinEdge.y,
+ z = pos.z - area.MinEdge.z,
+ }
local size = height * step
local count = 0
- for index1 = 0, height, step do --go through each level of the pyramid
- local newindex1 = (index1 + offset[axis]) * stride[axis] + 1 --offset contributed by axis plus 1 to make it 1-indexed
+ -- For each level of the pyramid
+ for index1 = 0, height, step do
+ -- Offset contributed by axis plus 1 to make it 1-indexed
+ local new_index1 = (index1 + offset[axis]) * stride[axis] + 1
for index2 = -size, size do
- local newindex2 = newindex1 + (index2 + offset[other1]) * stride[other1]
+ local new_index2 = new_index1 + (index2 + offset[other1]) * stride[other1]
for index3 = -size, size do
- local i = newindex2 + (index3 + offset[other2]) * stride[other2]
- nodes[i] = node_id
+ local i = new_index2 + (index3 + offset[other2]) * stride[other2]
+ data[i] = node_id
end
end
count = count + (size * 2 + 1) ^ 2
size = size - 1
end
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
+ mh.finish(manip, data)
return count
end
---adds a spiral centered at `pos` with side length `length`, height `height`, space between walls `spacer`, composed of `nodename`, returning the number of nodes added
-worldedit.spiral = function(pos, length, height, spacer, nodename)
+--- Adds a spiral.
+-- @param pos Position to center spiral at.
+-- @param length Spral length.
+-- @param height Spiral height.
+-- @param spacer Space between walls.
+-- @param node_name Name of node to make spiral of.
+-- @return Number of nodes added.
+-- TODO: Add axis option.
+function worldedit.spiral(pos, length, height, spacer, node_name)
local extent = math.ceil(length / 2)
- local pos1 = {x=pos.x - extent, y=pos.y, z=pos.z - extent}
- local pos2 = {x=pos.x + extent, y=pos.y + height, z=pos.z + extent}
-
- --set up voxel manipulator
- local manip = minetest.get_voxel_manip()
- local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
- local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
-
- --fill emerged area with ignore
- local nodes = {}
- local ignore = minetest.get_content_id("ignore")
- for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
- nodes[i] = ignore
- end
- --set up variables
- local node_id = minetest.get_content_id(nodename)
+ local manip, area = mh.init_axis_radius_length(pos, "y", extent, height)
+ local data = mh.get_empty_data(area)
+
+ -- Set up variables
+ local node_id = minetest.get_content_id(node_name)
local stride = {x=1, y=area.ystride, z=area.zstride}
- local offsetx, offsety, offsetz = pos.x - emerged_pos1.x, pos.y - emerged_pos1.y, pos.z - emerged_pos1.z
- local i = offsetz * stride.z + offsety * stride.y + offsetx + 1
+ local offset_x, offset_y, offset_z = pos.x - area.MinEdge.x, pos.y - area.MinEdge.y, pos.z - area.MinEdge.z
+ local i = offset_z * stride.z + offset_y * stride.y + offset_x + 1
- --add first column
+ -- Add first column
local count = height
local column = i
for y = 1, height do
- nodes[column] = node_id
+ data[column] = node_id
column = column + stride.y
end
- --add spiral segments
- local strideaxis, strideother = stride.x, stride.z
+ -- Add spiral segments
+ local stride_axis, stride_other = stride.x, stride.z
local sign = -1
local segment_length = 0
spacer = spacer + 1
- for segment = 1, math.floor(length / spacer) * 2 do --go through each segment except the last
- if segment % 2 == 1 then --change sign and length every other turn starting with the first
+ -- Go through each segment except the last
+ for segment = 1, math.floor(length / spacer) * 2 do
+ -- Change sign and length every other turn starting with the first
+ if segment % 2 == 1 then
sign = -sign
segment_length = segment_length + spacer
end
- for index = 1, segment_length do --fill segment
- i = i + strideaxis * sign --move along the direction of the segment
+ -- Fill segment
+ for index = 1, segment_length do
+ -- Move along the direction of the segment
+ i = i + stride_axis * sign
local column = i
- for y = 1, height do --add column
- nodes[column] = node_id
+ -- Add column
+ for y = 1, height do
+ data[column] = node_id
column = column + stride.y
end
end
count = count + segment_length * height
- strideaxis, strideother = strideother, strideaxis --swap axes
+ stride_axis, stride_other = stride_other, stride_axis -- Swap axes
end
- --add shorter final segment
+ -- Add shorter final segment
sign = -sign
for index = 1, segment_length do
- i = i + strideaxis * sign
+ i = i + stride_axis * sign
local column = i
- for y = 1, height do --add column
- nodes[column] = node_id
+ -- Add column
+ for y = 1, height do
+ data[column] = node_id
column = column + stride.y
end
end
count = count + segment_length * height
- --update map nodes
- manip:set_data(nodes)
- manip:write_to_map()
- manip:update_map()
+ mh.finish(manip, data)
return count
-end \ No newline at end of file
+end
diff --git a/worldedit/serialization.lua b/worldedit/serialization.lua
index f129168..bec7e09 100644
--- a/worldedit/serialization.lua
+++ b/worldedit/serialization.lua
@@ -1,5 +1,5 @@
-worldedit = worldedit or {}
-local minetest = minetest -- Local copy of global
+--- Schematic serialization and deserialiation.
+-- @module worldedit.serialization
worldedit.LATEST_SERIALIZATION_VERSION = 5
local LATEST_SERIALIZATION_HEADER = worldedit.LATEST_SERIALIZATION_VERSION .. ":"
@@ -52,11 +52,10 @@ end
-- @return The serialized data.
-- @return The number of nodes serialized.
function worldedit.serialize(pos1, pos2)
- -- Keep area loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ pos1, pos2 = worldedit.sort_pos(pos1, pos2)
+
+ worldedit.keep_loaded(pos1, pos2)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local pos = {x=pos1.x, y=0, z=0}
local count = 0
local result = {}
@@ -112,7 +111,7 @@ end
-- Contains code based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile)
-- by ChillCode, available under the MIT license.
-- @return A node list in the latest format, or nil on failure.
-function worldedit.load_schematic(value)
+local function load_schematic(value)
local version, header, content = worldedit.read_header(value)
local nodes = {}
if version == 1 or version == 2 then -- Original flat table format
@@ -187,15 +186,15 @@ end
-- @return Low corner position.
-- @return High corner position.
-- @return The number of nodes.
-worldedit.allocate = function(origin_pos, value)
- local nodes = worldedit.load_schematic(value)
+function worldedit.allocate(origin_pos, value)
+ local nodes = load_schematic(value)
if not nodes then return nil end
return worldedit.allocate_with_nodes(origin_pos, nodes)
end
-- Internal
-worldedit.allocate_with_nodes = function(origin_pos, nodes)
+function worldedit.allocate_with_nodes(origin_pos, nodes)
local huge = math.huge
local pos1x, pos1y, pos1z = huge, huge, huge
local pos2x, pos2y, pos2z = -huge, -huge, -huge
@@ -217,14 +216,12 @@ end
--- Loads the nodes represented by string `value` at position `origin_pos`.
-- @return The number of nodes deserialized.
-worldedit.deserialize = function(origin_pos, value)
- local nodes = worldedit.load_schematic(value)
+function worldedit.deserialize(origin_pos, value)
+ local nodes = load_schematic(value)
if not nodes then return nil end
- -- Make area stay loaded
local pos1, pos2 = worldedit.allocate_with_nodes(origin_pos, nodes)
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ worldedit.keep_loaded(pos1, pos2)
local origin_x, origin_y, origin_z = origin_pos.x, origin_pos.y, origin_pos.z
local count = 0
diff --git a/worldedit/visualization.lua b/worldedit/visualization.lua
index dbee5d0..5ac49f3 100644
--- a/worldedit/visualization.lua
+++ b/worldedit/visualization.lua
@@ -1,57 +1,38 @@
-worldedit = worldedit or {}
-local minetest = minetest --local copy of global
-
---modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions
-worldedit.sort_pos = function(pos1, pos2)
- pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
- pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
- if pos1.x > pos2.x then
- pos2.x, pos1.x = pos1.x, pos2.x
- end
- if pos1.y > pos2.y then
- pos2.y, pos1.y = pos1.y, pos2.y
- end
- if pos1.z > pos2.z then
- pos2.z, pos1.z = pos1.z, pos2.z
- end
- return pos1, pos2
-end
-
---determines the volume of the region defined by positions `pos1` and `pos2`, returning the volume
-worldedit.volume = function(pos1, pos2)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- return (pos2.x - pos1.x + 1) * (pos2.y - pos1.y + 1) * (pos2.z - pos1.z + 1)
-end
+--- Functions for visibly hiding nodes
+-- @module worldedit.visualization
minetest.register_node("worldedit:placeholder", {
drawtype = "airlike",
paramtype = "light",
sunlight_propagates = true,
diggable = false,
+ walkable = false,
groups = {not_in_creative_inventory=1},
})
---hides all nodes in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes, returning the number of nodes hidden
-worldedit.hide = function(pos1, pos2)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+--- Hides all nodes in a region defined by positions `pos1` and `pos2` by
+-- non-destructively replacing them with invisible nodes.
+-- @return The number of nodes hidden.
+function worldedit.hide(pos1, pos2)
+ pos1, pos2 = worldedit.sort_pos(pos1, pos2)
+
+ worldedit.keep_loaded(pos1, pos2)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local pos = {x=pos1.x, y=0, z=0}
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
+ local get_node, get_meta, swap_node = minetest.get_node,
+ minetest.get_meta, minetest.swap_node
while pos.x <= pos2.x do
pos.y = pos1.y
while pos.y <= pos2.y do
pos.z = pos1.z
while pos.z <= pos2.z do
local node = get_node(pos)
- if node.name ~= "worldedit:placeholder" then
- local data = get_meta(pos):to_table() --obtain metadata of original node
- data.fields.worldedit_placeholder = node.name --add the node's name
- node.name = "worldedit:placeholder" --set node name
- add_node(pos, node) --add placeholder node
- get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata
+ if node.name ~= "air" and node.name ~= "worldedit:placeholder" then
+ -- Save the node's original name
+ get_meta(pos):set_string("worldedit_placeholder", node.name)
+ -- Swap in placeholder node
+ node.name = "worldedit:placeholder"
+ swap_node(pos, node)
end
pos.z = pos.z + 1
end
@@ -62,40 +43,44 @@ worldedit.hide = function(pos1, pos2)
return worldedit.volume(pos1, pos2)
end
---suppresses all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively replacing them with invisible nodes, returning the number of nodes suppressed
-worldedit.suppress = function(pos1, pos2, nodename)
- --ignore placeholder supression
- if nodename == "worldedit:placeholder" then
+--- Suppresses all instances of `node_name` in a region defined by positions
+-- `pos1` and `pos2` by non-destructively replacing them with invisible nodes.
+-- @return The number of nodes suppressed.
+function worldedit.suppress(pos1, pos2, node_name)
+ -- Ignore placeholder supression
+ if node_name == "worldedit:placeholder" then
return 0
end
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+ pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
- local nodes = minetest.find_nodes_in_area(pos1, pos2, nodename)
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
+ worldedit.keep_loaded(pos1, pos2)
+
+ local nodes = minetest.find_nodes_in_area(pos1, pos2, node_name)
+ local get_node, get_meta, swap_node = minetest.get_node,
+ minetest.get_meta, minetest.swap_node
for _, pos in ipairs(nodes) do
local node = get_node(pos)
- local data = get_meta(pos):to_table() --obtain metadata of original node
- data.fields.worldedit_placeholder = node.name --add the node's name
- node.name = "worldedit:placeholder" --set node name
- add_node(pos, node) --add placeholder node
- get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata
+ -- Save the node's original name
+ get_meta(pos):set_string("worldedit_placeholder", node.name)
+ -- Swap in placeholder node
+ node.name = "worldedit:placeholder"
+ swap_node(pos, node)
end
return #nodes
end
---highlights all instances of `nodename` in a region defined by positions `pos1` and `pos2` by non-destructively hiding all other nodes, returning the number of nodes found
-worldedit.highlight = function(pos1, pos2, nodename)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
+--- Highlights all instances of `node_name` in a region defined by positions
+-- `pos1` and `pos2` by non-destructively hiding all other nodes.
+-- @return The number of nodes found.
+function worldedit.highlight(pos1, pos2, node_name)
+ pos1, pos2 = worldedit.sort_pos(pos1, pos2)
+
+ worldedit.keep_loaded(pos1, pos2)
- local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
local pos = {x=pos1.x, y=0, z=0}
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
+ local get_node, get_meta, swap_node = minetest.get_node,
+ minetest.get_meta, minetest.swap_node
local count = 0
while pos.x <= pos2.x do
pos.y = pos1.y
@@ -103,14 +88,14 @@ worldedit.highlight = function(pos1, pos2, nodename)
pos.z = pos1.z
while pos.z <= pos2.z do
local node = get_node(pos)
- if node.name == nodename then --node found
+ if node.name == node_name then -- Node found
count = count + 1
- elseif node.name ~= "worldedit:placeholder" then --hide other nodes
- local data = get_meta(pos):to_table() --obtain metadata of original node
- data.fields.worldedit_placeholder = node.name --add the node's name
- node.name = "worldedit:placeholder" --set node name
- add_node(pos, node) --add placeholder node
- get_meta(pos):from_table(data) --set placeholder metadata to the original node's metadata
+ elseif node.name ~= "worldedit:placeholder" then -- Hide other nodes
+ -- Save the node's original name
+ get_meta(pos):set_string("worldedit_placeholder", node.name)
+ -- Swap in placeholder node
+ node.name = "worldedit:placeholder"
+ swap_node(pos, node)
end
pos.z = pos.z + 1
end
@@ -121,22 +106,26 @@ worldedit.highlight = function(pos1, pos2, nodename)
return count
end
---restores all nodes hidden with WorldEdit functions in a region defined by positions `pos1` and `pos2`, returning the number of nodes restored
-worldedit.restore = function(pos1, pos2)
- --make area stay loaded
- local manip = minetest.get_voxel_manip()
- manip:read_from_map(pos1, pos2)
-
+-- Restores all nodes hidden with WorldEdit functions in a region defined
+-- by positions `pos1` and `pos2`.
+-- @return The number of nodes restored.
+function worldedit.restore(pos1, pos2)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
+
+ worldedit.keep_loaded(pos1, pos2)
+
local nodes = minetest.find_nodes_in_area(pos1, pos2, "worldedit:placeholder")
- local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
+ local get_node, get_meta, swap_node = minetest.get_node,
+ minetest.get_meta, minetest.swap_node
for _, pos in ipairs(nodes) do
local node = get_node(pos)
- local data = get_meta(pos):to_table() --obtain node metadata
- node.name = data.fields.worldedit_placeholder --set node name
- data.fields.worldedit_placeholder = nil --delete old nodename
- add_node(pos, node) --add original node
- get_meta(pos):from_table(data) --set original node metadata
+ local meta = get_meta(pos)
+ local data = meta:to_table()
+ node.name = data.fields.worldedit_placeholder
+ data.fields.worldedit_placeholder = nil
+ meta:from_table(data)
+ swap_node(pos, node)
end
return #nodes
end
+
diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua
index 9daa809..424082f 100644
--- a/worldedit_commands/init.lua
+++ b/worldedit_commands/init.lua
@@ -1,7 +1,5 @@
minetest.register_privilege("worldedit", "Can use WorldEdit commands")
---wip: fold the hollow stuff into the main functions and add a hollow flag at the end, then add the compatibility stuff
-
worldedit.set_pos = {}
worldedit.inspect = {}
@@ -340,10 +338,11 @@ minetest.register_chatcommand("/replace", {
description = "Replace all instances of <search node> with <replace node> in the current WorldEdit region",
privs = {worldedit=true},
func = safe_region(function(name, param)
- local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$")
- local newsearchnode = worldedit.normalize_nodename(searchnode)
- local newreplacenode = worldedit.normalize_nodename(replacenode)
- local count = worldedit.replace(worldedit.pos1[name], worldedit.pos2[name], newsearchnode, newreplacenode)
+ local found, _, search_node, replace_node = param:find("^([^%s]+)%s+(.+)$")
+ local norm_search_node = worldedit.normalize_nodename(search_node)
+ local norm_replace_node = worldedit.normalize_nodename(replace_node)
+ local count = worldedit.replace(worldedit.pos1[name], worldedit.pos2[name],
+ norm_search_node, norm_replace_node)
worldedit.player_notify(name, count .. " nodes replaced")
end, check_replace),
})
@@ -353,10 +352,11 @@ minetest.register_chatcommand("/replaceinverse", {
description = "Replace all nodes other than <search node> with <replace node> in the current WorldEdit region",
privs = {worldedit=true},
func = safe_region(function(name, param)
- local found, _, searchnode, replacenode = param:find("^([^%s]+)%s+(.+)$")
- local newsearchnode = worldedit.normalize_nodename(searchnode)
- local newreplacenode = worldedit.normalize_nodename(replacenode)
- local count = worldedit.replaceinverse(worldedit.pos1[name], worldedit.pos2[name], searchnode, replacenode)
+ local found, _, search_node, replace_node = param:find("^([^%s]+)%s+(.+)$")
+ local norm_search_node = worldedit.normalize_nodename(search_node)
+ local norm_replace_node = worldedit.normalize_nodename(replace_node)
+ local count = worldedit.replace(worldedit.pos1[name], worldedit.pos2[name],
+ norm_search_node, norm_replace_node, true)
worldedit.player_notify(name, count .. " nodes replaced")
end, check_replace),
})
@@ -383,7 +383,7 @@ minetest.register_chatcommand("/hollowsphere", {
func = safe_region(function(name, param)
local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$")
local node = get_node(name, nodename)
- local count = worldedit.hollow_sphere(worldedit.pos1[name], tonumber(radius), node)
+ local count = worldedit.sphere(worldedit.pos1[name], tonumber(radius), node, true)
worldedit.player_notify(name, count .. " nodes added")
end, check_sphere),
})
@@ -422,7 +422,7 @@ minetest.register_chatcommand("/hollowdome", {
func = safe_region(function(name, param)
local found, _, radius, nodename = param:find("^(%d+)%s+(.+)$")
local node = get_node(name, nodename)
- local count = worldedit.hollow_dome(worldedit.pos1[name], tonumber(radius), node)
+ local count = worldedit.dome(worldedit.pos1[name], tonumber(radius), node, true)
worldedit.player_notify(name, count .. " nodes added")
end, check_dome),
})
@@ -466,7 +466,7 @@ minetest.register_chatcommand("/hollowcylinder", {
length = length * sign
end
local node = get_node(name, nodename)
- local count = worldedit.hollow_cylinder(worldedit.pos1[name], axis, length, tonumber(radius), node)
+ local count = worldedit.cylinder(worldedit.pos1[name], axis, length, tonumber(radius), node, true)
worldedit.player_notify(name, count .. " nodes added")
end, check_cylinder),
})
@@ -1114,7 +1114,7 @@ minetest.register_chatcommand("/clearobjects", {
description = "Clears all objects within the WorldEdit region",
privs = {worldedit=true},
func = safe_region(function(name, param)
- local count = worldedit.clearobjects(worldedit.pos1[name], worldedit.pos2[name])
+ local count = worldedit.clear_objects(worldedit.pos1[name], worldedit.pos2[name])
worldedit.player_notify(name, count .. " objects cleared")
end),
})
diff --git a/worldedit_commands/mark.lua b/worldedit_commands/mark.lua
index e07e849..4062cae 100644
--- a/worldedit_commands/mark.lua
+++ b/worldedit_commands/mark.lua
@@ -19,7 +19,7 @@ worldedit.mark_pos1 = function(name)
--add marker
worldedit.marker1[name] = minetest.add_entity(pos1, "worldedit:pos1")
if worldedit.marker1[name] ~= nil then
- worldedit.marker1[name]:get_luaentity().name = name
+ worldedit.marker1[name]:get_luaentity().player_name = name
end
end
worldedit.mark_region(name)
@@ -42,7 +42,7 @@ worldedit.mark_pos2 = function(name)
--add marker
worldedit.marker2[name] = minetest.add_entity(pos2, "worldedit:pos2")
if worldedit.marker2[name] ~= nil then
- worldedit.marker2[name]:get_luaentity().name = name
+ worldedit.marker2[name]:get_luaentity().player_name = name
end
end
worldedit.mark_region(name)
@@ -76,7 +76,7 @@ worldedit.mark_region = function(name)
visual_size={x=sizex * 2, y=sizey * 2},
collisionbox = {-sizex, -sizey, -thickness, sizex, sizey, thickness},
})
- marker:get_luaentity().name = name
+ marker:get_luaentity().player_name = name
table.insert(markers, marker)
end
@@ -88,7 +88,7 @@ worldedit.mark_region = function(name)
collisionbox = {-thickness, -sizey, -sizez, thickness, sizey, sizez},
})
marker:setyaw(math.pi / 2)
- marker:get_luaentity().name = name
+ marker:get_luaentity().player_name = name
table.insert(markers, marker)
end
@@ -107,13 +107,13 @@ minetest.register_entity(":worldedit:pos1", {
physical = false,
},
on_step = function(self, dtime)
- if worldedit.marker1[self.name] == nil then
+ if worldedit.marker1[self.player_name] == nil then
self.object:remove()
end
end,
on_punch = function(self, hitter)
self.object:remove()
- worldedit.marker1[self.name] = nil
+ worldedit.marker1[self.player_name] = nil
end,
})
@@ -128,13 +128,13 @@ minetest.register_entity(":worldedit:pos2", {
physical = false,
},
on_step = function(self, dtime)
- if worldedit.marker2[self.name] == nil then
+ if worldedit.marker2[self.player_name] == nil then
self.object:remove()
end
end,
on_punch = function(self, hitter)
self.object:remove()
- worldedit.marker2[self.name] = nil
+ worldedit.marker2[self.player_name] = nil
end,
})
@@ -147,15 +147,16 @@ minetest.register_entity(":worldedit:region_cube", {
physical = false,
},
on_step = function(self, dtime)
- if worldedit.marker_region[self.name] == nil then
+ if worldedit.marker_region[self.player_name] == nil then
self.object:remove()
return
end
end,
on_punch = function(self, hitter)
- for _, entity in ipairs(worldedit.marker_region[self.name]) do
+ for _, entity in ipairs(worldedit.marker_region[self.player_name]) do
entity:remove()
end
- worldedit.marker_region[self.name] = nil
+ worldedit.marker_region[self.player_name] = nil
end,
-}) \ No newline at end of file
+})
+