2019-09-24 23:04:55 +02:00
--this adds a button that stashes/sorts your inventory into nearby chests in some kind of intelligent way - mewmew
2019-10-24 23:00:14 +02:00
-- modified by gerkiz
2019-09-24 23:04:55 +02:00
local print_color = { r = 120 , g = 255 , b = 0 }
local function create_floaty_text ( surface , position , name , count , height_offset )
2019-10-15 04:33:42 +02:00
if global.autostash_floating_text_y_offsets [ position.x .. " _ " .. position.y ] then
global.autostash_floating_text_y_offsets [ position.x .. " _ " .. position.y ] = global.autostash_floating_text_y_offsets [ position.x .. " _ " .. position.y ] - 0.5
2019-09-24 23:04:55 +02:00
else
2019-10-15 04:33:42 +02:00
global.autostash_floating_text_y_offsets [ position.x .. " _ " .. position.y ] = 0
2019-09-24 23:04:55 +02:00
end
surface.create_entity ( {
name = " flying-text " ,
2019-10-15 04:33:42 +02:00
position = { position.x , position.y + global.autostash_floating_text_y_offsets [ position.x .. " _ " .. position.y ] } ,
2019-09-24 23:04:55 +02:00
text = " - " .. count .. " " .. name ,
color = { r = 255 , g = 255 , b = 255 } ,
} )
end
local function chest_is_valid ( chest )
for _ , e in pairs ( chest.surface . find_entities_filtered ( { type = { " inserter " , " loader " } , area = { { chest.position . x - 1 , chest.position . y - 1 } , { chest.position . x + 1 , chest.position . y + 1 } } } ) ) do
2019-09-25 00:07:55 +02:00
if e.name ~= " long-handed-inserter " then
if e.position . x == chest.position . x then
if e.direction == 0 or e.direction == 4 then
return false
end
2019-09-24 23:04:55 +02:00
end
2019-09-25 00:07:55 +02:00
if e.position . y == chest.position . y then
if e.direction == 2 or e.direction == 6 then
return false
end
2019-09-24 23:04:55 +02:00
end
end
end
2019-09-25 00:07:55 +02:00
local inserter = chest.surface . find_entity ( " long-handed-inserter " , { chest.position . x - 2 , chest.position . y } )
if inserter then
if inserter.direction == 2 or inserter.direction == 6 then
return false
end
end
local inserter = chest.surface . find_entity ( " long-handed-inserter " , { chest.position . x + 2 , chest.position . y } )
if inserter then
if inserter.direction == 2 or inserter.direction == 6 then
return false
end
end
local inserter = chest.surface . find_entity ( " long-handed-inserter " , { chest.position . x , chest.position . y - 2 } )
if inserter then
if inserter.direction == 0 or inserter.direction == 4 then
return false
end
end
local inserter = chest.surface . find_entity ( " long-handed-inserter " , { chest.position . x , chest.position . y + 2 } )
if inserter then
if inserter.direction == 0 or inserter.direction == 4 then
return false
end
end
2019-09-24 23:04:55 +02:00
return true
end
local function get_nearby_chests ( player )
local r = player.force . character_reach_distance_bonus + 10
local r_square = r * r
local chests = { }
local area = { { player.position . x - r , player.position . y - r } , { player.position . x + r , player.position . y + r } }
for _ , e in pairs ( player.surface . find_entities_filtered ( { type = " container " , area = area } ) ) do
if ( ( player.position . x - e.position . x ) ^ 2 + ( player.position . y - e.position . y ) ^ 2 ) <= r_square then
2019-09-25 00:26:01 +02:00
chests [ # chests + 1 ] = e
2019-09-24 23:04:55 +02:00
end
end
for _ , e in pairs ( player.surface . find_entities_filtered ( { name = " logistic-chest-storage " , area = area } ) ) do
if ( ( player.position . x - e.position . x ) ^ 2 + ( player.position . y - e.position . y ) ^ 2 ) <= r_square then
2019-09-25 00:26:01 +02:00
chests [ # chests + 1 ] = e
2019-09-24 23:04:55 +02:00
end
end
for _ , e in pairs ( player.surface . find_entities_filtered ( { name = " logistic-chest-passive-provider " , area = area } ) ) do
if ( ( player.position . x - e.position . x ) ^ 2 + ( player.position . y - e.position . y ) ^ 2 ) <= r_square then
2019-09-25 00:26:01 +02:00
chests [ # chests + 1 ] = e
2019-09-24 23:04:55 +02:00
end
end
return chests
end
local function does_inventory_contain_item_type ( inventory , item_subgroup )
for name , count in pairs ( inventory.get_contents ( ) ) do
if game.item_prototypes [ name ] . subgroup.name == item_subgroup then return true end
end
return false
end
2019-09-25 00:26:01 +02:00
local function insert_item_into_chest ( player_inventory , chests , filtered_chests , name , count )
--Attempt to store in chests that already have the same item.
2019-09-24 23:04:55 +02:00
for _ , chest in pairs ( chests ) do
local chest_inventory = chest.get_inventory ( defines.inventory . chest )
if chest_inventory.can_insert ( { name = name , count = count } ) then
if chest_inventory.find_item_stack ( name ) then
local inserted_count = chest_inventory.insert ( { name = name , count = count } )
2019-10-24 23:00:14 +02:00
2019-09-24 23:04:55 +02:00
player_inventory.remove ( { name = name , count = inserted_count } )
create_floaty_text ( chest.surface , chest.position , name , inserted_count )
count = count - inserted_count
if count <= 0 then return end
end
end
2019-09-25 00:26:01 +02:00
end
2019-09-24 23:04:55 +02:00
--Attempt to store in empty chests.
2019-09-25 00:26:01 +02:00
for _ , chest in pairs ( filtered_chests ) do
2019-09-24 23:04:55 +02:00
local chest_inventory = chest.get_inventory ( defines.inventory . chest )
if chest_inventory.can_insert ( { name = name , count = count } ) then
if chest_inventory.is_empty ( ) then
local inserted_count = chest_inventory.insert ( { name = name , count = count } )
player_inventory.remove ( { name = name , count = inserted_count } )
create_floaty_text ( chest.surface , chest.position , name , inserted_count )
count = count - inserted_count
if count <= 0 then return end
end
end
end
--Attempt to store in chests with same item subgroup.
local item_subgroup = game.item_prototypes [ name ] . subgroup.name
if item_subgroup then
2019-09-25 00:26:01 +02:00
for _ , chest in pairs ( filtered_chests ) do
2019-09-24 23:04:55 +02:00
local chest_inventory = chest.get_inventory ( defines.inventory . chest )
if chest_inventory.can_insert ( { name = name , count = count } ) then
if does_inventory_contain_item_type ( chest_inventory , item_subgroup ) then
local inserted_count = chest_inventory.insert ( { name = name , count = count } )
player_inventory.remove ( { name = name , count = inserted_count } )
create_floaty_text ( chest.surface , chest.position , name , inserted_count )
count = count - inserted_count
if count <= 0 then return end
end
end
end
end
--Attempt to store in mixed chests.
2019-09-25 00:26:01 +02:00
for _ , chest in pairs ( filtered_chests ) do
2019-09-24 23:04:55 +02:00
local chest_inventory = chest.get_inventory ( defines.inventory . chest )
if chest_inventory.can_insert ( { name = name , count = count } ) then
local inserted_count = chest_inventory.insert ( { name = name , count = count } )
player_inventory.remove ( { name = name , count = inserted_count } )
create_floaty_text ( chest.surface , chest.position , name , inserted_count )
count = count - inserted_count
if count <= 0 then return end
end
end
end
2019-10-24 23:00:14 +02:00
local function auto_stash ( player , event )
local button = event.button
2019-09-24 23:04:55 +02:00
if not player.character then player.print ( " It seems that you are not in the realm of the living. " , print_color ) return end
if not player.character . valid then player.print ( " It seems that you are not in the realm of the living. " , print_color ) return end
local inventory = player.get_inventory ( defines.inventory . character_main )
if inventory.is_empty ( ) then player.print ( " Inventory is empty. " , print_color ) return end
local chests = get_nearby_chests ( player )
if not chests [ 1 ] then player.print ( " No valid nearby containers found. " , print_color ) return end
2019-09-25 00:26:01 +02:00
local filtered_chests = { }
for _ , e in pairs ( chests ) do
if chest_is_valid ( e ) then filtered_chests [ # filtered_chests + 1 ] = e end
end
2019-10-15 04:33:42 +02:00
global.autostash_floating_text_y_offsets = { }
2019-09-24 23:04:55 +02:00
2019-10-10 03:18:59 +02:00
local hotbar_items = { }
for i = 1 , 100 , 1 do
local prototype = player.get_quick_bar_slot ( i )
if prototype then
hotbar_items [ prototype.name ] = true
end
end
2019-10-24 23:00:14 +02:00
local ore_types = {
[ " coal " ] = true ,
[ " stone " ] = true ,
[ " iron-ore " ] = true ,
[ " copper-ore " ] = true ,
[ " uranium-ore " ] = true
}
2019-09-24 23:04:55 +02:00
for name , count in pairs ( inventory.get_contents ( ) ) do
2019-10-24 23:00:14 +02:00
if not inventory.find_item_stack ( name ) . grid and not hotbar_items [ name ] then
if button == defines.mouse_button_type . right then
if ore_types [ name ] then
insert_item_into_chest ( inventory , chests , filtered_chests , name , count )
end
elseif button == defines.mouse_button_type . left then
insert_item_into_chest ( inventory , chests , filtered_chests , name , count )
end
2019-09-30 14:08:45 +02:00
end
2019-09-24 23:04:55 +02:00
end
2019-10-24 23:00:14 +02:00
2019-10-15 04:33:42 +02:00
global.autostash_floating_text_y_offsets = nil
2019-09-24 23:04:55 +02:00
end
local function create_gui_button ( player )
if player.gui . top.auto_stash then return end
2019-10-10 03:18:59 +02:00
local b = player.gui . top.add ( { type = " sprite-button " , sprite = " item/wooden-chest " , name = " auto_stash " , tooltip = " Sort your inventory into nearby chests, \n excluding quickbar items. " } )
2019-09-24 23:04:55 +02:00
b.style . font_color = { r = 0.11 , g = 0.8 , b = 0.44 }
b.style . font = " heading-1 "
b.style . minimal_height = 38
b.style . minimal_width = 38
2019-10-02 21:13:14 +02:00
b.style . maximal_height = 38
b.style . maximal_width = 38
b.style . padding = 1
b.style . margin = 0
2019-09-24 23:04:55 +02:00
end
local function on_player_joined_game ( event )
create_gui_button ( game.players [ event.player_index ] )
end
local function on_gui_click ( event )
if not event.element then return end
if not event.element . valid then return end
if event.element . name == " auto_stash " then
2019-10-24 23:00:14 +02:00
auto_stash ( game.players [ event.player_index ] , event )
2019-09-24 23:04:55 +02:00
end
2019-10-24 23:00:14 +02:00
2019-09-24 23:04:55 +02:00
end
local event = require ' utils.event '
event.add ( defines.events . on_player_joined_game , on_player_joined_game )
event.add ( defines.events . on_gui_click , on_gui_click )