Allow freezing several items at once
[freezer.git] / init.lua
1 --
2 -- Freezer for mintest: a device which turns water (in buckets) into ice
3 -- And does a couple of other tricks, discovering which is left as a pleasant
4 -- surprise for the player.
5 --
6
7 -- enable extra popsicle types provided there are both vessels and fruits/veggies available
8 -- fruit + glass -> juice; juice @ freezer -> popsicle + empty glass
9
10 if minetest.get_modpath("vessels") then
11 dofile(minetest.get_modpath("freezer") .. "/juices.lua")
12 end
13
14 --
15 -- Formspecs
16 --
17
18 local function active_formspec(fuel_percent, item_percent)
19 local formspec =
20 "size[8,8.5]"..
21 default.gui_bg..
22 default.gui_bg_img..
23 default.gui_slots..
24 "list[current_name;src;2.5,1;1,1;]"..
25 "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[lowpart:"..
26 (item_percent)..":gui_furnace_arrow_fg.png^[transformR270]"..
27 "list[current_name;dst;4.75,0.96;3,2;]"..
28 "list[current_player;main;0,4.25;8,1;]"..
29 "list[current_player;main;0,5.5;8,3;8]"..
30 "listring[current_name;dst]"..
31 "listring[current_player;main]"..
32 "listring[current_name;src]"..
33 "listring[current_player;main]"..
34 default.get_hotbar_bg(0, 4.25)
35 return formspec
36 end
37
38 local inactive_formspec =
39 "size[8,8.5]"..
40 default.gui_bg..
41 default.gui_bg_img..
42 default.gui_slots..
43 "list[current_name;src;2.5,1.5;1,1;]"..
44 "image[3.75,1.5;1,1;gui_furnace_arrow_bg.png^[transformR270]"..
45 "list[current_name;dst;4.75,0.96;3,2;]"..
46 "list[current_player;main;0,4.25;8,1;]"..
47 "list[current_player;main;0,5.5;8,3;8]"..
48 "listring[current_name;dst]"..
49 "listring[current_player;main]"..
50 "listring[current_name;src]"..
51 "listring[current_player;main]"..
52 default.get_hotbar_bg(0, 4.25)
53
54 --
55 -- Node callback functions that are the same for active and inactive freezer
56 --
57
58 local function can_dig(pos, player)
59 local meta = minetest.get_meta(pos);
60 local inv = meta:get_inventory()
61 return inv:is_empty("dst") and inv:is_empty("src")
62 end
63
64
65 local function allow_metadata_inventory_put(pos, listname, index, stack, player)
66 if minetest.is_protected(pos, player:get_player_name()) then
67 return 0
68 end
69 local meta = minetest.get_meta(pos)
70 local inv = meta:get_inventory()
71 if listname == "src" then
72 return stack:get_count()
73 elseif listname == "dst" then
74 return 0
75 end
76 end
77
78
79 local function allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
80 local meta = minetest.get_meta(pos)
81 local inv = meta:get_inventory()
82 local stack = inv:get_stack(from_list, from_index)
83 return allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
84 end
85
86
87 local function allow_metadata_inventory_take(pos, listname, index, stack, player)
88 if minetest.is_protected(pos, player:get_player_name()) then
89 return 0
90 end
91 return stack:get_count()
92 end
93
94
95 local function swap_node(pos, name)
96 local node = minetest.get_node(pos)
97 if node.name == name then
98 return
99 end
100 node.name = name
101 minetest.swap_node(pos, node)
102 end
103
104
105 local function freezer_node_timer(pos, elapsed)
106 --
107 -- Inizialize metadata
108 --
109 local meta = minetest.get_meta(pos)
110
111 local src_time = meta:get_float("src_time") or 0
112
113
114 local inv = meta:get_inventory()
115 local srclist = inv:get_list("src")
116
117 local dstlist = inv:get_list("dst")
118
119 --
120 -- Cooking
121 --
122
123 -- takes both regular and river water
124 if inv:contains_item("src", "bucket:bucket_water") or
125 inv:contains_item("src", "bucket:bucket_river_water") then
126 if inv:room_for_item("dst", "default:ice") then
127 inv:remove_item("src", "bucket:bucket_water")
128 inv:remove_item("src", "bucket:bucket_river_water")
129 inv:add_item("dst", "default:ice")
130 inv:add_item("dst", "bucket:bucket_empty")
131 end
132 end
133
134 -- an extra recipe involving liquid in a bucket, for good measure
135 -- a cactus pulp bucket gives 2 hp, but freezing it gives 3 popsicles, each
136 -- of them giving 1 hp, achieving 50% increase in efficiency through processing
137 if minetest.get_modpath("ethereal") then
138 if inv:contains_item("src", "ethereal:bucket_cactus") then
139 if inv:room_for_item("dst", "freezer:cactus_popsicle 3") then
140 inv:remove_item("src", "ethereal:bucket_cactus")
141 inv:add_item("dst", "freezer:cactus_popsicle 3")
142 inv:add_item("dst", "bucket:bucket_empty")
143 end
144 end
145 end
146
147 -- and yet another liquid in a bucket, this time with no extravagance though
148 if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" then
149 if inv:contains_item("src", "mobs:bucket_milk") then
150 if inv:room_for_item("dst", "freezer:milk_popsicle 3") then
151 inv:remove_item("src", "mobs:bucket_milk")
152 inv:add_item("dst", "freezer:milk_popsicle 3")
153 inv:add_item("dst", "bucket:bucket_empty")
154 end
155 end
156 end
157
158 -- and of course what is hot can be cooled down
159 if minetest.get_modpath("farming") then
160 if inv:contains_item("src", "farming:coffee_cup_hot") then
161 while inv:room_for_item("dst", "farming:coffee_cup") do
162 local removed = inv:remove_item("src", "farming:coffee_cup_hot")
163 if removed:get_count() > 0 then
164 inv:add_item("dst", "farming:coffee_cup")
165 else
166 break
167 end
168 end
169 end
170 end
171
172 -- juices -> popsicles
173 -- since we're dealing with 1 glass and not 1 bucket, the output is 1 item
174 if minetest.get_modpath("vessels") then
175 local input_stack = inv:get_stack("src", 1);
176 local input_name = input_stack:get_name();
177 if minetest.get_item_group(input_name, "juice") > 0 then
178 local output_name = input_name .. "_popsicle"
179 while inv:room_for_item("dst", output_name) do
180 local removed = inv:remove_item("src", input_name)
181 if removed:get_count() > 0 then
182 inv:add_item("dst", output_name)
183 inv:add_item("dst", "vessels:drinking_glass")
184 else
185 break
186 end
187 end
188 end
189 end
190
191
192 -- pelmeni
193 -- while freezing is a crucial step in preparation, the full chain involves extra steps:
194 -- raw pelmeni -> pack of frozen pelmeni -> actual cooked pelmeni
195 if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" and minetest.get_modpath("farming") then
196 if inv:contains_item("src", "freezer:pelmeni_raw") then
197 if inv:room_for_item("dst", "freezer:pelmeni_pack 3") then
198 inv:remove_item("src", "freezer:pelmeni_raw")
199 inv:add_item("dst", "freezer:pelmeni_pack 3")
200 end
201 end
202 end
203
204 -- aspic
205 if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" and minetest.get_modpath("ethereal") then
206 if inv:contains_item("src", "freezer:meat_broth") then
207 if inv:room_for_item("dst", "freezer:aspic 5") then
208 inv:remove_item("src", "freezer:meat_broth")
209 inv:add_item("dst", "freezer:aspic 5")
210 inv:add_item("dst", "bucket:bucket_empty")
211 end
212 end
213 end
214
215 -- Check if we have cookable content
216 return true
217 end
218
219
220 --
221 -- Node definitions
222 --
223
224 minetest.register_node("freezer:freezer", {
225 description = "Freezer",
226 tiles = {
227 "freezer_top.png", "freezer_top.png",
228 "freezer_side.png", "freezer_side.png",
229 "freezer_side.png", "freezer_front.png"
230 },
231 paramtype2 = "facedir",
232 groups = {cracky = 2, tubedevice = 1, tubedevice_receiver = 1},
233 legacy_facedir_simple = true,
234 is_ground_content = false,
235 sounds = default.node_sound_stone_defaults(),
236
237 tube = (function() if minetest.get_modpath("pipeworks") then return {
238 -- using a different stack from defaut when inserting
239 insert_object = function(pos, node, stack, direction)
240 local meta = minetest.get_meta(pos)
241 local inv = meta:get_inventory()
242 local timer = minetest.get_node_timer(pos)
243 if not timer:is_started() then
244 timer:start(1.0)
245 end
246 return inv:add_item("src", stack)
247 end,
248 can_insert = function(pos,node,stack,direction)
249 local meta = minetest.get_meta(pos)
250 local inv = meta:get_inventory()
251 return inv:room_for_item("src", stack)
252 end,
253 -- the default stack, from which objects will be taken
254 input_inventory = "dst",
255 connect_sides = {left = 1, right = 1, back = 1, front = 1, bottom = 1, top = 1}
256 } end end)(),
257
258 can_dig = can_dig,
259
260 on_timer = freezer_node_timer,
261
262 on_construct = function(pos)
263 local meta = minetest.get_meta(pos)
264 meta:set_string("formspec", inactive_formspec)
265 local inv = meta:get_inventory()
266 inv:set_size('src', 1)
267 inv:set_size('dst', 6)
268 end,
269
270 on_metadata_inventory_move = function(pos)
271 local timer = minetest.get_node_timer(pos)
272 timer:start(1.0)
273 end,
274 on_metadata_inventory_put = function(pos)
275 -- start timer function, it will sort out whether freezer will work or not.
276 local timer = minetest.get_node_timer(pos)
277 timer:start(1.0)
278 end,
279 on_blast = function(pos)
280 local drops = {}
281 default.get_inventory_drops(pos, "src", drops)
282 default.get_inventory_drops(pos, "dst", drops)
283 drops[#drops+1] = "freezer:freezer"
284 minetest.remove_node(pos)
285 return drops
286 end,
287
288 allow_metadata_inventory_put = allow_metadata_inventory_put,
289 allow_metadata_inventory_move = allow_metadata_inventory_move,
290 allow_metadata_inventory_take = allow_metadata_inventory_take,
291 })
292
293
294 if minetest.get_modpath("ethereal") then
295 minetest.register_craftitem("freezer:cactus_popsicle", {
296 description = "Cactus Pulp Popsicle",
297 inventory_image = "cactus_popsicle.png",
298 wield_image = "cactus_popsicle.png",
299 stack_max = 99,
300 groups = { not_in_creative_inventory = 1 },
301 on_use = minetest.item_eat(1, "default:stick"),
302 })
303 end
304
305
306 if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" then
307 minetest.register_craftitem("freezer:milk_popsicle", {
308 description = "Eskimo icecream",
309 inventory_image = "milk_popsicle.png",
310 wield_image = "milk_popsicle.png",
311 stack_max = 99,
312 groups = { not_in_creative_inventory = 1 },
313 on_use = minetest.item_eat(1, "default:stick"),
314 })
315 end
316
317 -- aspic
318 -- bones + bucket of water + meat = broth -> freezer -> portions of aspic
319
320 if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" and minetest.get_modpath("ethereal") then
321 minetest.register_craftitem("freezer:meat_broth", {
322 description = "Meat broth",
323 inventory_image = "meat_broth.png",
324 wield_image = "meat_broth.png",
325 stack_max = 99,
326 groups = { },
327 on_use = minetest.item_eat(3, "bucket:bucket_empty"),
328 })
329
330 minetest.register_craft({
331 type = "shapeless",
332 output = "freezer:meat_broth",
333 recipe = {"mobs:meat_raw", "ethereal:bone", "bucket:bucket_river_water"},
334 })
335
336 minetest.register_craft({
337 type = "shapeless",
338 output = "freezer:meat_broth",
339 recipe = {"mobs:meat_raw", "ethereal:bone", "bucket:bucket_water"},
340 })
341
342 minetest.register_craftitem("freezer:aspic", {
343 description = "A portion of aspic",
344 inventory_image = "aspic.png",
345 wield_image = "aspic.png",
346 stack_max = 99,
347 groups = { not_in_creative_inventory = 1 },
348 on_use = minetest.item_eat(6),
349 })
350 end
351
352 -- pelmeni (dumplings with meat filling)
353 if minetest.get_modpath("mobs") and mobs and mobs.mod == "redo" and minetest.get_modpath("farming") then
354
355 -- both the dough and the frozen pelmeni are nigh inedible
356 -- only the cooked product should reveal the benefits of preparing this food
357
358 minetest.register_craftitem("freezer:pelmeni_raw", {
359 description = "Raw pelmeni",
360 inventory_image = "pelmeni_raw.png",
361 wield_image = "pelmeni_raw.png",
362 stack_max = 99,
363 groups = { },
364 on_use = minetest.item_eat(1),
365 })
366
367 minetest.register_craftitem("freezer:pelmeni_pack", {
368 description = "A pack of frozen pelmeni",
369 inventory_image = "pelmeni_pack.png",
370 wield_image = "pelmeni_pack.png",
371 stack_max = 99,
372 groups = { not_in_creative_inventory = 1 },
373 on_use = minetest.item_eat(1),
374 })
375
376 minetest.register_craftitem("freezer:pelmeni", {
377 description = "Cooked pelmeni",
378 inventory_image = "pelmeni.png",
379 wield_image = "pelmeni.png",
380 stack_max = 99,
381 groups = { not_in_creative_inventory = 1 },
382 on_use = minetest.item_eat(10),
383 })
384
385 minetest.register_craft({
386 type = "shapeless",
387 output = "freezer:pelmeni_raw",
388 recipe = {"mobs:meat_raw", "farming:flour", "farming:flour", "farming:flour"},
389 })
390
391 minetest.register_craft({
392 type = "cooking",
393 cooktime = 10,
394 output = "freezer:pelmeni",
395 recipe = "freezer:pelmeni_pack"
396 })
397
398
399 end
400
401
402 minetest.register_craft({
403 output = "freezer:freezer",
404 recipe = {
405 {"default:steel_ingot", "default:mese_crystal", "default:steel_ingot"},
406 {"default:steel_ingot", "", "default:steel_ingot"},
407 {"default:steel_ingot", "default:mese_crystal", "default:steel_ingot"}
408 }
409 })
410
411
412 minetest.register_craft({
413 output = "default:snowblock 3",
414 type = "shapeless",
415 recipe = {
416 "default:ice"
417 }
418 })