1
0
mirror of https://github.com/Wyrrrd/Autofilter.git synced 2026-02-10 19:27:14 +01:00
Files
Autofilter/control.lua
2024-11-06 15:40:02 +01:00

257 lines
7.7 KiB
Lua

--control.lua
--functions definitions
local function get_item_name(item)
if not item then
return
end
local itemname = item
if type(itemname) ~= "string" then
itemname = itemname.name
if type(itemname) ~= "string" then
itemname = itemname.name
end
end
return itemname
end
local function concatenate_tables(table1,table2)
for i = 1,#table2 do
table1[#table1+1]=table2[i]
end
return table1
end
local function string_to_table(str)
local words = {}
for word in str:gmatch("([^%s]+)") do
words[#words+1] = word
end
return words
end
local function toggle_shortcut(event)
local player = game.get_player(event.player_index)
local input = event.prototype_name or event.input_name
if player and input == "autofilter" then
-- Toggle shortcut state
player.set_shortcut_toggled(input, not player.is_shortcut_toggled(input))
end
end
local function is_filter_empty(inserter)
for slot = 1,inserter.filter_slot_count do
if inserter.get_filter(slot) then
return false
end
end
return true
end
local function deduplicate_items(items)
local dedup_items = {}
local marker = false
for i=1,#items do
for j=i+1,#items do
if items[i] == items[j] then
marker = true
end
end
if not marker then
dedup_items[#dedup_items+1]=items[i]
end
marker = false
end
return dedup_items
end
local function remove_noninsertable_items(items,entity)
local search_inventories = {
chest = {defines.inventory.chest},
furnace = {defines.inventory.furnace_source},
roboport = {defines.inventory.roboport_robot, defines.inventory.roboport_material},
assembling_machine = {defines.inventory.assembling_machine_input},
lab = {defines.inventory.lab_input},
rocket_silo = {defines.inventory.rocket_silo_rocket, defines.inventory.rocket_silo_input},
cargo_wagon = {defines.inventory.cargo_wagon},
turret = {defines.inventory.turret_ammo},
artillery_turret = {defines.inventory.artillery_turret_ammo},
artillery_wagon = {defines.inventory.artillery_wagon_ammo},
spider = {defines.inventory.spider_ammo},
hub = {defines.inventory.hub_main},
cargo_landing_pad = {defines.inventory.cargo_landing_pad_main}
}
local insert_items = {}
local no_inventory_flag = true
local item_insertable_flag = false
for i=1,#items do
-- Check fuel inventory
local inventory = entity.get_fuel_inventory()
if inventory and inventory.valid then
no_inventory_flag = false
if inventory.can_insert({name=items[i]}) then
item_insertable_flag = true
end
end
-- Check other inventories
if search_inventories[entity.prototype] then
for _,search_inventory in pairs(search_inventories[entity.prototype]) do
inventory = entity.get_inventory(search_inventory)
if inventory and inventory.valid then
no_inventory_flag = false
if inventory.can_insert({name=items[i]}) then
item_insertable_flag = true
end
end
end
end
if no_inventory_flag then
insert_items = items
break
end
if item_insertable_flag then
insert_items[#insert_items+1]=items[i]
item_insertable_flag = false
end
end
return insert_items
end
local function get_items_by_content(inventory)
local content_items = {}
for _,item in pairs(inventory.get_contents()) do
content_items[#content_items+1] = get_item_name(item)
end
return content_items
end
local function get_items_by_inventory_filter(inventory)
local filter_items = {}
for slot = 1,#inventory do
if inventory.get_filter(slot) then
filter_items[#filter_items+1] = get_item_name(inventory.get_filter(slot))
end
end
return filter_items
end
local function get_items_by_entity_filter(entity)
local filter_items = {}
for slot = 1,entity.filter_slot_count do
if entity.get_filter(slot) then
filter_items[#filter_items+1] = get_item_name(entity.get_filter(slot))
end
end
return filter_items
end
local function get_items_by_transport_line(belt)
local belt_items = {}
for i = 1,belt.get_max_transport_line_index() do
local line = belt.get_transport_line(i)
if line and line.valid then
belt_items = concatenate_tables(belt_items,get_items_by_content(line))
end
end
return belt_items
end
local function on_built_entity(event)
if game.players[event.player_index].is_shortcut_toggled("autofilter") then
local inserter = event.entity
local mode = string_to_table(game.players[event.player_index].mod_settings["autofilter_mode"].value)
if inserter and inserter.valid and inserter.type == "inserter" then
if inserter.filter_slot_count then
if not inserter.use_filters and is_filter_empty(inserter) and inserter.inserter_filter_mode == "whitelist" then
-- Read pickup and drop position entity
local pickup = inserter.surface.find_entities_filtered({
position = inserter.pickup_position,
force = inserter.force,
surface = inserter.surface,
collision_mask_layer= "is_object",
to_be_deconstructed = false,
limit = 1
})
local drop = inserter.surface.find_entities_filtered({
position = inserter.drop_position,
force = inserter.force,
surface = inserter.surface,
collision_mask= "is_object",
to_be_deconstructed = false,
limit = 1
})
if pickup[1] and pickup[1].valid then
-- Prequisites
local inventory_pickup = pickup[1].get_output_inventory()
if (pickup[1].type == "transport-belt" or pickup[1].type == "underground-belt" or pickup[1].type == "splitter") then
local maxlines = pickup[1].get_max_transport_line_index()
end
local items = {}
local check = false
-- Read each mode element
for _,step in pairs(mode) do
if step == "contents" then
-- Read inventory contents at pickup, write to filter
if inventory_pickup and not inventory_pickup.is_empty() then
items = concatenate_tables(items,get_items_by_content(inventory_pickup))
end
elseif step == "filter" then
-- Read inventory filter at pickup, write to filter
if inventory_pickup and inventory_pickup.is_filtered() then
items = concatenate_tables(items,get_items_by_inventory_filter(inventory_pickup))
end
-- Read entity filter at pickup, write to filter
if pickup[1].filter_slot_count > 0 then
items = concatenate_tables(items,get_items_by_entity_filter(pickup[1]))
end
elseif step == "belt" then
-- Read belt transport lines at pickup, write to filter
if (pickup[1].type == "transport-belt" or pickup[1].type == "underground-belt" or pickup[1].type == "splitter") and pickup[1].get_max_transport_line_index() then
items = concatenate_tables(items,get_items_by_transport_line(pickup[1]))
end
elseif step == "check" then
-- Drop inventory insertion check
if drop[1] and drop[1].valid then
items = remove_noninsertable_items(items,drop[1])
end
end
end
-- Filter candidate cleanup
if #items > 0 then
-- Deduplication
items = deduplicate_items(items)
-- Debug message
if __DebugAdapter then
__DebugAdapter.print("[Autofilter] Inserter at (" .. inserter.position.x .. "," .. inserter.position.y .. ") had its filter set to: " .. table.concat(items,", "))
end
-- Enable filters
inserter.use_filters = true
-- Writing filters until full
for slot = 1, inserter.filter_slot_count do
inserter.set_filter(slot,items[slot])
end
end
end
end
end
end
end
end
--event handling
script.on_event({defines.events.on_lua_shortcut, "autofilter"}, toggle_shortcut)
script.on_event(defines.events.on_built_entity, on_built_entity,{{filter="type", type = "inserter"}})