Convert furnace ABM to node timer

Node timers are higher precision and a better guarantee
of happening at regular intervals, whereas ABM's may be
postponed, cancelled or missed if a player is too far.

The largest benefit is that once the furnace is done
cooking, no more ABM's are fired - the timer is stopped
instead and no more events are created until items
are put in the furnace.

This patch is larger due to the migration of the timer
function and indentation change as a result of the somewhat
reduced complexity. I've tested with several furnaces and
this works correctly and behavior is not affected, although
people may find that their furnaces now work more
regularly.

If you place several furnaces next to eachother, you will
still find all furnace timers firing exactly at the same
time. This is a bug in core that should not coalesce node
timers at second intervals.
This commit is contained in:
Auke Kok 2016-02-09 22:03:40 -08:00 committed by paramat
parent f600a9f645
commit 8f095c62a8

View File

@ -90,66 +90,6 @@ local function allow_metadata_inventory_take(pos, listname, index, stack, player
return stack:get_count() return stack:get_count()
end end
--
-- Node definitions
--
minetest.register_node("default:furnace", {
description = "Furnace",
tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_front.png"
},
paramtype2 = "facedir",
groups = {cracky=2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
can_dig = can_dig,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
})
minetest.register_node("default:furnace_active", {
description = "Furnace",
tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png",
{
image = "default_furnace_front_active.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.5
},
}
},
paramtype2 = "facedir",
light_source = 8,
drop = "default:furnace",
groups = {cracky=2, not_in_creative_inventory=1},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
can_dig = can_dig,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
})
--
-- ABM
--
local function swap_node(pos, name) local function swap_node(pos, name)
local node = minetest.get_node(pos) local node = minetest.get_node(pos)
if node.name == name then if node.name == name then
@ -159,11 +99,7 @@ local function swap_node(pos, name)
minetest.swap_node(pos, node) minetest.swap_node(pos, node)
end end
minetest.register_abm({ local function furnace_node_timer(pos, elapsed)
nodenames = {"default:furnace", "default:furnace_active"},
interval = 1.0,
chance = 1,
action = function(pos, node, active_object_count, active_object_count_wider)
-- --
-- Inizialize metadata -- Inizialize metadata
-- --
@ -172,19 +108,7 @@ minetest.register_abm({
local src_time = meta:get_float("src_time") or 0 local src_time = meta:get_float("src_time") or 0
local fuel_totaltime = meta:get_float("fuel_totaltime") or 0 local fuel_totaltime = meta:get_float("fuel_totaltime") or 0
--
-- Inizialize inventory
--
local inv = meta:get_inventory() local inv = meta:get_inventory()
for listname, size in pairs({
src = 1,
fuel = 1,
dst = 4,
}) do
if inv:get_size(listname) ~= size then
inv:set_size(listname, size)
end
end
local srclist = inv:get_list("src") local srclist = inv:get_list("src")
local fuellist = inv:get_list("fuel") local fuellist = inv:get_list("fuel")
local dstlist = inv:get_list("dst") local dstlist = inv:get_list("dst")
@ -235,7 +159,6 @@ minetest.register_abm({
fuel_totaltime = fuel.time fuel_totaltime = fuel.time
fuel_time = 0 fuel_time = 0
end end
else else
-- We don't need to get new fuel since there is no cookable item -- We don't need to get new fuel since there is no cookable item
@ -264,17 +187,24 @@ minetest.register_abm({
local fuel_state = "Empty" local fuel_state = "Empty"
local active = "inactive " local active = "inactive "
local result = false
if fuel_time <= fuel_totaltime and fuel_totaltime ~= 0 then if fuel_time <= fuel_totaltime and fuel_totaltime ~= 0 then
active = "active " active = "active "
local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100) local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100)
fuel_state = fuel_percent .. "%" fuel_state = fuel_percent .. "%"
formspec = active_formspec(fuel_percent, item_percent) formspec = active_formspec(fuel_percent, item_percent)
swap_node(pos, "default:furnace_active") swap_node(pos, "default:furnace_active")
-- make sure timer restarts automatically
result = true
else else
if not fuellist[1]:is_empty() then if not fuellist[1]:is_empty() then
fuel_state = "0%" fuel_state = "0%"
end end
swap_node(pos, "default:furnace") swap_node(pos, "default:furnace")
-- stop timer on the inactive furnace
local timer = minetest.get_node_timer(pos)
timer:stop()
end end
local infotext = "Furnace " .. active .. "(Item: " .. item_state .. "; Fuel: " .. fuel_state .. ")" local infotext = "Furnace " .. active .. "(Item: " .. item_state .. "; Fuel: " .. fuel_state .. ")"
@ -287,5 +217,81 @@ minetest.register_abm({
meta:set_float("src_time", src_time) meta:set_float("src_time", src_time)
meta:set_string("formspec", formspec) meta:set_string("formspec", formspec)
meta:set_string("infotext", infotext) meta:set_string("infotext", infotext)
return result
end
--
-- Node definitions
--
minetest.register_node("default:furnace", {
description = "Furnace",
tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png", "default_furnace_front.png"
},
paramtype2 = "facedir",
groups = {cracky=2},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
can_dig = can_dig,
on_timer = furnace_node_timer,
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec", inactive_formspec)
local inv = meta:get_inventory()
inv:set_size('src', 1)
inv:set_size('fuel', 1)
inv:set_size('dst', 4)
end, end,
on_metadata_inventory_put = function(pos)
-- start timer function, it will sort out whether furnace can burn or not.
local timer = minetest.get_node_timer(pos)
timer:start(1.0)
end,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
}) })
minetest.register_node("default:furnace_active", {
description = "Furnace",
tiles = {
"default_furnace_top.png", "default_furnace_bottom.png",
"default_furnace_side.png", "default_furnace_side.png",
"default_furnace_side.png",
{
image = "default_furnace_front_active.png",
backface_culling = false,
animation = {
type = "vertical_frames",
aspect_w = 16,
aspect_h = 16,
length = 1.5
},
}
},
paramtype2 = "facedir",
light_source = 8,
drop = "default:furnace",
groups = {cracky=2, not_in_creative_inventory=1},
legacy_facedir_simple = true,
is_ground_content = false,
sounds = default.node_sound_stone_defaults(),
on_timer = furnace_node_timer,
can_dig = can_dig,
allow_metadata_inventory_put = allow_metadata_inventory_put,
allow_metadata_inventory_move = allow_metadata_inventory_move,
allow_metadata_inventory_take = allow_metadata_inventory_take,
})