Search code examples
saveconfiggodotgdscript

Creating a multi-value storing Save System in godot using CFG file system


I was looking to create a save system in Godot for my game and as I'm not that adept at coding, the only method I could make sense of was writing the data in config files.

The following code is on a Singleton script called save_system.gd. It saves and loads the value of one variable array inventory.inventory_ingredients as follows -

var save_path = "res://Saves/save-file.cfg";
var config= ConfigFile.new()
var load_response = config.load(save_path)

func saveValue(section,key):
    config.set_value(section,key,inventory.inventory_ingredients)
    config.save(save_path)

func loadValue(section,key):
    inventory.inventory_ingredients = config.get_value(section, key, inventory.inventory_ingredients)

In the start of my game, I have a "Load Game" button that loads the array as follows -

func _on_Load_pressed():
    save_system.loadValue("Inventory", "ingredients")

When I trigger the save function, the following script is used -

save_system.saveValue("Inventory","ingredients")

Everything so far runs perfectly - like I want it to. But, I would like to expand the number of variables that are saved. To do the same bit of code for every variable separately in every scene in quite a lengthy task and would require huge lines of code. How do I minimize the number of lines, and perhaps a bunch 2-3 variables saved at one go from a node? I would prefer a method that would use the "cfg" method that I have used.

For example, I have a node with 3 variables (x,y,z) that I want to be saved in the following way. Currently, the only method I know to do this is to to do this manually as -

save_system.saveValue("Variables","x")
save_system.saveValue("Variables","y")
save_system.saveValue("Variables","z")

and a similar method for loading. I want to avoid this. What do I do?


Solution

  • Write JSON to a text file

    JSON is well-known standard for serializing data, and Godot provides standard library functions to work with JSON.

    extends Node
    
    func load_save() -> Dictionary:
        var f := File.new()
        f.open("user://save.json", File.READ)
        var result := JSON.parse(f.get_as_text())
        f.close()
    
        if result.error:
            printerr("Failed to parse save file: ", f.error_string)
        return result.result as Dictionary
    
    func save(data: Dictionary):
        var f := File.new()
        f.open("user://save.json", File.WRITE)
        prints("Saving to", f.get_path_absolute())
        f.store_string(JSON.print(data))
        f.close()
    
    func _ready():
        save({
            "inventory": {
                "ingredients": ["apple", "pear"],
                "items": ["spoon", "fork"]
            },
            "stats": {
                "health": 10,
                "experience": 20,
            }
        })
    
        print(load_save())
    

    We're writing the save file to a user path, which is a platform-specific location appropriate for application data. JSON can be used to save arbitrarily complex data as long as it consists of primitive data types supported by JSON (string, number, dict, array, true, false, null).