2020-02-19 00:47:23 +01:00
local S = minetest.get_translator ( " hopper " )
2022-07-10 20:25:00 +02:00
local FS = hopper.translator_escaped
2017-03-31 08:58:28 +02:00
-- Target inventory retrieval
-- looks first for a registration matching the specific node name, then for a registration
-- matching group and value, then for a registration matching a group and *any* value
2024-07-21 03:16:35 +02:00
hopper.get_registered = function ( target_node_name )
2017-03-31 08:58:28 +02:00
local output = hopper.containers [ target_node_name ]
if output ~= nil then return output end
2017-09-02 04:53:03 +02:00
2017-03-31 08:58:28 +02:00
local target_def = minetest.registered_nodes [ target_node_name ]
2017-05-07 21:06:26 +02:00
if target_def == nil or target_def.groups == nil then return nil end
2017-09-02 04:53:03 +02:00
2017-03-31 08:58:28 +02:00
for group , value in pairs ( target_def.groups ) do
local registered_group = hopper.groups [ group ]
if registered_group ~= nil then
output = registered_group [ value ]
if output ~= nil then return output end
output = registered_group [ " all " ]
2017-09-02 04:53:03 +02:00
if output ~= nil then return output end
end
2017-03-31 08:58:28 +02:00
end
2017-09-02 04:53:03 +02:00
2017-03-31 08:58:28 +02:00
return nil
end
hopper.get_eject_button_texts = function ( pos , loc_X , loc_Y )
if not hopper.config . eject_button_enabled then return " " end
2022-07-10 20:25:00 +02:00
local texture , eject_button_tooltip
2017-03-31 08:58:28 +02:00
if minetest.get_meta ( pos ) : get_string ( " eject " ) == " true " then
2022-07-10 20:25:00 +02:00
texture = " hopper_mode_eject.png "
eject_button_tooltip = FS ( " This hopper is currently set to eject items from its output \n even if there isn't a compatible block positioned to receive it. \n Click this button to disable this feature. " )
2017-03-31 08:58:28 +02:00
else
2022-07-10 20:25:00 +02:00
texture = " hopper_mode_hold.png "
eject_button_tooltip = FS ( " This hopper is currently set to hold on to item if there \n isn't a compatible block positioned to receive it. \n Click this button to have it eject items instead. " )
2017-03-31 08:58:28 +02:00
end
2022-07-10 20:25:00 +02:00
return ( " image_button_exit[%g,%g;1,1;%s;eject;] " ) : format ( loc_X , loc_Y , texture ) ..
" tooltip[eject; " .. eject_button_tooltip .. " ] "
2017-03-31 08:58:28 +02:00
end
hopper.get_string_pos = function ( pos )
return pos.x .. " , " .. pos.y .. " , " .. pos.z
end
-- Apparently node_sound_metal_defaults is a newer thing, I ran into games using an older version of the default mod without it.
if default.node_sound_metal_defaults ~= nil then
hopper.metal_sounds = default.node_sound_metal_defaults ( )
else
hopper.metal_sounds = default.node_sound_stone_defaults ( )
end
-------------------------------------------------------------------------------------------
-- Inventory transfer functions
2017-04-02 06:39:31 +02:00
local delay = function ( x )
return ( function ( ) return x end )
end
local get_placer = function ( player_name )
if player_name ~= " " then
return minetest.get_player_by_name ( player_name ) or {
is_player = delay ( true ) ,
get_player_name = delay ( player_name ) ,
is_fake_player = " :hopper " ,
get_wielded_item = delay ( ItemStack ( nil ) )
}
end
return nil
end
2017-03-31 08:58:28 +02:00
-- Used to remove items from the target block and put it into the hopper's inventory
2024-07-21 03:16:35 +02:00
hopper.take_item_from = function ( hopper_pos , target_pos , target_node , target_inv_info )
2017-05-07 21:06:26 +02:00
local target_def = minetest.registered_nodes [ target_node.name ]
if not target_def then
return
end
2017-03-31 08:58:28 +02:00
2024-07-21 03:16:35 +02:00
local target_inv_name = target_inv_info [ " inventory_name " ]
local target_get_inv = target_inv_info [ " get_inventory " ]
2017-03-31 08:58:28 +02:00
--hopper inventory
2024-07-21 03:16:35 +02:00
local hopper_meta = minetest.get_meta ( hopper_pos )
2017-03-31 08:58:28 +02:00
local hopper_inv = hopper_meta : get_inventory ( )
2017-04-02 06:39:31 +02:00
local placer = get_placer ( hopper_meta : get_string ( " placer " ) )
2017-09-02 04:53:03 +02:00
2017-03-31 08:58:28 +02:00
--source inventory
2024-07-21 03:16:35 +02:00
local target_inv
if target_get_inv then
target_inv = target_get_inv ( target_pos )
if not target_inv then
minetest.log ( " error " , " No inventory from api get_inventory function: " ..
target_node.name .. " on " .. vector.to_string ( target_pos ) )
return false
end
else
target_inv = minetest.get_meta ( target_pos ) : get_inventory ( )
end
local target_inv_size = target_inv : get_size ( target_inv_name )
if target_inv : is_empty ( target_inv_name ) == false then
2017-03-31 08:58:28 +02:00
for i = 1 , target_inv_size do
2024-07-21 03:16:35 +02:00
local stack = target_inv : get_stack ( target_inv_name , i )
2017-03-31 08:58:28 +02:00
local item = stack : get_name ( )
if item ~= " " then
if hopper_inv : room_for_item ( " main " , item ) then
local stack_to_take = stack : take_item ( 1 )
if target_def.allow_metadata_inventory_take == nil
or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper
2024-07-21 03:16:35 +02:00
or target_def.allow_metadata_inventory_take ( target_pos , target_inv_name , i , stack_to_take , placer ) > 0 then
target_inv : set_stack ( target_inv_name , i , stack )
2017-03-31 08:58:28 +02:00
--add to hopper
2017-09-02 04:53:03 +02:00
hopper_inv : add_item ( " main " , stack_to_take )
2017-03-31 08:58:28 +02:00
if target_def.on_metadata_inventory_take ~= nil and placer ~= nil then
2024-07-21 03:16:35 +02:00
target_def.on_metadata_inventory_take ( target_pos , target_inv_name , i , stack_to_take , placer )
2017-03-31 08:58:28 +02:00
end
break
end
end
end
end
end
end
-- Used to put items from the hopper inventory into the target block
2024-07-21 03:16:35 +02:00
hopper.send_item_to = function ( hopper_pos , target_pos , target_node , target_inv_info , filtered_items )
2017-03-31 08:58:28 +02:00
local hopper_meta = minetest.get_meta ( hopper_pos )
local target_def = minetest.registered_nodes [ target_node.name ]
2017-05-07 21:06:26 +02:00
if not target_def then
return false
end
2017-09-02 04:53:03 +02:00
2017-03-31 08:58:28 +02:00
local eject_item = hopper.config . eject_button_enabled and hopper_meta : get_string ( " eject " ) == " true " and target_def.buildable_to
2017-09-02 04:53:03 +02:00
2024-07-21 03:16:35 +02:00
if not eject_item and not target_inv_info then
2017-03-31 08:58:28 +02:00
return false
end
--hopper inventory
local hopper_meta = minetest.get_meta ( hopper_pos ) ;
local hopper_inv = hopper_meta : get_inventory ( )
if hopper_inv : is_empty ( " main " ) == true then
return false
end
local hopper_inv_size = hopper_inv : get_size ( " main " )
2017-04-02 06:39:31 +02:00
local placer = get_placer ( hopper_meta : get_string ( " placer " ) )
2017-03-31 08:58:28 +02:00
--target inventory
2024-07-21 03:16:35 +02:00
local target_inv_name = target_inv_info [ " inventory_name " ]
local target_get_inv = target_inv_info [ " get_inventory " ]
local target_inv
if target_get_inv then
target_inv = target_get_inv ( target_pos )
if not target_inv then
minetest.log ( " error " , " No inventory from api get_inventory function: " ..
target_node.name .. " on " .. vector.to_string ( target_pos ) )
return false
end
else
target_inv = minetest.get_meta ( target_pos ) : get_inventory ( )
end
2017-03-31 08:58:28 +02:00
for i = 1 , hopper_inv_size do
local stack = hopper_inv : get_stack ( " main " , i )
local item = stack : get_name ( )
if item ~= " " and ( filtered_items == nil or filtered_items [ item ] ) then
2024-07-21 03:16:35 +02:00
if target_inv_name then
if target_inv : room_for_item ( target_inv_name , item ) then
2017-03-31 08:58:28 +02:00
local stack_to_put = stack : take_item ( 1 )
if target_def.allow_metadata_inventory_put == nil
or placer == nil -- backwards compatibility, older versions of this mod didn't record who placed the hopper
2024-07-21 03:16:35 +02:00
or target_def.allow_metadata_inventory_put ( target_pos , target_inv_name , i , stack_to_put , placer ) > 0 then
2017-03-31 08:58:28 +02:00
hopper_inv : set_stack ( " main " , i , stack )
--add to target node
2024-07-21 03:16:35 +02:00
target_inv : add_item ( target_inv_name , stack_to_put )
2017-03-31 08:58:28 +02:00
if target_def.on_metadata_inventory_put ~= nil and placer ~= nil then
2024-07-21 03:16:35 +02:00
target_def.on_metadata_inventory_put ( target_pos , target_inv_name , i , stack_to_put , placer )
2017-03-31 08:58:28 +02:00
end
return true
end
end
elseif eject_item then
local stack_to_put = stack : take_item ( 1 )
minetest.add_item ( target_pos , stack_to_put )
hopper_inv : set_stack ( " main " , i , stack )
return true
end
end
end
return false
end