]> git.lizzy.rs Git - worldedit.git/commitdiff
Improved stacking
authorCy <whatever>
Mon, 30 Jun 2014 23:14:14 +0000 (16:14 -0700)
committerCy <whatever>
Mon, 30 Jun 2014 23:14:14 +0000 (16:14 -0700)
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
worldedit_commands/init.lua

index 40915ed5799746d4a675b0095cf2b257ad545fa8..0a37e16cfb5ffed562ed08d650f8708dc3f80edf 100644 (file)
@@ -172,6 +172,129 @@ worldedit.copy = function(pos1, pos2, axis, amount) --wip: replace the old versi
        return worldedit.volume(pos1, pos2)\r
 end\r
 \r
+worldedit.copy2 = function(pos1, pos2, direction, volume)\r
+    -- the overlap shouldn't matter as long as we\r
+    -- 1) start at the furthest separated corner\r
+    -- 2) complete an edge before moving inward, either edge works\r
+    -- 3) complete a face before moving inward, similarly\r
+    --\r
+    -- to do this I\r
+    -- 1) find the furthest destination in the direction, of each axis\r
+    -- 2) call those the furthest separated corner\r
+    -- 3) make sure to iterate inward from there\r
+    -- 4) nested loop to make sure complete edge, complete face, then complete cube.\r
+    \r
+       local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node\r
+    local somemeta = get_meta(pos1) -- hax lol\r
+    local to_table = somemeta.to_table\r
+    local from_table = somemeta.from_table\r
+    somemeta = nil\r
+\r
+       local pos1, pos2 = worldedit.sort_pos(pos1, pos2)\r
+       local manip = minetest.get_voxel_manip()\r
+       manip:read_from_map(pos1, pos2)\r
+\r
+    local sx,sy,sz -- direction sign\r
+    local ix,iy,iz -- initial destination\r
+    local ex,ey,ez -- final destination\r
+    local originalx,originaly,originalz -- source \r
+    -- vim -> :'<,'>s/\<\([ioes]\?\)x\>/\1y/g\r
+    if direction.x > 0 then \r
+        originalx = pos2.x\r
+        ix = originalx + direction.x\r
+        ex = pos1.x + direction.x\r
+        sx = -1\r
+    elseif direction.x < 0 then \r
+        originalx = pos1.x\r
+        ix = originalx + direction.x\r
+        ex = pos2.x + direction.x\r
+        sx = 1\r
+    else \r
+        originalx = pos1.x\r
+        ix = originalx -- whatever\r
+        ex = pos2.x\r
+        sx = 1\r
+    end\r
+\r
+    if direction.y > 0 then \r
+        originaly = pos2.y\r
+        iy = originaly + direction.y\r
+        ey = pos1.y + direction.y\r
+        sy = -1\r
+    elseif direction.y < 0 then \r
+        originaly = pos1.y\r
+        iy = originaly + direction.y\r
+        ey = pos2.y + direction.y\r
+        sy = 1\r
+    else \r
+        originaly = pos1.y\r
+        iy = originaly -- whatever\r
+        ey = pos2.y\r
+        sy = 1\r
+    end\r
+\r
+    if direction.z > 0 then \r
+        originalz = pos2.z\r
+        iz = originalz + direction.z\r
+        ez = pos1.z + direction.z\r
+        sz = -1\r
+    elseif direction.z < 0 then \r
+        originalz = pos1.z\r
+        iz = originalz + direction.z\r
+        ez = pos2.z + direction.z\r
+        sz = 1\r
+    else \r
+        originalz = pos1.z\r
+        iz = originalz -- whatever\r
+        ez = pos2.z\r
+        sz = 1\r
+    end\r
+    -- print('copy',originalx,ix,ex,sx,originaly,iy,ey,sy,originalz,iz,ez,sz)\r
+\r
+    local ox,oy,oz\r
+\r
+    ox = originalx\r
+    for x = ix,ex,sx do\r
+        oy = originaly\r
+        for y = iy,ey,sy do\r
+            oz = originalz\r
+            for z = iz,ez,sz do\r
+                -- reusing pos1/pos2 as source/dest here\r
+                pos1.x = ox; pos1.y = oy; pos1.z = oz\r
+                pos2.x = x; pos2.y = y; pos2.z = z\r
+                local node = get_node(pos1)\r
+                               local meta = to_table(get_meta(pos1)) --get meta of current node\r
+                add_node(pos2,node)\r
+                from_table(get_meta(pos2),meta)\r
+                oz = oz + sz\r
+            end\r
+            oy = oy + sy\r
+        end\r
+        ox = ox + sx\r
+    end\r
+end            \r
+\r
+worldedit.stack2 = function(pos1, pos2, direction, amount, finished) \r
+    local i = 0\r
+    local translated = {x=0,y=0,z=0}\r
+    local function nextone()\r
+        if i <= amount then\r
+            i = i + 1\r
+            translated.x = translated.x + direction.x\r
+            translated.y = translated.y + direction.y\r
+            translated.z = translated.z + direction.z\r
+            worldedit.copy2(pos1,pos2,translated,volume)\r
+            minetest.after(0,nextone)\r
+        else\r
+            if finished then\r
+                finished()\r
+            end\r
+        end\r
+    end\r
+    nextone()\r
+    return nil\r
+end\r
+\r
 --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\r
 worldedit.copy = function(pos1, pos2, axis, amount)\r
        local pos1, pos2 = worldedit.sort_pos(pos1, pos2)\r
index 04f2f4c25a4490f01de09b77064b247536b0412c..e7b0f748a19dce839afd1c894dd6f633a9c64981 100644 (file)
@@ -619,6 +619,52 @@ minetest.register_chatcommand("/stack", {
        end),\r
 })\r
 \r
+minetest.register_chatcommand("/stack2", {\r
+       params = "<count> <x>/<y>/<z>",\r
+       description = "Stack the current WorldEdit region <count> times translating each time by x, y and z in the respective directions.",\r
+       privs = {worldedit=true},\r
+       func = function(name, param)\r
+               local pos1, pos2 = worldedit.pos1[name], worldedit.pos2[name]\r
+        if pos1 == nil or pos2 == nil then\r
+            worldedit.player_notify(name, "Select a position first!")\r
+            return\r
+        end\r
+        local repetitions, incs = param:match("([0-9]+)%s*(.+)")\r
+        repetitions = repetitions and tonumber(repetitions)\r
+        if repetitions == nil then\r
+                       worldedit.player_notify(name, "invalid count: " .. param)\r
+            return \r
+        end\r
+\r
+        local x,y,z = incs:match("(.+)/(.+)/(.+)")\r
+        if x == nil then\r
+            worldedit.player_notify(name, "invalid increments: " .. param)\r
+            return\r
+        end\r
+        x = tonumber(x)\r
+        y = tonumber(y)\r
+        z = tonumber(z)\r
+        if x == nil or y == nil or z == nil then\r
+            worldedit.player_notify(name, "increments must be numbers: " .. param)\r
+            return\r
+        end\r
+\r
+        local count = worldedit.volume(pos1,pos2) * repetitions\r
+\r
+        return safe_region(function()\r
+                 worldedit.stack2(pos1, pos2, {x=x,y=y,z=z}, repetitions,\r
+          function()\r
+                   worldedit.player_notify(name, count .. " nodes stacked")\r
+        end)\r
+\r
+        end,\r
+        function() \r
+            return count\r
+       end)(name,param) -- more hax\r
+       end\r
+})\r
+\r
+\r
 minetest.register_chatcommand("/stretch", {\r
        params = "<stretchx> <stretchy> <stretchz>",\r
        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",\r