Damage anvil after falling
[MineClone/MineClone2.git] / mods / ITEMS / mcl_furnaces / init.lua
blobaaecd647962f7794852b874745003d008be499cc
2 --
3 -- Formspecs
4 --
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]"..
22 "tooltip[doc;Help]"..
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]"
29 end
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]"..
44 "tooltip[doc;Help]"..
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)
57 end
58 end
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
66 return 0
67 end
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
74 return 1
75 else
76 return 0
77 end
78 end
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()
91 else
92 if inv:get_stack(listname, index):get_count() == 0 then
93 return 1
94 else
95 return 0
96 end
97 end
98 else
99 return 0
101 elseif listname == "src" then
102 return stack:get_count()
103 elseif listname == "dst" then
104 return 0
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
117 return 0
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
136 return
138 node.name = name
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
156 local fuel
158 local update = true
159 while update do
160 update = false
162 srclist = inv:get_list("src")
163 fuellist = inv:get_list("fuel")
166 -- Cooking
169 -- Check if we have cookable content
170 local aftercooked
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
177 src_time = 0
178 src_item = srclist[1]:get_name()
179 update = true
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
186 if cookable then
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")
206 src_time = 0
207 update = true
209 elseif src_time ~= 0 then
210 -- If output slot is occupied, stop cooking
211 src_time = 0
212 update = true
215 else
216 -- Furnace ran out of fuel
217 if cookable then
218 -- We need to get new fuel
219 local afterfuel
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
224 fuel_totaltime = 0
225 src_time = 0
226 else
227 -- Take fuel from fuel list
228 inv:set_stack("fuel", 1, afterfuel.items[1])
229 update = true
230 fuel_totaltime = fuel.time + (fuel_time - fuel_totaltime)
231 src_time = src_time + elapsed
233 else
234 -- We don't need to get new fuel since there is no cookable item
235 fuel_totaltime = 0
236 src_time = 0
238 fuel_time = 0
241 elapsed = 0
244 if fuel and fuel_totaltime > fuel.time then
245 fuel_totaltime = fuel.time
247 if srclist[1]:is_empty() then
248 src_time = 0
252 -- Update formspec and node
254 local formspec = inactive_formspec
255 local item_state
256 local item_percent = 0
257 if cookable then
258 item_percent = math.floor(src_time / cooked.time * 100)
261 local result = false
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
268 result = true
269 else
270 swap_node(pos, "mcl_furnaces:furnace")
271 -- stop timer on the inactive furnace
272 minetest.get_node_timer(pos):stop()
276 -- Set meta values
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)
284 return result
287 local on_rotate
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,
297 tiles = {
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)
310 local meta2 = meta
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())
321 end,
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)
330 end,
332 on_metadata_inventory_move = function(pos)
333 minetest.get_node_timer(pos):start(1.0)
334 end,
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)
338 end,
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,
346 _mcl_hardness = 3.5,
347 on_rotate = on_rotate,
350 minetest.register_node("mcl_furnaces:furnace_active", {
351 description = "Burning Furnace",
352 _doc_items_create_entry = false,
353 tiles = {
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",
359 paramtype = "light",
360 light_source = 13,
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)
369 local meta2 = meta
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())
380 end,
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,
389 _mcl_hardness = 3.5,
390 on_rotate = on_rotate,
393 minetest.register_craft({
394 output = "mcl_furnaces:furnace",
395 recipe = {
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")