diff options
| author | Anthony Zhang <azhang9@gmail.com> | 2014-07-06 19:11:23 -0400 | 
|---|---|---|
| committer | Anthony Zhang <azhang9@gmail.com> | 2014-07-06 19:11:23 -0400 | 
| commit | b32aadd7fafdaef8c6ab1dd578860717d144d4f9 (patch) | |
| tree | a3353089fe27cab44befccbc9756a731c3c35d60 | |
| parent | 2c4a79180503adfdb0ba6c4b0f893ebb16521bd3 (diff) | |
| parent | c22b5565114941ce5d62f64916fe713eb1141880 (diff) | |
Merge pull request #47 from cyisfor/master
Stacking in any direction
| -rw-r--r-- | worldedit/manipulations.lua | 136 | ||||
| -rw-r--r-- | worldedit_commands/init.lua | 68 | 
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",
 | 
