Version 0.41.3
[MineClone/MineClone2/MineClone2-Fixes.git] / mods / ITEMS / mcl_chests / init.lua
blobe17dcd5978a4ee10d3459b4a7436899773911427
1 local no_rotate, simple_rotate
2 if minetest.get_modpath("screwdriver") then
3 no_rotate = screwdriver.disallow
4 simple_rotate = screwdriver.rotate_simple
5 end
7 --[[ List of open chests.
8 Key: Player name
9 Value:
10 If player is using a chest: { pos = <chest node position> }
11 Otherwise: nil ]]
12 local open_chests = {}
13 -- To be called if a player opened a chest
14 local player_chest_open = function(player, pos)
15 open_chests[player:get_player_name()] = { pos = pos }
16 end
18 local trapped_chest_mesecons_rules = mesecon.rules.pplate
20 -- To be called if a player closed a chest
21 local player_chest_close = function(player)
22 local name = player:get_player_name()
23 if open_chests[name] == nil then
24 return
25 end
26 local pos = open_chests[name].pos
27 local node = minetest.get_node(pos)
29 if node.name == "mcl_chests:trapped_chest_on" then
30 minetest.swap_node(pos, {name="mcl_chests:trapped_chest", param2 = node.param2})
31 mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
32 elseif node.name == "mcl_chests:trapped_chest_on_left" then
33 minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
34 mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
36 local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
37 minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
38 mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
39 elseif node.name == "mcl_chests:trapped_chest_on_right" then
40 minetest.swap_node(pos, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
41 mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
43 local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
44 minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
45 mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
46 end
48 open_chests[name] = nil
49 end
51 -- This is a helper function to register both chests and trapped chests. Trapped chests will make use of the additional parameters
52 local register_chest = function(basename, desc, longdesc, usagehelp, tiles_table, hidden, mesecons, on_rightclick_addendum, on_rightclick_addendum_left, on_rightclick_addendum_right, drop, formspec_basename)
53 -- START OF register_chest FUNCTION BODY
54 if not drop then
55 drop = "mcl_chests:"..basename
56 else
57 drop = "mcl_chests:"..drop
58 end
59 if not formspec_basename then
60 formspec_basename = basename
61 end
63 minetest.register_node("mcl_chests:"..basename, {
64 description = desc,
65 _doc_items_longdesc = longdesc,
66 _doc_items_usagehelp = usagehelp,
67 _doc_items_hidden = hidden,
68 tiles = tiles_table.small,
69 paramtype = "light",
70 paramtype2 = "facedir",
71 stack_max = 64,
72 drop = drop,
73 groups = {handy=1,axey=1, container=2, deco_block=1, material_wood=1},
74 is_ground_content = false,
75 sounds = mcl_sounds.node_sound_wood_defaults(),
76 on_construct = function(pos)
77 local param2 = minetest.get_node(pos).param2
78 local meta = minetest.get_meta(pos)
79 --[[ This is a workaround for Minetest issue 5894
80 <https://github.com/minetest/minetest/issues/5894>.
81 Apparently if we don't do this, double chests initially don't work when
82 placed at chunk borders, and some chests randomly don't work after
83 placing. ]]
84 -- FIXME: Remove this workaround when the bug has been fixed.
85 -- BEGIN OF WORKAROUND --
86 meta:set_string("workaround", "ignore_me")
87 meta:set_string("workaround", nil) -- Done to keep metadata clean
88 -- END OF WORKAROUND --
89 local inv = meta:get_inventory()
90 inv:set_size("main", 9*3)
91 --[[ The "input" list is *another* workaround (hahahaha!) around the fact that Minetest
92 does not support listrings to put items into an alternative list if the first one
93 happens to be full. See <https://github.com/minetest/minetest/issues/5343>.
94 This list is a hidden input-only list and immediately puts items into the appropriate chest.
95 It is only used for listrings and hoppers. This workaround is not that bad because it only
96 requires a simple “inventory allows” check for large chests.]]
97 -- FIXME: Refactor the listrings as soon Minetest supports alternative listrings
98 -- BEGIN OF LISTRING WORKAROUND
99 inv:set_size("input", 1)
100 -- END OF LISTRING WORKAROUND
101 if minetest.get_node(mcl_util.get_double_container_neighbor_pos(pos, param2, "right")).name == "mcl_chests:"..basename then
102 minetest.swap_node(pos, {name="mcl_chests:"..basename.."_right",param2=param2})
103 local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "right")
104 minetest.swap_node(p, { name = "mcl_chests:"..basename.."_left", param2 = param2 })
105 elseif minetest.get_node(mcl_util.get_double_container_neighbor_pos(pos, param2, "left")).name == "mcl_chests:"..basename then
106 minetest.swap_node(pos, {name="mcl_chests:"..basename.."_left",param2=param2})
107 local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "left")
108 minetest.swap_node(p, { name = "mcl_chests:"..basename.."_right", param2 = param2 })
110 end,
111 after_dig_node = function(pos, oldnode, oldmetadata, digger)
112 local meta = minetest.get_meta(pos)
113 local meta2 = meta
114 meta:from_table(oldmetadata)
115 local inv = meta:get_inventory()
116 for i=1,inv:get_size("main") do
117 local stack = inv:get_stack("main", i)
118 if not stack:is_empty() then
119 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}
120 minetest.add_item(p, stack)
123 meta:from_table(meta2:to_table())
124 end,
125 on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
126 minetest.log("action", player:get_player_name()..
127 " moves stuff in chest at "..minetest.pos_to_string(pos))
128 end,
129 on_metadata_inventory_put = function(pos, listname, index, stack, player)
130 minetest.log("action", player:get_player_name()..
131 " moves stuff to chest at "..minetest.pos_to_string(pos))
132 -- BEGIN OF LISTRING WORKAROUND
133 if listname == "input" then
134 local inv = minetest.get_inventory({type="node", pos=pos})
135 inv:add_item("main", stack)
137 -- END OF LISTRING WORKAROUND
138 end,
139 on_metadata_inventory_take = function(pos, listname, index, stack, player)
140 minetest.log("action", player:get_player_name()..
141 " takes stuff from chest at "..minetest.pos_to_string(pos))
142 end,
143 _mcl_blast_resistance = 2.5,
144 _mcl_hardness = 2.5,
146 on_rightclick = function(pos, node, clicker)
147 minetest.show_formspec(clicker:get_player_name(),
148 "mcl_chests:"..formspec_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
149 "size[9,8.75]"..
150 mcl_vars.inventory_header..
151 "background[-0.19,-0.25;9.41,10.48;mcl_chests_inventory_chest.png]"..
152 "image[0,-0.2;5,0.75;mcl_chests_fnt_chest.png]"..
153 "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]"..
154 "list[current_player;main;0,4.5;9,3;9]"..
155 "list[current_player;main;0,7.74;9,1;]"..
156 "listring[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main]"..
157 "listring[current_player;main]")
159 if on_rightclick_addendum then
160 on_rightclick_addendum(pos, node, clicker)
162 end,
164 on_destruct = function(pos)
165 local players = minetest.get_connected_players()
166 for p=1, #players do
167 minetest.close_formspec(players[p]:get_player_name(), "mcl_chests:"..formspec_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z)
169 end,
170 mesecons = mesecons,
171 on_rotate = simple_rotate,
174 minetest.register_node("mcl_chests:"..basename.."_left", {
175 tiles = tiles_table.left,
176 paramtype = "light",
177 paramtype2 = "facedir",
178 groups = {handy=1,axey=1, container=5,not_in_creative_inventory=1, material_wood=1},
179 drop = drop,
180 is_ground_content = false,
181 sounds = mcl_sounds.node_sound_wood_defaults(),
182 on_destruct = function(pos)
183 local n = minetest.get_node(pos)
184 if n.name == "mcl_chests:"..basename then
185 return
188 local players = minetest.get_connected_players()
189 for p=1, #players do
190 minetest.close_formspec(players[p]:get_player_name(), "mcl_chests:"..formspec_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z)
193 local param2 = n.param2
194 local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "left")
195 if not p or minetest.get_node(p).name ~= "mcl_chests:"..basename.."_right" then
196 return
198 minetest.swap_node(p, { name = "mcl_chests:"..basename, param2 = param2 })
199 end,
200 after_dig_node = function(pos, oldnode, oldmetadata, digger)
201 local meta = minetest.get_meta(pos)
202 local meta2 = meta
203 meta:from_table(oldmetadata)
204 local inv = meta:get_inventory()
205 for i=1,inv:get_size("main") do
206 local stack = inv:get_stack("main", i)
207 if not stack:is_empty() then
208 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}
209 minetest.add_item(p, stack)
212 meta:from_table(meta2:to_table())
213 end,
214 -- BEGIN OF LISTRING WORKAROUND
215 allow_metadata_inventory_put = function(pos, listname, index, stack, player)
216 if listname == "input" then
217 local inv = minetest.get_inventory({type="node", pos=pos})
218 if inv:room_for_item("main", stack) then
219 return -1
220 else
221 local other_pos = mcl_util.get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "left")
222 local other_inv = minetest.get_inventory({type="node", pos=other_pos})
223 if other_inv:room_for_item("main", stack) then
224 return -1
225 else
226 return 0
229 else
230 return stack:get_count()
232 end,
233 -- END OF LISTRING WORKAROUND
234 on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
235 minetest.log("action", player:get_player_name()..
236 " moves stuff in chest at "..minetest.pos_to_string(pos))
237 end,
238 on_metadata_inventory_put = function(pos, listname, index, stack, player)
239 minetest.log("action", player:get_player_name()..
240 " moves stuff to chest at "..minetest.pos_to_string(pos))
241 -- BEGIN OF LISTRING WORKAROUND
242 if listname == "input" then
243 local inv = minetest.get_inventory({type="node", pos=pos})
244 local leftover = inv:add_item("main", stack)
245 if not leftover:is_empty() then
246 local other_pos = mcl_util.get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "left")
247 local other_inv = minetest.get_inventory({type="node", pos=other_pos})
248 other_inv:add_item("main", leftover)
251 -- END OF LISTRING WORKAROUND
252 end,
253 on_metadata_inventory_take = function(pos, listname, index, stack, player)
254 minetest.log("action", player:get_player_name()..
255 " takes stuff from chest at "..minetest.pos_to_string(pos))
256 end,
257 _mcl_blast_resistance = 2.5,
258 _mcl_hardness = 2.5,
260 on_rightclick = function(pos, node, clicker)
261 local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
263 minetest.show_formspec(clicker:get_player_name(),
264 "mcl_chests:"..formspec_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
265 "size[9,11.5]"..
266 "background[-0.19,-0.25;9.41,12.5;mcl_chests_inventory_chest_large.png]"..
267 mcl_vars.inventory_header..
268 "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,0.5;9,3;]"..
269 "list[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main;0,3.5;9,3;]"..
270 "list[current_player;main;0,7.5;9,3;9]"..
271 "list[current_player;main;0,10.75;9,1;]"..
272 -- BEGIN OF LISTRING WORKAROUND
273 "listring[current_player;main]"..
274 "listring[nodemeta:"..pos.x..","..pos.y..","..pos.z..";input]"..
275 -- END OF LISTRING WORKAROUND
276 "listring[current_player;main]"..
277 "listring[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main]"..
278 "listring[current_player;main]"..
279 "listring[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main]")
281 if on_rightclick_addendum_left then
282 on_rightclick_addendum_left(pos, node, clicker)
284 end,
285 mesecons = mesecons,
286 on_rotate = no_rotate,
289 minetest.register_node("mcl_chests:"..basename.."_right", {
290 tiles = tiles_table.right,
291 paramtype = "light",
292 paramtype2 = "facedir",
293 groups = {handy=1,axey=1, container=6,not_in_creative_inventory=1, material_wood=1},
294 drop = drop,
295 is_ground_content = false,
296 sounds = mcl_sounds.node_sound_wood_defaults(),
297 on_destruct = function(pos)
298 local n = minetest.get_node(pos)
299 if n.name == "mcl_chests:"..basename then
300 return
303 local players = minetest.get_connected_players()
304 for p=1, #players do
305 minetest.close_formspec(players[p]:get_player_name(), "mcl_chests:"..formspec_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z)
308 local param2 = n.param2
309 local p = mcl_util.get_double_container_neighbor_pos(pos, param2, "right")
310 if not p or minetest.get_node(p).name ~= "mcl_chests:"..basename.."_left" then
311 return
313 minetest.swap_node(p, { name = "mcl_chests:"..basename, param2 = param2 })
314 end,
315 after_dig_node = function(pos, oldnode, oldmetadata, digger)
316 local meta = minetest.get_meta(pos)
317 local meta2 = meta
318 meta:from_table(oldmetadata)
319 local inv = meta:get_inventory()
320 for i=1,inv:get_size("main") do
321 local stack = inv:get_stack("main", i)
322 if not stack:is_empty() then
323 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}
324 minetest.add_item(p, stack)
327 meta:from_table(meta2:to_table())
328 end,
329 -- BEGIN OF LISTRING WORKAROUND
330 allow_metadata_inventory_put = function(pos, listname, index, stack, player)
331 if listname == "input" then
332 local other_pos = mcl_util.get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "right")
333 local other_inv = minetest.get_inventory({type="node", pos=other_pos})
334 if other_inv:room_for_item("main", stack) then
335 return -1
336 else
337 local inv = minetest.get_inventory({type="node", pos=pos})
338 if inv:room_for_item("main", stack) then
339 return -1
340 else
341 return 0
344 else
345 return stack:get_count()
347 end,
348 -- END OF LISTRING WORKAROUND
349 on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
350 minetest.log("action", player:get_player_name()..
351 " moves stuff in chest at "..minetest.pos_to_string(pos))
352 end,
353 on_metadata_inventory_put = function(pos, listname, index, stack, player)
354 minetest.log("action", player:get_player_name()..
355 " moves stuff to chest at "..minetest.pos_to_string(pos))
356 -- BEGIN OF LISTRING WORKAROUND
357 if listname == "input" then
358 local other_pos = mcl_util.get_double_container_neighbor_pos(pos, minetest.get_node(pos).param2, "right")
359 local other_inv = minetest.get_inventory({type="node", pos=other_pos})
360 local leftover = other_inv:add_item("main", stack)
361 if not leftover:is_empty() then
362 local inv = minetest.get_inventory({type="node", pos=pos})
363 inv:add_item("main", leftover)
366 -- END OF LISTRING WORKAROUND
367 end,
368 on_metadata_inventory_take = function(pos, listname, index, stack, player)
369 minetest.log("action", player:get_player_name()..
370 " takes stuff from chest at "..minetest.pos_to_string(pos))
371 end,
372 _mcl_blast_resistance = 2.5,
373 _mcl_hardness = 2.5,
375 on_rightclick = function(pos, node, clicker)
376 local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
378 minetest.show_formspec(clicker:get_player_name(),
379 "mcl_chests:"..formspec_basename.."_"..pos.x.."_"..pos.y.."_"..pos.z,
381 "size[9,11.5]"..
382 "background[-0.19,-0.25;9.41,12.5;mcl_chests_inventory_chest_large.png]"..
383 mcl_vars.inventory_header..
384 "list[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main;0,0.5;9,3;]"..
385 "list[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main;0,3.5;9,3;]"..
386 "list[current_player;main;0,7.5;9,3;9]"..
387 "list[current_player;main;0,10.75;9,1;]"..
388 -- BEGIN OF LISTRING WORKAROUND
389 "listring[current_player;main]"..
390 "listring[nodemeta:"..pos.x..","..pos.y..","..pos.z..";input]"..
391 -- END OF LISTRING WORKAROUND
392 "listring[current_player;main]"..
393 "listring[nodemeta:"..pos_other.x..","..pos_other.y..","..pos_other.z..";main]"..
394 "listring[current_player;main]"..
395 "listring[nodemeta:"..pos.x..","..pos.y..","..pos.z..";main]")
397 if on_rightclick_addendum_right then
398 on_rightclick_addendum_right(pos, node, clicker)
400 end,
401 mesecons = mesecons,
402 on_rotate = no_rotate,
405 if minetest.get_modpath("doc") then
406 doc.add_entry_alias("nodes", "mcl_chests:"..basename, "nodes", "mcl_chests:"..basename.."_left")
407 doc.add_entry_alias("nodes", "mcl_chests:"..basename, "nodes", "mcl_chests:"..basename.."_right")
410 -- END OF register_chest FUNCTION BODY
413 register_chest("chest",
414 "Chest",
415 "Chests are containers which provide 27 inventory slots. Chests can be turned into large chests with double the capacity by placing two chests next to each other.",
416 "To access the chest's inventory, rightclick the chest. When broken, the items of the chest will drop out.",
418 small = {"default_chest_top.png", "mcl_chests_chest_bottom.png",
419 "mcl_chests_chest_right.png", "mcl_chests_chest_left.png",
420 "mcl_chests_chest_back.png", "default_chest_front.png"},
421 left = {"default_chest_top_big.png", "default_chest_top_big.png",
422 "mcl_chests_chest_right.png", "mcl_chests_chest_left.png",
423 "default_chest_side_big.png^[transformFX", "default_chest_front_big.png"},
424 right = {"default_chest_top_big.png^[transformFX", "default_chest_top_big.png^[transformFX",
425 "mcl_chests_chest_right.png", "mcl_chests_chest_left.png",
426 "default_chest_side_big.png", "default_chest_front_big.png^[transformFX"},
428 false
431 local traptiles = {
432 small = {"mcl_chests_chest_trapped_top.png", "mcl_chests_chest_trapped_bottom.png",
433 "mcl_chests_chest_trapped_right.png", "mcl_chests_chest_trapped_left.png",
434 "mcl_chests_chest_trapped_back.png", "mcl_chests_chest_trapped_front.png"},
435 left = {"mcl_chests_chest_trapped_top_big.png", "mcl_chests_chest_trapped_top_big.png",
436 "mcl_chests_chest_trapped_right.png", "mcl_chests_chest_trapped_left.png",
437 "mcl_chests_chest_trapped_side_big.png^[transformFX", "mcl_chests_chest_trapped_front_big.png"},
438 right = {"mcl_chests_chest_trapped_top_big.png^[transformFX", "mcl_chests_chest_trapped_top_big.png^[transformFX",
439 "mcl_chests_chest_trapped_right.png", "mcl_chests_chest_trapped_left.png",
440 "mcl_chests_chest_trapped_side_big.png", "mcl_chests_chest_trapped_front_big.png^[transformFX"},
443 register_chest("trapped_chest",
444 "Trapped Chest",
445 "A trapped chest is a container which provides 27 inventory slots. When it is opened, it sends a redstone signal to its adjacent blocks as long it stays open. Trapped chests can be turned into large trapped chests with double the capacity by placing two trapped chests next to each other.",
446 "To access the inventory of a trapped chest, rightclick it. When broken, the items will drop out.",
447 traptiles,
448 nil,
449 {receptor = {
450 state = mesecon.state.off,
451 rules = trapped_chest_mesecons_rules,
453 function(pos, node, clicker)
454 minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on", param2 = node.param2})
455 mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
456 player_chest_open(clicker, pos)
457 end,
458 function(pos, node, clicker)
459 local meta = minetest.get_meta(pos)
460 meta:set_int("players", 1)
462 minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2})
463 mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
465 local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
466 minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_on_right", param2 = node.param2})
467 mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules)
469 player_chest_open(clicker, pos)
470 end,
471 function(pos, node, clicker)
472 local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
474 minetest.swap_node(pos, {name="mcl_chests:trapped_chest_on_right", param2 = node.param2})
475 mesecon.receptor_on(pos, trapped_chest_mesecons_rules)
477 minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_on_left", param2 = node.param2})
478 mesecon.receptor_on(pos_other, trapped_chest_mesecons_rules)
480 player_chest_open(clicker, pos)
484 register_chest("trapped_chest_on",
485 nil, nil, nil, traptiles, true,
486 {receptor = {
487 state = mesecon.state.on,
488 rules = trapped_chest_mesecons_rules,
490 function(pos, node, clicker)
491 player_chest_open(clicker, pos)
492 end,
493 function(pos, node, clicker)
494 player_chest_open(clicker, pos)
495 end,
496 function(pos, node, clicker)
497 player_chest_open(clicker, pos)
498 end,
499 "trapped_chest",
500 "trapped_chest"
503 local function close_if_trapped_chest(pos, player)
504 local node = minetest.get_node(pos)
506 if node.name == "mcl_chests:trapped_chest_on" then
507 minetest.swap_node(pos, {name="mcl_chests:trapped_chest", param2 = node.param2})
508 mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
510 player_chest_close(player)
511 elseif node.name == "mcl_chests:trapped_chest_on_left" then
512 minetest.swap_node(pos, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
513 mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
515 local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "left")
516 minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
517 mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
519 player_chest_close(player)
520 elseif node.name == "mcl_chests:trapped_chest_on_right" then
521 minetest.swap_node(pos, {name="mcl_chests:trapped_chest_right", param2 = node.param2})
522 mesecon.receptor_off(pos, trapped_chest_mesecons_rules)
524 local pos_other = mcl_util.get_double_container_neighbor_pos(pos, node.param2, "right")
525 minetest.swap_node(pos_other, {name="mcl_chests:trapped_chest_left", param2 = node.param2})
526 mesecon.receptor_off(pos_other, trapped_chest_mesecons_rules)
528 player_chest_close(player)
532 -- Disable trapped chest when it has been closed
533 minetest.register_on_player_receive_fields(function(player, formname, fields)
534 if formname:find("mcl_chests:trapped_chest_") == 1 then
535 if fields.quit then
536 player_chest_close(player)
539 end)
541 minetest.register_on_leaveplayer(function(player)
542 player_chest_close(player)
543 end)
545 minetest.register_craft({
546 output = 'mcl_chests:chest',
547 recipe = {
548 {'group:wood', 'group:wood', 'group:wood'},
549 {'group:wood', '', 'group:wood'},
550 {'group:wood', 'group:wood', 'group:wood'},
554 minetest.register_craft({
555 type = 'fuel',
556 recipe = 'mcl_chests:chest',
557 burntime = 15
560 minetest.register_craft({
561 type = 'fuel',
562 recipe = 'mcl_chests:trapped_chest',
563 burntime = 15
566 minetest.register_node("mcl_chests:ender_chest", {
567 description = "Ender Chest",
568 _doc_items_longdesc = "Ender chests grant you access to a single personal interdimensional inventory with 27 slots. This inventory is the same no matter from which ender chest you access it from. If you put one item into one ender chest, you will find it in all other ender chests. Each player will only see their own items, but not the items of other players.",
569 _doc_items_usagehelp = "Rightclick the ender chest to access your personal interdimensional inventory.",
570 tiles = {"mcl_chests_ender_chest_top.png", "mcl_chests_ender_chest_bottom.png",
571 "mcl_chests_ender_chest_right.png", "mcl_chests_ender_chest_left.png",
572 "mcl_chests_ender_chest_back.png", "mcl_chests_ender_chest_front.png"},
573 -- Note: The “container” group is missing here because the ender chest does not
574 -- have an inventory on its own
575 groups = {pickaxey=1, deco_block=1, material_stone=1},
576 is_ground_content = false,
577 paramtype = "light",
578 light_source = 7,
579 paramtype2 = "facedir",
580 sounds = mcl_sounds.node_sound_stone_defaults(),
581 drop = "mcl_core:obsidian 8",
582 on_construct = function(pos)
583 local meta = minetest.get_meta(pos)
584 meta:set_string("formspec",
585 "size[9,8.75]"..
586 mcl_vars.inventory_header..
587 "background[-0.19,-0.25;9.41,10.48;mcl_chests_inventory_chest.png]"..
588 "image[0,-0.2;5,0.75;mcl_chests_fnt_ender_chest.png]"..
589 "list[current_player;enderchest;0,0.5;9,3;]"..
590 "list[current_player;main;0,4.5;9,3;9]"..
591 "list[current_player;main;0,7.74;9,1;]"..
592 "listring[current_player;enderchest]"..
593 "listring[current_player;main]")
594 end,
595 _mcl_blast_resistance = 3000,
596 _mcl_hardness = 22.5,
597 on_rotate = simple_rotate,
600 minetest.register_on_joinplayer(function(player)
601 local inv = player:get_inventory()
602 inv:set_size("enderchest", 9*3)
603 end)
605 minetest.register_craft({
606 output = 'mcl_chests:ender_chest',
607 recipe = {
608 {'mcl_core:obsidian', 'mcl_core:obsidian', 'mcl_core:obsidian'},
609 {'mcl_core:obsidian', 'mcl_end:ender_eye', 'mcl_core:obsidian'},
610 {'mcl_core:obsidian', 'mcl_core:obsidian', 'mcl_core:obsidian'},
614 -- Shulker boxes
615 local boxtypes = {
616 white = "White Shulker Box",
617 grey = "Light Grey Shulker Box",
618 orange = "Orange Shulker Box",
619 cyan = "Cyan Shulker Box",
620 magenta = "Magenta Shulker Box",
621 violet = "Purple Shulker Box",
622 lightblue = "Light Blue Shulker Box",
623 blue = "Blue Shulker Box",
624 yellow = "Yellow Shulker Box",
625 brown = "Brown Shulker Box",
626 green = "Lime Shulker Box",
627 dark_green = "Green Shulker Box",
628 pink = "Pink Shulker Box",
629 red = "Red Shulker Box",
630 dark_grey = "Grey Shulker Box",
631 black = "Black Shulker Box",
634 local shulker_mob_textures = {
635 white = "mobs_mc_shulker_white.png",
636 grey = "mobs_mc_shulker_silver.png",
637 orange = "mobs_mc_shulker_orange.png",
638 cyan = "mobs_mc_shulker_cyan.png",
639 magenta = "mobs_mc_shulker_magenta.png",
640 violet = "mobs_mc_shulker_purple.png",
641 lightblue = "mobs_mc_shulker_light_blue.png",
642 blue = "mobs_mc_shulker_blue.png",
643 yellow = "mobs_mc_shulker_yellow.png",
644 brown = "mobs_mc_shulker_brown.png",
645 green = "mobs_mc_shulker_lime.png",
646 dark_green = "mobs_mc_shulker_green.png",
647 pink = "mobs_mc_shulker_pink.png",
648 red = "mobs_mc_shulker_red.png",
649 dark_grey = "mobs_mc_shulker_gray.png",
650 black = "mobs_mc_shulker_black.png",
653 for color, desc in pairs(boxtypes) do
654 local mob_texture = shulker_mob_textures[color]
655 minetest.register_node("mcl_chests:"..color.."_shulker_box", {
656 description = desc,
657 _doc_items_longdesc = "A shulker box is a portable container which provides 27 inventory slots for any item except shulker boxes. Shulker boxes keep their inventory when broken, so shulker boxes as well as their contents can be taken as a single item. Shulker boxes come in many different colors.",
658 _doc_items_usagehelp = "To access the inventory of a shulker box, place and right-click it. To take a shulker box and its contents with you, just break and collect it, the items will not fall out. Place the shulker box again to be able to retrieve its contents.",
659 tiles = {
660 "mcl_chests_"..color.."_shulker_box_top.png", -- top
661 "[combine:16x16:-32,-28="..mob_texture, -- bottom
662 "[combine:16x16:0,-36="..mob_texture..":0,-16="..mob_texture, -- side
663 "[combine:16x16:-32,-36="..mob_texture..":-32,-16="..mob_texture, -- side
664 "[combine:16x16:-16,-36="..mob_texture..":-16,-16="..mob_texture, -- side
665 "[combine:16x16:-48,-36="..mob_texture..":-48,-16="..mob_texture, -- side
667 groups = {handy=1,pickaxey=1, container=3, deco_block=1, dig_by_piston=1, shulker_box=1},
668 is_ground_content = false,
669 sounds = mcl_sounds.node_sound_stone_defaults(),
670 stack_max = 1,
671 drop = "",
672 paramtype = "light",
673 paramtype2 = "facedir",
674 -- TODO: Make shulker boxes rotatable
675 -- This doesn't work, it just destroys the inventory:
676 -- on_place = minetest.rotate_node,
677 on_construct = function(pos)
678 local meta = minetest.get_meta(pos)
679 meta:set_string("formspec",
680 "size[9,8.75]"..
681 mcl_vars.inventory_header..
682 "background[-0.19,-0.25;9.41,10.48;mcl_chests_inventory_chest.png]"..
683 "image[0,-0.2;5,0.75;mcl_chests_fnt_shulker_box.png]"..
684 "list[current_name;main;0,0.5;9,3;]"..
685 "list[current_player;main;0,4.5;9,3;9]"..
686 "list[current_player;main;0,7.74;9,1;]"..
687 "listring[current_name;main]"..
688 "listring[current_player;main]")
689 local inv = meta:get_inventory()
690 inv:set_size("main", 9*3)
691 end,
692 _on_dispense = function(stack, pos, droppos, dropnode, dropdir)
693 -- Place shulker box as node
694 if minetest.registered_nodes[dropnode.name].buildable_to then
695 minetest.set_node(droppos, {name = stack:get_name(), param2 = minetest.dir_to_facedir(dropdir)})
696 local imeta = stack:get_metadata()
697 local iinv_main = minetest.deserialize(imeta)
698 local ninv = minetest.get_inventory({type="node", pos=droppos})
699 ninv:set_list("main", iinv_main)
700 stack:take_item()
702 return stack
703 end,
704 after_place_node = function(pos, placer, itemstack, pointed_thing)
705 local nmeta = minetest.get_meta(pos)
706 local ninv = nmeta:get_inventory()
707 local imeta = itemstack:get_metadata()
708 local iinv_main = minetest.deserialize(imeta)
709 ninv:set_list("main", iinv_main)
710 ninv:set_size("main", 9*3)
711 if minetest.settings:get_bool("creative_mode") then
712 if not ninv:is_empty("main") then
713 return nil
714 else
715 return itemstack
717 else
718 return nil
720 end,
721 on_destruct = function(pos)
722 local meta = minetest.get_meta(pos)
723 local inv = meta:get_inventory()
724 local items = {}
725 for i=1, inv:get_size("main") do
726 local stack = inv:get_stack("main", i)
727 items[i] = stack:to_string()
729 local data = minetest.serialize(items)
730 local boxitem = ItemStack("mcl_chests:"..color.."_shulker_box")
731 boxitem:set_metadata(data)
733 if minetest.settings:get_bool("creative_mode") then
734 if not inv:is_empty("main") then
735 minetest.add_item(pos, boxitem)
737 else
738 minetest.add_item(pos, boxitem)
740 end,
741 allow_metadata_inventory_put = function(pos, listname, index, stack, player)
742 -- Do not allow to place shulker boxes into shulker boxes
743 local group = minetest.get_item_group(stack:get_name(), "shulker_box")
744 if group == 0 or group == nil then
745 return stack:get_count()
746 else
747 return 0
749 end,
750 _mcl_blast_resistance = 30,
751 _mcl_hardness = 6,
754 minetest.register_craft({
755 type = "shapeless",
756 output = 'mcl_chests:'..color..'_shulker_box',
757 recipe = { 'group:shulker_box', 'mcl_dye:'..color }
761 minetest.register_craft({
762 output = 'mcl_chests:violet_shulker_box',
763 recipe = {
764 {'mcl_mobitems:shulker_shell'},
765 {'mcl_chests:chest'},
766 {'mcl_mobitems:shulker_shell'},