Here's my core code for my Player class:
extends Node
var m_aData = {}
func getPassword():
return m_aData["password"]
func setPassword(a):
m_aData["password"] = a
func getData():
return m_aData
func setData(a):
m_aData = a
Add additional accessor methods to add support for additional fields. These will get and set the m_aData dictionary. The initial dictionary is empty, and automatically creates new entries when a set*() method references one that doesn't already exist. This is the only file you will ever have to update when you add or remove fields from the Player class.
Reading and writing the JSON files will automatically read/write the new fields you add to Player, and you can follow this pattern for every persistent data type you want to add to your game.
Here's how I save the dictionay to a JSON file:
func createAccount(stAccountname,stUsername,stPassword,stPath):
print("Preparing new account")
var player = load("res://player/Player.gd").new()
var stData
player.setAccountName(stAccountname)
player.setPlayerName(stUsername)
player.setPassword(stPassword)
stData = player.getData()
return ConfigurationWriter.write(stPath,to_json(stData))
ConfigurationWriter.write() is just a helper function that opens a file, writes the JSON text, and closes the file; with error handling built-in. You will never have to modify this function to add or remove Player data fields.
Here's an example of reading the player data to validate the password:
func authenticatePassword(stPath,stPassword):
var ret = false
print("Authenticating password")
if stPath != null && stPassword != null:
var stData = ConfigurationReader.read(stPath)
var aData
if stData != null:
aData = parse_json(stData)
ret = aData["password"] == stPassword
else:
print("Can't read data from " + stPath)
return ret;
Again, ConfigurationReader.read() is just a convenience method to open a file, read it, and return the raw text data (saved in JSON format).