Extract function for getting item from supplier, prepare for crafting supplier

This commit is contained in:
Zenon Seth 2023-11-19 11:22:48 +00:00
parent ad6fe4a4e5
commit 3a492da4a0
6 changed files with 82 additions and 67 deletions

View File

@ -3,6 +3,7 @@ logistica.controllers = {}
logistica.injectors = {}
logistica.requesters = {}
logistica.suppliers = {}
logistica.craftsups = {}
logistica.mass_storage = {}
logistica.item_storage = {}
logistica.misc_machines = {}
@ -30,6 +31,10 @@ function logistica.is_supplier(name)
return logistica.suppliers[name] ~= nil
end
function logistica.is_crafting_supplier(name)
return logistica.craftsups[name] ~= nil
end
function logistica.is_mass_storage(name)
return logistica.mass_storage[name] ~= nil
end

View File

@ -111,7 +111,7 @@ function logistica.pull_items_from_network_into_mass_storage(pos)
local numTaken = 0
for hash, _ in pairs(network.supplier_cache[requestStack:get_name()] or {}) do
local taken = logistica.take_item_from_supplier(minetest.get_position_from_hash(hash), requestStack)
local taken = logistica.take_item_from_supplier_simple(minetest.get_position_from_hash(hash), requestStack)
numTaken = numTaken + taken:get_count()
logistica.insert_item_into_mass_storage(pos, meta:get_inventory(), taken)
if numTaken >= spaceForItems then return end -- everything isnerted, return

View File

@ -106,8 +106,8 @@ local function update_network_cache(network, cacheOps)
end
-- smartly tries to update the the cache for the given position
local function update_network_cache_for_pos(pos, cacheOps)
local network = logistica.get_network_or_nil(pos)
local function update_network_cache_for_pos(pos, cacheOps, optNetwork)
local network = optNetwork or logistica.get_network_or_nil(pos)
if not network then return end
local meta = get_meta(pos)
local hash = minetest.hash_node_position(pos)
@ -128,8 +128,8 @@ local function update_network_cache_for_pos(pos, cacheOps)
save_prev_cache(meta, listName, currCacheItems)
end
local function remove_network_cache_for_pos(pos, cacheOps)
local network = logistica.get_network_or_nil(pos)
local function remove_network_cache_for_pos(pos, cacheOps, optNetwork)
local network = optNetwork or logistica.get_network_or_nil(pos)
if not network then return end
local meta = get_meta(pos)
local hash = minetest.hash_node_position(pos)
@ -156,12 +156,13 @@ end
-- updates the storage cache for the specific position
-- `type` is one of LOG_CACHE_MASS_STORAGE, LOG_CACHE_SUPPLIER, LOG_CACHE_REQUESTER
function logistica.update_cache_at_pos(pos, type)
update_network_cache_for_pos(pos, type)
-- optNetwork is optional, the network it belongs to
function logistica.update_cache_at_pos(pos, type, optNetwork)
update_network_cache_for_pos(pos, type, optNetwork)
end
-- removes the given pos's cache from the network
-- `type` is one of LOG_CACHE_MASS_STORAGE, LOG_CACHE_SUPPLIER, LOG_CACHE_REQUESTER
function logistica.update_cache_node_removed_at_pos(pos, type)
remove_network_cache_for_pos(pos, type)
function logistica.update_cache_node_removed_at_pos(pos, type, optNetwork)
remove_network_cache_for_pos(pos, type, optNetwork)
end

View File

@ -141,11 +141,9 @@ local function recursive_scan_for_nodes_for_controller(network, positionHashes,
network.injectors[otherHash] = true
valid = true
end
if logistica.is_supplier(otherName) then
network.suppliers[otherHash] = true
valid = true
end
if logistica.is_vaccuum_supplier(otherName) then
if logistica.is_supplier(otherName)
or logistica.is_crafting_supplier(otherName)
or logistica.is_vaccuum_supplier(otherName) then
network.suppliers[otherHash] = true
valid = true
end

View File

@ -1,19 +1,12 @@
local MASS_STORAGE_LIST_NAME = "storage"
local ITEM_STORAGE_LIST_NAME = "main"
local SUPPLIER_LIST_NAME = "main"
local function get_meta(pos)
logistica.load_position(pos)
return minetest.get_meta(pos)
end
local function updateSupplierCacheFor(supplierPosList)
for _, pos in ipairs(supplierPosList) do
logistica.update_cache_at_pos(pos, LOG_CACHE_SUPPLIER)
end
end
-- tries to take a stack from the network locations
-- calls the collectorFunc with the stack - collectorFunc needs to return how many were left-over<br>
-- `collectorFunc = function(stackToInsert)`<br>
@ -38,55 +31,24 @@ end
-- calls the collectorFunc with the stack when necessary
-- note that it may be called multiple times as the itemstack is gathered from mass storage
function logistica.take_stack_from_suppliers(stackToTake, network, collectorFunc, isAutomatedRequest, useMetadata, dryRun)
local eq = function(s1, s2) return s1:get_name() == s2:get_name() end
if stackToTake:get_stack_max() == 1 and useMetadata then eq = function(s1, s2) return s1:equals(s2) end end
local takeStack = ItemStack(stackToTake)
local requestedAmount = stackToTake:get_count()
local remaining = requestedAmount
local stackName = stackToTake:get_name()
local validSupplers = network.supplier_cache[stackName] or {}
local modifiedPos = {}
for hash, _ in pairs(validSupplers) do
local supplierPos = minetest.get_position_from_hash(hash)
local supplierInv = get_meta(supplierPos):get_inventory()
local supplyList = supplierInv:get_list(SUPPLIER_LIST_NAME)
for i, supplyStack in ipairs(supplyList) do
if eq(supplyStack, stackToTake) then
table.insert(modifiedPos, supplierPos)
local supplyCount = supplyStack:get_count()
if supplyCount >= remaining then -- enough to fulfil requested
local toSend = ItemStack(supplyStack) ; toSend:set_count(remaining)
local leftover = collectorFunc(toSend)
local newSupplyCount = supplyCount - remaining + leftover
supplyStack:set_count(newSupplyCount)
if not dryRun then
supplierInv:set_stack(SUPPLIER_LIST_NAME, i, supplyStack)
if newSupplyCount <= 0 then
updateSupplierCacheFor(modifiedPos)
end
end
return true
else -- not enough to fulfil requested
local toSend = ItemStack(supplyStack)
local leftover = collectorFunc(toSend)
remaining = remaining - (supplyCount - leftover)
supplyStack:set_count(leftover)
if leftover > 0 then -- for some reason we could not insert all - exit early
if not dryRun then
supplierInv:set_stack(SUPPLIER_LIST_NAME, i, supplyStack)
end
return true
end
end
local pos = minetest.get_position_from_hash(hash)
logistica.load_position(pos)
local nodeName = minetest.get_node(pos).name
if logistica.is_supplier(nodeName) or logistica.is_vaccuum_supplier(nodeName) then
remaining = logistica.take_item_from_supplier(pos, takeStack, network, collectorFunc, useMetadata, dryRun)
elseif logistica.is_crafting_supplier(nodeName) then
remaining = logistica.take_item_from_crafting_supplier(pos, takeStack, network, collectorFunc, useMetadata, dryRun)
end
if remaining <= 0 then
return true
end
-- if we get there, we did not fulfil the request from this supplier
-- but some items still may have been inserted
if not dryRun then
supplierInv:set_list(SUPPLIER_LIST_NAME, supplyList)
end
end
if not dryRun then
updateSupplierCacheFor(modifiedPos)
takeStack:set_count(remaining)
end
return false
end
@ -215,7 +177,7 @@ function logistica.insert_item_in_network(itemstack, networkId, dryRun)
workingStack = remainingStack
end
-- finally try to add to passive suppliers that accept this
-- try to add to passive suppliers that accept this
local suppliers = network.suppliers
for hash, _ in pairs(suppliers) do
local pos = minetest.get_position_from_hash(hash)
@ -225,6 +187,7 @@ function logistica.insert_item_in_network(itemstack, networkId, dryRun)
workingStack = leftover
end
-- [Keep this last] delete the item if any trashcan accepts it
local trashcans = network.trashcans or {}
for hash, _ in pairs(trashcans) do
local pos = minetest.get_position_from_hash(hash)

View File

@ -13,11 +13,13 @@ function logistica.get_supplier_inv_size(pos)
end
-- returns an ItemStack of how many items were taken
function logistica.take_item_from_supplier(pos, stack)
function logistica.take_item_from_supplier_simple(pos, stack)
logistica.load_position(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:remove_item(META_SUPPLIER_LIST, stack)
local removed = inv:remove_item(META_SUPPLIER_LIST, stack)
logistica.update_cache_at_pos(pos, LOG_CACHE_SUPPLIER)
return removed
end
@ -34,4 +36,50 @@ function logistica.put_item_in_supplier(pos, stack)
logistica.update_cache_at_pos(pos, LOG_CACHE_SUPPLIER)
end
return leftover
end
end
-- returns the leftover stack that still needs to be fulfilled (or empty stack if entire request was fulfilled)
function logistica.take_item_from_supplier(supplierPos, stackToTake, network, collectorFunc, useMetadata, dryRun)
local eq = function(s1, s2) return s1:get_name() == s2:get_name() end
if stackToTake:get_stack_max() == 1 and useMetadata then eq = function(s1, s2) return s1:equals(s2) end end
logistica.load_position(supplierPos)
local remaining = stackToTake:get_count()
local supplierInv = minetest.get_meta(supplierPos):get_inventory()
local supplyList = supplierInv:get_list(META_SUPPLIER_LIST)
for i, supplyStack in ipairs(supplyList) do
if eq(supplyStack, stackToTake) then
local supplyCount = supplyStack:get_count()
if supplyCount >= remaining then -- enough to fulfil requested
local toSend = ItemStack(supplyStack) ; toSend:set_count(remaining)
local leftover = collectorFunc(toSend)
local newSupplyCount = supplyCount - remaining + leftover
supplyStack:set_count(newSupplyCount)
if not dryRun then
supplierInv:set_stack(META_SUPPLIER_LIST, i, supplyStack)
if newSupplyCount <= 0 then
logistica.update_cache_at_pos(supplierPos, LOG_CACHE_SUPPLIER, network)
end
end
return 0
else -- not enough to fulfil requested
local toSend = ItemStack(supplyStack)
local leftover = collectorFunc(toSend)
remaining = remaining - (supplyCount - leftover)
supplyStack:set_count(leftover)
if leftover > 0 then -- for some reason we could not insert all - exit early
if not dryRun then
supplierInv:set_stack(META_SUPPLIER_LIST, i, supplyStack)
end
return 0
end
end
end
end
-- if we get there, we did not fulfil the request from this supplier
-- but some items still may have been inserted
if not dryRun then
logistica.update_cache_at_pos(supplierPos, LOG_CACHE_SUPPLIER, network)
end
return remaining
end