+2 votes

I have an array with dictionaries in it, each dictionary is a different item. I'm trying to save and load this inventory. The file is saving correctly, and when I load the file I have a print() which is printing the correct value from the line it's reading. However after all the items have been appended, the inventory is just full of whatever item was in the last slot.
For example if I save an inventory with item A, item B, and item C. After loading the inventory would be 3 duplicates of item C.

This is my code:

func save_game():
    var savegame = File.new()
    savegame.open("user://savegame.save", File.WRITE)

    for i in range(inventory.size()):
        var data = inventory[i]
        savegame.store_line(data.to_json())

    savegame.close()


func load_game():
    var savegame = File.new()
    if !savegame.file_exists("user://savegame.save"):
        return

    var current_line = {}
    savegame.open("user://savegame.save", File.READ)
    while(!savegame.eof_reached()):
        var line = savegame.get_line()
        if line.empty():
            break

        current_line.clear()
        current_line.parse_json(line)
        print(current_line) #this is printing the correct value
        inventory.append(current_line) #this is not appending the correct value

    savegame.close()
in Engine by (665 points)

I had a similar problem with a dictionary of dictionaries. See my related question and the answers on reddit here

2 Answers

+1 vote
Best answer

I never used json before, but maybe you are parsing it wrong. I'd suggest trying the easy method and just use store_var and get_var to store the entire array of dictionaries at once.

fixed, woops... put_var was for packets not files

by (840 points)
selected by

I didn't think of that, I was just following the tutorial on the Godot Docs. But this works, thank you. Also it's store_var instead of put_var.

I'm still unsure why my original method wasn't working.

+3 votes

The problem is that Dictionary, Array and Reference classes are passed by reference, and not by value. Since Dictionary::parse_json would edit the same dictionary in-place, you would add three reference to the same Dictionary.

There are two ways to workaround this.
The first one would be to move the declaration of current_line inside the loop.
The second would be to use the Dictionary copy constructor, like so:

inventory.append(Dictionary(current_line))
by (1,566 points)

I liked the last option but it doesn't seem to do the trick in my similar case. Placing current_line within the loop did however.

@duke_meister It is quite probable that I messed something up, since I didn't test it. Maybe if somebody else confirms, I'll change it.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.