Different result when using a copy of a dictionary

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By cheo

Hi

When trying to update the content of a dictionary, I get different results when using the copy of a dictionary instead of the original dictionary. The result obtained from the copy is the correct one. Copying it back will not solve the issue.

Line 37 of item_instance.gd produces the correct result:
var inventory = str2var(var2str(InventoryController.inventory))

Line 38 of item_instance.gd produces the incorrect result:
var inventory = InventoryController.inventory

You can download the project from BitBucket and reproduce the issue, play around and hopefully find the solution. I was unable to do so.

Note that the issue occurs only when grabbing several objects at once.

Thanks in advance.

:bust_in_silhouette: Reply From: AlexTheRegent

When player pickup N item, you call _on_item_grabbed N times. _on_item_grabbed adds all content of ground inventory to player inventory. So when you have M items on the floor, you will add (N * M) items to player’s inventory. You should add only picking up object, not all items at once. Dirty workaround would be to empty ground_inventory after item pickup (note that it still will be called M times, but (M-1) calls will work with empty dict, i.e. do nothing).
Moreover, in your case items will be added more than (N * M) times. This is because queue_free is not executed immediately (it is executed during idle frames), and item might be picked up more than once before it is freed. Quick fix would be next check at top of the _on_item_grabbed

if is_queued_for_deletion():
  return

To make live update of your inventory (wishlisted in bitbucket), you need to use Godot’s implementation of Observer pattern (signals). And I highly recommend to read some books about game programming, in your current implementation of game components are tightly coupled and you will not be able to maintain it pretty quick. Here’s one of the books you can read (you can skip III, IV and VI chapters): Table of Contents · Game Programming Patterns

I was able to fix the issue thanks to your hint on _on_item_grabbed being called for each item instance on the ground and by deleting the nodes with is_queued_for_deletion()

The top of _on_item_grabbed looks like this:

if is_queued_for_deletion():
    return
queue_free()

I’ll definitely go through the book you recommended.

Thanks a lot for your insight on this.

cheo | 2021-01-09 17:47