494afbdb79
- Place flow first, so crude glass curing detects properly from a lateral move - Set DNT on the correct node
115 lines
3.5 KiB
Lua
115 lines
3.5 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local minetest, nodecore, pairs, vector
|
|
= minetest, nodecore, pairs, vector
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local floodable = {}
|
|
minetest.after(0, function()
|
|
for k, v in pairs(minetest.registered_nodes) do
|
|
if v.floodable then floodable[k] = true end
|
|
end
|
|
end)
|
|
|
|
function nodecore.fluidwander(name, gencheck, movedist, scandist)
|
|
movedist = movedist or 2
|
|
scandist = scandist or 8
|
|
local function movesrc(pos, np, node, flowname, gen)
|
|
minetest.set_node(pos, {name = flowname, param2 = 7})
|
|
minetest.set_node(np, node)
|
|
minetest.get_meta(np):set_int("fluidgen_" .. name, gen + 1)
|
|
nodecore.dnt_set(np, "fluidwander_" .. name)
|
|
end
|
|
return function(pos, node)
|
|
local meta = minetest.get_meta(pos)
|
|
local gen = meta:get_int("fluidgen_" .. name)
|
|
if gencheck(pos, node, gen) then return end
|
|
|
|
-- Search for nearby flowing nodes; these are the only
|
|
-- nodes the source may be moved into.
|
|
local miny = pos.y
|
|
local maxy = pos.y
|
|
local found = {}
|
|
local attdist = 1/0
|
|
local attract = {}
|
|
local flowname = minetest.registered_items[node.name].liquid_alternative_flowing
|
|
nodecore.scan_flood(pos, movedist, function(p)
|
|
if p.y > maxy then return false end
|
|
local nn = minetest.get_node(p).name
|
|
if nn == node.name then return end
|
|
if nn ~= flowname then return false end
|
|
if p.y > miny then return end
|
|
if p.y == miny then
|
|
found[#found + 1] = p
|
|
return
|
|
end
|
|
miny = p.y
|
|
found = {p}
|
|
end)
|
|
if #found < 1 then return end
|
|
|
|
-- If a place is found where the node can move downward, go immediately.
|
|
if miny < maxy and #found > 0 then
|
|
return movesrc(pos, nodecore.pickrand(found), node, flowname, gen)
|
|
end
|
|
|
|
-- If our only options are on the same level, search again to find
|
|
-- a place where we would be able to flow down if our flow reached.
|
|
-- This is interpeting the terrain as "subtly sloped" toward the
|
|
-- hole allowing the fluid to find it.
|
|
nodecore.scan_flood(pos, scandist, function(p)
|
|
if p.y > maxy then return false end
|
|
local nn = minetest.get_node(p).name
|
|
if nn == node.name then return end
|
|
if nn ~= flowname and not floodable[nn] then return false end
|
|
if p.y < maxy then
|
|
local diff = vector.subtract(p, pos)
|
|
diff.y = 0
|
|
local dsqr = vector.dot(diff, diff)
|
|
if dsqr > attdist then return end
|
|
if dsqr == attdist then
|
|
attract[#attract + 1] = p
|
|
return false
|
|
end
|
|
attdist = dsqr
|
|
attract = {p}
|
|
return false
|
|
end
|
|
end)
|
|
|
|
-- If no hole was found, terrain is level, wander randomly.
|
|
if #attract < 1 then
|
|
return movesrc(pos, nodecore.pickrand(found), node, flowname, gen)
|
|
end
|
|
|
|
-- Pick the flowing node that's closest to the down-hole.
|
|
local picked = nodecore.pickrand(attract)
|
|
local bestpos
|
|
local bestdsqr
|
|
for i = 1, #found do
|
|
local p = found[i]
|
|
local diff = vector.subtract(p, picked)
|
|
local dsqr = vector.dot(diff, diff)
|
|
if (not bestdsqr) or (dsqr < bestdsqr) then
|
|
bestdsqr = dsqr
|
|
bestpos = p
|
|
end
|
|
end
|
|
return movesrc(pos, bestpos, node, flowname, gen)
|
|
end
|
|
end
|
|
|
|
function nodecore.register_fluidwandering(name, nodenames, interval,
|
|
gencheck, movedist, scandist)
|
|
movedist = movedist or 2
|
|
scandist = scandist or 8
|
|
local labelname = "fluidwander_" .. name
|
|
nodecore.register_dnt({
|
|
name = labelname,
|
|
nodenames = nodenames,
|
|
time = interval,
|
|
autostart = true,
|
|
arealoaded = scandist > movedist and scandist or movedist,
|
|
action = nodecore.fluidwander(name, gencheck, movedist, scandist)
|
|
})
|
|
end
|