2017-01-17 19:50:56 +03:00
2017-01-27 14:42:05 +03:00
local chest = minetest.get_content_id ( " mcl_chests:chest " )
2017-01-17 19:50:56 +03:00
2017-01-17 20:41:25 +03:00
local mcl_hoppers_formspec =
2017-01-17 20:17:53 +03:00
" size[9,7] " ..
2017-01-17 20:41:25 +03:00
" background[-0.19,-0.25;9.41,10.48;mcl_hoppers_inventory.png] " ..
2017-02-18 01:06:52 +03:00
mcl_vars.inventory_header ..
2017-01-17 20:17:53 +03:00
" list[current_name;main;2,0.5;5,1;] " ..
" list[current_player;main;0,2.5;9,3;9] " ..
" list[current_player;main;0,5.74;9,1;] " ..
" listring[current_name;main] " ..
" listring[current_player;main] "
2017-01-17 19:50:56 +03:00
2017-01-17 20:41:25 +03:00
minetest.register_node ( " mcl_hoppers:hopper " , {
2017-02-22 16:00:58 +03:00
description = " Hopper " ,
inventory_image = " mcl_hoppers_item.png " ,
2017-03-11 01:31:57 +03:00
_doc_items_longdesc = [ [ Hoppers are containers with 5 inventory slots . They collect dropped items from above , take items from a container above and attempts to put its items it into an adjacent container . Hoppers can go either downwards or sideways . Hoppers interact with chests , droppers , dispensers , shulker boxes , furnaces and hoppers .
Hoppers interact with containers the following way :
• Furnaces : Hoppers from above will put items into the source slot . Hoppers from below take items from the output slot . They also take items from the fuel slot when they can ' t be used as a fuel. Sideway hoppers put items into the fuel slot
• Ender chests : Hoppers don ' t interact with ender chests
• Other containers : Hoppers interact with them normally ] ] ,
_doc_items_usagehelp = " To place a hopper vertically, place it on the floor or a ceiling. To place it sideways, place it at the side of a block. Remember you can place at usable blocks (such as chests) with sneak + right-click. The hopper will keep its orientation when the blocks around it are changed. To access the hopper's inventory, rightclick it. " ,
2017-02-22 16:00:58 +03:00
wield_image = " mcl_hoppers_item.png " ,
2017-02-27 03:33:34 +03:00
groups = { pickaxey = 1 , container = 2 , deco_block = 1 , } ,
2017-01-17 19:50:56 +03:00
drawtype = " nodebox " ,
paramtype = " light " ,
2017-03-20 22:06:24 +03:00
sunlight_propagates = true ,
2017-02-06 19:33:43 +03:00
tiles = { " mcl_hoppers_hopper_inside.png^mcl_hoppers_hopper_top.png " , " mcl_hoppers_hopper_outside.png " , " mcl_hoppers_hopper_outside.png " , " mcl_hoppers_hopper_inside.png " , " mcl_hoppers_hopper_outside.png " , " mcl_hoppers_hopper_outside.png " } ,
2017-01-17 19:50:56 +03:00
selection_box = { type = " regular " } ,
node_box = {
type = " fixed " ,
fixed = {
--funnel walls
{ - 0.5 , 0.0 , 0.4 , 0.5 , 0.5 , 0.5 } ,
{ 0.4 , 0.0 , - 0.5 , 0.5 , 0.5 , 0.5 } ,
{ - 0.5 , 0.0 , - 0.5 , - 0.4 , 0.5 , 0.5 } ,
{ - 0.5 , 0.0 , - 0.5 , 0.5 , 0.5 , - 0.4 } ,
--funnel base
{ - 0.5 , 0.0 , - 0.5 , 0.5 , 0.1 , 0.5 } ,
--spout
{ - 0.3 , - 0.3 , - 0.3 , 0.3 , 0.0 , 0.3 } ,
{ - 0.15 , - 0.3 , - 0.15 , 0.15 , - 0.5 , 0.15 } ,
} ,
} ,
2017-03-11 18:36:05 +03:00
is_ground_content = false ,
2017-01-17 19:50:56 +03:00
on_construct = function ( pos )
local meta = minetest.get_meta ( pos )
2017-01-17 20:41:25 +03:00
meta : set_string ( " formspec " , mcl_hoppers_formspec )
2017-01-17 19:50:56 +03:00
local inv = meta : get_inventory ( )
2017-01-17 20:17:53 +03:00
inv : set_size ( " main " , 5 )
2017-01-17 19:50:56 +03:00
end ,
2017-02-22 16:00:58 +03:00
2017-02-22 16:15:06 +03:00
on_place = function ( itemstack , placer , pointed_thing )
local upos = pointed_thing.under
local apos = pointed_thing.above
2017-02-22 16:00:58 +03:00
2017-03-02 18:09:13 +03:00
local uposnode = minetest.get_node ( upos )
local uposnodedef = minetest.registered_nodes [ uposnode.name ]
-- Use pointed node's on_rightclick function first, if present
if placer and not placer : get_player_control ( ) . sneak then
if uposnodedef and uposnodedef.on_rightclick then
return uposnodedef.on_rightclick ( pointed_thing.under , uposnode , placer , itemstack ) or itemstack
end
end
2017-02-22 16:15:06 +03:00
local bpos
if uposnodedef.buildable_to then
bpos = upos
else
local aposnodedef = minetest.registered_nodes [ minetest.get_node ( apos ) . name ]
if aposnodedef.buildable_to then
bpos = apos
end
end
if bpos == nil then
return itemstack
end
local x = upos.x - apos.x
local y = upos.y - apos.y
local z = upos.z - apos.z
2017-02-22 16:00:58 +03:00
if x == - 1 then
2017-02-22 16:15:06 +03:00
minetest.set_node ( bpos , { name = " mcl_hoppers:hopper_side " , param2 = 0 } )
2017-02-22 16:00:58 +03:00
elseif x == 1 then
2017-02-22 16:15:06 +03:00
minetest.set_node ( bpos , { name = " mcl_hoppers:hopper_side " , param2 = 2 } )
2017-02-22 16:00:58 +03:00
elseif z == - 1 then
2017-02-22 16:15:06 +03:00
minetest.set_node ( bpos , { name = " mcl_hoppers:hopper_side " , param2 = 3 } )
2017-02-22 16:00:58 +03:00
elseif z == 1 then
2017-02-22 16:15:06 +03:00
minetest.set_node ( bpos , { name = " mcl_hoppers:hopper_side " , param2 = 1 } )
else
minetest.set_node ( bpos , { name = " mcl_hoppers:hopper " , param2 = 0 } )
end
if not minetest.setting_getbool ( " creative_mode " ) then
itemstack : take_item ( )
2017-02-22 16:00:58 +03:00
end
2017-02-22 16:15:06 +03:00
return itemstack
2017-02-22 16:00:58 +03:00
end ,
2017-01-17 20:30:35 +03:00
after_dig_node = function ( pos , oldnode , oldmetadata , digger )
local meta = minetest.get_meta ( pos )
local meta2 = meta
meta : from_table ( oldmetadata )
2017-01-17 19:50:56 +03:00
local inv = meta : get_inventory ( )
2017-01-17 20:30:35 +03:00
for i = 1 , inv : get_size ( " main " ) do
local stack = inv : get_stack ( " main " , i )
if not stack : is_empty ( ) then
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 }
minetest.add_item ( p , stack )
end
end
meta : from_table ( meta2 : to_table ( ) )
2017-01-17 19:50:56 +03:00
end ,
on_metadata_inventory_move = function ( pos , from_list , from_index , to_list , to_index , count , player )
minetest.log ( " action " , player : get_player_name ( ) ..
2017-01-17 20:41:25 +03:00
" moves stuff in mcl_hoppers at " .. minetest.pos_to_string ( pos ) )
2017-01-17 19:50:56 +03:00
end ,
on_metadata_inventory_put = function ( pos , listname , index , stack , player )
minetest.log ( " action " , player : get_player_name ( ) ..
2017-01-17 20:41:25 +03:00
" moves stuff to mcl_hoppers at " .. minetest.pos_to_string ( pos ) )
2017-01-17 19:50:56 +03:00
end ,
on_metadata_inventory_take = function ( pos , listname , index , stack , player )
minetest.log ( " action " , player : get_player_name ( ) ..
2017-01-17 20:41:25 +03:00
" takes stuff from mcl_hoppers at " .. minetest.pos_to_string ( pos ) )
2017-01-17 19:50:56 +03:00
end ,
2017-02-11 20:46:23 +03:00
sounds = mcl_sounds.node_sound_metal_defaults ( ) ,
2017-02-22 18:03:59 +03:00
_mcl_blast_resistance = 24 ,
2017-02-27 03:33:34 +03:00
_mcl_hardness = 3 ,
2017-01-17 19:50:56 +03:00
} )
2017-01-17 20:41:25 +03:00
minetest.register_node ( " mcl_hoppers:hopper_side " , {
2017-01-17 19:56:18 +03:00
description = " Hopper (Side) " ,
2017-03-02 21:53:53 +03:00
_doc_items_create_entry = false ,
2017-02-22 16:00:58 +03:00
drop = " mcl_hoppers:hopper " ,
2017-02-27 03:33:34 +03:00
groups = { pickaxey = 1 , container = 2 , not_in_creative_inventory = 1 } ,
2017-01-17 19:50:56 +03:00
drawtype = " nodebox " ,
paramtype = " light " ,
2017-03-20 22:06:24 +03:00
sunlight_propagates = true ,
2017-01-17 19:50:56 +03:00
paramtype2 = " facedir " ,
2017-02-06 19:33:43 +03:00
tiles = { " mcl_hoppers_hopper_inside.png^mcl_hoppers_hopper_top.png " , " mcl_hoppers_hopper_outside.png " , " mcl_hoppers_hopper_outside.png " , " mcl_hoppers_hopper_inside.png " , " mcl_hoppers_hopper_outside.png " , " mcl_hoppers_hopper_outside.png " } ,
2017-01-17 19:50:56 +03:00
selection_box = { type = " regular " } ,
node_box = {
type = " fixed " ,
fixed = {
--funnel walls
{ - 0.5 , 0.0 , 0.4 , 0.5 , 0.5 , 0.5 } ,
{ 0.4 , 0.0 , - 0.5 , 0.5 , 0.5 , 0.5 } ,
{ - 0.5 , 0.0 , - 0.5 , - 0.4 , 0.5 , 0.5 } ,
{ - 0.5 , 0.0 , - 0.5 , 0.5 , 0.5 , - 0.4 } ,
--funnel base
{ - 0.5 , 0.0 , - 0.5 , 0.5 , 0.1 , 0.5 } ,
--spout
{ - 0.3 , - 0.3 , - 0.3 , 0.3 , 0.0 , 0.3 } ,
{ - 0.7 , - 0.3 , - 0.15 , 0.15 , 0.0 , 0.15 } ,
} ,
} ,
2017-03-11 18:36:05 +03:00
is_ground_content = false ,
2017-01-17 19:50:56 +03:00
on_construct = function ( pos )
local meta = minetest.get_meta ( pos )
2017-01-17 20:41:25 +03:00
meta : set_string ( " formspec " , mcl_hoppers_formspec )
2017-01-17 19:50:56 +03:00
local inv = meta : get_inventory ( )
2017-01-17 20:17:53 +03:00
inv : set_size ( " main " , 5 )
2017-01-17 19:50:56 +03:00
end ,
2017-02-22 16:00:58 +03:00
2017-01-17 20:30:35 +03:00
after_dig_node = function ( pos , oldnode , oldmetadata , digger )
local meta = minetest.get_meta ( pos )
local meta2 = meta
meta : from_table ( oldmetadata )
2017-01-17 19:50:56 +03:00
local inv = meta : get_inventory ( )
2017-01-17 20:30:35 +03:00
for i = 1 , inv : get_size ( " main " ) do
local stack = inv : get_stack ( " main " , i )
if not stack : is_empty ( ) then
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 }
minetest.add_item ( p , stack )
end
end
meta : from_table ( meta2 : to_table ( ) )
2017-01-17 19:50:56 +03:00
end ,
on_metadata_inventory_move = function ( pos , from_list , from_index , to_list , to_index , count , player )
minetest.log ( " action " , player : get_player_name ( ) ..
2017-01-17 20:41:25 +03:00
" moves stuff in mcl_hoppers at " .. minetest.pos_to_string ( pos ) )
2017-01-17 19:50:56 +03:00
end ,
on_metadata_inventory_put = function ( pos , listname , index , stack , player )
minetest.log ( " action " , player : get_player_name ( ) ..
2017-01-17 20:41:25 +03:00
" moves stuff to mcl_hoppers at " .. minetest.pos_to_string ( pos ) )
2017-01-17 19:50:56 +03:00
end ,
on_metadata_inventory_take = function ( pos , listname , index , stack , player )
minetest.log ( " action " , player : get_player_name ( ) ..
2017-01-17 20:41:25 +03:00
" takes stuff from mcl_hoppers at " .. minetest.pos_to_string ( pos ) )
2017-01-17 19:50:56 +03:00
end ,
2017-02-11 20:46:23 +03:00
sounds = mcl_sounds.node_sound_metal_defaults ( ) ,
2017-02-22 18:03:59 +03:00
_mcl_blast_resistance = 24 ,
2017-02-27 03:33:34 +03:00
_mcl_hardness = 3 ,
2017-01-17 19:50:56 +03:00
} )
2017-02-14 03:37:30 +03:00
-- Make hoppers suck in dropped items
2017-01-17 19:50:56 +03:00
minetest.register_abm ( {
2017-05-15 01:45:54 +03:00
label = " Hoppers suck in dropped items " ,
2017-01-17 20:41:25 +03:00
nodenames = { " mcl_hoppers:hopper " , " mcl_hoppers:hopper_side " } ,
2017-01-17 19:50:56 +03:00
interval = 1.0 ,
chance = 1 ,
action = function ( pos , node , active_object_count , active_object_count_wider )
2017-02-14 03:37:30 +03:00
local abovenode = minetest.get_node ( { x = pos.x , y = pos.y + 1 , z = pos.z } )
-- Don't bother checking item enties if node above is a container (should save some CPU)
if minetest.registered_items [ abovenode.name ] . groups.container then
return
end
local meta = minetest.get_meta ( pos )
2017-01-17 19:50:56 +03:00
local inv = meta : get_inventory ( )
2017-03-15 20:33:16 +03:00
for _ , object in ipairs ( minetest.get_objects_inside_radius ( pos , 2 ) ) do
2017-01-17 19:50:56 +03:00
if not object : is_player ( ) and object : get_luaentity ( ) and object : get_luaentity ( ) . name == " __builtin:item " then
if inv and inv : room_for_item ( " main " , ItemStack ( object : get_luaentity ( ) . itemstring ) ) then
2017-03-15 20:33:16 +03:00
-- Item must get sucked in when the item just TOUCHES the block above the hopper
-- This is the reason for the Y calculation.
-- Test: Items on farmland and slabs get sucked, but items on full blocks don't
2017-01-17 19:50:56 +03:00
local posob = object : getpos ( )
2017-03-15 20:33:16 +03:00
local posob_miny = posob.y + object : get_properties ( ) . collisionbox [ 2 ]
if math.abs ( posob.x - pos.x ) <= 0.5 and ( posob_miny - pos.y < 1.5 and posob.y - pos.y >= 0.3 ) then
2017-01-17 19:50:56 +03:00
inv : add_item ( " main " , ItemStack ( object : get_luaentity ( ) . itemstring ) )
object : get_luaentity ( ) . itemstring = " "
object : remove ( )
end
end
end
end
end ,
} )
2017-02-21 05:22:25 +03:00
-- Iterates through all items in the given inventory and
-- return the slot of the first item which matches a condition
2017-06-12 20:06:33 +03:00
local get_eligible_transfer_item = function ( src_inventory , src_list , dst_inventory , dst_list , condition )
local size = src_inventory : get_size ( src_list )
2017-02-21 05:22:25 +03:00
local stack
for i = 1 , size do
2017-06-12 20:06:33 +03:00
stack = src_inventory : get_stack ( src_list , i )
if not stack : is_empty ( ) and condition ( stack , src_inventory , src_list , dst_inventory , dst_list ) then
2017-02-21 05:22:25 +03:00
return i
end
end
return nil
end
2017-02-21 05:38:24 +03:00
-- Returns true if given itemstack is a shulker box
local is_not_shulker_box = function ( itemstack )
local g = minetest.get_item_group ( itemstack : get_name ( ) , " shulker_box " )
return g == 0 or g == nil
end
2017-06-12 20:06:33 +03:00
-- Returns true if itemstack is fuel, but not for lava bucket if destination already has one
local is_transferrable_fuel = function ( itemstack , src_inventory , src_list , dst_inventory , dst_list )
if mcl_util.is_fuel ( itemstack ) then
if itemstack : get_name ( ) == " bucket:bucket_lava " then
return dst_inventory : is_empty ( dst_list )
else
return true
end
else
return false
end
end
2017-01-17 19:50:56 +03:00
minetest.register_abm ( {
2017-05-15 01:45:54 +03:00
label = " Hopper/container item exchange " ,
2017-01-17 20:41:25 +03:00
nodenames = { " mcl_hoppers:hopper " } ,
2017-02-14 03:32:13 +03:00
neighbors = { " group:container " } ,
2017-01-17 19:50:56 +03:00
interval = 1.0 ,
chance = 1 ,
action = function ( pos , node , active_object_count , active_object_count_wider )
2017-02-14 03:25:02 +03:00
-- Get node pos' for item transfer
local uppos = { x = pos.x , y = pos.y + 1 , z = pos.z }
local downpos = { x = pos.x , y = pos.y - 1 , z = pos.z }
2017-01-17 19:50:56 +03:00
2017-02-14 03:25:02 +03:00
-- Suck an item from the container above into the hopper
local upnode = minetest.get_node ( uppos )
local g = minetest.registered_nodes [ upnode.name ] . groups.container
if g == 2 or g == 3 then
-- Typical container inventory
mcl_util.move_item_container ( uppos , " main " , - 1 , pos )
elseif g == 4 then
-- Furnace output
mcl_util.move_item_container ( uppos , " dst " , - 1 , pos )
2017-03-03 01:45:42 +03:00
-- Also suck in non-fuel items from fuel slot
local finv = minetest.get_inventory ( { type = " node " , pos = uppos } )
if finv and not mcl_util.is_fuel ( finv : get_stack ( " fuel " , 1 ) ) then
mcl_util.move_item_container ( uppos , " fuel " , - 1 , pos )
end
2017-01-17 19:50:56 +03:00
end
2017-02-14 03:25:02 +03:00
2017-02-14 03:31:24 +03:00
-- Move an item from the hopper into container below
2017-02-21 05:38:24 +03:00
local downnode = minetest.get_node ( downpos )
g = minetest.registered_nodes [ downnode.name ] . groups.container
local slot_id = - 1
if g == 3 then
-- For shulker boxes, only select non-shulker boxes
local sinv = minetest.get_inventory ( { type = " node " , pos = pos } )
2017-06-12 20:06:33 +03:00
local dinv = minetest.get_inventory ( { type = " node " , pos = downpos } )
slot_id = get_eligible_transfer_item ( sinv , " main " , dinv , " main " , is_not_shulker_box )
2017-02-21 05:38:24 +03:00
end
if slot_id then
mcl_util.move_item_container ( pos , " main " , slot_id , downpos )
2017-06-12 23:51:17 +03:00
if g == 4 then
-- Start furnace's timer function, it will sort out whether furnace can burn or not.
minetest.get_node_timer ( downpos ) : start ( 1.0 )
end
2017-02-21 05:38:24 +03:00
end
2017-01-17 19:50:56 +03:00
end ,
} )
minetest.register_abm ( {
2017-05-15 01:45:54 +03:00
label = " Side-hopper/container item exchange " ,
2017-01-17 20:41:25 +03:00
nodenames = { " mcl_hoppers:hopper_side " } ,
2017-02-14 03:32:13 +03:00
neighbors = { " group:container " } ,
2017-01-17 19:50:56 +03:00
interval = 1.0 ,
chance = 1 ,
action = function ( pos , node , active_object_count , active_object_count_wider )
2017-02-14 03:25:02 +03:00
-- Determine to which side the hopper is facing, get nodes
local face = minetest.get_node ( pos ) . param2
2017-01-17 19:50:56 +03:00
local front = { }
if face == 0 then
front = { x = pos.x - 1 , y = pos.y , z = pos.z }
elseif face == 1 then
front = { x = pos.x , y = pos.y , z = pos.z + 1 }
elseif face == 2 then
front = { x = pos.x + 1 , y = pos.y , z = pos.z }
elseif face == 3 then
front = { x = pos.x , y = pos.y , z = pos.z - 1 }
end
2017-02-14 03:25:02 +03:00
local above = { x = pos.x , y = pos.y + 1 , z = pos.z }
2017-01-17 19:50:56 +03:00
2017-02-14 03:25:02 +03:00
local frontnode = minetest.get_node ( front )
2017-02-22 16:00:58 +03:00
2017-02-14 03:25:02 +03:00
-- Suck an item from the container above into the hopper
local abovenode = minetest.get_node ( above )
local g = minetest.registered_nodes [ abovenode.name ] . groups.container
if g == 2 or g == 3 then
-- Typical container inventory
mcl_util.move_item_container ( above , " main " , - 1 , pos )
elseif g == 4 then
-- Furnace output
mcl_util.move_item_container ( above , " dst " , - 1 , pos )
2017-01-17 19:50:56 +03:00
end
2017-02-14 03:31:24 +03:00
-- Move an item from the hopper into the container to which the hopper points to
2017-02-21 04:09:34 +03:00
local g = minetest.registered_nodes [ frontnode.name ] . groups.container
2017-02-21 05:38:24 +03:00
if g == 2 then
2017-02-21 04:09:34 +03:00
mcl_util.move_item_container ( pos , " main " , - 1 , front )
2017-02-21 05:38:24 +03:00
elseif g == 3 then
-- Put non-shulker boxes into shulker box
local sinv = minetest.get_inventory ( { type = " node " , pos = pos } )
2017-06-12 20:06:33 +03:00
local dinv = minetest.get_inventory ( { type = " node " , pos = front } )
local slot_id = get_eligible_transfer_item ( sinv , " main " , dinv , " main " , is_not_shulker_box )
2017-02-21 05:38:24 +03:00
if slot_id then
mcl_util.move_item_container ( pos , " main " , slot_id , front )
end
2017-02-21 04:09:34 +03:00
elseif g == 4 then
2017-02-21 05:22:25 +03:00
-- Put fuel into fuel slot
2017-02-21 05:38:24 +03:00
local sinv = minetest.get_inventory ( { type = " node " , pos = pos } )
2017-06-12 20:06:33 +03:00
local dinv = minetest.get_inventory ( { type = " node " , pos = front } )
local slot_id , stack = get_eligible_transfer_item ( sinv , " main " , dinv , " fuel " , is_transferrable_fuel )
2017-02-21 05:22:25 +03:00
if slot_id then
mcl_util.move_item_container ( pos , " main " , slot_id , front , " fuel " )
end
2017-06-12 23:51:17 +03:00
-- Start furnace's timer function, it will sort out whether furnace can burn or not.
minetest.get_node_timer ( front ) : start ( 1.0 )
2017-02-21 04:09:34 +03:00
end
2017-02-14 03:25:02 +03:00
end
2017-01-17 19:50:56 +03:00
} )
minetest.register_craft ( {
2017-02-22 16:00:58 +03:00
output = " mcl_hoppers:hopper " ,
2017-01-17 19:50:56 +03:00
recipe = {
2017-02-11 23:14:40 +03:00
{ " mcl_core:iron_ingot " , " " , " mcl_core:iron_ingot " } ,
{ " mcl_core:iron_ingot " , " mcl_chests:chest " , " mcl_core:iron_ingot " } ,
{ " " , " mcl_core:iron_ingot " , " " } ,
2017-01-17 19:50:56 +03:00
}
} )
2017-02-22 16:00:58 +03:00
2017-03-20 20:12:05 +03:00
-- Add entry aliases for the Help
if minetest.get_modpath ( " doc " ) then
doc.add_entry_alias ( " nodes " , " mcl_hoppers:hopper " , " nodes " , " mcl_hoppers:hopper_side " )
end
2017-02-22 16:00:58 +03:00
-- Legacy
minetest.register_alias ( " mcl_hoppers:hopper_item " , " mcl_hoppers:hopper " )