From 174416b010cd7833edb12f7ec7db7ab8f1918bce Mon Sep 17 00:00:00 2001 From: Cy Date: Mon, 30 Jun 2014 16:13:44 -0700 Subject: [PATCH 1/2] Randomized set Can /set node node2 node3 and it will randomly choose between those three. --- worldedit/manipulations.lua | 13 ++++++++++--- worldedit_commands/init.lua | 22 +++++++++++++--------- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/worldedit/manipulations.lua b/worldedit/manipulations.lua index 1d4c6dc..40915ed 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 diff --git a/worldedit_commands/init.lua b/worldedit_commands/init.lua index 2bbfeed..04f2f4c 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 = "", description = "Set the current WorldEdit region to ", 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) From c22b5565114941ce5d62f64916fe713eb1141880 Mon Sep 17 00:00:00 2001 From: Cy Date: Mon, 30 Jun 2014 16:14:14 -0700 Subject: [PATCH 2/2] 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. --- worldedit/manipulations.lua | 123 ++++++++++++++++++++++++++++++++++++ worldedit_commands/init.lua | 46 ++++++++++++++ 2 files changed, 169 insertions(+) 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 = " //", + description = "Stack the current WorldEdit region 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 = " ", description = "Scale the current WorldEdit positions and region by a factor of , , along the X, Y, and Z axes, repectively, with position 1 as the origin",