Fill an item stack from an inventory/container
Posted: Sat Sep 05, 2020 2:24 am
Filling a stack (or larger container) with content from other inventories has some pitfalls. LuaInventory.find_item_stack looks like a good start, but if the items in the inventory are not stacked as much as they could be, it needs to be called multiple times as items are removed. Additionally damaged and undamaged items do not stack, but they have the same item name so find_item_stack will return which ever is first.
For example consider the gun turrets in this chest:
This can be worked around but need a bunch of Lua checking each inventory slot.
Something like:
LuaInventory.fill_stack(stack, item_name) → boolean
Fill stack with items from this inventory
Parameters
stack :: LuaItemStack Stack to fill, may be empty
item_name :: string Item to fill stack with. If stack is non-empty, must be the same as stack.name
Return value
true if stack is now full
Extending `LuaInventory.find_item_stack` to differentiate damaged and undamaged items in some way would be another option which I think covers all cases if called in a loop until it returns nil.
---
The full use case was to try and fill as many of the filtered (blue, as per LuaInventory.get_filter(slot_index)) slots in a wagon as possible pulling form another container. Probably the entire thing is too specific.
For example consider the gun turrets in this chest:
Code: Select all
-- doesn't handle uncompressed stacks without a loop
-- doesn't handle damaged vs undamaged items
existing_stack.transfer_stack(inventory.find_item_stack(existing_stack.name))
Something like:
LuaInventory.fill_stack(stack, item_name) → boolean
Fill stack with items from this inventory
Parameters
stack :: LuaItemStack Stack to fill, may be empty
item_name :: string Item to fill stack with. If stack is non-empty, must be the same as stack.name
Return value
true if stack is now full
Code: Select all
function fill_stack(self, stack, item_name)
local stack_size = game.item_prototypes[item_name].stack_size
if stack.valid_for_read then
assert(item_name == stack.name)
if stack.count == stack_size then
return true -- full already, do nothing
end
end -- else empty stack
for i=1,#self do
stack.transfer_stack(self[i]) -- no-op if not stackable
if stack.valid_for_read and stack.count >= stack_size then
return true -- full, finished
end
end
return false -- not full
end
Code: Select all
inventory.find_item_stack('gun-turret') -- as now, don't care, whichever comes first
inventory.find_item_stack('gun-turret', true) -- only find damaged items
inventory.find_item_stack('gun-turret', false) -- only find undamaged items
The full use case was to try and fill as many of the filtered (blue, as per LuaInventory.get_filter(slot_index)) slots in a wagon as possible pulling form another container. Probably the entire thing is too specific.