6 function default.get_furnace_active_formspec(fuel_percent, item_percent)
8 "list[context;src;2.75,0.5;1,1;]"..
9 "list[context;fuel;2.75,2.5;1,1;]"..
10 "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:"..
11 (100-fuel_percent)..":default_furnace_fire_fg.png]"..
12 "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:"..
13 (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
14 "list[context;dst;4.75,0.96;2,2;]"..
15 "list[current_player;main;0,4.25;8,1;]"..
16 "list[current_player;main;0,5.5;8,3;8]"..
17 "listring[context;dst]"..
18 "listring[current_player;main]"..
19 "listring[context;src]"..
20 "listring[current_player;main]"..
21 "listring[context;fuel]"..
22 "listring[current_player;main]"..
23 default.get_hotbar_bg(0, 4.25)
26 function default.get_furnace_inactive_formspec()
27 return "size[8,8.5]"..
28 "list[context;src;2.75,0.5;1,1;]"..
29 "list[context;fuel;2.75,2.5;1,1;]"..
30 "image[2.75,1.5;1,1;default_furnace_fire_bg.png]"..
31 "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"..
32 "list[context;dst;4.75,0.96;2,2;]"..
33 "list[current_player;main;0,4.25;8,1;]"..
34 "list[current_player;main;0,5.5;8,3;8]"..
35 "listring[context;dst]"..
36 "listring[current_player;main]"..
37 "listring[context;src]"..
38 "listring[current_player;main]"..
39 "listring[context;fuel]"..
40 "listring[current_player;main]"..
41 default.get_hotbar_bg(0, 4.25)
45 -- Node callback functions that are the same for active and inactive furnace
48 local function can_dig(pos, player)
49 local meta = minetest.get_meta(pos);
50 local inv = meta:get_inventory()
51 return inv:is_empty("fuel") and inv:is_empty("dst") and inv:is_empty("src")
54 local function allow_metadata_inventory_put(pos, listname, index, stack, player)
55 if minetest.is_protected(pos, player:get_player_name()) then
58 local meta = minetest.get_meta(pos)
59 local inv = meta:get_inventory()
60 if listname == "fuel" then
61 if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
62 if inv:is_empty("src") then
63 meta:set_string("infotext", "Furnace is empty")
65 return stack:get_count()
69 elseif listname == "src" then
70 return stack:get_count()
71 elseif listname == "dst" then
76 local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
77 local meta = minetest.get_meta(pos)
78 local inv = meta:get_inventory()
79 local stack = inv:get_stack(from_list, from_index)
80 return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
83 local function allow_metadata_inventory_take(pos, listname, index, stack, player)
84 if minetest.is_protected(pos, player:get_player_name()) then
87 return stack:get_count()
90 local function swap_node(pos, name)
91 local node = minetest.get_node(pos)
92 if node.name == name then
96 minetest.swap_node(pos, node)
99 local function furnace_node_timer(pos, elapsed)
101 -- Inizialize metadata
103 local meta = minetest.get_meta(pos)
104 local fuel_time = meta:get_float("fuel_time") or 0
105 local src_time = meta:get_float("src_time") or 0
106 local fuel_totaltime = meta:get_float("fuel_totaltime") or 0
108 local inv = meta:get_inventory()
109 local srclist, fuellist
111 local cookable, cooked
115 while elapsed > 0 and update do
118 srclist = inv:get_list("src")
119 fuellist = inv:get_list("fuel")
125 -- Check if we have cookable content
127 cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
128 cookable = cooked.time ~= 0
130 local el = math.min(elapsed, fuel_totaltime - fuel_time)
131 if cookable then -- fuel lasts long enough, adjust el to cooking duration
132 el = math.min(el, cooked.time - src_time)
135 -- Check if we have enough fuel to burn
136 if fuel_time < fuel_totaltime then
137 -- The furnace is currently active and has enough fuel
138 fuel_time = fuel_time + el
139 -- If there is a cookable item then check if it is ready yet
141 src_time = src_time + el
142 if src_time >= cooked.time then
143 -- Place result in dst list if possible
144 if inv:room_for_item("dst", cooked.item) then
145 inv:add_item("dst", cooked.item)
146 inv:set_stack("src", 1, aftercooked.items[1])
147 src_time = src_time - cooked.time
151 -- Item could not be cooked: probably missing fuel
156 -- Furnace ran out of fuel
158 -- We need to get new fuel
160 fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
162 if fuel.time == 0 then
163 -- No valid fuel in fuel list
167 -- Take fuel from fuel list
168 inv:set_stack("fuel", 1, afterfuel.items[1])
170 fuel_totaltime = fuel.time + (fuel_totaltime - fuel_time)
173 -- We don't need to get new fuel since there is no cookable item
180 elapsed = elapsed - el
183 if fuel and fuel_totaltime > fuel.time then
184 fuel_totaltime = fuel.time
186 if srclist[1]:is_empty() then
191 -- Update formspec, infotext and node
195 local item_percent = 0
197 item_percent = math.floor(src_time / cooked.time * 100)
198 if item_percent > 100 then
199 item_state = "100% (output full)"
201 item_state = item_percent .. "%"
204 if srclist[1]:is_empty() then
207 item_state = "Not cookable"
211 local fuel_state = "Empty"
212 local active = "inactive"
215 if fuel_totaltime ~= 0 then
217 local fuel_percent = math.floor(fuel_time / fuel_totaltime * 100)
218 fuel_state = fuel_percent .. "%"
219 formspec = default.get_furnace_active_formspec(fuel_percent, item_percent)
220 swap_node(pos, "default:furnace_active")
221 -- make sure timer restarts automatically
224 if not fuellist[1]:is_empty() then
227 formspec = default.get_furnace_inactive_formspec()
228 swap_node(pos, "default:furnace")
229 -- stop timer on the inactive furnace
230 minetest.get_node_timer(pos):stop()
233 local infotext = "Furnace " .. active .. "\n(Item: " .. item_state ..
234 "; Fuel: " .. fuel_state .. ")"
239 meta:set_float("fuel_totaltime", fuel_totaltime)
240 meta:set_float("fuel_time", fuel_time)
241 meta:set_float("src_time", src_time)
242 meta:set_string("formspec", formspec)
243 meta:set_string("infotext", infotext)
252 minetest.register_node("default:furnace", {
253 description = "Furnace",
255 "default_furnace_top.png", "default_furnace_bottom.png",
256 "default_furnace_side.png", "default_furnace_side.png",
257 "default_furnace_side.png", "default_furnace_front.png"
259 paramtype2 = "facedir",
261 legacy_facedir_simple = true,
262 is_ground_content = false,
263 sounds = default.node_sound_stone_defaults(),
267 on_timer = furnace_node_timer,
269 on_construct = function(pos)
270 local meta = minetest.get_meta(pos)
271 meta:set_string("formspec", default.get_furnace_inactive_formspec())
272 local inv = meta:get_inventory()
273 inv:set_size('src', 1)
274 inv:set_size('fuel', 1)
275 inv:set_size('dst', 4)
278 on_metadata_inventory_move = function(pos)
279 minetest.get_node_timer(pos):start(1.0)
281 on_metadata_inventory_put = function(pos)
282 -- start timer function, it will sort out whether furnace can burn or not.
283 minetest.get_node_timer(pos):start(1.0)
285 on_blast = function(pos)
287 default.get_inventory_drops(pos, "src", drops)
288 default.get_inventory_drops(pos, "fuel", drops)
289 default.get_inventory_drops(pos, "dst", drops)
290 drops[#drops+1] = "default:furnace"
291 minetest.remove_node(pos)
295 allow_metadata_inventory_put = allow_metadata_inventory_put,
296 allow_metadata_inventory_move = allow_metadata_inventory_move,
297 allow_metadata_inventory_take = allow_metadata_inventory_take,
300 minetest.register_node("default:furnace_active", {
301 description = "Furnace",
303 "default_furnace_top.png", "default_furnace_bottom.png",
304 "default_furnace_side.png", "default_furnace_side.png",
305 "default_furnace_side.png",
307 image = "default_furnace_front_active.png",
308 backface_culling = false,
310 type = "vertical_frames",
317 paramtype2 = "facedir",
319 drop = "default:furnace",
320 groups = {cracky=2, not_in_creative_inventory=1},
321 legacy_facedir_simple = true,
322 is_ground_content = false,
323 sounds = default.node_sound_stone_defaults(),
324 on_timer = furnace_node_timer,
328 allow_metadata_inventory_put = allow_metadata_inventory_put,
329 allow_metadata_inventory_move = allow_metadata_inventory_move,
330 allow_metadata_inventory_take = allow_metadata_inventory_take,