Automatic backup when new save file is made

Godot Version

4.2.2 stable

Question

Hi, I hope this isn’ t an old question, I haven’t found anything related.
I finally managed to create a working save system (my worst nightmare, as in Godot as it was in Unity) with the excellent tutorial by Queble.
Now I would add some code for the game to automatically make a backup of the old savefile when the player saves (the old savefile would be renamed to “save.bak” and the new file would take its place with the usual name “save.json”).
Any help would be appreciated, thanks! (save function code below)

func _ready():
verify_save_directory(SAVE_DIR)

func verify_save_directory(path : String):
DirAccess.make_dir_absolute(path)

func save_data(path : String):

var file = FileAccess.open_encrypted_with_pass(path, FileAccess.WRITE, SECURITY_KEY)
if file == null:
	print(FileAccess.get_open_error())
	return

var data = {
	"game_data_in_file":{
		... putting variables to file ...
	}
}

var json_string = JSON.stringify(data, "\t")
file.store_string(json_string)
file.close()
print("Save done!")

Then… Just read the old save file and write it to a new file before overriding it?

var file = FileAccess.open_encrypted_with_pass(path, FileAccess.READ, SECURITY_KEY)
var old_data := file.get_as_text()

file = FileAccess.open_encrypted_with_pass(path + ".bak", FileAccess.WRITE, SECURITY_KEY)
file.store_string(old_data)

(untested, but should work)

1 Like

Thanks for the quick response, I tried immediately modifying code as below:

func save_data(path : String):

var file = FileAccess.open_encrypted_with_pass(path, FileAccess.WRITE, SECURITY_KEY)
var old_data := file.get_as_text()

file = FileAccess.open_encrypted_with_pass(path + ".bak", FileAccess.WRITE, SECURITY_KEY)
file.store_string(old_data)

if file == null:
	print(FileAccess.get_open_error())
	return

var data = {
	"game_data_in_file":{
		```... putting variables to file ...```
	}
}

var json_string = JSON.stringify(data, "\t")
file.store_string(json_string)
file.close()
print("Save done!")

But, it creates immediately two files:
“save.json” with a single line of code, which has no (or incomplete) save datas (it can’ t be read from the load function)
and a second file:
“save.json.bak” that is the real file with save datas.
Maybe (surely) I inserted the new lines of code in the wrong places?

When you open the first file, you open it with FileAccess.WRITE instead FileAccess.READ. Change the second parameter and it should work.

1 Like

Instead of reading and writing the old file, you can rename it to backup name instead. Renaming a file to existing name automatically overwrites the old file.

3 Likes

Hi, I corrected my typo (WRITE instead of READ) and reordered the code a bit, and it worked.
(here below is the working version)

var file = FileAccess.open_encrypted_with_pass(path, FileAccess.READ, SECURITY_KEY)
if file == null:
	print(FileAccess.get_open_error())
else:
	var old_data := file.get_as_text()
	file = FileAccess.open_encrypted_with_pass(path + ".bak", FileAccess.WRITE, SECURITY_KEY)
	file.store_string(old_data)

file = FileAccess.open_encrypted_with_pass(path, FileAccess.WRITE, SECURITY_KEY)

var data = {
	"game_data_in_file":{
		etc etc
	}
}

var json_string = JSON.stringify(data, "\t")
file.store_string(json_string)
file.close()
print("Save done!")

Thanks!

1 Like