Aaron Suen f5e966480b Fix delayed witness mis-ordering
Witness checks include data about the node in
place at the time that the witness even occurred,
so players are not awarded credit if the node they
see there was changed again afterwards.  A lot of
old witness code inserted the witness right
before the node was changed, since the node
change was done as a tail call, but this does not
work with delayed witnessing because the
delayed witness data would be tied to the old
node, not the replacement one.

Moving witness to after node setting should fix
a number of broken hints that should have been
delayed-witnessable, e.g. brick bonding.
2021-12-12 00:04:37 -05:00

51 lines
1.6 KiB
Lua

-- LUALOCALS < ---------------------------------------------------------
local math, minetest, nodecore, pairs
= math, minetest, nodecore, pairs
local math_random
= math.random
-- LUALOCALS > ---------------------------------------------------------
local harden_to = {}
local harden_idx = {}
local soften_to = {}
minetest.after(0, function()
for _, v in pairs(minetest.registered_nodes) do
if v.strata then
for i, n in pairs(v.strata) do
harden_to[n] = v.strata[i + 1]
soften_to[n] = v.strata[i - 1]
harden_idx[n] = i
end
end
end
end)
minetest.register_abm({
label = "stone hardening",
nodenames = {"group:stone"},
neighbors = {"group:lava"},
neighbors_invert = true,
interval = 10,
chance = 50,
action = function(pos)
local water = #nodecore.find_nodes_around(pos, "group:water")
local lux = #nodecore.find_nodes_around(pos, "group:lux_fluid")
if water == lux then return end
local node = minetest.get_node(pos)
node.name = (water > lux and harden_to or soften_to)[node.name]
if not node.name then return end
local lava = #nodecore.find_nodes_around(pos, "group:lava")
if lava < 1 then return end
local fluid = water > lux and (water - lux) or (lux - water)
local chance = harden_idx[node.name] - (fluid > lava and fluid or lava) / 8
if (chance > 0) and (math_random() > (1/3) ^ chance) then return end
nodecore.log("info", (water > lux and "hardened" or "softened")
.. " to " .. node.name .. " at " .. minetest.pos_to_string(pos))
nodecore.set_loud(pos, node)
return nodecore.witness(pos, "stone " .. (water > lux and "hardened" or "softened"))
end
})