[boskid][2.0.55] LuaItemStack::transfer_stack() always true if LuaItemStack::can_set_stack() would succeed

This subforum contains all the issues which we already resolved.
Pi-C
Smart Inserter
Smart Inserter
Posts: 1754
Joined: Sun Oct 14, 2018 8:13 am
Contact:

[boskid][2.0.55] LuaItemStack::transfer_stack() always true if LuaItemStack::can_set_stack() would succeed

Post by Pi-C »

TLDR
It seems LuaItemStack::transfer_stack() will always return true if LuaItemStack::can_set_stack() would succeed – even if no items have been transferred.
The problem:
LuaItemStack::can_set_stack() will succeed if the given stack can be used at all in the given inventory. For example, it would succeed if you used it with a "firearm-magazine" in a slot of a car's ammo inventory, but it wouldn't if you'd used it with "coal". As expected, it also would succeed if there already was a "piercing-rounds-magazine" in the slot because LuaItemStack::set_stack() would just replace the existing item with the new one.

LuaItemStack::transfer_stack() will return true if you try to transfer a "firearm-magazine" into a car's ammo inventory if the stack was empty or already contained "firearm-magazine" items – as expected. However, it will also return true if the stack was partially filled with "piercing-round-magazine" items, which is unexpected.

Upon closer inspection, it seems that LuaItemStack::transfer_stack() returns true because a transfer actually succeeded: stack.count will be incremented even if slot.name and stack.name differ!
How to reproduce:
Start a new game without mods and enter the following on the console:

Code: Select all

/c
p = game.player; pos = p.position
car = p.surface.create_entity({name = "car", force = p.force, position = {pos.x + 5, pos.y}})
ammo = car.get_inventory(defines.inventory.car_ammo)
slot = ammo[1]

stack = {name = "piercing-rounds-magazine", quality = "normal", count = 10}
game.print(string.format("Transferring %s: %s", stack.name, slot.transfer_stack(stack)))

stack.name = "firearm-magazine"
game.print(string.format("Transferring %s: %s", stack.name, slot.transfer_stack(stack)))

stack.name = "coal"
game.print(string.format("Transferring %s: %s", stack.name, slot.transfer_stack(stack)))
You will see that both messages for ammo items show the return value 'true', while transferring coal returns 'false'. Now open the car and check the ammo inventory! You will notice that it contains 20 "piercing-rounds-magazine"items although there should be just 10.

I should mention that I don't have SA, this was tested with plain Factorio 2.0.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 3975
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: LuaItemStack::transfer_stack() always true if LuaItemStack::can_set_stack() would succeed

Post by boskid »

When reporting bugs, please always include a game version.

I see the return value of the transfer_stack has changed between 2.0.47 and 2.0.55: in 2.0.55 it reports success even when nothing was transferred because the transfer being done is unlimited and there seems to be an issue between two pieces of code communicating that a transfer is supposed to be unlimited. You should be able to workaround this by using second parameter of the transfer_stack() which is "amount", just provide the count of items you have in the source stack and the return value should behave correctly up to 2.0.55 (i will be fixing this for 2.0.56 later). This behavior can also be seen in 2.0.47 if you explicitly provide the `amount` for transfer_stack to be larger than the item count in the provided stack.

As for the 20 piercing magazines, i was unable to reproduce this: when testing in 2.0.47, 2.0.55 and 2.0.56(unreleased) there was always only 10 magazines in the car's ammo slot after the reproduction command.
User avatar
boskid
Factorio Staff
Factorio Staff
Posts: 3975
Joined: Thu Dec 14, 2017 6:56 pm
Contact:

Re: LuaItemStack::transfer_stack() always true if LuaItemStack::can_set_stack() would succeed

Post by boskid »

transfer_stack returning true when doing unlimited transfers is now fixed for 2.0.56. Workaround mentioned is valid.

As for the 20 magazines issue after transfer, i was unable to reproduce it.
Pi-C
Smart Inserter
Smart Inserter
Posts: 1754
Joined: Sun Oct 14, 2018 8:13 am
Contact:

Re: LuaItemStack::transfer_stack() always true if LuaItemStack::can_set_stack() would succeed

Post by Pi-C »

boskid wrote: Sun Jun 15, 2025 5:24 am When reporting bugs, please always include a game version.
Sorry, may mistake. It was late when I sent this, so I forgot to include the version number. But it happened with version 2.0.55.
I see the return value of the transfer_stack has changed between 2.0.47 and 2.0.55: in 2.0.55 it reports success even when nothing was transferred because the transfer being done is unlimited and there seems to be an issue between two pieces of code communicating that a transfer is supposed to be unlimited.
Thanks for the explanation!
You should be able to workaround this by using second parameter of the transfer_stack() which is "amount", just provide the count of items you have in the source stack and the return value should behave correctly up to 2.0.55 (i will be fixing this for 2.0.56 later).
Yes, this works! I've already worked around this in my code by making sure that slot.name and stack.name are equal, but this is much better.
As for the 20 piercing magazines, i was unable to reproduce this: when testing in 2.0.47, 2.0.55 and 2.0.56(unreleased) there was always only 10 magazines in the car's ammo slot after the reproduction command.
Strange. I am sure that I've really seen 20 items in the inventory after running the command. Of course, I didn't make a screenshot – and now I can't reproduce this either.
A good mod deserves a good changelog. Here's a tutorial (WIP) about Factorio's way too strict changelog syntax!
Post Reply

Return to “Resolved Problems and Bugs”