6 local function active_formspec(fuel_percent
, item_percent
)
7 return "size[9,8.75]"..
8 "background[-0.19,-0.25;9.41,9.49;crafting_inventory_furnace.png]"..
9 mcl_vars
.inventory_header
..
10 "list[current_player;main;0,4.5;9,3;9]"..
11 "list[current_player;main;0,7.74;9,1;]"..
12 "list[current_name;src;2.75,0.5;1,1;]"..
13 "list[current_name;fuel;2.75,2.5;1,1;]"..
14 "list[current_name;dst;5.75,1.5;1,1;]"..
15 "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:"..
16 (100-fuel_percent
)..":default_furnace_fire_fg.png]"..
17 "image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[lowpart:"..
18 (item_percent
)..":gui_furnace_arrow_fg.png^[transformR270]"..
19 "image_button[8,0;1,1;craftguide_book.png;craftguide;]"..
20 "image_button[8,1;1,1;doc_button_icon_lores.png;doc;]"..
21 "tooltip[craftguide;Recipe book]"..
23 "listring[current_name;dst]"..
24 "listring[current_player;main]"..
25 "listring[current_name;src]"..
26 "listring[current_player;main]"..
27 "listring[current_name;fuel]"..
28 "listring[current_player;main]"
31 local inactive_formspec
= "size[9,8.75]"..
32 "background[-0.19,-0.25;9.41,9.49;crafting_inventory_furnace.png]"..
33 mcl_vars
.inventory_header
..
34 "list[current_player;main;0,4.5;9,3;9]"..
35 "list[current_player;main;0,7.74;9,1;]"..
36 "list[current_name;src;2.75,0.5;1,1;]"..
37 "list[current_name;fuel;2.75,2.5;1,1;]"..
38 "list[current_name;dst;5.75,1.5;1,1;]"..
39 "image[2.75,1.5;1,1;default_furnace_fire_bg.png]"..
40 "image[4.1,1.5;1.5,1;gui_furnace_arrow_bg.png^[transformR270]"..
41 "image_button[8,0;1,1;craftguide_book.png;craftguide;]"..
42 "image_button[8,1;1,1;doc_button_icon_lores.png;doc;]"..
43 "tooltip[craftguide;Recipe book]"..
45 "listring[current_name;dst]"..
46 "listring[current_player;main]"..
47 "listring[current_name;src]"..
48 "listring[current_player;main]"..
49 "listring[current_name;fuel]"..
50 "listring[current_player;main]"
52 local receive_fields
= function(pos
, formname
, fields
, sender
)
53 if fields
.craftguide
then
54 mcl_craftguide
.show_craftguide(sender
)
55 elseif fields
.doc
and minetest
.get_modpath("doc") then
56 doc
.show_entry(sender
:get_player_name(), "nodes", "mcl_furnaces:furnace", true)
61 -- Node callback functions that are the same for active and inactive furnace
64 local function allow_metadata_inventory_put(pos
, listname
, index
, stack
, player
)
65 if minetest
.is_protected(pos
, player
:get_player_name()) then
68 local meta
= minetest
.get_meta(pos
)
69 local inv
= meta
:get_inventory()
70 if listname
== "fuel" then
71 -- Special case: empty bucket (not a fuel, but used for sponge drying)
72 if stack
:get_name() == "mcl_buckets:bucket_empty" then
73 if inv
:get_stack(listname
, index
):get_count() == 0 then
80 -- Test stack with size 1 because we burn one fuel at a time
81 local teststack
= ItemStack(stack
)
82 teststack
:set_count(1)
83 local output
, decremented_input
= minetest
.get_craft_result({method
="fuel", width
=1, items
={teststack
}})
84 if output
.time
~= 0 then
85 -- Only allow to place 1 item if fuel get replaced by recipe.
86 -- This is the case for lava buckets.
87 local replace_item
= decremented_input
.items
[1]
88 if replace_item
:is_empty() then
89 -- For most fuels, just allow to place everything
90 return stack
:get_count()
92 if inv
:get_stack(listname
, index
):get_count() == 0 then
101 elseif listname
== "src" then
102 return stack
:get_count()
103 elseif listname
== "dst" then
108 local function allow_metadata_inventory_move(pos
, from_list
, from_index
, to_list
, to_index
, count
, player
)
109 local meta
= minetest
.get_meta(pos
)
110 local inv
= meta
:get_inventory()
111 local stack
= inv
:get_stack(from_list
, from_index
)
112 return allow_metadata_inventory_put(pos
, to_list
, to_index
, stack
, player
)
115 local function allow_metadata_inventory_take(pos
, listname
, index
, stack
, player
)
116 if minetest
.is_protected(pos
, player
:get_player_name()) then
119 return stack
:get_count()
122 local function on_metadata_inventory_take(pos
, listname
, index
, stack
, player
)
123 -- Award smelting achievements
124 if listname
== "dst" then
125 if stack
:get_name() == "mcl_core:iron_ingot" then
126 awards
.unlock(player
:get_player_name(), "mcl:acquireIron")
127 elseif stack
:get_name() == "mcl_fishing:fish_cooked" then
128 awards
.unlock(player
:get_player_name(), "mcl:cookFish")
133 local function swap_node(pos
, name
)
134 local node
= minetest
.get_node(pos
)
135 if node
.name
== name
then
139 minetest
.swap_node(pos
, node
)
142 local function furnace_node_timer(pos
, elapsed
)
144 -- Inizialize metadata
146 local meta
= minetest
.get_meta(pos
)
147 local fuel_time
= meta
:get_float("fuel_time") or 0
148 local src_time
= meta
:get_float("src_time") or 0
149 local src_item
= meta
:get_string("src_item") or ""
150 local fuel_totaltime
= meta
:get_float("fuel_totaltime") or 0
152 local inv
= meta
:get_inventory()
153 local srclist
, fuellist
155 local cookable
, cooked
162 srclist
= inv
:get_list("src")
163 fuellist
= inv
:get_list("fuel")
169 -- Check if we have cookable content
171 cooked
, aftercooked
= minetest
.get_craft_result({method
= "cooking", width
= 1, items
= srclist
})
172 cookable
= cooked
.time
~= 0
174 -- Check if src item has been changed
175 if srclist
[1]:get_name() ~= src_item
then
176 -- Reset cooking progress in this case
178 src_item
= srclist
[1]:get_name()
181 -- Check if we have enough fuel to burn
182 elseif fuel_time
< fuel_totaltime
then
183 -- The furnace is currently active and has enough fuel
184 fuel_time
= fuel_time
+ elapsed
185 -- If there is a cookable item then check if it is ready yet
187 -- Successful cooking requires space in dst slot and time
188 if inv
:room_for_item("dst", cooked
.item
) then
189 src_time
= src_time
+ elapsed
191 -- Place result in dst list if done
192 if src_time
>= cooked
.time
then
193 inv
:add_item("dst", cooked
.item
)
194 inv
:set_stack("src", 1, aftercooked
.items
[1])
196 -- Unique recipe: Pour water into empty bucket after cooking wet sponge successfully
197 if inv
:get_stack("fuel", 1):get_name() == "mcl_buckets:bucket_empty" then
198 if srclist
[1]:get_name() == "mcl_sponges:sponge_wet" then
199 inv
:set_stack("fuel", 1, "mcl_buckets:bucket_water")
200 -- Also for river water
201 elseif srclist
[1]:get_name() == "mcl_sponges:sponge_wet_river_water" then
202 inv
:set_stack("fuel", 1, "mcl_buckets:bucket_river_water")
209 elseif src_time
~= 0 then
210 -- If output slot is occupied, stop cooking
216 -- Furnace ran out of fuel
218 -- We need to get new fuel
220 fuel
, afterfuel
= minetest
.get_craft_result({method
= "fuel", width
= 1, items
= fuellist
})
222 if fuel
.time
== 0 then
223 -- No valid fuel in fuel list
227 -- Take fuel from fuel list
228 inv
:set_stack("fuel", 1, afterfuel
.items
[1])
230 fuel_totaltime
= fuel
.time
+ (fuel_time
- fuel_totaltime
)
231 src_time
= src_time
+ elapsed
234 -- We don't need to get new fuel since there is no cookable item
244 if fuel
and fuel_totaltime
> fuel
.time
then
245 fuel_totaltime
= fuel
.time
247 if srclist
[1]:is_empty() then
252 -- Update formspec and node
254 local formspec
= inactive_formspec
256 local item_percent
= 0
258 item_percent
= math
.floor(src_time
/ cooked
.time
* 100)
263 if fuel_totaltime
~= 0 then
264 local fuel_percent
= math
.floor(fuel_time
/ fuel_totaltime
* 100)
265 formspec
= active_formspec(fuel_percent
, item_percent
)
266 swap_node(pos
, "mcl_furnaces:furnace_active")
267 -- make sure timer restarts automatically
270 swap_node(pos
, "mcl_furnaces:furnace")
271 -- stop timer on the inactive furnace
272 minetest
.get_node_timer(pos
):stop()
278 meta
:set_float("fuel_totaltime", fuel_totaltime
)
279 meta
:set_float("fuel_time", fuel_time
)
280 meta
:set_float("src_time", src_time
)
281 meta
:set_string("src_item", srclist
[1]:get_name())
282 meta
:set_string("formspec", formspec
)
288 if minetest
.get_modpath("screwdriver") then
289 on_rotate
= screwdriver
.rotate_simple
292 minetest
.register_node("mcl_furnaces:furnace", {
293 description
= "Furnace",
294 _doc_items_longdesc
= "Furnaces cook or smelt several items, using a furnace fuel, into something else.",
295 _doc_items_usagehelp
= "Right-click the furnace to view it. Place a furnace fuel in the lower slot and the source material in the upper slot. The furnace will slowly use its fuel to smelt the item. The result will be placed into the output slot at the right side.",
296 _doc_items_hidden
= false,
298 "default_furnace_top.png", "default_furnace_bottom.png",
299 "default_furnace_side.png", "default_furnace_side.png",
300 "default_furnace_side.png", "default_furnace_front.png"
302 paramtype2
= "facedir",
303 groups
= {pickaxey
=1, container
=4, deco_block
=1, material_stone
=1},
304 is_ground_content
= false,
305 sounds
= mcl_sounds
.node_sound_stone_defaults(),
307 on_timer
= furnace_node_timer
,
308 after_dig_node
= function(pos
, oldnode
, oldmetadata
, digger
)
309 local meta
= minetest
.get_meta(pos
)
311 meta
:from_table(oldmetadata
)
312 local inv
= meta
:get_inventory()
313 for _
, listname
in ipairs({"src", "dst", "fuel"}) do
314 local stack
= inv
:get_stack(listname
, 1)
315 if not stack
:is_empty() then
316 local p
= {x
=pos
.x
+math
.random(0, 10)/10-0.5, y
=pos
.y
, z
=pos
.z
+math
.random(0, 10)/10-0.5}
317 minetest
.add_item(p
, stack
)
320 meta
:from_table(meta2
:to_table())
323 on_construct
= function(pos
)
324 local meta
= minetest
.get_meta(pos
)
325 meta
:set_string("formspec", inactive_formspec
)
326 local inv
= meta
:get_inventory()
327 inv
:set_size('src', 1)
328 inv
:set_size('fuel', 1)
329 inv
:set_size('dst', 1)
332 on_metadata_inventory_move
= function(pos
)
333 minetest
.get_node_timer(pos
):start(1.0)
335 on_metadata_inventory_put
= function(pos
)
336 -- start timer function, it will sort out whether furnace can burn or not.
337 minetest
.get_node_timer(pos
):start(1.0)
340 allow_metadata_inventory_put
= allow_metadata_inventory_put
,
341 allow_metadata_inventory_move
= allow_metadata_inventory_move
,
342 allow_metadata_inventory_take
= allow_metadata_inventory_take
,
343 on_metadata_inventory_take
= on_metadata_inventory_take
,
344 on_receive_fields
= receive_fields
,
345 _mcl_blast_resistance
= 17.5,
347 on_rotate
= on_rotate
,
350 minetest
.register_node("mcl_furnaces:furnace_active", {
351 description
= "Burning Furnace",
352 _doc_items_create_entry
= false,
354 "default_furnace_top.png", "default_furnace_bottom.png",
355 "default_furnace_side.png", "default_furnace_side.png",
356 "default_furnace_side.png", "default_furnace_front_active.png",
358 paramtype2
= "facedir",
361 drop
= "mcl_furnaces:furnace",
362 groups
= {pickaxey
=1, container
=4, deco_block
=1, not_in_creative_inventory
=1, material_stone
=1},
363 is_ground_content
= false,
364 sounds
= mcl_sounds
.node_sound_stone_defaults(),
365 on_timer
= furnace_node_timer
,
367 after_dig_node
= function(pos
, oldnode
, oldmetadata
, digger
)
368 local meta
= minetest
.get_meta(pos
)
370 meta
:from_table(oldmetadata
)
371 local inv
= meta
:get_inventory()
372 for _
, listname
in ipairs({"src", "dst", "fuel"}) do
373 local stack
= inv
:get_stack(listname
, 1)
374 if not stack
:is_empty() then
375 local p
= {x
=pos
.x
+math
.random(0, 10)/10-0.5, y
=pos
.y
, z
=pos
.z
+math
.random(0, 10)/10-0.5}
376 minetest
.add_item(p
, stack
)
379 meta
:from_table(meta2
:to_table())
383 allow_metadata_inventory_put
= allow_metadata_inventory_put
,
384 allow_metadata_inventory_move
= allow_metadata_inventory_move
,
385 allow_metadata_inventory_take
= allow_metadata_inventory_take
,
386 on_metadata_inventory_take
= on_metadata_inventory_take
,
387 on_receive_fields
= receive_fields
,
388 _mcl_blast_resistance
= 17.5,
390 on_rotate
= on_rotate
,
393 minetest
.register_craft({
394 output
= "mcl_furnaces:furnace",
396 { "mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble" },
397 { "mcl_core:cobble", "", "mcl_core:cobble" },
398 { "mcl_core:cobble", "mcl_core:cobble", "mcl_core:cobble" },
402 -- Add entry alias for the Help
403 if minetest
.get_modpath("doc") then
404 doc
.add_entry_alias("nodes", "mcl_furnaces:furnace", "nodes", "mcl_furnaces:furnace_active")