end\r
\r
\r
+local function deferred_execution(next_one, finished)\r
+ -- Allocate 100% of server step for execution (might lag a little)\r
+ local allocated_usecs =\r
+ tonumber(minetest.settings:get("dedicated_server_step")) * 1000000\r
+ local function f()\r
+ local deadline = minetest.get_us_time() + allocated_usecs\r
+ repeat\r
+ local is_done = next_one()\r
+ if is_done then\r
+ if finished then\r
+ finished()\r
+ end\r
+ return\r
+ end\r
+ until minetest.get_us_time() >= deadline\r
+ minetest.after(0, f)\r
+ end\r
+ f()\r
+end\r
+\r
--- Duplicates a region `amount` times with offset vector `direction`.\r
--- Stacking is spread across server steps, one copy per step.\r
+-- Stacking is spread across server steps.\r
-- @return The number of nodes stacked.\r
function worldedit.stack2(pos1, pos2, direction, amount, finished)\r
+ -- Protect arguments from external changes during execution\r
+ pos1 = table.copy(pos1)\r
+ pos2 = table.copy(pos2)\r
+ direction = table.copy(direction)\r
+\r
local i = 0\r
local translated = {x=0, y=0, z=0}\r
- local function next_one()\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)\r
- minetest.after(0, next_one)\r
- else\r
- if finished then\r
- finished()\r
- end\r
- end\r
+ local function step()\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)\r
+ i = i + 1\r
+ return i >= amount\r
end\r
- next_one()\r
+ deferred_execution(step, finished)\r
+\r
return worldedit.volume(pos1, pos2) * amount\r
end\r
\r
\r
\r
--- Duplicates a region along `axis` `amount` times.\r
--- Stacking is spread across server steps, one copy per step.\r
+-- Stacking is spread across server steps.\r
-- @param pos1\r
-- @param pos2\r
-- @param axis Axis direction, "x", "y", or "z".\r
-- @param count\r
-- @return The number of nodes stacked.\r
-function worldedit.stack(pos1, pos2, axis, count)\r
+function worldedit.stack(pos1, pos2, axis, count, finished)\r
local pos1, pos2 = worldedit.sort_pos(pos1, pos2)\r
local length = pos2[axis] - pos1[axis] + 1\r
if count < 0 then\r
count = -count\r
length = -length\r
end\r
- local amount = 0\r
- local copy = worldedit.copy\r
- local i = 1\r
- local function next_one()\r
- if i <= count then\r
- i = i + 1\r
- amount = amount + length\r
- copy(pos1, pos2, axis, amount)\r
- minetest.after(0, next_one)\r
- end\r
+\r
+ local i, distance = 0, 0\r
+ local function step()\r
+ distance = distance + length\r
+ worldedit.copy(pos1, pos2, axis, distance)\r
+ i = i + 1\r
+ return i >= count\r
end\r
- next_one()\r
+ deferred_execution(step, finished)\r
+\r
return worldedit.volume(pos1, pos2) * count\r
end\r
\r