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
local facedir_to_bottomdir = {
[ 0 ] = { x = 0 , y =- 1 , z = 0 } ,
{ x = 0 , y = 0 , z =- 1 } ,
{ x = 0 , y = 0 , z = 1 } ,
{ x =- 1 , y = 0 , z = 0 } ,
{ x = 1 , y = 0 , z = 0 } ,
{ x = 0 , y = 1 , z = 0 } ,
}
local bottomdir = function ( facedir )
return facedir_to_bottomdir [ math.floor ( facedir / 4 ) ]
end
local function get_sorter_formspec ( pos )
local spos = hopper.get_string_pos ( pos )
2024-07-21 03:16:35 +02:00
2017-04-01 17:48:54 +02:00
local filter_all = minetest.get_meta ( pos ) : get_string ( " filter_all " ) == " true "
local y_displace = 0
2022-07-10 20:25:00 +02:00
local filter_texture , filter_button_tooltip , filter_body
2017-04-01 17:48:54 +02:00
if filter_all then
filter_body = " "
2022-07-10 20:25:00 +02:00
filter_texture = " hopper_mode_off.png "
filter_button_tooltip = FS ( " This sorter is currently set to try sending all items \n in the direction of the arrow. Click this button \n to enable an item-type-specific filter. " )
2017-04-01 17:48:54 +02:00
else
2022-07-10 20:25:00 +02:00
filter_body = " label[3.7,0; " .. FS ( " Filter " ) .. " ]list[nodemeta: " .. spos .. " ;filter;0,0.5;8,1;] "
filter_texture = " hopper_mode_on.png "
filter_button_tooltip = FS ( " This sorter is currently set to only send items listed \n in the filter list in the direction of the arrow. \n Click this button to set it to try sending all \n items that way first. " )
2017-04-01 17:48:54 +02:00
y_displace = 1.6
end
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
local formspec =
2017-04-01 17:48:54 +02:00
" size[8, " .. 7 + y_displace .. " ] "
2017-03-31 08:58:28 +02:00
.. hopper.formspec_bg
2024-07-21 03:16:35 +02:00
.. filter_body
2017-04-01 17:48:54 +02:00
.. " list[nodemeta: " .. spos .. " ;main;3, " .. tostring ( 0.3 + y_displace ) .. " ;2,2;] "
2022-07-10 20:25:00 +02:00
.. ( " image_button_exit[0,%g;1,1;%s;filter_all;] " ) : format ( y_displace , filter_texture )
.. " tooltip[filter_all; " .. filter_button_tooltip .. " ] "
2017-04-01 17:48:54 +02:00
.. hopper.get_eject_button_texts ( pos , 6 , 0.8 + y_displace )
.. " list[current_player;main;0, " .. tostring ( 2.85 + y_displace ) .. " ;8,1;] "
.. " list[current_player;main;0, " .. tostring ( 4.08 + y_displace ) .. " ;8,3;8] "
2017-03-31 08:58:28 +02:00
.. " listring[nodemeta: " .. spos .. " ;main] "
.. " listring[current_player;main] "
return formspec
end
minetest.register_node ( " hopper:sorter " , {
description = S ( " Sorter " ) ,
_doc_items_longdesc = hopper.doc . sorter_long_desc ,
_doc_items_usagehelp = hopper.doc . sorter_usage ,
groups = { cracky = 3 } ,
sounds = hopper.metal_sounds ,
drawtype = " nodebox " ,
paramtype = " light " ,
paramtype2 = " facedir " ,
tiles = {
" hopper_bottom_ " .. hopper.config . texture_resolution .. " .png " ,
" hopper_top_ " .. hopper.config . texture_resolution .. " .png " ,
2017-04-01 17:48:54 +02:00
" hopper_bottom_ " .. hopper.config . texture_resolution .. " .png^hopper_sorter_arrow_ " .. hopper.config . texture_resolution .. " .png^[transformFX^hopper_sorter_sub_arrow_ " .. hopper.config . texture_resolution .. " .png^[transformFX " ,
" hopper_bottom_ " .. hopper.config . texture_resolution .. " .png^hopper_sorter_arrow_ " .. hopper.config . texture_resolution .. " .png^hopper_sorter_sub_arrow_ " .. hopper.config . texture_resolution .. " .png " ,
2017-03-31 08:58:28 +02:00
" hopper_top_ " .. hopper.config . texture_resolution .. " .png " ,
" hopper_bottom_ " .. hopper.config . texture_resolution .. " .png^hopper_sorter_arrow_ " .. hopper.config . texture_resolution .. " .png " ,
} ,
node_box = {
type = " fixed " ,
fixed = {
{ - 0.3 , - 0.3 , - 0.4 , 0.3 , 0.4 , 0.4 } ,
{ - 0.2 , - 0.2 , 0.4 , 0.2 , 0.2 , 0.7 } ,
{ - 0.2 , - 0.3 , - 0.2 , 0.2 , - 0.7 , 0.2 } ,
} ,
} ,
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
on_construct = function ( pos )
local meta = minetest.get_meta ( pos )
local inv = meta : get_inventory ( )
inv : set_size ( " main " , 2 * 2 )
inv : set_size ( " filter " , 8 )
end ,
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
on_place = function ( itemstack , placer , pointed_thing , node_name )
local pos2 = pointed_thing.above
local returned_stack , success = minetest.item_place_node ( itemstack , placer , pointed_thing )
if success then
local meta = minetest.get_meta ( pos2 )
meta : set_string ( " placer " , placer : get_player_name ( ) )
end
return returned_stack
end ,
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
can_dig = function ( pos , player )
local meta = minetest.get_meta ( pos ) ;
local inv = meta : get_inventory ( )
return inv : is_empty ( " main " )
end ,
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
on_rightclick = function ( pos , node , clicker , itemstack )
if minetest.is_protected ( pos , clicker : get_player_name ( ) ) and not minetest.check_player_privs ( clicker , " protection_bypass " ) then
return
end
minetest.show_formspec ( clicker : get_player_name ( ) ,
" hopper_formspec: " .. minetest.pos_to_string ( pos ) , get_sorter_formspec ( pos ) )
end ,
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
allow_metadata_inventory_put = function ( pos , listname , index , stack , player )
if listname == " filter " then
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
inv : set_stack ( listname , index , stack : take_item ( 1 ) )
return 0
end
return stack : get_count ( )
end ,
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
allow_metadata_inventory_take = function ( pos , listname , index , stack , player )
if listname == " filter " then
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
inv : set_stack ( listname , index , ItemStack ( " " ) )
return 0
end
return stack : get_count ( )
end ,
2024-07-21 03:16:35 +02:00
2017-04-29 23:12:56 +02:00
allow_metadata_inventory_move = function ( pos , from_list , from_index , to_list , to_index , count , player )
if to_list == " filter " then
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
local stack_moved = inv : get_stack ( from_list , from_index )
inv : set_stack ( to_list , to_index , stack_moved : take_item ( 1 ) )
return 0
elseif from_list == " filter " then
local inv = minetest.get_inventory ( { type = " node " , pos = pos } )
inv : set_stack ( from_list , from_index , ItemStack ( " " ) )
2024-07-21 03:16:35 +02:00
return 0
2017-04-29 23:12:56 +02:00
end
return count
end ,
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
on_metadata_inventory_put = function ( pos , listname , index , stack , player )
2022-07-10 20:25:16 +02:00
hopper.log_inventory ( ( " %s moves stuff to sorter at %s " ) : format (
2017-03-31 08:58:28 +02:00
player : get_player_name ( ) , minetest.pos_to_string ( pos ) ) )
local timer = minetest.get_node_timer ( pos )
if not timer : is_started ( ) then
timer : start ( 1 )
2024-07-21 03:16:35 +02:00
end
2017-03-31 08:58:28 +02:00
end ,
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
on_timer = function ( pos , elapsed )
local meta = minetest.get_meta ( pos ) ;
local inv = meta : get_inventory ( )
-- build a filter list
2024-07-21 03:16:35 +02:00
local filter_items = nil
2017-04-01 17:48:54 +02:00
if meta : get_string ( " filter_all " ) ~= " true " then
filter_items = { }
local filter_inv_size = inv : get_size ( " filter " )
for i = 1 , filter_inv_size do
local stack = inv : get_stack ( " filter " , i )
local item = stack : get_name ( )
if item ~= " " then
filter_items [ item ] = true
end
2017-03-31 08:58:28 +02:00
end
end
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
local node = minetest.get_node ( pos )
local dir = minetest.facedir_to_dir ( node.param2 )
local default_destination_pos = vector.add ( pos , dir )
2024-08-16 22:58:59 +02:00
local default_output_direction = ( dir.y == 0 ) and " side " or " bottom "
2017-03-31 08:58:28 +02:00
dir = bottomdir ( node.param2 )
local filter_destination_pos = vector.add ( pos , dir )
2024-08-16 22:58:59 +02:00
local filter_output_direction = ( dir.y == 0 ) and " side " or " bottom "
2017-03-31 08:58:28 +02:00
2024-08-16 22:58:59 +02:00
--- returns success? = true/false
local function try_send_item ( output_dir , dst_pos )
local dst_node = minetest.get_node ( dst_pos )
local registered_inventories = hopper.get_registered ( dst_node.name )
2024-07-21 03:16:35 +02:00
2024-08-16 22:58:59 +02:00
if registered_inventories ~= nil then
return hopper.send_item_to ( pos , dst_pos , dst_node , registered_inventories [ output_dir ] , filter_items )
2017-03-31 08:58:28 +02:00
end
2024-08-16 22:58:59 +02:00
return hopper.send_item_to ( pos , dst_pos , dst_node , nil , filter_items )
2017-03-31 08:58:28 +02:00
end
2024-07-21 03:16:35 +02:00
2024-08-16 22:58:59 +02:00
if not try_send_item ( filter_output_direction , filter_destination_pos ) then
-- weren't able to put something in the filter destination, for whatever reason.
-- Now we can start moving stuff forward to the default.
try_send_item ( default_output_direction , default_destination_pos )
2017-03-31 08:58:28 +02:00
end
2024-07-21 03:16:35 +02:00
2017-03-31 08:58:28 +02:00
if not inv : is_empty ( " main " ) then
minetest.get_node_timer ( pos ) : start ( 1 )
end
end ,
2020-02-19 00:47:23 +01:00
} )