Page 1 of 1

Transfer items between inventories with limit

Posted: Sun Nov 03, 2024 3:54 am
by y_e_a_r
Hi, I've been looking for a way to transfer items from one inventory to another with a limit and I'm having trouble finding the appropriate API call.

I can think of at least 2 places in the game where it seems this functionality is already implemented in the game:
- when inserters pick up items from an inventory
- when bots pick up items from an inventory

In both cases, the inserter and the bots might not pick up the entire stack and have a limit on the max number of items they can hold.

I raised this question in the #mod-dev-help channel on the Factorio discord and received a couple of suggestions but unfortunately none of them worked out. Here's the link to that question if you want to see the ideas: https://discord.com/channels/1396775903 ... 8800197632. Among the suggestions were:
- Use LuaInverntory.insert({name, count}). While this works for "normal" items, it doesn't preserve stack information like ammo usage, health, spoilage, tags, etc.
- Use LuaInventory.insert(LuaItemStack). While this preserves stack infromation, it doesn't have an option to limit the number of transferred items.

Another suggestion is to manually set stack counts to "split" the stack into a portion to keep in the inventory and a portion to transfer. Unfortunately this doesn't work because setting LuaItemStack.count seems to reset stack information.

It's definitely possible to re-implement all the edge case interactions around ammo, health, spoilage and tags but that logic would be pretty hard to write and test, especially if that logic already exists for inserters and bots.

Is there a recommended way to do this? If not, would it be possible to extend the API to add first-class support for this use case?

I have a couple of ideas for some API extensions that would make this possible without requiring modders to re-implement logic.

Idea 1: Set maximum item counts on LuaInventory

Code: Select all

LuaInventory.set_max_item_count({name, quality?}, max_count)
Once this is set, items will never be inserted into the inventory past the max_count, similar to the inventory bar today. This would be nice because it covers all ways of inserting items which would add useful flexibility to LuaInventory but I imagine it would be difficult to implement and probably require a couple more helper methods for getting and clearing max item counts.

Idea 2: Add a new method to transfer up to a max count of items from one inventory to another

Code: Select all

LuaInventory.insert_from_inventory(other_inventory, {name, quality?}, max_count)
This is similar to Idea 1 except it doesn't require storing any data on LuaInventory so hopefully it would be easier to implement.

Idea 3: Extend the existing insert method with an optional max count argument

Code: Select all

-- current method signature:
LuaInventory.insert(items) → uint

-- proposed method signature:
LuaInventory.insert(items, max_count?) → uint
This is nice because it doesn't even require making a new function but would require looping over item stacks in Lua compared to Idea 2 where the loop could be done in C++.

It would be really nice if any of those methods returned some additional information like:
- What are the updated item counts in the "transferred from" and "transferred to" inventories?
- Were all items moved or are there remaining items in the other inventory/stack?

What do people think?

Re: Transfer items between inventories with limit

Posted: Sun Nov 03, 2024 9:56 am
by curiosity
There is no LuaItemStack.split_stack either, despite the player doing it routinely with right click.

Re: Transfer items between inventories with limit

Posted: Sun Nov 03, 2024 5:44 pm
by Silari
Ran into this issue with Manual Logistics. I never found a way to deal with these easily. As is, it defaults to ignoring items with health/durability/grids, because dealing with those would take a lot of extra work. It'd be nice to have tools in the API to deal with those easier - the ability to have the engine handle all the details by telling the two inventories to move X items and to figure out the details in-engine would be great.