diff --git a/worldeditadditions/floodfill.lua b/worldeditadditions/floodfill.lua index 8125d10..f81952b 100644 --- a/worldeditadditions/floodfill.lua +++ b/worldeditadditions/floodfill.lua @@ -43,39 +43,22 @@ end ------------------------------------------------------------------------------- --- These really should be in a utilities file, but Lua is being stupid and preventing access to it (and minetest is also being stupid, as we can't modularise our code the way you ought to be able to - or at least the documentation on dofile() is so poor I've no idea at this point) -local function vector2string(v) - return "(" .. v.x ..", " .. v.y ..", " .. v.z ..")" -end - -local clock = os.clock -function sleep(n) -- seconds - local t0 = clock() - while clock() - t0 <= n do end -end - - function worldedit.floodfill(start_pos, radius, replace_node) -- Calculate the area we want to modify local pos1 = vector.add(start_pos, { x = radius, y = 0, z = radius }) local pos2 = vector.subtract(start_pos, { x = radius, y = radius, z = radius }) pos1, pos2 = worldedit.sort_pos(pos1, pos2) -- Just in case - minetest.log("action", "radius: " .. radius) - minetest.log("action", "pos1: " .. vector2string(pos1)) - minetest.log("action", "pos2: " .. vector2string(pos2)) - -- Fetch the nodes in the specified area local manip, area = worldedit.manip_helpers.init(pos1, pos2) local data = manip:get_data() -- Setup for the floodfill operation itself - local start_pos_index = area:index(start_pos.x, start_pos.y, start_pos.z); + local start_pos_index = area:index(start_pos.x, start_pos.y, start_pos.z) local search_id = data[start_pos_index] local replace_id = minetest.get_content_id(replace_node) - - minetest.log("action", "ids: " .. search_id .. " -> " .. replace_id) + local radius_sq = radius*radius local count = 0 local remaining_nodes = Queue.new() @@ -94,27 +77,37 @@ function worldedit.floodfill(start_pos, radius, replace_node) -- Check all the nearby nodes -- We don't need to go upwards here, since we're filling in lake-style local xplus = cur + 1 -- +X - if data[xplus] == search_id and not Queue.contains(remaining_nodes, xplus) then + if data[xplus] == search_id and + worldeditadditions.vector.lengthsquared(vector.subtract(area:position(xplus), start_pos)) < radius_sq and + not Queue.contains(remaining_nodes, xplus) then -- minetest.log("action", "[floodfill] [+X] index " .. xplus .. " is a " .. data[xplus] .. ", searching for a " .. search_id) Queue.enqueue(remaining_nodes, xplus) end local xminus = cur - 1 -- -X - if data[xminus] == search_id and not Queue.contains(remaining_nodes, xminus) then + if data[xminus] == search_id and + worldeditadditions.vector.lengthsquared(vector.subtract(area:position(xminus), start_pos)) < radius_sq and + not Queue.contains(remaining_nodes, xminus) then -- minetest.log("action", "[floodfill] [-X] index " .. xminus .. " is a " .. data[xminus] .. ", searching for a " .. search_id) Queue.enqueue(remaining_nodes, xminus) end local zplus = cur + area.zstride -- +Z - if data[zplus] == search_id and not Queue.contains(remaining_nodes, zplus) then + if data[zplus] == search_id and + worldeditadditions.vector.lengthsquared(vector.subtract(area:position(zplus), start_pos)) < radius_sq and + not Queue.contains(remaining_nodes, zplus) then -- minetest.log("action", "[floodfill] [+Z] index " .. zplus .. " is a " .. data[zplus] .. ", searching for a " .. search_id) Queue.enqueue(remaining_nodes, zplus) end local zminus = cur - area.zstride -- -Z - if data[zminus] == search_id and not Queue.contains(remaining_nodes, zminus) then + if data[zminus] == search_id and + worldeditadditions.vector.lengthsquared(vector.subtract(area:position(zminus), start_pos)) < radius_sq and + not Queue.contains(remaining_nodes, zminus) then -- minetest.log("action", "[floodfill] [-Z] index " .. zminus .. " is a " .. data[zminus] .. ", searching for a " .. search_id) Queue.enqueue(remaining_nodes, zminus) end local yminus = cur - area.ystride -- -Y - if data[yminus] == search_id and not Queue.contains(remaining_nodes, yminus) then + if data[yminus] == search_id and + worldeditadditions.vector.lengthsquared(vector.subtract(area:position(yminus), start_pos)) < radius_sq and + not Queue.contains(remaining_nodes, yminus) then -- minetest.log("action", "[floodfill] [-Y] index " .. yminus .. " is a " .. data[yminus] .. ", searching for a " .. search_id) Queue.enqueue(remaining_nodes, yminus) end diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua index 5f818e8..7f72611 100644 --- a/worldeditadditions/init.lua +++ b/worldeditadditions/init.lua @@ -5,4 +5,7 @@ -- @license Mozilla Public License, 2.0 -- @author Starbeamrainbowlabs +worldeditadditions = {} + +dofile(minetest.get_modpath("worldeditadditions") .. "/utils.lua") dofile(minetest.get_modpath("worldeditadditions") .. "/floodfill.lua") diff --git a/worldeditadditions/utils.lua b/worldeditadditions/utils.lua new file mode 100644 index 0000000..d894361 --- /dev/null +++ b/worldeditadditions/utils.lua @@ -0,0 +1,9 @@ +worldeditadditions.vector = {} + +function worldeditadditions.vector.tostring(v) + return "(" .. v.x ..", " .. v.y ..", " .. v.z ..")" +end + +function worldeditadditions.vector.lengthsquared(v) + return v.x*v.x + v.y*v.y + v.z*v.z +end diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua index 20e3ec7..5ca75a3 100644 --- a/worldeditadditions_commands/init.lua +++ b/worldeditadditions_commands/init.lua @@ -24,11 +24,10 @@ minetest.register_chatcommand("/floodfill", { replace_node = worldedit.normalize_nodename(replace_node) - minetest.log("action", "Floodfill settings - node: " .. replace_node .. ", radius: " .. radius) - + local start_time = os.clock() local nodes_replaced = worldedit.floodfill(worldedit.pos1[name], radius, replace_node) - worldedit.player_notify(name, nodes_replaced .. " replaced") - minetest.log("action", name .. "used floodfill at (" .. worldedit.pos1[name].x .. "," .. worldedit.pos1[name].y .. "," .. worldedit.pos1[name].z .. "), replacing " .. nodes_replaced .. " nodes") + worldedit.player_notify(name, nodes_replaced .. " nodes replaced in " .. (os.clock() - start_time) .. "s") + minetest.log("action", name .. " used floodfill at " .. worldeditadditions.vector.tostring(worldedit.pos1[name]) .. ", replacing " .. nodes_replaced .. " nodes in " .. (os.clock() - start_time) .. "s") end })