]> git.lizzy.rs Git - Crafter.git/blob - mods/utility/init.lua
Remove furnace infotext
[Crafter.git] / mods / utility / init.lua
1 --formspecs
2
3 local furnace = {}
4
5 function furnace.get_hotbar_bg(x,y)
6         local out = ""
7         for i=0,7,1 do
8                 out = out .."image["..x+i..","..y..";1,1;gui_furnace_arrow_bg.png]"
9         end
10         return(out)
11 end
12
13 function furnace.get_inventory_drops(pos, inventory, drops)
14         local inv = minetest.get_meta(pos):get_inventory()
15         local n = #drops
16         for i = 1, inv:get_size(inventory) do
17                 local stack = inv:get_stack(inventory, i)
18                 if stack:get_count() > 0 then
19                         drops[n+1] = stack:to_table()
20                         n = n + 1
21                 end
22         end
23 end
24
25 function furnace.get_furnace_active_formspec(fuel_percent, item_percent)
26         return "size[8,8.5]"..
27                 "list[context;src;2.75,0.5;1,1;]"..
28                 "list[context;fuel;2.75,2.5;1,1;]"..
29                 "image[2.75,1.5;1,1;default_furnace_fire_bg.png^[lowpart:"..
30                 (fuel_percent)..":default_furnace_fire_fg.png]"..
31                 "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:"..
32                 (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
33                 "list[context;dst;4.75,0.96;2,2;]"..
34                 "list[current_player;main;0,4.25;8,1;]"..
35                 "list[current_player;main;0,5.5;8,3;8]"..
36                 "listring[context;dst]"..
37                 "listring[current_player;main]"..
38                 "listring[context;src]"..
39                 "listring[current_player;main]"..
40                 "listring[context;fuel]"..
41                 "listring[current_player;main]"..
42                 furnace.get_hotbar_bg(0, 4.25)
43 end
44
45 function furnace.get_furnace_inactive_formspec()
46         return "size[8,8.5]"..
47                 "list[context;src;2.75,0.5;1,1;]"..
48                 "list[context;fuel;2.75,2.5;1,1;]"..
49                 "image[2.75,1.5;1,1;default_furnace_fire_bg.png]"..
50                 "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"..
51                 "list[context;dst;4.75,0.96;2,2;]"..
52                 "list[current_player;main;0,4.25;8,1;]"..
53                 "list[current_player;main;0,5.5;8,3;8]"..
54                 "listring[context;dst]"..
55                 "listring[current_player;main]"..
56                 "listring[context;src]"..
57                 "listring[current_player;main]"..
58                 "listring[context;fuel]"..
59                 "listring[current_player;main]"..
60                 furnace.get_hotbar_bg(0, 4.25)
61 end
62
63 --
64 -- Node callback functions that are the same for active and inactive furnace
65 --
66
67 local function can_dig(pos, player)
68         local meta = minetest.get_meta(pos);
69         local inv = meta:get_inventory()
70         return inv:is_empty("fuel") and inv:is_empty("dst") and inv:is_empty("src")
71 end
72
73 local function allow_metadata_inventory_put(pos, listname, index, stack, player)
74         if minetest.is_protected(pos, player:get_player_name()) then
75                 return 0
76         end
77         local meta = minetest.get_meta(pos)
78         local inv = meta:get_inventory()
79         if listname == "fuel" then
80                 if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
81                         if inv:is_empty("src") then
82                                 --meta:set_string("infotext", "Furnace is empty")
83                         end
84                         return stack:get_count()
85                 else
86                         return 0
87                 end
88         elseif listname == "src" then
89                 return stack:get_count()
90         elseif listname == "dst" then
91                 return 0
92         end
93 end
94
95 local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
96         local meta = minetest.get_meta(pos)
97         local inv = meta:get_inventory()
98         local stack = inv:get_stack(from_list, from_index)
99         return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
100 end
101
102 local function allow_metadata_inventory_take(pos, listname, index, stack, player)
103         if minetest.is_protected(pos, player:get_player_name()) then
104                 return 0
105         end
106         return stack:get_count()
107 end
108
109 local function swap_node(pos, name)
110         local node = minetest.get_node(pos)
111         if node.name == name then
112                 return
113         end
114         node.name = name
115         minetest.swap_node(pos, node)
116 end
117
118 local function furnace_node_timer(pos, elapsed)
119         --
120         -- Initialize metadata
121         --
122         local meta = minetest.get_meta(pos)
123         local fuel_time = meta:get_float("fuel_time") or 0
124         local src_time = meta:get_float("src_time") or 0
125         local fuel_totaltime = meta:get_float("fuel_totaltime") or 0
126
127         local inv = meta:get_inventory()
128         local srclist, fuellist
129         local dst_full = false
130
131         local cookable, cooked
132         local fuel
133
134         local update = true
135         while elapsed > 0 and update do
136                 update = false
137
138                 srclist = inv:get_list("src")
139                 fuellist = inv:get_list("fuel")
140
141                 --
142                 -- Cooking
143                 --
144
145                 -- Check if we have cookable content
146                 local aftercooked
147                 cooked, aftercooked = minetest.get_craft_result({method = "cooking", width = 1, items = srclist})
148                 cookable = cooked.time ~= 0
149
150                 local el = math.min(elapsed, fuel_totaltime - fuel_time)
151                 if cookable then -- fuel lasts long enough, adjust el to cooking duration
152                         el = math.min(el, cooked.time - src_time)
153                 end
154
155                 -- Check if we have enough fuel to burn
156                 if fuel_time < fuel_totaltime then
157                         -- The furnace is currently active and has enough fuel
158                         fuel_time = fuel_time + el
159                         -- If there is a cookable item then check if it is ready yet
160                         if cookable then
161                                 src_time = src_time + el
162                                 if src_time >= cooked.time then
163                                         -- Place result in dst list if possible
164                                         if inv:room_for_item("dst", cooked.item) then
165                                                 inv:add_item("dst", cooked.item)
166                                                 inv:set_stack("src", 1, aftercooked.items[1])
167                                                 src_time = src_time - cooked.time
168                                                 update = true
169                                         else
170                                                 dst_full = true
171                                         end
172                                 else
173                                         -- Item could not be cooked: probably missing fuel
174                                         update = true
175                                 end
176                         end
177                 else
178                         -- Furnace ran out of fuel
179                         if cookable then
180                                 -- We need to get new fuel
181                                 local afterfuel
182                                 fuel, afterfuel = minetest.get_craft_result({method = "fuel", width = 1, items = fuellist})
183
184                                 if fuel.time == 0 then
185                                         -- No valid fuel in fuel list
186                                         fuel_totaltime = 0
187                                         src_time = 0
188                                 else
189                                         -- Take fuel from fuel list
190                                         inv:set_stack("fuel", 1, afterfuel.items[1])
191                                         -- Put replacements in dst list or drop them on the furnace.
192                                         local replacements = fuel.replacements
193                                         if replacements[1] then
194                                                 local leftover = inv:add_item("dst", replacements[1])
195                                                 if not leftover:is_empty() then
196                                                         local above = vector.new(pos.x, pos.y + 1, pos.z)
197                                                         local drop_pos = minetest.find_node_near(above, 1, {"air"}) or above
198                                                         minetest.item_drop(replacements[1], nil, drop_pos)
199                                                 end
200                                         end
201                                         update = true
202                                         fuel_totaltime = fuel.time + (fuel_totaltime - fuel_time)
203                                 end
204                         else
205                                 -- We don't need to get new fuel since there is no cookable item
206                                 fuel_totaltime = 0
207                                 src_time = 0
208                         end
209                         fuel_time = 0
210                 end
211
212                 elapsed = elapsed - el
213         end
214
215         if fuel and fuel_totaltime > fuel.time then
216                 fuel_totaltime = fuel.time
217         end
218         if srclist and srclist[1]:is_empty() then
219                 src_time = 0
220         end
221
222         --
223         -- Update formspec, infotext and node
224         --
225         local formspec
226         local item_state
227         local item_percent = 0
228         if cookable then
229                 item_percent = math.floor(src_time / cooked.time * 100)
230                 if dst_full then
231                         item_state = "100% (output full)"
232                 else
233                         item_state = "@1%", item_percent
234                 end
235         else
236                 if srclist and not srclist[1]:is_empty() then
237                         item_state = "Not cookable"
238                 else
239                         item_state = "Empty"
240                 end
241         end
242
243         local fuel_state = "Empty"
244         local active = false
245         local result = false
246
247         if fuel_totaltime ~= 0 then
248                 active = true
249                 local fuel_percent = 100 - math.floor(fuel_time / fuel_totaltime * 100)
250                 fuel_state = "@1%", fuel_percent
251                 formspec = furnace.get_furnace_active_formspec(fuel_percent, item_percent)
252                 swap_node(pos, "utility:furnace_active")
253                 -- make sure timer restarts automatically
254                 result = true
255         else
256                 if fuellist and not fuellist[1]:is_empty() then
257                         fuel_state = "@1%", 0
258                 end
259                 formspec = furnace.get_furnace_inactive_formspec()
260                 swap_node(pos, "utility:furnace")
261                 -- stop timer on the inactive furnace
262                 minetest.get_node_timer(pos):stop()
263         end
264
265
266         local infotext
267         if active then
268                 infotext = "Furnace active"
269         else
270                 infotext = "Furnace inactive"
271         end
272         infotext = infotext .. "\n" .. "(Item: @1; Fuel: @2)", item_state, fuel_state
273
274         --
275         -- Set meta values
276         --
277         meta:set_float("fuel_totaltime", fuel_totaltime)
278         meta:set_float("fuel_time", fuel_time)
279         meta:set_float("src_time", src_time)
280         meta:set_string("formspec", formspec)
281         --meta:set_string("infotext", infotext)
282
283         return result
284 end
285
286 --
287 -- Node definitions
288 --
289
290 minetest.register_node("utility:furnace", {
291         description = "Furnace",
292         tiles = {
293                 "furnace_top.png", "furnace_bottom.png",
294                 "furnace_side.png", "furnace_side.png",
295                 "furnace_side.png", "furnace_front.png"
296         },
297         paramtype2 = "facedir",
298         groups = {stone=2},
299         legacy_facedir_simple = true,
300         is_ground_content = false,
301         sounds = main.stoneSound(),
302
303         can_dig = can_dig,
304
305         on_timer = furnace_node_timer,
306
307         on_construct = function(pos)
308                 local meta = minetest.get_meta(pos)
309                 local inv = meta:get_inventory()
310                 inv:set_size('src', 1)
311                 inv:set_size('fuel', 1)
312                 inv:set_size('dst', 4)
313                 furnace_node_timer(pos, 0)
314         end,
315
316         on_metadata_inventory_move = function(pos)
317                 minetest.get_node_timer(pos):start(1.0)
318         end,
319         on_metadata_inventory_put = function(pos)
320                 -- start timer function, it will sort out whether furnace can burn or not.
321                 minetest.get_node_timer(pos):start(1.0)
322         end,
323         on_blast = function(pos)
324                 local drops = {}
325                 furnace.get_inventory_drops(pos, "src", drops)
326                 furnace.get_inventory_drops(pos, "fuel", drops)
327                 furnace.get_inventory_drops(pos, "dst", drops)
328                 drops[#drops+1] = "default:furnace"
329                 minetest.remove_node(pos)
330                 return drops
331         end,
332
333         allow_metadata_inventory_put = allow_metadata_inventory_put,
334         allow_metadata_inventory_move = allow_metadata_inventory_move,
335         allow_metadata_inventory_take = allow_metadata_inventory_take,
336 })
337
338 minetest.register_node("utility:furnace_active", {
339         description = "Furnace",
340         tiles = {
341                 "furnace_top.png", "furnace_bottom.png",
342                 "furnace_side.png", "furnace_side.png",
343                 "furnace_side.png",
344                 {
345                         image = "furnace_front_active.png",
346                         backface_culling = false,
347                         animation = {
348                                 type = "vertical_frames",
349                                 aspect_w = 16,
350                                 aspect_h = 16,
351                                 length = 1.5
352                         },
353                 }
354         },
355         paramtype2 = "facedir",
356         light_source = 8,
357         drop = "default:furnace",
358         groups = {stone=2, not_in_creative_inventory=1},
359         legacy_facedir_simple = true,
360         is_ground_content = false,
361         sounds = main.stoneSound(),
362         on_timer = furnace_node_timer,
363
364         can_dig = can_dig,
365
366         allow_metadata_inventory_put = allow_metadata_inventory_put,
367         allow_metadata_inventory_move = allow_metadata_inventory_move,
368         allow_metadata_inventory_take = allow_metadata_inventory_take,
369 })
370
371 minetest.register_craft({
372         output = "utility:furnace",
373         recipe = {
374                 {"main:stone", "main:stone", "main:stone"},
375                 {"main:stone", "",           "main:stone"},
376                 {"main:stone", "main:stone", "main:stone"},
377         }
378 })