195 lines
6.2 KiB
Lua

local math = require("__flib__/math")
local table = require("__flib__/table")
local constants = require("__QuickItemSearch__/constants")
local search = require("__QuickItemSearch__/scripts/search")
local logistic_request = {}
function logistic_request.set(player, player_table, name, counts, is_temporary)
local requests = player_table.logistic_requests
local request_data = requests.by_name[name]
local request_index
if request_data then
request_index = request_data.index
else
request_data = { min = 0, max = math.max_uint }
-- search for first empty slot
local i = 1
while true do
local existing_request = player.get_personal_logistic_slot(i)
if existing_request.name then
i = i + 1
else
request_index = i
break
end
end
end
-- save previous request if this one is temporary
if is_temporary then
-- Do not overwrite previously stored request.
if not requests.temporary[name] then
requests.temporary[name] = table.deep_copy(request_data)
-- Store age of temporary request in order to allow player to
-- persist changes after temporary requests have been fulfilled.
requests.temporary[name].age = game.tick
end
else
-- delete temporary request for this item if there is one
requests.temporary[name] = nil
end
-- set on player
-- this will create or update the data in the requests table automatically
player.set_personal_logistic_slot(request_index, {
name = name,
min = counts.min,
max = counts.max,
})
end
function logistic_request.clear(player, player_table, name)
local requests = player_table.logistic_requests
if not requests then
return
end
local request_data = requests.by_name[name]
if request_data then
player.clear_personal_logistic_slot(request_data.index)
end
end
function logistic_request.update(player, player_table, slot_index)
local requests = player_table.logistic_requests
if not requests then
return
end
local existing_request = player.get_personal_logistic_slot(slot_index)
if existing_request then
local request_data = requests.by_index[slot_index]
if request_data then
if request_data.name == existing_request.name then
-- update counts
request_data.min = existing_request.min
request_data.max = existing_request.max
else
requests.by_name[request_data.name] = nil
if existing_request.name then
existing_request.index = slot_index
requests.by_index[slot_index] = existing_request
requests.by_name[existing_request.name] = existing_request
else
-- delete this request's data entirely
requests.by_index[slot_index] = nil
end
end
elseif existing_request.name then
existing_request.index = slot_index
requests.by_index[slot_index] = existing_request
requests.by_name[existing_request.name] = existing_request
end
-- Update previous request's quantities if affected. Allows player
-- to make changes to logistic requests that are affected by
-- temporary requests or quick-trashing, and still preserve those
-- (manual) changes after temporary requests are fullfilled.
if existing_request.name then
local temporary_request = requests.temporary[existing_request.name]
local current_age = game.tick
if temporary_request and temporary_request.age < current_age then
temporary_request.age = current_age
temporary_request.min = existing_request.min
temporary_request.max = existing_request.max
end
end
end
end
function logistic_request.refresh(player, player_table)
local requests = {
by_index = {},
by_name = {},
temporary = {},
}
local character = player.character
if character then
for i = 1, character.request_slot_count do
local filter = player.get_personal_logistic_slot(i)
if filter and filter.name then
filter.index = i
requests.by_index[i] = filter
requests.by_name[filter.name] = filter
end
end
end
-- preserve valid temporary requests
local item_prototypes = game.item_prototypes
for item_name, request in pairs(player_table.logistic_requests.temporary) do
if item_prototypes[item_name] then
requests.temporary[item_name] = request
end
end
player_table.logistic_requests = requests
end
function logistic_request.update_temporaries(player, player_table, combined_contents)
local requests = player_table.logistic_requests
if not requests then
return
end
local temporary_requests = requests.temporary
for name, old_request_data in pairs(temporary_requests) do
local existing_request_data = requests.by_name[name]
if existing_request_data then
local has_count = combined_contents[name] or 0
-- if the request has been satisfied
if has_count >= existing_request_data.min and has_count <= existing_request_data.max then
-- clear the temporary request data first to avoid setting the slot twice
temporary_requests[name] = nil
-- set the former request
player.set_personal_logistic_slot(existing_request_data.index, old_request_data)
end
else
temporary_requests[name] = nil
end
end
end
function logistic_request.quick_trash_all(player, player_table)
local main_inventory = player.get_main_inventory()
if not main_inventory or not main_inventory.valid then
return
end
local requests = player_table.logistic_requests
if not requests then
return
end
local prototypes = game.item_prototypes
for name, count in pairs(search.get_combined_inventory_contents(player, main_inventory)) do
if not constants.ignored_item_types[prototypes[name].type] then
local existing_request = requests.by_name[name]
if existing_request then
if count > existing_request.min then
logistic_request.set(
player,
player_table,
name,
{ min = existing_request.min, max = existing_request.min },
true
)
end
else
logistic_request.set(player, player_table, name, { min = 0, max = 0 }, true)
end
end
end
end
return logistic_request