0 votes

Hi,

i followed this guide https://coffeecoderblog.wordpress.com/2016/07/03/creating-a-save-system-in-godot/ to create a save/load system for my game. I managed to correctly save the data i wanted (i verified in the save file and the data is stored correctly), but i can't manage to correctly load the data.

The code seems correct to me but it returns this error when i run the program: "Invalid get index 'constrnumber' (on base: 'Dictionary')."

I copy my code here, hoping someone can kindly explain to me why it isn't working, or what am i doing wrong.
The line that generates the error is this one
constrnumber = currentLine["constrnumber"]

extends Node    

# declare our variables
var constrnumber = 0



# initialize stuff here
func _ready():



    # first determine if a Saves directory exists.
    # if it doesn't, create it.
    var dir = Directory.new()
    if !dir.dir_exists("user://Saves"):
        dir.open("user://")
        dir.make_dir("user://Saves")

# the following functions are getters and setters for the variables

# get the construction number
func get_constrnumber():
    return constrnumber

# set the construction number
func set_constrnumber(var amount):
    constrnumber += amount



# the following functions save and load a game, depending on what the player does at the main/pause menus.
# at the end of each level, the save function is automatically called.

# first create a dictionary to store the save info in. Similar to a serializable class in Unity in which 
# the player data would be stored.
var GameData = {
    "constrnumber":0
}

# this saves the current game state
func save_game_state(var saveName):

    # create a file object
    var saveGame = File.new()
    saveGame.open("user://Saves/"+saveName+".save", File.WRITE)

    # create a data object to store the current save data in
    var data = GameData

    # store the data
    data.constrnumber = get_constrnumber()


    # write the data to disk
    #saveGame.store_line(data.to_json())
    saveGame.store_line(to_json(data))
    saveGame.close()

# this loads a previously saved game state
func load_game_state(var saveName):

    # create a file object
    var loadGame = File.new()

    # see if the file actually exists before opening it
    if !loadGame.file_exists("user://Saves/"+saveName+".save"):
        print ("File not found! Aborting...")
        return

    # use an empty dictionary to assign temporary data to
    var currentLine = {}


    # read the data in
    loadGame.open("user://Saves/"+saveName+".save", File.READ)
    while(!loadGame.eof_reached()):

        # use currentLine to parse through the file
        #currentLine.parse_json(loadGame.get_line())
        #loadGame.get_line(parse_json(line))
#warning-ignore:unused_variable
        var current_line = parse_json(loadGame.get_line())

        # assign the data to the variables
        constrnumber = currentLine["constrnumber"]
    loadGame.close()

Thank you all.

in Engine by (32 points)
edited by

1 Answer

+1 vote
Best answer

You're declaring this dictionary
var currentLine = {}

Then assigning this dictionary
var current_line = parse_json(loadGame.get_line())

Then getting from the empty dictionary and ignoring current_line where you assigned the parse_json result:
constrnumber = currentLine["constrnumber"]

My proposal/correction for the parse_json part:
currentLine = parse_json(loadGame.get_line())

by (3,358 points)
selected by

Thank you. I suppose i turn blind after some hours writing code XD

That problem is solved but now the line "constrnumber = currentLine["constrnumber"]"
returns an error: "Invalid get index 'constrnumber' (on base: 'Nil')."

Please help me if you can also with this one, i'm going crazy... I tried many solutions but can't manage to solve this other problem.

Did you print out get_line() to check that the string loaded properly?
Did you check the file contents that it actually cotains something?

Not the first one.

I did the second one and the file contains the right information:

{"constrnumber":50}

I don't know why you would read the file line by line. Probably your code reads and decodes the first line correctly and then reads another...emtpy line which leads to "null".

Instead try to read the file as a whole with get_as_text ( )

loadGame.open("user://Saves/"+saveName+".save", File.READ)
var contents = loadGame.get_as_text()
print("debug: file contents: "+contents)
currentLine = parse_json(contents)
constrnumber = currentLine["constrnumber"]
loadGame.close()

Ok i used your code and the information is correctly loaded and verified in the debugger output window.

But it doesn't show visually on the actual program:

    get_node("counter2").set_text(str(saveload.constrnumber))

counter2 is a label
saveload.gd is the singleton script in which is declared constrnumber

I don't understand why it doesn't show the number.

This is impossible to tell with this information.

"doesn't show visually" means the label is invisible?

Check the output window for errors.
Put some test text in the editor in the label and check if it displays correctly.

Make sure that you actually load the file before you set the label.
Make sure that the node address is correctly. In your case "counter2" should be a direct child of the node which has the script assigned.

Print out str(saveload.constrnumber) before you assign it to the label. That makes sure that this code is executed and you'll see if the contents are correct.

I'll now go offline tonight. If you don't succeed. I might find some time tomorrow to answer. Or you could open a new question (as the topic has moved) and post details/screenshot about your node tree and code.

Thank you so much for all your help! ^^

Very appreciated.

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 Frequently asked questions and 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 [email protected] with your username.