0 votes

Hello, I normally don't like to ask, but I'm hoping someone can help me make sense of this as I'm new to Godot. I've been pouring over tutorials, documentation, and forums all day with no luck.
The gist of it:
I'm trying to work out a save feature that I can save a main dictionary containing sub dictionaries with a bunch of variables from user input in one scene, and then load each sub dictionary up in another scene as a clickable button. (Think like a character creator, and then when finished you could click the character you made to start the game from a list of your characters.)

The problem I'm having is that every entry time I save the data, it overwrites what was there before, meaning only ONE key:sub dictionary ever shows up.
I have tried to use seek_end()as some other people have posted, but when I do that, it simply doesn't save it, and when you back out of the character creator after hitting the save button, nothing has changed.
Can anyone help me shine a light on what I'm missing? I'm pretty sure the problem lies somewhere in how it's being saved, and when I tried to error check the store_var() method, I get "Null" back instead of OK.
This is my main Save Code (after organizing the dictionaries)

func save_entry(playerdata):
var save_file = File.new()
if save_file.file_exists("user://PlayerData.dat"):
    save_file.open("user://PlayerData.dat",File.READ_WRITE)
else:
    save_file.open("user://PlayerData.dat",File.WRITE)

save_file.seek_end()
print(playerdata) #Just to test and make sure the data is organized right
var err = save_file.store_var(playerdata)
if err == OK : print("Saved Successfully") 
else: print(err) #This just gives me "Null"
save_file.close()

and then on my scene that contains the list, it's like this:

func load_to_list(): 
var fileob = File.new()
if fileob.file_exists(loadfile): #Loadfile is a var with the filepath
    fileob.open(loadfile, File.READ)
    var playerlistdata : Dictionary = fileob.get_var()
    fileob.close()
    var keylist = playerlistdata.keys()
    print(listsize) #just to confirm only 1 shows up

    for char in keylist:
        var button_instance = newbutton.instance()
        get_node("ScrollContainer/Char List Container").add_child(button_instance)
        button_instance.text = char
        button_instance.next_scene_path = myplayerinfo

else:
    print("No data file found.")

func _ready():
    load_to_list()

Any help is appreciated. Spent a huge amount of time spinning my wheels on this.

Godot version 3.2.3
in Engine by (14 points)
edited by

Have you tried something like save_file.seek_end(-1) to move the cursor right before the end? Also, in the following code snippet:

if save_file.file_exists("user://PlayerData.dat"):
    save_file.open("user://PlayerData.dat",File.READ_WRITE)
else:
    save_file.open("user://PlantData.dat",File.WRITE)

Why is the part after the else statement is saving it to the file "PlantData.dat"?

Thanks for your reply.
I had not tried adding the -1 to seek_end(), but I just did now and there was no change.
As for the other part, that's just a typo. Sorry, lol.

2 Answers

0 votes

I was able to get this working using var2str() and str2var().
I couldn't get it to work using store_var().

extends Node

const SAVE_FILE_PATH := "res://SaveData.txt"

func clear_save_file() -> void:
    var dir := Directory.new()
    if dir.file_exists(SAVE_FILE_PATH):
        dir.remove(SAVE_FILE_PATH) # delete the old save file
    open_save_file(File.new()) # create new save file

func open_save_file(file: File) -> void:
    assert(file)
    assert(!file.is_open())
    var open_mode: int = file.READ_WRITE if file.file_exists(SAVE_FILE_PATH) else file.WRITE
    var open_error: int = file.open(SAVE_FILE_PATH, open_mode)
    assert(open_error == OK, str("Error opening file at: ", SAVE_FILE_PATH))
    assert(file.is_open())

func set_save_file_dict(dict: Dictionary) -> void:
    var file := File.new()
    clear_save_file()
    open_save_file(file)
    var var_as_str := var2str(dict)
    file.store_string(var_as_str)
    file.close()

func get_save_file_dict() -> Dictionary:
    var file := File.new()
    open_save_file(file)
    var file_text := file.get_as_text()
    assert(!file_text.empty(), "File is empty")
    file.close()
    var file_text_as_var = str2var(file_text)
    assert(typeof(file_text_as_var) == TYPE_DICTIONARY)
    var dict: Dictionary = file_text_as_var
    assert(!dict.empty())
    return dict

func append_save_file_dict(append_dict: Dictionary) -> void:
    assert(!append_dict.empty())
    var save_file_dict := get_save_file_dict()
    var saved_keys := save_file_dict.keys()
    var append_keys := append_dict.keys()
    var append_values := append_dict.values()

    for i in append_dict.size():
        var append_key = append_keys[i]
        var append_value = append_values[i]
        assert(!saved_keys.has(append_key), str("Key already exists in save file dict: ", append_key))
        save_file_dict[append_key] = append_value

    set_save_file_dict(save_file_dict)

func _ready():
    set_save_file_dict({A = 1, B = 2, C = 3})
    print(get_save_file_dict())
    append_save_file_dict({X = 7, Y = 8, Z = 9})
    print(get_save_file_dict())

Prints:

{A:1, B:2, C:3}
{A:1, B:2, C:3, X:7, Y:8, Z:9}
by (224 points)
0 votes

I don't have much experience with files, but I think that you want an array of dictionaries?

Load the variable (array), append the dictionary, overwrite the file.

by (105 points)
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.