unity-elastic-inventory icon indicating copy to clipboard operation
unity-elastic-inventory copied to clipboard

Zero quantity item problem

Open myfbone opened this issue 3 months ago • 4 comments

The documentation says that in order to transfer an item from one inventory to another, you need to remove an entry and add this entry like this:

public void TransferItem (IItemEntryReadOnly item, int quantity, IInventoryInstance from, IInventoryInstance to) {
    from.RemoveEntry(item.Id, quantity);
    to.AddEntry(item);
}

inventory.TransferItem(entry, 1, playerInventory, chestInventory);

However, this doesn't work when you try to transfer an item that is not unique, and you transfer the whole quantity of the item. The quantity is set to 0 in the new inventory. This happens because RemoveEntry function sets the quantity of the entry to 0 and the same item later being added to the new inventory by reference.

It could worth to update the documentation explaining that in such cases one must set the quality by hand or perhaps adding item by definition instead. Additionally, to that, perhaps inventory should print a warning that an item added has 0 quantity.

myfbone avatar Aug 26 '25 21:08 myfbone

So this scenario should work. I'll have to make sure there are tests with RemoveEntry and AddEntry for unique and non-unique. Are you sure this is happening with non-unique items? I'm wondering if this bug only happens with unique items. Regardless I'll check the test suite on my next pass.

ashblue avatar Aug 31 '25 22:08 ashblue

Yes I am sure. Look (code from InventoryInstance):

        public void RemoveEntry (string entryId, int quantity = 1) {
            var entry = _idToEntry[entryId];

            // Leave the implementation up to the remove method
            if (!entry.Definition.Unique) {
                Remove(entry.Definition, quantity);
                return;
            }

            _uniqueEntries.Remove(entry);
            _idToEntry.Remove(entry.Id);

            Events.ItemRemoved.Invoke(entry);
            Events.ItemChanged.Invoke(entry);
        }

If not unique then you remove by definition

Then you subtract quantity and then remove if it's 0

        public void Remove (IItemDefinition item, int quantity = 1) {
            if (item.Unique) throw new System.ArgumentException("Unique items cannot be removed by definition. Use an ID instead");

            var entry = _entries[item];
            entry.SetQuantity(entry.Quantity - quantity);

            if (entry.Quantity <= 0) {
                _entries.Remove(item);
                _idToEntry.Remove(entry.Id);
            }

            Events.ItemRemoved.Invoke(entry);
            Events.ItemChanged.Invoke(entry);
        }

The problem is that the same entry that just was set quantity to 0 get's transferred to another inventory

myfbone avatar Sep 01 '25 20:09 myfbone

Imagine Inventory A has 3 sticks, none unique, it's just one entry We get this entry and call RemoveEntry with quantity 3. Now we have entry of sticks with quantity 0 (it's out of Inventory A) and we transfer it to Inventory B by calling AddEntry Now we have Inventory B with 0 sticks

myfbone avatar Sep 01 '25 20:09 myfbone

Ah it's that chunk of code >_>. Yeah that was causing some issues I previously patched. This is all clicking. The unique entry support is powerful but created a few edge cases for sure.

ashblue avatar Sep 07 '25 22:09 ashblue