2012-10-14 03:45:50 +02:00
worldedit = worldedit or { }
2013-07-12 20:22:30 +02:00
local minetest = minetest --local copy of global
2012-10-14 03:45:50 +02:00
2013-06-23 05:05:34 +02:00
--adds a hollow sphere centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
2013-06-23 05:08:51 +02:00
worldedit.hollow_sphere = function ( pos , radius , nodename )
2013-07-12 20:22:30 +02:00
--set up voxel manipulator
local manip = minetest.get_voxel_manip ( )
2013-07-21 22:54:25 +02:00
local pos1 = { x = pos.x - radius , y = pos.y - radius , z = pos.z - radius }
local pos2 = { x = pos.x + radius , y = pos.y + radius , z = pos.z + radius }
local emerged_pos1 , emerged_pos2 = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = emerged_pos1 , MaxEdge = emerged_pos2 } )
2013-07-12 20:22:30 +02:00
2013-07-21 22:54:25 +02:00
--fill emerged area with ignore
local nodes = { }
local ignore = minetest.get_content_id ( " ignore " )
for i = 1 , worldedit.volume ( emerged_pos1 , emerged_pos2 ) do
nodes [ i ] = ignore
end
--fill selected area with node
2013-07-12 20:22:30 +02:00
local node_id = minetest.get_content_id ( nodename )
local min_radius , max_radius = radius * ( radius - 1 ) , radius * ( radius + 1 )
2013-07-28 03:34:42 +02:00
local offsetx , offsety , offsetz = pos.x - emerged_pos1.x , pos.y - emerged_pos1.y , pos.z - emerged_pos1.z
local zstride , ystride = area.zstride , area.ystride
2013-06-25 00:21:48 +02:00
local count = 0
2013-07-28 03:34:42 +02:00
for z = - radius , radius do
2013-07-28 23:08:12 +02:00
local newz = ( z + offsetz ) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
2013-07-28 03:34:42 +02:00
for y = - radius , radius do
local newy = newz + ( y + offsety ) * ystride
for x = - radius , radius do
local squared = x * x + y * y + z * z
if squared >= min_radius and squared <= max_radius then --position is on surface of sphere
2013-07-28 23:08:12 +02:00
local i = newy + ( x + offsetx )
2013-07-28 03:34:42 +02:00
nodes [ i ] = node_id
count = count + 1
end
2012-10-14 03:45:50 +02:00
end
end
end
2013-07-12 20:22:30 +02:00
--update map nodes
manip : set_data ( nodes )
manip : write_to_map ( )
manip : update_map ( )
2013-06-25 00:21:48 +02:00
return count
2012-10-14 03:45:50 +02:00
end
2013-06-23 05:05:34 +02:00
--adds a sphere centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
2013-06-23 05:08:51 +02:00
worldedit.sphere = function ( pos , radius , nodename )
2013-07-12 20:22:30 +02:00
--set up voxel manipulator
local manip = minetest.get_voxel_manip ( )
2013-07-21 22:54:25 +02:00
local pos1 = { x = pos.x - radius , y = pos.y - radius , z = pos.z - radius }
local pos2 = { x = pos.x + radius , y = pos.y + radius , z = pos.z + radius }
local emerged_pos1 , emerged_pos2 = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = emerged_pos1 , MaxEdge = emerged_pos2 } )
2013-07-12 20:22:30 +02:00
2013-07-21 22:54:25 +02:00
--fill emerged area with ignore
local nodes = { }
local ignore = minetest.get_content_id ( " ignore " )
for i = 1 , worldedit.volume ( emerged_pos1 , emerged_pos2 ) do
nodes [ i ] = ignore
end
--fill selected area with node
2013-07-12 20:22:30 +02:00
local node_id = minetest.get_content_id ( nodename )
local max_radius = radius * ( radius + 1 )
2013-07-28 03:34:42 +02:00
local offsetx , offsety , offsetz = pos.x - emerged_pos1.x , pos.y - emerged_pos1.y , pos.z - emerged_pos1.z
local zstride , ystride = area.zstride , area.ystride
2013-06-25 00:21:48 +02:00
local count = 0
2013-07-28 03:34:42 +02:00
for z = - radius , radius do
2013-07-28 23:08:12 +02:00
local newz = ( z + offsetz ) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
2013-07-28 03:34:42 +02:00
for y = - radius , radius do
local newy = newz + ( y + offsety ) * ystride
for x = - radius , radius do
if x * x + y * y + z * z <= max_radius then --position is inside sphere
2013-07-28 23:08:12 +02:00
local i = newy + ( x + offsetx )
2013-07-28 03:34:42 +02:00
nodes [ i ] = node_id
count = count + 1
end
2013-04-28 00:28:20 +02:00
end
end
end
2013-07-12 20:22:30 +02:00
--update map nodes
manip : set_data ( nodes )
manip : write_to_map ( )
manip : update_map ( )
2013-06-25 00:21:48 +02:00
return count
2013-04-28 00:28:20 +02:00
end
2013-06-23 05:05:34 +02:00
--adds a hollow dome centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
2013-07-21 22:54:25 +02:00
worldedit.hollow_dome = function ( pos , radius , nodename )
2013-07-12 20:22:30 +02:00
--set up voxel manipulator
local manip = minetest.get_voxel_manip ( )
2013-07-21 22:54:25 +02:00
local pos1 = { x = pos.x - radius , y = pos.y , z = pos.z - radius }
local pos2 = { x = pos.x + radius , y = pos.y + radius , z = pos.z + radius }
local emerged_pos1 , emerged_pos2 = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = emerged_pos1 , MaxEdge = emerged_pos2 } )
2013-07-12 20:22:30 +02:00
2013-07-21 22:54:25 +02:00
--fill emerged area with ignore
local nodes = { }
local ignore = minetest.get_content_id ( " ignore " )
for i = 1 , worldedit.volume ( emerged_pos1 , emerged_pos2 ) do
nodes [ i ] = ignore
end
2013-07-29 18:43:24 +02:00
local miny , maxy = 0 , radius
if radius < 0 then
radius = - radius
miny , maxy = - radius , 0
end
2013-07-21 22:54:25 +02:00
--fill selected area with node
2013-07-12 20:22:30 +02:00
local node_id = minetest.get_content_id ( nodename )
local min_radius , max_radius = radius * ( radius - 1 ) , radius * ( radius + 1 )
2013-07-28 03:34:42 +02:00
local offsetx , offsety , offsetz = pos.x - emerged_pos1.x , pos.y - emerged_pos1.y , pos.z - emerged_pos1.z
local zstride , ystride = area.zstride , area.ystride
2013-06-25 00:21:48 +02:00
local count = 0
2013-07-28 03:34:42 +02:00
for z = - radius , radius do
2013-07-28 23:08:12 +02:00
local newz = ( z + offsetz ) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
2013-07-29 18:43:24 +02:00
for y = miny , maxy do
2013-07-28 03:34:42 +02:00
local newy = newz + ( y + offsety ) * ystride
for x = - radius , radius do
local squared = x * x + y * y + z * z
if squared >= min_radius and squared <= max_radius then --position is on surface of sphere
2013-07-28 23:08:12 +02:00
local i = newy + ( x + offsetx )
2013-07-28 03:34:42 +02:00
nodes [ i ] = node_id
count = count + 1
end
2013-04-28 00:28:20 +02:00
end
end
end
2013-07-12 20:22:30 +02:00
--update map nodes
manip : set_data ( nodes )
manip : write_to_map ( )
manip : update_map ( )
2013-06-25 00:21:48 +02:00
return count
2013-04-28 00:28:20 +02:00
end
2013-06-23 05:05:34 +02:00
--adds a dome centered at `pos` with radius `radius`, composed of `nodename`, returning the number of nodes added
2013-07-29 00:15:46 +02:00
worldedit.dome = function ( pos , radius , nodename )
2013-07-12 20:22:30 +02:00
--set up voxel manipulator
local manip = minetest.get_voxel_manip ( )
2013-07-21 22:54:25 +02:00
local pos1 = { x = pos.x - radius , y = pos.y , z = pos.z - radius }
local pos2 = { x = pos.x + radius , y = pos.y + radius , z = pos.z + radius }
local emerged_pos1 , emerged_pos2 = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = emerged_pos1 , MaxEdge = emerged_pos2 } )
2013-07-12 20:22:30 +02:00
2013-07-21 22:54:25 +02:00
--fill emerged area with ignore
local nodes = { }
local ignore = minetest.get_content_id ( " ignore " )
for i = 1 , worldedit.volume ( emerged_pos1 , emerged_pos2 ) do
nodes [ i ] = ignore
end
2013-07-29 18:43:24 +02:00
local miny , maxy = 0 , radius
if radius < 0 then
radius = - radius
miny , maxy = - radius , 0
end
2013-07-21 22:54:25 +02:00
--fill selected area with node
2013-07-12 20:22:30 +02:00
local node_id = minetest.get_content_id ( nodename )
local max_radius = radius * ( radius + 1 )
2013-07-28 03:34:42 +02:00
local offsetx , offsety , offsetz = pos.x - emerged_pos1.x , pos.y - emerged_pos1.y , pos.z - emerged_pos1.z
local zstride , ystride = area.zstride , area.ystride
2013-06-25 00:21:48 +02:00
local count = 0
2013-07-28 03:34:42 +02:00
for z = - radius , radius do
2013-07-28 23:08:12 +02:00
local newz = ( z + offsetz ) * zstride + 1 --offset contributed by z plus 1 to make it 1-indexed
2013-07-29 18:43:24 +02:00
for y = miny , maxy do
2013-07-28 03:34:42 +02:00
local newy = newz + ( y + offsety ) * ystride
for x = - radius , radius do
if x * x + y * y + z * z <= max_radius then --position is inside sphere
2013-07-28 23:08:12 +02:00
local i = newy + ( x + offsetx )
2013-07-28 03:34:42 +02:00
nodes [ i ] = node_id
count = count + 1
end
2012-10-14 03:45:50 +02:00
end
end
end
2013-07-12 20:22:30 +02:00
--update map nodes
manip : set_data ( nodes )
manip : write_to_map ( )
manip : update_map ( )
2013-06-25 00:21:48 +02:00
return count
2012-10-14 03:45:50 +02:00
end
--adds a hollow cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`, returning the number of nodes added
2013-12-15 22:33:31 +01:00
worldedit.hollow_cylinder = function ( pos , axis , length , radius , nodename )
2012-10-14 03:45:50 +02:00
local other1 , other2
if axis == " x " then
other1 , other2 = " y " , " z "
elseif axis == " y " then
other1 , other2 = " x " , " z "
else --axis == "z"
other1 , other2 = " x " , " y "
end
2013-07-12 20:22:30 +02:00
--handle negative lengths
2012-10-14 03:45:50 +02:00
local currentpos = { x = pos.x , y = pos.y , z = pos.z }
if length < 0 then
length = - length
2013-06-23 18:46:59 +02:00
currentpos [ axis ] = currentpos [ axis ] - length
2012-10-14 03:45:50 +02:00
end
2013-06-23 18:46:59 +02:00
2013-12-15 22:33:31 +01:00
--set up voxel manipulator
2013-07-31 06:02:37 +02:00
local manip = minetest.get_voxel_manip ( )
local pos1 = {
[ axis ] = currentpos [ axis ] ,
[ other1 ] = currentpos [ other1 ] - radius ,
[ other2 ] = currentpos [ other2 ] - radius
}
local pos2 = {
[ axis ] = currentpos [ axis ] + length - 1 ,
[ other1 ] = currentpos [ other1 ] + radius ,
[ other2 ] = currentpos [ other2 ] + radius
}
2013-12-15 22:33:31 +01:00
local emerged_pos1 , emerged_pos2 = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = emerged_pos1 , MaxEdge = emerged_pos2 } )
2013-07-31 06:02:37 +02:00
2013-12-15 22:33:31 +01:00
--fill emerged area with ignore
2013-06-23 18:46:59 +02:00
local nodes = { }
2013-12-15 22:33:31 +01:00
local ignore = minetest.get_content_id ( " ignore " )
for i = 1 , worldedit.volume ( emerged_pos1 , emerged_pos2 ) do
nodes [ i ] = ignore
2013-06-23 18:46:59 +02:00
end
2012-10-14 03:45:50 +02:00
2013-12-15 22:33:31 +01:00
--fill selected area with node
local node_id = minetest.get_content_id ( nodename )
local min_radius , max_radius = radius * ( radius - 1 ) , radius * ( radius + 1 )
local stride = { x = 1 , y = area.ystride , z = area.zstride }
local offset = { x = currentpos.x - emerged_pos1.x , y = currentpos.y - emerged_pos1.y , z = currentpos.z - emerged_pos1.z }
local min_slice , max_slice = offset [ axis ] , offset [ axis ] + length - 1
2013-06-23 18:46:59 +02:00
local count = 0
2013-12-15 22:33:31 +01:00
for index2 = - radius , radius do
local newindex2 = ( index2 + offset [ other1 ] ) * stride [ other1 ] + 1 --offset contributed by other axis 1 plus 1 to make it 1-indexed
for index3 = - radius , radius do
local newindex3 = newindex2 + ( index3 + offset [ other2 ] ) * stride [ other2 ]
local squared = index2 * index2 + index3 * index3
if squared >= min_radius and squared <= max_radius then --position is on surface of cylinder
for index1 = min_slice , max_slice do --add column along axis
local i = newindex3 + index1 * stride [ axis ]
nodes [ i ] = node_id
end
count = count + length
end
2012-10-14 03:45:50 +02:00
end
end
2013-12-15 22:33:31 +01:00
--update map nodes
manip : set_data ( nodes )
manip : write_to_map ( )
manip : update_map ( )
2012-10-14 03:45:50 +02:00
return count
end
--adds a cylinder at `pos` along the `axis` axis ("x" or "y" or "z") with length `length` and radius `radius`, composed of `nodename`, returning the number of nodes added
2013-07-29 18:43:24 +02:00
worldedit.cylinder = function ( pos , axis , length , radius , nodename )
2012-10-14 03:45:50 +02:00
local other1 , other2
if axis == " x " then
other1 , other2 = " y " , " z "
elseif axis == " y " then
other1 , other2 = " x " , " z "
else --axis == "z"
other1 , other2 = " x " , " y "
end
2013-07-12 20:22:30 +02:00
--handle negative lengths
2012-10-14 03:45:50 +02:00
local currentpos = { x = pos.x , y = pos.y , z = pos.z }
if length < 0 then
length = - length
2013-07-12 20:22:30 +02:00
currentpos [ axis ] = currentpos [ axis ] - length
2012-10-14 03:45:50 +02:00
end
2013-07-12 20:22:30 +02:00
2013-07-28 03:34:42 +02:00
--set up voxel manipulator
local manip = minetest.get_voxel_manip ( )
local pos1 = {
[ axis ] = currentpos [ axis ] ,
[ other1 ] = currentpos [ other1 ] - radius ,
[ other2 ] = currentpos [ other2 ] - radius
}
local pos2 = {
[ axis ] = currentpos [ axis ] + length - 1 ,
[ other1 ] = currentpos [ other1 ] + radius ,
[ other2 ] = currentpos [ other2 ] + radius
}
local emerged_pos1 , emerged_pos2 = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = emerged_pos1 , MaxEdge = emerged_pos2 } )
--fill emerged area with ignore
2013-07-12 20:22:30 +02:00
local nodes = { }
2013-07-28 03:34:42 +02:00
local ignore = minetest.get_content_id ( " ignore " )
for i = 1 , worldedit.volume ( emerged_pos1 , emerged_pos2 ) do
nodes [ i ] = ignore
2013-07-12 20:22:30 +02:00
end
2012-10-14 03:45:50 +02:00
2013-07-28 03:34:42 +02:00
--fill selected area with node
local node_id = minetest.get_content_id ( nodename )
local max_radius = radius * ( radius + 1 )
local stride = { x = 1 , y = area.ystride , z = area.zstride }
local offset = { x = currentpos.x - emerged_pos1.x , y = currentpos.y - emerged_pos1.y , z = currentpos.z - emerged_pos1.z }
local min_slice , max_slice = offset [ axis ] , offset [ axis ] + length - 1
2013-07-12 20:22:30 +02:00
local count = 0
2013-07-31 06:02:37 +02:00
for index2 = - radius , radius do
local newindex2 = ( index2 + offset [ other1 ] ) * stride [ other1 ] + 1 --offset contributed by other axis 1 plus 1 to make it 1-indexed
for index3 = - radius , radius do
local newindex3 = newindex2 + ( index3 + offset [ other2 ] ) * stride [ other2 ]
2013-12-15 22:33:31 +01:00
if index2 * index2 + index3 * index3 <= max_radius then --position is within cylinder
2013-07-31 06:02:37 +02:00
for index1 = min_slice , max_slice do --add column along axis
2013-08-01 04:15:08 +02:00
local i = newindex3 + index1 * stride [ axis ]
2013-07-28 03:34:42 +02:00
nodes [ i ] = node_id
end
count = count + length
end
2013-07-12 20:22:30 +02:00
end
2013-07-28 03:34:42 +02:00
end
2012-10-14 03:45:50 +02:00
2013-07-28 03:34:42 +02:00
--update map nodes
manip : set_data ( nodes )
manip : write_to_map ( )
manip : update_map ( )
2013-07-12 20:22:30 +02:00
2012-10-14 03:45:50 +02:00
return count
end
2013-06-23 05:05:34 +02:00
--adds a pyramid centered at `pos` with height `height`, composed of `nodename`, returning the number of nodes added
2013-07-29 18:43:24 +02:00
worldedit.pyramid = function ( pos , axis , height , nodename )
2013-07-31 06:02:37 +02:00
local other1 , other2
if axis == " x " then
other1 , other2 = " y " , " z "
elseif axis == " y " then
other1 , other2 = " x " , " z "
else --axis == "z"
other1 , other2 = " x " , " y "
end
local pos1 = { x = pos.x - height , y = pos.y - height , z = pos.z - height }
2013-07-28 23:08:12 +02:00
local pos2 = { x = pos.x + height , y = pos.y + height , z = pos.z + height }
2013-07-28 03:34:42 +02:00
2013-07-31 06:02:37 +02:00
--handle inverted pyramids
local startaxis , endaxis , step
if height > 0 then
height = height - 1
step = 1
pos1 [ axis ] = pos [ axis ] --upper half of box
else
2013-08-01 04:15:08 +02:00
height = height + 1
2013-07-31 06:02:37 +02:00
step = - 1
2013-08-01 04:15:08 +02:00
pos2 [ axis ] = pos [ axis ] --lower half of box
2013-07-31 06:02:37 +02:00
end
2013-07-28 03:34:42 +02:00
--set up voxel manipulator
local manip = minetest.get_voxel_manip ( )
local emerged_pos1 , emerged_pos2 = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = emerged_pos1 , MaxEdge = emerged_pos2 } )
--fill emerged area with ignore
local nodes = { }
local ignore = minetest.get_content_id ( " ignore " )
for i = 1 , worldedit.volume ( emerged_pos1 , emerged_pos2 ) do
nodes [ i ] = ignore
end
--fill selected area with node
local node_id = minetest.get_content_id ( nodename )
2013-07-31 06:02:37 +02:00
local stride = { x = 1 , y = area.ystride , z = area.zstride }
2013-08-01 04:15:08 +02:00
local offset = { x = pos.x - emerged_pos1.x , y = pos.y - emerged_pos1.y , z = pos.z - emerged_pos1.z }
local size = height * step
2013-07-28 23:08:12 +02:00
local count = 0
2013-08-01 04:15:08 +02:00
for index1 = 0 , height , step do --go through each level of the pyramid
2013-07-31 06:02:37 +02:00
local newindex1 = ( index1 + offset [ axis ] ) * stride [ axis ] + 1 --offset contributed by axis plus 1 to make it 1-indexed
2013-08-01 04:15:08 +02:00
for index2 = - size , size do
2013-07-31 06:02:37 +02:00
local newindex2 = newindex1 + ( index2 + offset [ other1 ] ) * stride [ other1 ]
2013-08-01 04:15:08 +02:00
for index3 = - size , size do
2013-07-31 06:02:37 +02:00
local i = newindex2 + ( index3 + offset [ other2 ] ) * stride [ other2 ]
2013-07-28 23:08:12 +02:00
nodes [ i ] = node_id
end
end
2013-08-01 04:15:08 +02:00
count = count + ( size * 2 + 1 ) ^ 2
size = size - 1
2013-07-28 03:34:42 +02:00
end
--update map nodes
manip : set_data ( nodes )
manip : write_to_map ( )
manip : update_map ( )
2012-10-14 03:45:50 +02:00
return count
end
2013-08-01 04:15:08 +02:00
--adds a spiral centered at `pos` with side length `length`, height `height`, space between walls `spacer`, composed of `nodename`, returning the number of nodes added
worldedit.spiral = function ( pos , length , height , spacer , nodename )
local extent = math.ceil ( length / 2 )
local pos1 = { x = pos.x - extent , y = pos.y , z = pos.z - extent }
local pos2 = { x = pos.x + extent , y = pos.y + height , z = pos.z + extent }
--set up voxel manipulator
local manip = minetest.get_voxel_manip ( )
local emerged_pos1 , emerged_pos2 = manip : read_from_map ( pos1 , pos2 )
local area = VoxelArea : new ( { MinEdge = emerged_pos1 , MaxEdge = emerged_pos2 } )
--fill emerged area with ignore
local nodes = { }
local ignore = minetest.get_content_id ( " ignore " )
for i = 1 , worldedit.volume ( emerged_pos1 , emerged_pos2 ) do
nodes [ i ] = ignore
2012-10-14 03:45:50 +02:00
end
2013-08-01 04:15:08 +02:00
--
local node_id = minetest.get_content_id ( nodename )
local stride = { x = 1 , y = area.ystride , z = area.zstride }
local offsetx , offsety , offsetz = pos.x - emerged_pos1.x , pos.y - emerged_pos1.y , pos.z - emerged_pos1.z
local i = offsetz * stride.z + offsety * stride.y + offsetx + 1
--add first column
local column = i
for y = 1 , height do
nodes [ column ] = node_id
column = column + stride.y
end
--add spiral segments
local axis , other = " x " , " z "
local sign = 1
local count = height
for segment = 1 , length / spacer - 1 do --go through each segment except the last
for index = 1 , segment * spacer do --fill segment
i = i + stride [ axis ] * sign
local column = i
for y = 1 , height do --add column
nodes [ column ] = node_id
column = column + stride.y
2012-10-14 03:45:50 +02:00
end
2013-08-01 04:15:08 +02:00
count = count + height
end
axis , other = other , axis --swap axes
if segment % 2 == 1 then --change sign every other turn
sign = - sign
2012-10-14 03:45:50 +02:00
end
end
2013-08-01 04:15:08 +02:00
--add shorter final segment
for index = 1 , ( math.floor ( length / spacer ) - 2 ) * spacer do
i = i + stride [ axis ] * sign
local column = i
for y = 1 , height do --add column
nodes [ column ] = node_id
column = column + stride.y
2012-10-14 03:45:50 +02:00
end
2013-08-01 04:15:08 +02:00
count = count + height
2012-10-14 03:45:50 +02:00
end
2013-08-01 04:15:08 +02:00
print ( minetest.serialize ( nodes ) )
--update map nodes
manip : set_data ( nodes )
manip : write_to_map ( )
manip : update_map ( )
2012-10-14 03:45:50 +02:00
return count
2013-08-01 04:15:08 +02:00
end