1 worldedit = worldedit or {}
\r
2 local minetest = minetest --local copy of global
\r
4 --modifies positions `pos1` and `pos2` so that each component of `pos1` is less than or equal to its corresponding conent of `pos2`, returning two new positions
\r
5 worldedit.sort_pos = function(pos1, pos2)
\r
6 pos1 = {x=pos1.x, y=pos1.y, z=pos1.z}
\r
7 pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
\r
8 if pos1.x > pos2.x then
\r
9 pos2.x, pos1.x = pos1.x, pos2.x
\r
11 if pos1.y > pos2.y then
\r
12 pos2.y, pos1.y = pos1.y, pos2.y
\r
14 if pos1.z > pos2.z then
\r
15 pos2.z, pos1.z = pos1.z, pos2.z
\r
20 --determines the volume of the region defined by positions `pos1` and `pos2`, returning the volume
\r
21 worldedit.volume = function(pos1, pos2)
\r
22 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
23 return (pos2.x - pos1.x + 1) * (pos2.y - pos1.y + 1) * (pos2.z - pos1.z + 1)
\r
26 --sets a region defined by positions `pos1` and `pos2` to `nodename`, returning the number of nodes filled
\r
27 worldedit.set = function(pos1, pos2, nodenames)
\r
29 if type(nodenames) == 'string' then
\r
35 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
37 --set up voxel manipulator
\r
38 local manip = minetest.get_voxel_manip()
\r
39 local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
\r
40 local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
\r
42 --fill emerged area with ignore
\r
44 local ignore = minetest.get_content_id("ignore")
\r
45 for i = 1, worldedit.volume(emerged_pos1, emerged_pos2) do
\r
49 --fill selected area with node
\r
51 for i,v in ipairs(nodenames) do
\r
52 node_ids[i] = minetest.get_content_id(nodenames[i])
\r
54 if oneNode then --only one type of node
\r
56 for i in area:iterp(pos1, pos2) do nodes[i] = id end --fill area with node
\r
57 else --several types of nodes specified
\r
58 local id_count, rand = #node_ids, math.random
\r
59 for i in area:iterp(pos1, pos2) do nodes[i] = node_ids[rand(id_count)] end --fill randomly with all types of specified nodes
\r
63 manip:set_data(nodes)
\r
64 manip:write_to_map()
\r
67 return worldedit.volume(pos1, pos2)
\r
70 --replaces all instances of `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`, returning the number of nodes replaced
\r
71 worldedit.replace = function(pos1, pos2, searchnode, replacenode)
\r
72 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
74 --set up voxel manipulator
\r
75 local manip = minetest.get_voxel_manip()
\r
76 local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
\r
77 local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
\r
79 local nodes = manip:get_data()
\r
80 local searchnode_id = minetest.get_content_id(searchnode)
\r
81 local replacenode_id = minetest.get_content_id(replacenode)
\r
83 for i in area:iterp(pos1, pos2) do --replace searchnode with replacenode
\r
84 if nodes[i] == searchnode_id then
\r
85 nodes[i] = replacenode_id
\r
91 manip:set_data(nodes)
\r
92 manip:write_to_map()
\r
98 --replaces all nodes other than `searchnode` with `replacenode` in a region defined by positions `pos1` and `pos2`, returning the number of nodes replaced
\r
99 worldedit.replaceinverse = function(pos1, pos2, searchnode, replacenode)
\r
100 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
102 --set up voxel manipulator
\r
103 local manip = minetest.get_voxel_manip()
\r
104 local emerged_pos1, emerged_pos2 = manip:read_from_map(pos1, pos2)
\r
105 local area = VoxelArea:new({MinEdge=emerged_pos1, MaxEdge=emerged_pos2})
\r
107 local nodes = manip:get_data()
\r
108 local searchnode_id = minetest.get_content_id(searchnode)
\r
109 local replacenode_id = minetest.get_content_id(replacenode)
\r
111 for i in area:iterp(pos1, pos2) do --replace anything that is not searchnode with replacenode
\r
112 if nodes[i] ~= searchnode_id then
\r
113 nodes[i] = replacenode_id
\r
119 manip:set_data(nodes)
\r
120 manip:write_to_map()
\r
126 --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
127 worldedit.copy = function(pos1, pos2, axis, amount) --wip: replace the old version below
\r
128 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
130 if amount == 0 then
\r
134 local other1, other2
\r
135 if axis == "x" then
\r
136 other1, other2 = "y", "z"
\r
137 elseif axis == "y" then
\r
138 other1, other2 = "x", "z"
\r
140 other1, other2 = "x", "y"
\r
143 --make area stay loaded
\r
144 local manip = minetest.get_voxel_manip()
\r
145 manip:read_from_map(pos1, pos2)
\r
147 --prepare slice along axis
\r
150 [other1]=pos2[other1] - pos1[other1] + 1,
\r
151 [other2]=pos2[other2] - pos1[other2] + 1,
\r
154 local schematic = {size=extent, data=nodes}
\r
156 local currentpos = {x=pos1.x, y=pos1.y, z=pos1.z}
\r
157 local stride = {x=1, y=extent.x, z=extent.x * extent.y}
\r
158 local get_node = minetest.get_node
\r
159 for index1 = 1, extent[axis] do --go through each slice
\r
160 --copy slice into schematic
\r
161 local newindex1 = (index1 + offset[axis]) * stride[axis] + 1 --offset contributed by axis plus 1 to make it 1-indexed
\r
162 for index2 = 1, extent[other1] do
\r
163 local newindex2 = newindex1 + (index2 + offset[other1]) * stride[other1]
\r
164 for index3 = 1, extent[other2] do
\r
165 local i = newindex2 + (index3 + offset[other2]) * stride[other2]
\r
166 local node = get_node(pos)
\r
167 node.param1 = 255 --node will always appear
\r
172 --copy schematic to target
\r
173 currentpos[axis] = currentpos[axis] + amount
\r
174 place_schematic(currentpos, schematic)
\r
178 currentpos[axis] = currentpos[axis] + 1
\r
180 return worldedit.volume(pos1, pos2)
\r
183 worldedit.copy2 = function(pos1, pos2, direction, volume)
\r
184 -- the overlap shouldn't matter as long as we
\r
185 -- 1) start at the furthest separated corner
\r
186 -- 2) complete an edge before moving inward, either edge works
\r
187 -- 3) complete a face before moving inward, similarly
\r
190 -- 1) find the furthest destination in the direction, of each axis
\r
191 -- 2) call those the furthest separated corner
\r
192 -- 3) make sure to iterate inward from there
\r
193 -- 4) nested loop to make sure complete edge, complete face, then complete cube.
\r
195 local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
\r
196 local somemeta = get_meta(pos1) -- hax lol
\r
197 local to_table = somemeta.to_table
\r
198 local from_table = somemeta.from_table
\r
201 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
202 local manip = minetest.get_voxel_manip()
\r
203 manip:read_from_map(pos1, pos2)
\r
205 local sx, sy, sz -- direction sign
\r
206 local ix, iy, iz -- initial destination
\r
207 local ex, ey, ez -- final destination
\r
208 local originalx, originaly, originalz -- source
\r
209 -- vim -> :'<,'>s/\<\([ioes]\?\)x\>/\1y/g
\r
210 if direction.x > 0 then
\r
212 ix = originalx + direction.x
\r
213 ex = pos1.x + direction.x
\r
215 elseif direction.x < 0 then
\r
217 ix = originalx + direction.x
\r
218 ex = pos2.x + direction.x
\r
222 ix = originalx -- whatever
\r
227 if direction.y > 0 then
\r
229 iy = originaly + direction.y
\r
230 ey = pos1.y + direction.y
\r
232 elseif direction.y < 0 then
\r
234 iy = originaly + direction.y
\r
235 ey = pos2.y + direction.y
\r
239 iy = originaly -- whatever
\r
244 if direction.z > 0 then
\r
246 iz = originalz + direction.z
\r
247 ez = pos1.z + direction.z
\r
249 elseif direction.z < 0 then
\r
251 iz = originalz + direction.z
\r
252 ez = pos2.z + direction.z
\r
256 iz = originalz -- whatever
\r
260 -- print('copy',originalx,ix,ex,sx,originaly,iy,ey,sy,originalz,iz,ez,sz)
\r
265 for x = ix, ex, sx do
\r
267 for y = iy, ey, sy do
\r
269 for z = iz, ez, sz do
\r
270 -- reusing pos1/pos2 as source/dest here
\r
271 pos1.x, pos1.y, pos1.z = ox, oy, oz
\r
272 pos2.x, pos2.y, pos2.z = x, y, z
\r
273 local node = get_node(pos1)
\r
274 local meta = to_table(get_meta(pos1)) --get meta of current node
\r
275 add_node(pos2,node)
\r
276 from_table(get_meta(pos2),meta)
\r
285 --duplicates the region defined by positions `pos1` and `pos2` `amount` times with offset vector `direction`, returning the number of nodes stacked
\r
286 worldedit.stack2 = function(pos1, pos2, direction, amount, finished)
\r
288 local translated = {x=0,y=0,z=0}
\r
289 local function nextone()
\r
290 if i <= amount then
\r
292 translated.x = translated.x + direction.x
\r
293 translated.y = translated.y + direction.y
\r
294 translated.z = translated.z + direction.z
\r
295 worldedit.copy2(pos1, pos2, translated, volume)
\r
296 minetest.after(0, nextone)
\r
304 return worldedit.volume(pos1, pos2) * amount
\r
307 --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
308 worldedit.copy = function(pos1, pos2, axis, amount)
\r
309 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
311 --make area stay loaded
\r
312 local manip = minetest.get_voxel_manip()
\r
313 manip:read_from_map(pos1, pos2)
\r
315 local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
\r
317 local pos = {x=pos1.x, y=0, z=0}
\r
318 while pos.x <= pos2.x do
\r
320 while pos.y <= pos2.y do
\r
322 while pos.z <= pos2.z do
\r
323 local node = get_node(pos) --obtain current node
\r
324 local meta = get_meta(pos):to_table() --get meta of current node
\r
325 local value = pos[axis] --store current position
\r
326 pos[axis] = value + amount --move along axis
\r
327 add_node(pos, node) --copy node to new position
\r
328 get_meta(pos):from_table(meta) --set metadata of new node
\r
329 pos[axis] = value --restore old position
\r
337 local pos = {x=pos2.x, y=0, z=0}
\r
338 while pos.x >= pos1.x do
\r
340 while pos.y >= pos1.y do
\r
342 while pos.z >= pos1.z do
\r
343 local node = get_node(pos) --obtain current node
\r
344 local meta = get_meta(pos):to_table() --get meta of current node
\r
345 local value = pos[axis] --store current position
\r
346 pos[axis] = value + amount --move along axis
\r
347 add_node(pos, node) --copy node to new position
\r
348 get_meta(pos):from_table(meta) --set metadata of new node
\r
349 pos[axis] = value --restore old position
\r
357 return worldedit.volume(pos1, pos2)
\r
360 --moves 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 moved
\r
361 worldedit.move = function(pos1, pos2, axis, amount)
\r
362 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
364 --make area stay loaded
\r
365 local manip = minetest.get_voxel_manip()
\r
366 manip:read_from_map(pos1, pos2)
\r
368 --wip: move slice by slice using schematic method in the move axis and transfer metadata in separate loop (and if the amount is greater than the length in the axis, copy whole thing at a time and erase original after, using schematic method)
\r
369 local get_node, get_meta, add_node, remove_node = minetest.get_node, minetest.get_meta, minetest.add_node, minetest.remove_node
\r
371 local pos = {x=pos1.x, y=0, z=0}
\r
372 while pos.x <= pos2.x do
\r
374 while pos.y <= pos2.y do
\r
376 while pos.z <= pos2.z do
\r
377 local node = get_node(pos) --obtain current node
\r
378 local meta = get_meta(pos):to_table() --get metadata of current node
\r
380 local value = pos[axis] --store current position
\r
381 pos[axis] = value + amount --move along axis
\r
382 add_node(pos, node) --move node to new position
\r
383 get_meta(pos):from_table(meta) --set metadata of new node
\r
384 pos[axis] = value --restore old position
\r
392 local pos = {x=pos2.x, y=0, z=0}
\r
393 while pos.x >= pos1.x do
\r
395 while pos.y >= pos1.y do
\r
397 while pos.z >= pos1.z do
\r
398 local node = get_node(pos) --obtain current node
\r
399 local meta = get_meta(pos):to_table() --get metadata of current node
\r
401 local value = pos[axis] --store current position
\r
402 pos[axis] = value + amount --move along axis
\r
403 add_node(pos, node) --move node to new position
\r
404 get_meta(pos):from_table(meta) --set metadata of new node
\r
405 pos[axis] = value --restore old position
\r
413 return worldedit.volume(pos1, pos2)
\r
416 --duplicates the region defined by positions `pos1` and `pos2` along the `axis` axis ("x" or "y" or "z") `count` times, returning the number of nodes stacked
\r
417 worldedit.stack = function(pos1, pos2, axis, count)
\r
418 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
419 local length = pos2[axis] - pos1[axis] + 1
\r
425 local copy = worldedit.copy
\r
427 function nextone()
\r
430 amount = amount + length
\r
431 copy(pos1, pos2, axis, amount)
\r
432 minetest.after(0,nextone)
\r
436 return worldedit.volume(pos1, pos2) * count
\r
439 --stretches the region defined by positions `pos1` and `pos2` by an factor of positive integers `stretchx`, `stretchy`. and `stretchz` along the X, Y, and Z axes, respectively, with `pos1` as the origin, returning the number of nodes scaled, the new scaled position 1, and the new scaled position 2
\r
440 worldedit.stretch = function(pos1, pos2, stretchx, stretchy, stretchz) --wip: test this
\r
441 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
443 --prepare schematic of large node
\r
444 local get_node, get_meta, place_schematic = minetest.get_node, minetest.get_meta, minetest.place_schematic
\r
445 local placeholder_node = {name="", param1=255, param2=0}
\r
447 for i = 1, stretchx * stretchy * stretchz do
\r
448 nodes[i] = placeholder_node
\r
450 local schematic = {size={x=stretchx, y=stretchy, z=stretchz}, data=nodes}
\r
452 local sizex, sizey, sizez = stretchx - 1, stretchy - 1, stretchz - 1
\r
454 --make area stay loaded
\r
455 local manip = minetest.get_voxel_manip()
\r
457 x=pos1.x + (pos2.x - pos1.x) * stretchx + sizex,
\r
458 y=pos1.y + (pos2.y - pos1.y) * stretchy + sizey,
\r
459 z=pos1.z + (pos2.z - pos1.z) * stretchz + sizez,
\r
461 manip:read_from_map(pos1, new_pos2)
\r
463 local pos = {x=pos2.x, y=0, z=0}
\r
464 local bigpos = {x=0, y=0, z=0}
\r
465 while pos.x >= pos1.x do
\r
467 while pos.y >= pos1.y do
\r
469 while pos.z >= pos1.z do
\r
470 local node = get_node(pos) --obtain current node
\r
471 local meta = get_meta(pos):to_table() --get meta of current node
\r
473 --calculate far corner of the big node
\r
474 local posx = pos1.x + (pos.x - pos1.x) * stretchx
\r
475 local posy = pos1.y + (pos.y - pos1.y) * stretchy
\r
476 local posz = pos1.z + (pos.z - pos1.z) * stretchz
\r
478 --create large node
\r
479 placeholder_node.name = node.name
\r
480 placeholder_node.param2 = node.param2
\r
481 bigpos.x, bigpos.y, bigpos.z = posx, posy, posz
\r
482 place_schematic(bigpos, schematic)
\r
484 --fill in large node meta
\r
485 if next(meta.fields) ~= nil or next(meta.inventory) ~= nil then --node has meta fields
\r
486 for x = 0, sizex do
\r
487 for y = 0, sizey do
\r
488 for z = 0, sizez do
\r
489 bigpos.x, bigpos.y, bigpos.z = posx + x, posy + y, posz + z
\r
490 get_meta(bigpos):from_table(meta) --set metadata of new node
\r
501 return worldedit.volume(pos1, pos2) * stretchx * stretchy * stretchz, pos1, new_pos2
\r
504 --transposes a region defined by the positions `pos1` and `pos2` between the `axis1` and `axis2` axes, returning the number of nodes transposed, the new transposed position 1, and the new transposed position 2
\r
505 worldedit.transpose = function(pos1, pos2, axis1, axis2)
\r
506 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
509 local extent1, extent2 = pos2[axis1] - pos1[axis1], pos2[axis2] - pos1[axis2]
\r
511 if extent1 > extent2 then
\r
512 compare = function(extent1, extent2)
\r
513 return extent1 > extent2
\r
516 compare = function(extent1, extent2)
\r
517 return extent1 < extent2
\r
521 --calculate the new position 2 after transposition
\r
522 local new_pos2 = {x=pos2.x, y=pos2.y, z=pos2.z}
\r
523 new_pos2[axis1] = pos1[axis1] + extent2
\r
524 new_pos2[axis2] = pos1[axis2] + extent1
\r
526 --make area stay loaded
\r
527 local manip = minetest.get_voxel_manip()
\r
528 local upperbound = {x=pos2.x, y=pos2.y, z=pos2.z}
\r
529 if upperbound[axis1] < new_pos2[axis1] then upperbound[axis1] = new_pos2[axis1] end
\r
530 if upperbound[axis2] < new_pos2[axis2] then upperbound[axis2] = new_pos2[axis2] end
\r
531 manip:read_from_map(pos1, upperbound)
\r
533 local pos = {x=pos1.x, y=0, z=0}
\r
534 local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
\r
535 while pos.x <= pos2.x do
\r
537 while pos.y <= pos2.y do
\r
539 while pos.z <= pos2.z do
\r
540 local extent1, extent2 = pos[axis1] - pos1[axis1], pos[axis2] - pos1[axis2]
\r
541 if compare(extent1, extent2) then --transpose only if below the diagonal
\r
542 local node1 = get_node(pos)
\r
543 local meta1 = get_meta(pos):to_table()
\r
544 local value1, value2 = pos[axis1], pos[axis2] --save position values
\r
545 pos[axis1], pos[axis2] = pos1[axis1] + extent2, pos1[axis2] + extent1 --swap axis extents
\r
546 local node2 = get_node(pos)
\r
547 local meta2 = get_meta(pos):to_table()
\r
548 add_node(pos, node1)
\r
549 get_meta(pos):from_table(meta1)
\r
550 pos[axis1], pos[axis2] = value1, value2 --restore position values
\r
551 add_node(pos, node2)
\r
552 get_meta(pos):from_table(meta2)
\r
560 return worldedit.volume(pos1, pos2), pos1, new_pos2
\r
563 --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
564 worldedit.flip = function(pos1, pos2, axis)
\r
565 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
567 --make area stay loaded
\r
568 local manip = minetest.get_voxel_manip()
\r
569 manip:read_from_map(pos1, pos2)
\r
571 --wip: flip the region slice by slice along the flip axis using schematic method
\r
572 local pos = {x=pos1.x, y=0, z=0}
\r
573 local start = pos1[axis] + pos2[axis]
\r
574 pos2[axis] = pos1[axis] + math.floor((pos2[axis] - pos1[axis]) / 2)
\r
575 local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
\r
576 while pos.x <= pos2.x do
\r
578 while pos.y <= pos2.y do
\r
580 while pos.z <= pos2.z do
\r
581 local node1 = get_node(pos)
\r
582 local meta1 = get_meta(pos):to_table()
\r
583 local value = pos[axis]
\r
584 pos[axis] = start - value
\r
585 local node2 = get_node(pos)
\r
586 local meta2 = get_meta(pos):to_table()
\r
587 add_node(pos, node1)
\r
588 get_meta(pos):from_table(meta1)
\r
590 add_node(pos, node2)
\r
591 get_meta(pos):from_table(meta2)
\r
598 return worldedit.volume(pos1, pos2)
\r
601 --rotates a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise around axis `axis` (90 degree increment), returning the number of nodes rotated
\r
602 worldedit.rotate = function(pos1, pos2, axis, angle)
\r
603 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
606 if axis == "x" then
\r
607 axis1, axis2 = "z", "y"
\r
608 elseif axis == "y" then
\r
609 axis1, axis2 = "x", "z"
\r
611 axis1, axis2 = "y", "x"
\r
613 angle = angle % 360
\r
616 if angle == 90 then
\r
617 worldedit.flip(pos1, pos2, axis1)
\r
618 count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2)
\r
619 elseif angle == 180 then
\r
620 worldedit.flip(pos1, pos2, axis1)
\r
621 count = worldedit.flip(pos1, pos2, axis2)
\r
622 elseif angle == 270 then
\r
623 worldedit.flip(pos1, pos2, axis2)
\r
624 count, pos1, pos2 = worldedit.transpose(pos1, pos2, axis1, axis2)
\r
626 return count, pos1, pos2
\r
629 --rotates all oriented nodes in a region defined by the positions `pos1` and `pos2` by `angle` degrees clockwise (90 degree increment) around the Y axis, returning the number of nodes oriented
\r
630 worldedit.orient = function(pos1, pos2, angle) --wip: support 6D facedir rotation along arbitrary axis
\r
631 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
632 local registered_nodes = minetest.registered_nodes
\r
634 local wallmounted = {
\r
635 [90]={[0]=0, [1]=1, [2]=5, [3]=4, [4]=2, [5]=3},
\r
636 [180]={[0]=0, [1]=1, [2]=3, [3]=2, [4]=5, [5]=4},
\r
637 [270]={[0]=0, [1]=1, [2]=4, [3]=5, [4]=3, [5]=2}
\r
640 [90]={[0]=1, [1]=2, [2]=3, [3]=0},
\r
641 [180]={[0]=2, [1]=3, [2]=0, [3]=1},
\r
642 [270]={[0]=3, [1]=0, [2]=1, [3]=2}
\r
645 angle = angle % 360
\r
649 local wallmounted_substitution = wallmounted[angle]
\r
650 local facedir_substitution = facedir[angle]
\r
652 --make area stay loaded
\r
653 local manip = minetest.get_voxel_manip()
\r
654 manip:read_from_map(pos1, pos2)
\r
657 local get_node, get_meta, add_node = minetest.get_node, minetest.get_meta, minetest.add_node
\r
658 local pos = {x=pos1.x, y=0, z=0}
\r
659 while pos.x <= pos2.x do
\r
661 while pos.y <= pos2.y do
\r
663 while pos.z <= pos2.z do
\r
664 local node = get_node(pos)
\r
665 local def = registered_nodes[node.name]
\r
667 if def.paramtype2 == "wallmounted" then
\r
668 node.param2 = wallmounted_substitution[node.param2]
\r
669 local meta = get_meta(pos):to_table()
\r
670 add_node(pos, node)
\r
671 get_meta(pos):from_table(meta)
\r
673 elseif def.paramtype2 == "facedir" then
\r
674 node.param2 = facedir_substitution[node.param2]
\r
675 local meta = get_meta(pos):to_table()
\r
676 add_node(pos, node)
\r
677 get_meta(pos):from_table(meta)
\r
690 --fixes the lighting in a region defined by positions `pos1` and `pos2`, returning the number of nodes updated
\r
691 worldedit.fixlight = function(pos1, pos2)
\r
692 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
694 --make area stay loaded
\r
695 local manip = minetest.get_voxel_manip()
\r
696 manip:read_from_map(pos1, pos2)
\r
698 local nodes = minetest.find_nodes_in_area(pos1, pos2, "air")
\r
699 local dig_node = minetest.dig_node
\r
700 for _, pos in ipairs(nodes) do
\r
706 --clears all objects in a region defined by the positions `pos1` and `pos2`, returning the number of objects cleared
\r
707 worldedit.clearobjects = function(pos1, pos2)
\r
708 local pos1, pos2 = worldedit.sort_pos(pos1, pos2)
\r
710 --make area stay loaded
\r
711 local manip = minetest.get_voxel_manip()
\r
712 manip:read_from_map(pos1, pos2)
\r
714 local pos1x, pos1y, pos1z = pos1.x, pos1.y, pos1.z
\r
715 local pos2x, pos2y, pos2z = pos2.x + 1, pos2.y + 1, pos2.z + 1
\r
716 local center = {x=(pos1x + pos2x) / 2, y=(pos1y + pos2y) / 2, z=(pos1z + pos2z) / 2} --center of region
\r
717 local radius = ((center.x - pos1x + 0.5) + (center.y - pos1y + 0.5) + (center.z - pos1z + 0.5)) ^ 0.5 --bounding sphere radius
\r
719 for _, obj in pairs(minetest.get_objects_inside_radius(center, radius)) do --all objects in bounding sphere
\r
720 local entity = obj:get_luaentity()
\r
721 if not (entity and entity.name:find("^worldedit:")) then --avoid WorldEdit entities
\r
722 local pos = obj:getpos()
\r
723 if pos.x >= pos1x and pos.x <= pos2x
\r
724 and pos.y >= pos1y and pos.y <= pos2y
\r
725 and pos.z >= pos1z and pos.z <= pos2z then --inside region
\r