summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--worldedit/manipulations.lua136
-rw-r--r--worldedit_commands/init.lua68
2 files changed, 192 insertions, 12 deletions
diff --git a/worldedit/manipulations.lua b/worldedit/manipulations.lua
index 1d4c6dc..0a37e16 100644
--- a/worldedit/manipulations.lua
+++ b/worldedit/manipulations.lua
@@ -24,7 +24,11 @@ worldedit.volume = function(pos1, pos2)
end
--sets a region defined by positions `pos1` and `pos2` to `nodename`, returning the number of nodes filled
-worldedit.set = function(pos1, pos2, nodename)
+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
@@ -40,9 +44,12 @@ worldedit.set = function(pos1, pos2, nodename)
end
--fill selected area with node
- local node_id = minetest.get_content_id(nodename)
+ local node_ids = {}
+ for i,v in ipairs(nodenames) do
+ node_ids[i] = minetest.get_content_id(nodenames[i])
+ end
for i in area:iterp(pos1, pos2) do
- nodes[i] = node_id
+ nodes[i] = node_ids[math.random(#node_ids)]
end
--update map nodes
@@ -165,6 +172,129 @@ worldedit.copy = function(pos1, pos2, axis, amount) --wip: replace the old versi
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 = ox; pos1.y = oy; pos1.z = oz
+ pos2.x = x; pos2.y = y; pos2.z = 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
+ end
+ oy = oy + sy
+ end
+ ox = ox + sx
+ end
+end
+
+worldedit.stack2 = function(pos1, pos2, direction, amount, finished)
+ local i = 0
+ local translated = {x=0,y=0,z=0}
+ local function nextone()
+ 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)
+ else
+ if finished then
+ finished()
+ end
+ end
+ end
+ nextone()
+ return nil
+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)
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua
index 2bbfeed..e7b0f74 100644
--- a/worldedit_commands/init.lua
+++ b/worldedit_commands/init.lua
@@ -278,22 +278,26 @@ minetest.register_chatcommand("/volume", {
end,
})
-local check_set = function(name, param)
- local node = get_node(name, param)
- if not node then return nil end
- return check_region(name, param)
-end
-
minetest.register_chatcommand("/set", {
params = "<node>",
description = "Set the current WorldEdit region to <node>",
privs = {worldedit=true},
func = safe_region(function(name, param)
+ local nodes = {}
+
+ for nodename in param:gmatch("[^%s]+") do
+ local node = get_node(name, nodename)
+ if not node then
+ worldedit.player_notify(name, 'Could not identify node "'..name..'"')
+ return
+ end
+ nodes[#nodes+1] = node
+ end
+
local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
- local node = get_node(name, param)
- local count = worldedit.set(pos1, pos2, node)
+ local count = worldedit.set(pos1, pos2, nodes)
worldedit.player_notify(name, count .. " nodes set")
- end, check_set),
+ end, check_region),
})
local check_replace = function(name, param)
@@ -615,6 +619,52 @@ minetest.register_chatcommand("/stack", {
end),
})
+minetest.register_chatcommand("/stack2", {
+ params = "<count> <x>/<y>/<z>",
+ description = "Stack the current WorldEdit region <count> times translating each time by x, y and z in the respective directions.",
+ privs = {worldedit=true},
+ func = function(name, param)
+ local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]
+ if pos1 == nil or pos2 == nil then
+ worldedit.player_notify(name, "Select a position first!")
+ return
+ end
+ local repetitions, incs = param:match("([0-9]+)%s*(.+)")
+ repetitions = repetitions and tonumber(repetitions)
+ if repetitions == nil then
+ worldedit.player_notify(name, "invalid count: " .. param)
+ return
+ end
+
+ local x,y,z = incs:match("(.+)/(.+)/(.+)")
+ if x == nil then
+ worldedit.player_notify(name, "invalid increments: " .. param)
+ return
+ end
+ x = tonumber(x)
+ y = tonumber(y)
+ z = tonumber(z)
+ if x == nil or y == nil or z == nil then
+ worldedit.player_notify(name, "increments must be numbers: " .. param)
+ return
+ end
+
+ local count = worldedit.volume(pos1,pos2) * repetitions
+
+ return safe_region(function()
+ worldedit.stack2(pos1, pos2, {x=x,y=y,z=z}, repetitions,
+ function()
+ worldedit.player_notify(name, count .. " nodes stacked")
+ end)
+
+ end,
+ function()
+ return count
+ end)(name,param) -- more hax
+ end
+})
+
+
minetest.register_chatcommand("/stretch", {
params = "<stretchx> <stretchy> <stretchz>",
description = "Scale the current WorldEdit positions and region by a factor of <stretchx>, <stretchy>, <stretchz> along the X, Y, and Z axes, repectively, with position 1 as the origin",