3459e94de8
make `flood_fill` able to be interrupted if its callback returns false; the meaning that was previously indicated by this return value is now indicated by nil instead. update code that uses this function to account for this change.
89 lines
2 KiB
Lua
89 lines
2 KiB
Lua
function blockgame.reg_simple_node (name, desc, groups)
|
|
local my_modname = minetest.get_current_modname()
|
|
return blockgame.register_node(my_modname .. ":" .. name, {
|
|
description = desc,
|
|
tiles = {
|
|
my_modname .. "_" .. name .. ".png",
|
|
},
|
|
groups = groups,
|
|
})
|
|
end
|
|
|
|
|
|
|
|
function blockgame.air_flows_through (pos, node)
|
|
node = node or minetest.get_node(pos)
|
|
return blockgame.item_matches(node.name, {
|
|
"air",
|
|
"group:air_flowable",
|
|
})
|
|
end
|
|
|
|
|
|
|
|
function blockgame.attempt_place (pos, node)
|
|
if minetest.get_node(pos).name ~= "air" then return false end
|
|
minetest.set_node(pos, node)
|
|
return true
|
|
end
|
|
|
|
|
|
|
|
function blockgame.random_walk (data)
|
|
local pos = vector.copy(data.pos)
|
|
local min_steps = data.min_steps or 0
|
|
local max_steps = data.max_steps or 8
|
|
local check = data.check
|
|
local neighborhood = data.neighborhood or blockgame.vector.dirs
|
|
|
|
local steps = math.random(min_steps, max_steps)
|
|
local step = 0
|
|
|
|
while step < steps do
|
|
local dir = blockgame.random_element(neighborhood)
|
|
local new_pos = pos + dir
|
|
if check(new_pos, minetest.get_node(new_pos)) then pos = new_pos end
|
|
step = step + 1
|
|
end
|
|
return pos
|
|
end
|
|
|
|
|
|
|
|
function blockgame.flood_fill (start, step, max_range)
|
|
max_range = max_range or 4
|
|
|
|
local queue = { { pos = start, range = 0 } }
|
|
local visited = {}
|
|
local matches = {}
|
|
local rejected = {}
|
|
|
|
local cancel = false
|
|
|
|
while #queue > 0 and not cancel do
|
|
local current = table.remove(queue, 1)
|
|
local pos = current.pos
|
|
local range = current.range
|
|
|
|
local hash = minetest.hash_node_position(pos)
|
|
|
|
if not visited[hash] and range <= max_range and step(pos, range) then
|
|
local step_result = step(pos, range)
|
|
|
|
if step_result then
|
|
table.insert(matches, pos)
|
|
|
|
local neighbors = blockgame.vector.get_neighbors(pos)
|
|
for _, p in pairs(neighbors) do
|
|
table.insert(queue, { pos = p, range = range + 1 })
|
|
end
|
|
elseif step_result == nil then
|
|
table.insert(rejected, pos)
|
|
else cancel = true end
|
|
end
|
|
|
|
visited[hash] = true
|
|
end
|
|
|
|
return matches, rejected
|
|
end
|