1 local S = minetest.get_translator("hopper")
2 -- Target inventory retrieval
4 -- looks first for a registration matching the specific node name, then for a registration
5 -- matching group and value, then for a registration matching a group and *any* value
6 hopper.get_registered_inventories_for = function(target_node_name)
7 local output = hopper.containers[target_node_name]
8 if output ~= nil then return output end
10 local target_def = minetest.registered_nodes[target_node_name]
11 if target_def == nil or target_def.groups == nil then return nil end
13 for group, value in pairs(target_def.groups) do
14 local registered_group = hopper.groups[group]
15 if registered_group ~= nil then
16 output = registered_group[value]
17 if output ~= nil then return output end
18 output = registered_group["all"]
19 if output ~= nil then return output end
26 hopper.get_eject_button_texts = function(pos, loc_X, loc_Y)
27 if not hopper.config.eject_button_enabled then return "" end
29 local eject_button_text, eject_button_tooltip
30 if minetest.get_meta(pos):get_string("eject") == "true" then
31 eject_button_text = S("Don't\nEject")
32 eject_button_tooltip = S("This hopper is currently set to eject items from its output\neven if there isn't a compatible block positioned to receive it.\nClick this button to disable this feature.")
34 eject_button_text = S("Eject\nItems")
35 eject_button_tooltip = S("This hopper is currently set to hold on to item if there\nisn't a compatible block positioned to receive it.\nClick this button to have it eject items instead.")
37 return "button_exit["..loc_X..","..loc_Y..";1,1;eject;"..eject_button_text.."]tooltip[eject;"..eject_button_tooltip.."]"
40 hopper.get_string_pos = function(pos)
41 return pos.x .. "," .. pos.y .. "," ..pos.z
44 -- Apparently node_sound_metal_defaults is a newer thing, I ran into games using an older version of the default mod without it.
45 hopper.metal_sounds = main.stoneSound()
47 -------------------------------------------------------------------------------------------
48 -- Inventory transfer functions
50 local delay = function(x)
51 return (function() return x end)
54 local get_placer = function(player_name)
55 if player_name ~= "" then
56 return minetest.get_player_by_name(player_name) or {
57 is_player = delay(true),
58 get_player_name = delay(player_name),
59 is_fake_player = ":hopper",
60 get_wielded_item = delay(ItemStack(nil))
66 -- Used to remove items from the target block and put it into the hopper's inventory
67 hopper.take_item_from = function(hopper_pos, target_pos, target_node, target_inventory_name)
68 if target_inventory_name == nil then
71 local target_def = minetest.registered_nodes[target_node.name]
72 if not target_def then
77 local hopper_meta = minetest.get_meta(hopper_pos);
78 local hopper_inv = hopper_meta:get_inventory()
79 local placer = get_placer(hopper_meta:get_string("placer"))
82 local target_inv = minetest.get_meta(target_pos):get_inventory()
83 local target_inv_size = target_inv:get_size(target_inventory_name)
84 if target_inv:is_empty(target_inventory_name) == false then
85 for i = 1,target_inv_size do
86 local stack = target_inv:get_stack(target_inventory_name, i)
87 local item = stack:get_name()
89 if hopper_inv:room_for_item("main", item) then
90 local stack_to_take = stack:take_item(1)
91 if target_def.allow_metadata_inventory_take == nil
92 or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper
93 or target_def.allow_metadata_inventory_take(target_pos, target_inventory_name, i, stack_to_take, placer) > 0 then
94 target_inv:set_stack(target_inventory_name, i, stack)
96 hopper_inv:add_item("main", stack_to_take)
97 if target_def.on_metadata_inventory_take ~= nil and placer ~= nil then
98 target_def.on_metadata_inventory_take(target_pos, target_inventory_name, i, stack_to_take, placer)
108 -- Used to put items from the hopper inventory into the target block
109 hopper.send_item_to = function(hopper_pos, target_pos, target_node, target_inventory_name, filtered_items)
110 local hopper_meta = minetest.get_meta(hopper_pos)
111 local target_def = minetest.registered_nodes[target_node.name]
112 if not target_def then
116 local eject_item = hopper.config.eject_button_enabled and hopper_meta:get_string("eject") == "true" and target_def.buildable_to
118 if not eject_item and not target_inventory_name then
123 local hopper_meta = minetest.get_meta(hopper_pos);
124 local hopper_inv = hopper_meta:get_inventory()
125 if hopper_inv:is_empty("main") == true then
128 local hopper_inv_size = hopper_inv:get_size("main")
129 local placer = get_placer(hopper_meta:get_string("placer"))
132 local target_inv = minetest.get_meta(target_pos):get_inventory()
134 for i = 1,hopper_inv_size do
135 local stack = hopper_inv:get_stack("main", i)
136 local item = stack:get_name()
137 if item ~= "" and (filtered_items == nil or filtered_items[item]) then
138 if target_inventory_name then
139 if target_inv:room_for_item(target_inventory_name, item) then
140 local stack_to_put = stack:take_item(1)
141 if target_def.allow_metadata_inventory_put == nil
142 or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper
143 or target_def.allow_metadata_inventory_put(target_pos, target_inventory_name, i, stack_to_put, placer) > 0 then
144 hopper_inv:set_stack("main", i, stack)
146 target_inv:add_item(target_inventory_name, stack_to_put)
147 if target_def.on_metadata_inventory_put ~= nil and placer ~= nil then
148 target_def.on_metadata_inventory_put(target_pos, target_inventory_name, i, stack_to_put, placer)
153 elseif eject_item then
154 local stack_to_put = stack:take_item(1)
155 minetest.add_item(target_pos, stack_to_put)
156 hopper_inv:set_stack("main", i, stack)