diff options
| author | Cy <whatever> | 2014-06-30 16:14:14 -0700 | 
|---|---|---|
| committer | Cy <whatever> | 2014-06-30 16:14:14 -0700 | 
| commit | c22b5565114941ce5d62f64916fe713eb1141880 (patch) | |
| tree | a3353089fe27cab44befccbc9756a731c3c35d60 | |
| parent | 174416b010cd7833edb12f7ec7db7ab8f1918bce (diff) | |
Improved stacking
This stack / copy uses a direction vector, so it's not limited to only
along the X/Y/Z axis, and can go diagonally. This enables things like
building staircases.
| -rw-r--r-- | worldedit/manipulations.lua | 123 | ||||
| -rw-r--r-- | worldedit_commands/init.lua | 46 | 
2 files changed, 169 insertions, 0 deletions
| diff --git a/worldedit/manipulations.lua b/worldedit/manipulations.lua index 40915ed..0a37e16 100644 --- a/worldedit/manipulations.lua +++ b/worldedit/manipulations.lua @@ -172,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 04f2f4c..e7b0f74 100644 --- a/worldedit_commands/init.lua +++ b/worldedit_commands/init.lua @@ -619,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",
 | 
