It doesn't have any syntax errors, so I guess there's only one way to find out if it actually works :P

This commit is contained in:
Starbeamrainbowlabs 2018-05-20 11:52:16 +01:00
commit 02b54e6215
Signed by: sbrl
GPG Key ID: 1BE5172E637709C2
7 changed files with 135 additions and 0 deletions

0
modpack.txt Normal file
View File

View File

@ -0,0 +1 @@
worldedit

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -0,0 +1 @@
worldeditadditions

View File

@ -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 = "<replace_node> [<radius>]",
description = "Floods all connected nodes of the same type starting at pos1 with <replace_node>, in a box-shape with a radius of <radius>, 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
})