From 02b54e621578c36f637b9f9f4462c6f74753526b Mon Sep 17 00:00:00 2001 From: Starbeamrainbowlabs Date: Sun, 20 May 2018 11:52:16 +0100 Subject: [PATCH] It doesn't have any syntax errors, so I guess there's only one way to find out if it actually works :P --- modpack.txt | 0 worldeditadditions/depends.txt | 1 + worldeditadditions/floodfill.lua | 66 +++++++++++++++++++++++++ worldeditadditions/init.lua | 8 +++ worldeditadditions/queue.lua | 31 ++++++++++++ worldeditadditions_commands/depends.txt | 1 + worldeditadditions_commands/init.lua | 28 +++++++++++ 7 files changed, 135 insertions(+) create mode 100644 modpack.txt create mode 100644 worldeditadditions/depends.txt create mode 100644 worldeditadditions/floodfill.lua create mode 100644 worldeditadditions/init.lua create mode 100644 worldeditadditions/queue.lua create mode 100644 worldeditadditions_commands/depends.txt create mode 100644 worldeditadditions_commands/init.lua diff --git a/modpack.txt b/modpack.txt new file mode 100644 index 0000000..e69de29 diff --git a/worldeditadditions/depends.txt b/worldeditadditions/depends.txt new file mode 100644 index 0000000..74054c6 --- /dev/null +++ b/worldeditadditions/depends.txt @@ -0,0 +1 @@ +worldedit diff --git a/worldeditadditions/floodfill.lua b/worldeditadditions/floodfill.lua new file mode 100644 index 0000000..2d37e11 --- /dev/null +++ b/worldeditadditions/floodfill.lua @@ -0,0 +1,66 @@ +--- Flood-fill command for complex lakes etc. +-- @module worldeditadditions.floodfill + +local Queue = require "queue" + +local function floodfill(start_pos, radius, replace_node) + -- Calculate the area we want to modify + local pos1, pos2 = centre_pos + pos1.x = pos1.x - radius + pos1.z = pos1.z - radius + pos2.x = pos2.x + radius + pos2.y = pos2.y + radius + pos2.z = pos2.z + radius + pos1, pos2 = worldedit.sort_pos(pos1, pos2) -- Just in case + + -- Fetch the nodes in the specified area + local manip, area = worldedit.manip_helpers.init() + 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 search_id = data[start_pos_index] + local replace_id = minetest.get_content_id(replace_node) + + local count = 0 + local remaining_nodes = Queue.new() + Queue.enqueue(remaining_nodes, start_pos_index) + + -- Do the floodfill + while Queue.is_empty(remaining_nodes) == false do + local cur = Queue.dequeue(remaining_nodes) + + -- TODO: Check distance from start_pos + + -- Replace this node + data[cur] = replace_id + count = count + 1 + + -- Check all the nearby nodes + -- We don't need to go upwards here, since we're filling in lake-style + if data[cur + 1] == search_id then -- +X + Queue.enqueue(remaining_nodes, cur + 1) + end + if data[cur - 1] == search_id then -- -X + Queue.enqueue(remaining_nodes, cur - 1) + end + if data[cur + area.zstride] == search_id then -- +Z + Queue.enqueue(remaining_nodes, cur + area.zstride) + end + if data[cur - area.zstride] == search_id then -- -Z + Queue.enqueue(remaining_nodes, cur - area.zstride) + end + if data[cur - area.ystride] == search_id then -- -Y + Queue.enqueue(remaining_nodes, cur - area.ystride) + end + end + + -- Save the modified nodes back to disk & return + worldedit.manip_helpers.finish(manip, data) + + return count +end + + +return floodfill diff --git a/worldeditadditions/init.lua b/worldeditadditions/init.lua new file mode 100644 index 0000000..c6da867 --- /dev/null +++ b/worldeditadditions/init.lua @@ -0,0 +1,8 @@ +--- WorldEditAdditions +-- @module worldeditadditions +-- @release 0.1 +-- @copyright 2018 Starbeamrainbowlabs +-- @license Mozilla Public License, 2.0 +-- @author Starbeamrainbowlabs + +worldedit.floodfill = require "floodfill" diff --git a/worldeditadditions/queue.lua b/worldeditadditions/queue.lua new file mode 100644 index 0000000..44e725b --- /dev/null +++ b/worldeditadditions/queue.lua @@ -0,0 +1,31 @@ +--- A Queue implementation, taken & adapted from https://www.lua.org/pil/11.4.html +-- @module worldeditadditions.utils.queue + +local Queue = {} +function Queue.new() + return { first = 0, last = -1 } +end + +function Queue.enqueue(queue, value) + local new_last = queue.last + 1 + queue.last = new_last + queue[new_last] = value +end + +function Queue.is_empty(queue) + return new_first > queue.last +end + +function Queue.dequeue(queue) + local first = queue.first + if Queue.is_empty(queue) then + error("Error: The queue is empty!") + end + + local value = queue[first] + queue[first] = nil -- Help the garbage collector out + list.first = first + 1 + return value +end + +return Queue diff --git a/worldeditadditions_commands/depends.txt b/worldeditadditions_commands/depends.txt new file mode 100644 index 0000000..8de07e1 --- /dev/null +++ b/worldeditadditions_commands/depends.txt @@ -0,0 +1 @@ +worldeditadditions diff --git a/worldeditadditions_commands/init.lua b/worldeditadditions_commands/init.lua new file mode 100644 index 0000000..df479f8 --- /dev/null +++ b/worldeditadditions_commands/init.lua @@ -0,0 +1,28 @@ +--- WorldEditAdditions-ChatCommands +-- @module worldeditadditions_commands +-- @release 0.1 +-- @copyright 2018 Starbeamrainbowlabs +-- @license Mozilla Public License, 2.0 +-- @author Starbeamrainbowlabs + +minetest.register_chatcommand("/floodfill", { + params = " []", + description = "Floods all connected nodes of the same type starting at pos1 with , in a box-shape with a radius of , which defaults to 50.", + privs = { worldedit = true }, + -- TODO: Integrate will the safe_region feature of regular worldedit + func = function(name, params_text) + local found, _, replace_node, radius = params_text:find("([a-z:_\\-]+)%s+([0-9]+)") + if found == nil then + found, _, replace_node = params_text:find("([a-z:_\\-]+)") + radius = 50 + end + if found == nil then + replace_node = "default:water_source" + end + + 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.x .. "," .. worldedit.pos1.y .. "," .. worldedit.pos1.z .. "), replacing " .. nodes_replaced .. " nodes") + end +})