Singleton not updating

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

SOLVED

Hey guys,

Got a quick question here.

I have defined a dictionary in an auto-loaded singleton (ProgressData). This dictionary keeps track of the player’s inventory. This variable is declared on top of the script like so:

var inven_data

When I loot a chest, that dictionary gets a new key with all the variables of that particular item. This happens in an instance in the scene tree, like so. (it basically copies the dictionary entry from loot chest’s dictionary into the inventory dictionary.

ProgressData.inven_data[counter] = loot_dic[extra_arg_0]

When the loot panel is closed the dictionary is saved to json. Based on the json and using the print command I can see this all works great.

Now the issue comes when I open my inventory after I looted a chest. I populate my inventory based on ProgressData.inven_data like so (note that my node names are identical to the dictionary keys.)

if ProgressData.inven_data.has(str(node_name)):
      bunch of code to populate text fields and set texture for icon etc.

I know my code underneath this line works because when I open my game my inventory populates without error from the loaded json file. However, when I open my inventory after looting a chest in a game session, my inventory does not include the items I just looted. If I loot a chest, close the game, open it, and then open my inventory the items I looted in the previous game session ARE in my inventory.

So it seems that the variable inven_data in my singleton ProgressData does not update during the game session. Although the same variable is used within that singleton to safe my game successfully. It is almost as if two versions of that variable exist(??)

PS I hope this all makes sense, I didn’t want to copy-paste huge code snippets. It is my first question in these forums and I hope I have formatted correctly.

Welcome on board!

Now, by the looks of it, it seems that you have a system in place that loads everything on startup, but you don’t have anything to refresh the inventory after a chest is looted. You say that using a print statement correctly prints what the inventory should include and that’s because you read from the json file, but that does not automatically refresh your inventory. Are you sure you implement the function after you close the loot panel? You write:

I populate my inventory based on ProgressData.inven_data

How often do you do that? Do you do it right after you have closed the loot panel? The point is to refresh everything based on the new json file that was created. There’s got to be something that does not get updated when it should. You must have forgotten to call the update function when needed.

johnygames | 2019-08-13 17:27

Hey Johny, thx

I populate the inventory every time the inventory scene is called(as a new instance). The inventory loads from inven_data in the singleton ProgressData, the same variable that is used to save to json. I could load again from the json, but I thought, considering the json is correctly saved using the variable inven_data. I should be able to load the inventory from that variable. I think my line of logic goes wrong there, but I don’t see how. I save to json using this function inside the ProgressData script. This function is called when the player loots something.

func _on_SaveInventory():
	var save_file = File.new()
	save_file.open("user://Inventory_save.json", File.WRITE)	
	save_file.store_line(to_json(inven_data))
	save_file.close()

You say that using a print statement correctly prints what the inventory should include and that’s because you read from the json file

I used the print command on ProgressData.inven_data.

Dumdidum | 2019-08-13 21:48

I cannot debug your code, since I don’t have a copy of it, but I insist that there’s got to be a discrepancy between the code you use to populate the inventory when you start the game and the code you use to populate it when the loot panel is gone. Try using the exact same function, namely, populate the inventory from the json file, just as you would if you were to close the game and reopen it.

It might even be the case that you create a new instance of something (maybe a node? maybe a script? maybe the file where you save inventory items?) thus erasing the changes that you’ve just made.

johnygames | 2019-08-13 22:05

Hey Johny,

Thanks again for your quick reply. Your comment was very helpful. Your comment on ‘discrepancy’ made me look at my code differently, and, I was able to pinpoint the problem.

In the LootPanel scene i was adding a dictionary key to ProgressData.invendata, but unintentionally that was an int. That’s why after reloading the game from json it worked as that int had been turned into a str by parsing it to json. I have edited my code in the LootPanel from

ProgressData.inven_data[counter] = loot_dic[extra_arg_0]

to

ProgressData.inven_data[str(counter)] = loot_dic[extra_arg_0]

Now the code runs perfectly without having the reload the json every time.

Dumdidum | 2019-08-13 22:32

Glad I helped! I am turning my previous comment into an answer so that others can find it useful too.

johnygames | 2019-08-13 23:59

:bust_in_silhouette: Reply From: johnygames

There’s got to be a discrepancy between the code you use to populate the inventory when you start the game and the code you use to populate it when the loot panel is gone. Try using the exact same function, namely, populate the inventory from the json file, just as you would if you were to close the game and reopen it.

It might even be the case that you create a new instance of something (maybe a node? maybe a script? maybe the file where you save inventory items?) thus erasing the changes that you’ve just made.

EDIT: As you said down below, change your ProgressData.inven_data[counter] = loot_dic[extra_arg_0] into ProgressData.inven_data[str(counter)] = loot_dic[extra_arg_0]
in order to fix the discrepancy issue.