Extinguish fire using an ABM instead of timers

Even the mitigated timers seem to have lead to slow
memory leaks. Once Minetest has used up all the RAM,
it will free some, then quickly use memory up again,
then repeat it ad nauseum, requiring 100% CPU. On a
PC with 2GB of RAM this could be reliably triggered
by having a fire burn a forest for 20 to 30 minutes.

This patch removes fire node timers completely and
instead extinguishes fire using an ABM.
master
cora 2022-02-10 15:05:35 +01:00 committed by Nils Dagsson Moskopp
parent ef7370550f
commit 5d09ec311c
No known key found for this signature in database
GPG Key ID: A3BC671C35191080
1 changed files with 19 additions and 15 deletions

View File

@ -95,10 +95,6 @@ local spawn_fire = function(pos, age)
minetest.check_single_for_falling({x=pos.x, y=pos.y+1, z=pos.z})
end
local function fire_timer(pos)
return minetest.get_node_timer(pos):start(math.random(30, 60))
end
minetest.register_node("mcl_fire:fire", {
description = S("Fire"),
_doc_items_longdesc = fire_help,
@ -131,15 +127,6 @@ minetest.register_node("mcl_fire:fire", {
end,
drop = "",
sounds = {},
on_timer= function(pos)
local p=has_flammable(pos)
if not p or minetest.get_item_group(minetest.get_node(p).name, "flammable") == -1 then
minetest.remove_node(pos)
return
end
-- Restart timer
return true
end,
-- Turn into eternal fire on special blocks, light Nether portal (if possible), start burning timer
on_construct = function(pos)
local bpos = {x=pos.x, y=pos.y-1, z=pos.z}
@ -154,7 +141,6 @@ minetest.register_node("mcl_fire:fire", {
mcl_portals.light_nether_portal(pos)
end
spawn_smoke(pos)
fire_timer(pos)
end,
on_destruct = function(pos)
mcl_particles.delete_node_particlespawners(pos)
@ -433,6 +419,25 @@ else -- Fire enabled
end,
})
minetest.register_abm({
label = "Remove fires",
nodenames = {"mcl_fire:fire"},
interval = 12,
chance = 4,
catch_up = false,
action = function(pos)
local p=has_flammable(pos)
if p then
local n=minetest.get_node_or_nil(p)
if n and minetest.get_item_group(n.name, "flammable") < 1 then
minetest.remove_node(pos)
end
else
minetest.remove_node(pos)
end
end,
})
-- Remove flammable nodes around basic flame
minetest.register_abm({
label = "Remove flammable nodes",
@ -455,7 +460,6 @@ else -- Fire enabled
def._on_burn(p)
elseif fgroup ~= -1 then
spawn_fire(p)
fire_timer(p)
minetest.check_for_falling(p)
end
end