Fixed some bugs, but it keeps running out of memory.

This commit is contained in:
Starbeamrainbowlabs 2018-05-20 12:23:09 +01:00
parent 02b54e6215
commit 0bb807ff86
Signed by: sbrl
GPG key ID: 1BE5172E637709C2
4 changed files with 52 additions and 43 deletions

View file

@ -1,20 +1,52 @@
--- Flood-fill command for complex lakes etc. --- Flood-fill command for complex lakes etc.
-- @module worldeditadditions.floodfill -- @module worldeditadditions.floodfill
local Queue = require "queue" -------------------------------------------------------------------------------
--- A Queue implementation, taken & adapted from https://www.lua.org/pil/11.4.html
-- @submodule worldeditadditions.utils.queue
local function floodfill(start_pos, radius, replace_node) 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 queue.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
queue.first = first + 1
return value
end
-------------------------------------------------------------------------------
function worldedit.floodfill(start_pos, radius, replace_node)
-- Calculate the area we want to modify -- Calculate the area we want to modify
local pos1, pos2 = centre_pos local pos1 = vector.add(start_pos, { x = radius, y = 0, z = radius })
pos1.x = pos1.x - radius local pos2 = vector.subtract(start_pos, { x = radius, y = radius, z = 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 pos1, pos2 = worldedit.sort_pos(pos1, pos2) -- Just in case
minetest.log("action", "radius: " .. radius)
minetest.log("action", "pos1: (" .. pos1.x .. ", " .. pos1.y .. ", " .. pos1.z .. ")")
minetest.log("action", "pos2: (" .. pos2.x .. ", " .. pos2.y .. ", " .. pos2.z .. ")")
-- Fetch the nodes in the specified area -- Fetch the nodes in the specified area
local manip, area = worldedit.manip_helpers.init() local manip, area = worldedit.manip_helpers.init(pos1, pos2)
local data = manip:get_data() local data = manip:get_data()
-- Setup for the floodfill operation itself -- Setup for the floodfill operation itself
@ -23,6 +55,8 @@ local function floodfill(start_pos, radius, replace_node)
local search_id = data[start_pos_index] local search_id = data[start_pos_index]
local replace_id = minetest.get_content_id(replace_node) local replace_id = minetest.get_content_id(replace_node)
minetest.log("action", "ids: " .. search_id .. " -> " .. replace_id)
local count = 0 local count = 0
local remaining_nodes = Queue.new() local remaining_nodes = Queue.new()
Queue.enqueue(remaining_nodes, start_pos_index) Queue.enqueue(remaining_nodes, start_pos_index)

View file

@ -5,4 +5,4 @@
-- @license Mozilla Public License, 2.0 -- @license Mozilla Public License, 2.0
-- @author Starbeamrainbowlabs -- @author Starbeamrainbowlabs
worldedit.floodfill = require "floodfill" dofile(minetest.get_modpath("worldeditadditions") .. "/floodfill.lua")

View file

@ -1,31 +0,0 @@
--- 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

@ -12,17 +12,23 @@ minetest.register_chatcommand("/floodfill", {
-- TODO: Integrate will the safe_region feature of regular worldedit -- TODO: Integrate will the safe_region feature of regular worldedit
func = function(name, params_text) func = function(name, params_text)
local found, _, replace_node, radius = params_text:find("([a-z:_\\-]+)%s+([0-9]+)") local found, _, replace_node, radius = params_text:find("([a-z:_\\-]+)%s+([0-9]+)")
if found == nil then if found == nil then
found, _, replace_node = params_text:find("([a-z:_\\-]+)") found, _, replace_node = params_text:find("([a-z:_\\-]+)")
radius = 50 radius = 25
end end
if found == nil then if found == nil then
replace_node = "default:water_source" replace_node = "default:water_source"
end end
radius = tonumber(radius)
replace_node = worldedit.normalize_nodename(replace_node)
minetest.log("action", "Floodfill settings - node: " .. replace_node .. ", radius: " .. radius)
local nodes_replaced = worldedit.floodfill(worldedit.pos1[name], radius, replace_node) local nodes_replaced = worldedit.floodfill(worldedit.pos1[name], radius, replace_node)
worldedit.player_notify(name, nodes_replaced .. " replaced") 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") minetest.log("action", name .. "used floodfill at (" .. worldedit.pos1[name].x .. "," .. worldedit.pos1[name].y .. "," .. worldedit.pos1[name].z .. "), replacing " .. nodes_replaced .. " nodes")
end end
}) })