return count\r
end\r
\r
+--adds a hollow cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, returning the number of nodes added\r
+worldedit.hollow_cylinder = function(pos, axis, length, radius, nodename)\r
+ local other1, other2\r
+ if axis == "x" then\r
+ other1, other2 = "y", "z"\r
+ elseif axis == "y" then\r
+ other1, other2 = "x", "z"\r
+ else --axis == "z"\r
+ other1, other2 = "x", "y"\r
+ end\r
+\r
+ local env = minetest.env\r
+ local currentpos = {x=pos.x, y=pos.y, z=pos.z}\r
+ local node = {name=nodename}\r
+ local count = 0\r
+ for i = 1, length do\r
+ local offset1, offset2 = 0, radius\r
+ local delta = -radius\r
+ while offset1 <= offset2 do\r
+ --add node at each octant\r
+ local first1, first2 = pos[other1] + offset1, pos[other1] - offset1\r
+ local second1, second2 = pos[other2] + offset2, pos[other2] - offset2\r
+ currentpos[other1], currentpos[other2] = first1, second1\r
+ env:add_node(currentpos, node) --octant 1\r
+ currentpos[other1] = first2\r
+ env:add_node(currentpos, node) --octant 4\r
+ currentpos[other2] = second2\r
+ env:add_node(currentpos, node) --octant 5\r
+ currentpos[other1] = first1\r
+ env:add_node(currentpos, node) --octant 8\r
+ local first1, first2 = pos[other1] + offset2, pos[other1] - offset2\r
+ local second1, second2 = pos[other2] + offset1, pos[other2] - offset1\r
+ currentpos[other1], currentpos[other2] = first1, second1\r
+ env:add_node(currentpos, node) --octant 2\r
+ currentpos[other1] = first2\r
+ env:add_node(currentpos, node) --octant 3\r
+ currentpos[other2] = second2\r
+ env:add_node(currentpos, node) --octant 6\r
+ currentpos[other1] = first1\r
+ env:add_node(currentpos, node) --octant 7\r
+\r
+ count = count + 8 --wip: broken\r
+\r
+ --move to next location\r
+ delta = delta + (offset1 * 2) + 1\r
+ if delta >= 0 then\r
+ offset2 = offset2 - 1\r
+ delta = delta - (offset2 * 2)\r
+ end\r
+ offset1 = offset1 + 1\r
+ end\r
+ currentpos[axis] = currentpos[axis] + 1\r
+ end\r
+ return count\r
+end\r
+\r
+--adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, returning the number of nodes added\r
+worldedit.cylinder = function(pos, axis, length, radius, nodename)\r
+ local other1, other2\r
+ if axis == "x" then\r
+ other1, other2 = "y", "z"\r
+ elseif axis == "y" then\r
+ other1, other2 = "x", "z"\r
+ else --axis == "z"\r
+ other1, other2 = "x", "y"\r
+ end\r
+\r
+ local env = minetest.env\r
+ local currentpos = {x=pos.x, y=pos.y, z=pos.z}\r
+ local node = {name=nodename}\r
+ local count = 0\r
+ for i = 1, length do\r
+ local offset1, offset2 = 0, radius\r
+ local delta = -radius\r
+ while offset1 <= offset2 do\r
+ --connect each pair of octants\r
+ currentpos[other1] = pos[other1] - offset1\r
+ local second1, second2 = pos[other2] + offset2, pos[other2] - offset2\r
+ for i = 0, offset1 * 2 do\r
+ currentpos[other2] = second1\r
+ env:add_node(currentpos, node) --octant 1 to 4\r
+ currentpos[other2] = second2\r
+ env:add_node(currentpos, node) --octant 5 to 8\r
+ currentpos[other1] = currentpos[other1] + 1\r
+ end\r
+ currentpos[other1] = pos[other1] - offset2\r
+ local second1, second2 = pos[other2] + offset1, pos[other2] - offset1\r
+ for i = 0, offset2 * 2 do\r
+ currentpos[other2] = second1\r
+ env:add_node(currentpos, node) --octant 2 to 3\r
+ currentpos[other2] = second2\r
+ env:add_node(currentpos, node) --octant 6 to 7\r
+ currentpos[other1] = currentpos[other1] + 1\r
+ end\r
+\r
+ count = count + (offset1 * 4) + (offset2 * 4) + 4 --wip: broken\r
+\r
+ --move to next location\r
+ delta = delta + (offset1 * 2) + 1\r
+ offset1 = offset1 + 1\r
+ if delta >= 0 then\r
+ offset2 = offset2 - 1\r
+ delta = delta - (offset2 * 2)\r
+ end\r
+ end\r
+ currentpos[axis] = currentpos[axis] + 1\r
+ end\r
+ return count\r
+end\r
+\r
+--adds a spiral at `pos` with size `size`, returning the number of nodes changed\r
+worldedit.spiral = function(pos, size, nodename)\r
+ local shift_x, shift_y\r
+ sa = spiralt(size)\r
+ shift_y = #sa -- "Height" of the Array\r
+ local fe = sa[1]\r
+ shift_x = #fe -- "Width" of the Array\r
+ fe = nil\r
+\r
+ local count = 0\r
+ local node = {name=nodename}\r
+ for x, v in ipairs(sa) do\r
+ for y, z in ipairs(v) do\r
+ minetest.env:add_node({x=pos.x - shift_x + x,y=pos.y - shift_y + y,z=pos.z + z}, node)\r
+ count = count + 1\r
+ end\r
+ end\r
+ return count\r
+end\r
+\r
+--wip: \r
+sign = function(s)\r
+ if s > 0 then\r
+ return 1\r
+ end\r
+ if s < 0 then\r
+ return -1\r
+ end\r
+ return 0\r
+end\r
+\r
+--wip: needs to be faster\r
+function spiral_index(y, x) -- returns the value at (x, y) in a spiral that starts at 1 and goes outwards\r
+ if y == -x and y >= x then\r
+ return (2 * y + 1) ^ 2\r
+ end\r
+ local l = math.max(math.abs(y), math.abs(x))\r
+ local value\r
+ if math.abs(y) == l then\r
+ value = x\r
+ if y < 0 then\r
+ value = -value\r
+ end\r
+ else\r
+ value = y\r
+ if x < 0 then\r
+ value = -value\r
+ end\r
+ end\r
+ t1 = l * 2\r
+ if x + y < 0 then\r
+ t1 = -t1\r
+ end\r
+ t2 = y ^ 2 - x ^ 2\r
+ if t2 < 0 then\r
+ t2 = -t2\r
+ end\r
+ return ((2 * l - 1) ^ 2) + (l * 4) + t1 + (t2 * (l - value))\r
+end\r
+\r
+--wip: needs to be faster\r
+function spiralt(side)\r
+ local spiral = {}\r
+ local start, stop = math.floor((-side+1)/2), math.floor((side-1)/2)\r
+ for i = 1, side do\r
+ spiral[i] = {}\r
+ for j = 1, side do\r
+ spiral[i][j] = side ^ 2 - spiral_index(stop - i + 1,start + j - 1) --moves the coordinates so (0,0) is at the center of the spiral\r
+ end\r
+ end\r
+ return spiral\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
while pos.y <= pos2.y do\r
pos.z = pos1.z\r
while pos.z <= pos2.z do\r
- local node = env:get_node(pos, node)\r
+ local node = env:get_node(pos)\r
+ local meta1 = env:get_meta(pos):to_table()\r
local value = pos[axis]\r
- pos[axis] = value - amount\r
+ pos[axis] = value + amount\r
env:add_node(pos, node)\r
+ local meta2 = env:get_meta(pos)\r
+ meta2:from_table(meta1)\r
pos[axis] = value\r
pos.z = pos.z + 1\r
end\r
while pos.y >= pos1.y do\r
pos.z = pos2.z\r
while pos.z >= pos1.z do\r
- local node = minetest.env:get_node(pos, node)\r
+ local node = minetest.env:get_node(pos)\r
+ local meta1 = env:get_meta(pos):to_table()\r
local value = pos[axis]\r
pos[axis] = value + amount\r
minetest.env:add_node(pos, node)\r
+ local meta2 = env:get_meta(pos)\r
+ meta2:from_table(meta1)\r
pos[axis] = value\r
pos.z = pos.z - 1\r
end\r
while pos.y <= pos2.y do\r
pos.z = pos1.z\r
while pos.z <= pos2.z do\r
- local node = env:get_node(pos, node)\r
+ local node = env:get_node(pos)\r
+ local meta1 = env:get_meta(pos):to_table()\r
env:remove_node(pos)\r
local value = pos[axis]\r
- pos[axis] = value - amount\r
+ pos[axis] = value + amount\r
env:add_node(pos, node)\r
+ local meta2 = env:get_meta(pos)\r
+ meta2:from_table(meta1)\r
pos[axis] = value\r
pos.z = pos.z + 1\r
end\r
while pos.y >= pos1.y do\r
pos.z = pos2.z\r
while pos.z >= pos1.z do\r
- local node = minetest.env:get_node(pos, node)\r
+ local node = env:get_node(pos)\r
+ local meta1 = env:get_meta(pos):to_table()\r
env:remove_node(pos)\r
local value = pos[axis]\r
pos[axis] = value + amount\r
- minetest.env:add_node(pos, node)\r
+ env:add_node(pos, node)\r
+ local meta2 = env:get_meta(pos)\r
+ meta2:from_table(meta1)\r
pos[axis] = value\r
pos.z = pos.z - 1\r
end\r
return worldedit.volume(pos1, pos2)\r
end\r
\r
+--transposes a region defined by the positions `pos1` and `pos2` between the `axis1` and `axis2` axes, returning the number of nodes transposed\r
+worldedit.transpose = function(pos1, pos2, axis1, axis2)\r
+ local pos1, pos2 = worldedit.sort_pos(pos1, pos2)\r
+\r
+ local pos = {x=pos1.x, y=0, z=0}\r
+ local env = minetest.env\r
+ while pos.x <= pos2.x do\r
+ pos.y = pos1.y\r
+ while pos.y <= pos2.y do\r
+ pos.z = pos1.z\r
+ while pos.z <= pos2.z do\r
+ local extent1, extent2 = pos[axis1] - pos1[axis1], pos[axis2] - pos1[axis2]\r
+ if extent1 < extent2 then\r
+ local node1 = env:get_node(pos)\r
+ local meta1a = env:get_meta(pos):to_table()\r
+ local value1, value2 = pos[axis1], pos[axis2]\r
+ pos[axis1], pos[axis2] = pos1[axis1] + extent2, pos1[axis2] + extent1\r
+ local node2 = env:get_node(pos)\r
+ local meta2a = env:get_meta(pos):to_table()\r
+ env:add_node(pos, node1)\r
+ local meta1b = env:get_meta(pos)\r
+ meta1b:from_table(meta1a)\r
+ pos[axis1], pos[axis2] = pos1[axis1] + extent1, pos1[axis2] + extent2\r
+ env:add_node(pos, node2)\r
+ local meta2b = env:get_meta(pos)\r
+ meta2b:from_table(meta2a)\r
+ end\r
+ pos.z = pos.z + 1\r
+ end\r
+ pos.y = pos.y + 1\r
+ end\r
+ pos.x = pos.x + 1\r
+ end\r
+ return worldedit.volume(pos1, pos2)\r
+end\r
+\r
+--flips a region defined by the positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z"), returning the number of nodes flipped\r
+worldedit.flip = function(pos1, pos2, axis)\r
+ local pos1, pos2 = worldedit.sort_pos(pos1, pos2)\r
+\r
+ local pos = {x=pos1.x, y=0, z=0}\r
+ local start = pos1[axis] + pos2[axis]\r
+ pos2[axis] = pos1[axis] + math.floor((pos2[axis] - pos1[axis]) / 2)\r
+ local env = minetest.env\r
+ while pos.x <= pos2.x do\r
+ pos.y = pos1.y\r
+ while pos.y <= pos2.y do\r
+ pos.z = pos1.z\r
+ while pos.z <= pos2.z do\r
+ local node1 = env:get_node(pos)\r
+ local meta1a = env:get_meta(pos):to_table()\r
+ local value = pos[axis]\r
+ pos[axis] = start - value\r
+ local node2 = env:get_node(pos)\r
+ local meta2a = env:get_meta(pos):to_table()\r
+ env:add_node(pos, node1)\r
+ local meta1b = env:get_meta(pos)\r
+ meta1b:from_table(meta1a)\r
+ pos[axis] = value\r
+ env:add_node(pos, node2)\r
+ local meta2b = env:get_meta(pos)\r
+ meta2b:from_table(meta2a)\r
+ pos.z = pos.z + 1\r
+ end\r
+ pos.y = pos.y + 1\r
+ end\r
+ pos.x = pos.x + 1\r
+ end\r
+ return worldedit.volume(pos1, pos2)\r
+end\r
+\r
+--rotates a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise (if you are looking in the negative direction) around the `axis` (supporting 90 degree increments only), returning the number of nodes rotated\r
+worldedit.rotate = function(pos1, pos2, axis, angle)\r
+ local pos1, pos2 = worldedit.sort_pos(pos1, pos2)\r
+\r
+ if axis == 'x' then\r
+ axes = {'z', 'y'}\r
+ elseif axis == 'y' then\r
+ axes = {'x', 'z'}\r
+ else--if axis == 'z' then\r
+ axes = {'y', 'x'}\r
+ end\r
+ angle = angle % 360\r
+\r
+ local pos = {x=pos1.x, y=0, z=0}\r
+ local newpos = {x=0, y=0, z=0}\r
+ local offsetx, offsetz\r
+ local env = minetest.env\r
+\r
+ if angle == 90 then\r
+ worldedit.transpose(pos1, pos2, axes[1], axes[2])\r
+ worldedit.flip(pos1, pos2, axes[2])\r
+ elseif angle == 180 then\r
+ worldedit.flip(pos1, pos2, axes[1])\r
+ worldedit.flip(pos1, pos2, axes[2])\r
+ elseif angle == 270 then\r
+ worldedit.transpose(pos1, pos2, axes[1], axes[2])\r
+ worldedit.flip(pos1, pos2, axes[1])\r
+ else\r
+ return 0\r
+ end\r
+ return worldedit.volume(pos1, pos2)\r
+end\r
+\r
--digs a region defined by positions `pos1` and `pos2`, returning the number of nodes dug\r
worldedit.dig = function(pos1, pos2)\r
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)\r
count = count + 1\r
end\r
return count\r
-end
\ No newline at end of file
+end\r
+\r
+--loads the nodes represented by string `value` at position `originpos`, returning the number of nodes deserialized\r
+--based on [table.save/table.load](http://lua-users.org/wiki/SaveTableToFile) by ChillCode, available under the MIT license (GPL compatible)\r
+worldedit.deserialize_old = function(originpos, value)\r
+ --obtain the node table\r
+ local count = 0\r
+ local get_tables = loadstring(value)\r
+ if get_tables == nil then --error loading value\r
+ return count\r
+ end\r
+ local tables = get_tables()\r
+\r
+ --transform the node table into an array of nodes\r
+ for i = 1, #tables do\r
+ for j, v in pairs(tables[i]) do\r
+ if type(v) == "table" then\r
+ tables[i][j] = tables[v[1]]\r
+ end\r
+ end\r
+ end\r
+\r
+ --load the node array\r
+ local env = minetest.env\r
+ for i, v in ipairs(tables[1]) do\r
+ local pos = v[1]\r
+ pos.x, pos.y, pos.z = originpos.x + pos.x, originpos.y + pos.y, originpos.z + pos.z\r
+ env:add_node(pos, v[2])\r
+ count = count + 1\r
+ end\r
+ return count\r
+end\r