]> git.lizzy.rs Git - worldedit.git/commitdiff
Fix performance of //stack, //stack2
authorsfan5 <sfan5@live.de>
Sun, 8 Sep 2019 19:45:20 +0000 (21:45 +0200)
committersfan5 <sfan5@live.de>
Sun, 8 Sep 2019 20:14:07 +0000 (22:14 +0200)
worldedit/manipulations.lua

index 1858611e4294f06bf2d76d1da9c364f4745de1a1..25aa14110f0cbb63fad4edf64cf0ac93fcbc1401 100644 (file)
@@ -98,27 +98,47 @@ function worldedit.replace(pos1, pos2, search_node, replace_node, inverse)
 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
@@ -333,31 +353,29 @@ end
 \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