Cloud Storage

GD-Sync offers cloud storage, allowing you to save data online and retrieve it later from any device. This makes it ideal for features such as cross-device save files, player profiles, achievements, or other data that needs to persist between sessions.

The filesystem supports creating collections and documents. Documents can also function as collections, allowing you to nest collections and documents for organized, structured data storage.

A common example is storing save files online. Players can upload their save data to their account and later download it on another device to continue playing without losing progress. Files can also be made public so that other players can view them, which is useful for features like sharing player profiles.

To use cloud storage, first create a database in the control panel. Once the database is created, go to your API key and link the database to it.

GD-Sync’s cloud storage revolves around the built-in player account system that allows you to store data for each account. Each account has a storage limit of 1MB.

Account - Create

Accounts can be created directly from within the engine using GDSync.account_create(email : String, username : String, password : String). The function returns a response code, which will be one of the values defined in ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.

Usernames and passwords must be between 3 and 20 characters in length. Usernames must also match the configured username regex pattern from the database, and the email must be in a valid email format.

If email verification is enabled, GD-Sync will automatically send a verification email containing a code to the provided address.

Once the account has been successfully created, the user can proceed to log in.

func _ready():
	var response_code : int = await GDSync.account_create("email@email.com", "username", "password")
	
	if response_code == ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.SUCCESS:
		print("Account created!")
	else:
		match(response_code):
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.NO_RESPONSE_FROM_SERVER:
				push_error("No response from server")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.DATA_CAP_REACHED:
				push_error("Data transfer cap has been reached.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.RATE_LIMIT_EXCEEDED:
				push_error("Rate limit exceeded, please wait and try again.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.NO_DATABASE:
				push_error("API key has no linked database.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.STORAGE_FULL:
				push_error("Database is full.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.INVALID_EMAIL:
				push_error("Invalid email address.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.INVALID_USERNAME:
				push_error("Username contains illegal characters.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.EMAIL_ALREADY_EXISTS:
				push_error("An account with this email address already exists.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.USERNAME_ALREADY_EXISTS:
				push_error("An account with this username address already exists.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.USERNAME_TOO_SHORT:
				push_error("Username is too short.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.USERNAME_TOO_LONG:
				push_error("Username is too long.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.PASSWORD_TOO_SHORT:
				push_error("Password is too short.")
			ENUMS.ACCOUNT_CREATION_RESPONSE_CODE.PASSWORD_TOO_LONG:
				push_error("Password is too long.")
  

Account - Delete

Accounts can be deleted from within the engine using GDSync.account_delete(email : String, password : String). Accounts can also be removed directly from the control panel.The function returns a response code, which will be one of the values defined in ENUMS.ACCOUNT_DELETION_RESPONSE_CODE.

func _ready():
	var response_code : int = await GDSync.account_delete("email@email.com", "password")
	
	if response_code == ENUMS.ACCOUNT_DELETION_RESPONSE_CODE.SUCCESS:
		print("Account deleted!")
	else:
		match(response_code):
			ENUMS.ACCOUNT_DELETION_RESPONSE_CODE.NO_RESPONSE_FROM_SERVER:
				push_error("No response from server")
			ENUMS.ACCOUNT_DELETION_RESPONSE_CODE.DATA_CAP_REACHED:
				push_error("Data transfer cap has been reached.")
			ENUMS.ACCOUNT_DELETION_RESPONSE_CODE.RATE_LIMIT_EXCEEDED:
				push_error("Rate limit exceeded, please wait and try again.")
			ENUMS.ACCOUNT_DELETION_RESPONSE_CODE.NO_DATABASE:
				push_error("API key has no linked database.")
			ENUMS.ACCOUNT_DELETION_RESPONSE_CODE.EMAIL_OR_PASSWORD_INCORRECT:
				push_error("Email or password incorrect.")
  

Account - Login

Accounts can be logged into using GDSync.account_login(email : String, password : String, valid_time : float). The valid_time parameter specifies how long the login session should remain valid, in seconds. Login sessions do not automatically refresh.

This function returns a dictionary containing the login result. One of the fields is BanTime, which shows the Unix timestamp until the account is banned. If BanTime is -1, the account is permanently banned. The dictionary also includes a response code, which will be one of the values from ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.

You can also attempt to log in using GDSync.account_login_from_session(valid_time : float). This will try to restore a previous login session if it has not expired, and can also be used to refresh the current session to keep it active.

To log out, use GDSync.account_logout(). This returns a response code that can be any value from ENUMS.ACCOUNT_LOGOUT_RESPONSE_CODE.

When logged into an account, always use GDSync.quit() instead of get_tree().quit(). This allows the plugin to perform necessary callbacks to the server backend before shutting down.

{
	"Code" : 0,
	"BanTime" : 1719973379
}
  
func _ready():
	var response : Dictionary = await GDSync.account_login("email@email.com", "password")
	var response_code : int = response["Code"]
	
	if response_code == ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.SUCCESS:
		print("Logged in!")
	else:
		match(response_code):
			ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.NO_RESPONSE_FROM_SERVER:
				push_error("No response from server")
			ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.DATA_CAP_REACHED:
				push_error("Data transfer cap has been reached.")
			ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.RATE_LIMIT_EXCEEDED:
				push_error("Rate limit exceeded, please wait and try again.")
			ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.NO_DATABASE:
				push_error("API key has no linked database.")
			ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.EMAIL_OR_PASSWORD_INCORRECT:
				push_error("Email or password incorrect.")
			ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.NOT_VERIFIED:
				push_error("Email is not verified.")
			ENUMS.ACCOUNT_LOGIN_RESPONSE_CODE.BANNED:
				var ban_time : int = response["BanTime"]
			
				if ban_time == -1:
					push_error("Account is permanently banned.")
				else:
					var ban_time_string : String = Time.get_datetime_string_from_unix_time(ban_time, true)
					push_error("Account is banned until "+ban_time_string+".")
  

Account - Email Verification

GD-Sync includes built-in email verification for accounts. When enabled in the accountsystem settings, a verification email is automatically sent to the user after their account is created.

The email contains a verification code that must be entered in-game to complete the verification process. This can be done using GDSync.account_verify(email : String, code : String, valid_time : float). The function returns a response code from ENUMS.ACCOUNT_VERIFICATION_RESPONSE_CODE. If the verification is successful, the user is automatically logged in. The valid_time parameter specifies how long the login session should remain valid, in seconds.

A verification code remains valid for 10 minutes after being sent. If it expires, a new code can be requested using GDSync.account_resend_verification_code(email : String, password : String). This returns a response code from ENUMS.ACCOUNT_RESEND_VERIFICATION_RESPONSE_CODE.

Account - Moderation

GD-Sync includes a built-in account moderation system that allows you to manage accounts and ban users who violate the terms of your game.

Accounts can be moderated directly from the control panel, where users may be manually banned. They can also be banned from within the engine using GDSync.account_ban(ban_duration : float), which bans the currently logged-in account for the specified duration.

Players can report other users in-game using GDSync.account_create_report(username_to_report : String, report : String). This returns a response code from ENUMS.ACCOUNT_CREATE_REPORT_RESPONSE_CODE. A player can submit up to 10 reports in total and may only have one active report against another user. Submitting a new report against the same user while one is active will overwrite the previous report. Reports made against users can be reviewed in the control panel.

If automated bans are enabled in the accountsystem settings, any user who is reported more times than the configured report threshold will be automatically banned.

Account - Friends

GD-Sync accounts can have up to 50 friends. If a friend is inside a lobby, it will be visible to all other friends, making it easy for them to join and play together.

Friend requests can be sent using GDSync.account_send_friend_request(friend : String), which returns a response code from ENUMS.ACCOUNT_SEND_FRIEND_REQUEST_RESPONSE_CODE. Once a request is sent, the receiving account must accept it by calling GDSync.account_accept_friend_request(friend : String), which returns a response code from ENUMS.ACCOUNT_ACCEPT_FRIEND_REQUEST_RESPONSE_CODE.

To remove a friend or deny a pending request, use GDSync.account_remove_friend(friend : String). This returns a response code from ENUMS.ACCOUNT_REMOVE_FRIEND_RESPONSE_CODE.

Once a friend has been added, you can check their status individually using GDSync.account_get_friend_status(friend : String). This returns a dictionary containing the friend’s status, along with a response code from ENUMS.ACCOUNT_GET_FRIEND_STATUS_RESPONSE_CODE. To retrieve the status of all friends and any pending friend requests, use GDSync.account_get_friends(), which also returns a dictionary and a response code from ENUMS.ACCOUNT_GET_FRIENDS_RESPONSE_CODE.

Friend statuses are represented by the ENUMS.FRIEND_STATUS enum.

{
	"Code" : 0,
	"Result" : {
		"FriendStatus" : 2,
		"Lobby" : {
			"Name" : "Epic Lobby",
			"HasPassword" : false
		}
	}
}
  
{
	"Code" : 0,
	"Result" : {
		[
			{
				"Username" : "Epic Username",
				"FriendStatus" : 2,
				"Lobby" : {
					"Name" : "Epic Lobby",
					"HasPassword" : true
				}
			},
				"Username" : "Cool Username",
				"FriendStatus" : 2,
				"Lobby" : {
					"Name" : "",
					"HasPassword" : false
				}
			},
				"Username" : "Awesome Username",
				"FriendStatus" : 1
			}
		]
	}
}
  

Documents - Storing

To store data on an account, use GDSync.account_document_set(path : String, document : Dictionary, externally_visible : bool). This function returns a response code from ENUMS.ACCOUNT_DOCUMENT_SET_RESPONSE_CODE.

The path specifies where the document should be stored. If any collections in the path do not already exist, they are created automatically. A document can contain any Godot Variant type, except object encoding, which is not supported for safety reasons.

Documents and collections can be either public or private. Public documents can be read by other players. If externally_visible is set to true, all parent collections and documents are automatically made visible as well. If set to false, all nested collections and documents will be hidden.

The visibility of a collection or document can be updated at any time using GDSync.account_document_set_external_visible(path : String, externally_visible : bool = false). This returns a response code from ENUMS.ACCOUNT_DOCUMENT_SET_EXTERNAL_VISIBLE_RESPONSE_CODE.

Documents can also function as collections, allowing you to nest collections and documents for organized, structured data storage.

func _ready():
	var document : Dictionary = {
		"Info" : "This is a document!",
		"Numbers" : [1, 3, 523],
		"Godot" : "Is awesome"
	}
	
	var response_code : int = await GDSync.account_document_set("collection1/collection2/document1", document)
	
	if response_code == ENUMS.ACCOUNT_DOCUMENT_SET_RESPONSE_CODE.SUCCESS:
		print("Document created!")
	else:
		match(response_code):
			ENUMS.ACCOUNT_DOCUMENT_SET_RESPONSE_CODE.NO_RESPONSE_FROM_SERVER:
				push_error("No response from server")
			ENUMS.ACCOUNT_DOCUMENT_SET_RESPONSE_CODE.DATA_CAP_REACHED:
				push_error("Data transfer cap has been reached.")
			ENUMS.ACCOUNT_DOCUMENT_SET_RESPONSE_CODE.RATE_LIMIT_EXCEEDED:
				push_error("Rate limit exceeded, please wait and try again.")
			ENUMS.ACCOUNT_DOCUMENT_SET_RESPONSE_CODE.NO_DATABASE:
				push_error("API key has no linked database.")
			ENUMS.ACCOUNT_DOCUMENT_SET_RESPONSE_CODE.NOT_LOGGED_IN:
				push_error("There is not valid login session.")
			ENUMS.ACCOUNT_DOCUMENT_SET_RESPONSE_CODE.STORAGE_FULL:
				push_error("Database is full.")
  

Documents - Deleting

To delete data from an account, use GDSync.account_delete_document(path : String). This function returns a response code from ENUMS.ACCOUNT_DELETE_DOCUMENT_RESPONSE_CODE. It can be used to delete both collections and documents.

If the specified path contains any nested collections or documents, those will be deleted as well.

func _ready():
	var response_code : int = await GDSync.account_delete_document("collection1/collection2/document1")
	
	if response_code == ENUMS.ACCOUNT_DELETE_DOCUMENT_RESPONSE_CODE.SUCCESS:
		print("Document deleted!")
	else:
		match(response_code):
			ENUMS.ACCOUNT_DELETE_DOCUMENT_RESPONSE_CODE.NO_RESPONSE_FROM_SERVER:
				push_error("No response from server")
			ENUMS.ACCOUNT_DELETE_DOCUMENT_RESPONSE_CODE.DATA_CAP_REACHED:
				push_error("Data transfer cap has been reached.")
			ENUMS.ACCOUNT_DELETE_DOCUMENT_RESPONSE_CODE.RATE_LIMIT_EXCEEDED:
				push_error("Rate limit exceeded, please wait and try again.")
			ENUMS.ACCOUNT_DELETE_DOCUMENT_RESPONSE_CODE.NO_DATABASE:
				push_error("API key has no linked database.")
			ENUMS.ACCOUNT_DELETE_DOCUMENT_RESPONSE_CODE.NOT_LOGGED_IN:
				push_error("There is not valid login session.")
			ENUMS.ACCOUNT_DELETE_DOCUMENT_RESPONSE_CODE.DOESNT_EXIST:
				push_error("The specified path does not exist.")
  

Documents - Retrieving

To retrieve data from an account, use GDSync.account_get_document(path : String). This returns a dictionary in the defined format, along with a response code from ENUMS.ACCOUNT_GET_DOCUMENT_RESPONSE_CODE.

To check if a specific collection or document exists, use GDSync.account_has_document(path : String). This also returns a dictionary in the defined format, with a response code from ENUMS.ACCOUNT_HAS_DOCUMENT_RESPONSE_CODE.

To retrieve a document from a different account, use GDSync.account_get_external_document(external_username : String, path : String). This returns the same result as the regular get function, but the target document must be public for the request to succeed.

{
	"Code" : 0,
	"Result" : {*document*}
}
  
{
	"Code" : 0,
	"Result" : true
}
  
func _ready():
	var response : Dictionary = await GDSync.account_get_document("collection1/collection2/document1")
	var response_code : int = response["Code"]
	
	if response_code == ENUMS.ACCOUNT_GET_DOCUMENT_RESPONSE_CODE.SUCCESS:
		var document : Dictionary = response["Result"]
		
		print("Document retrieved!")
	else:
		match(response_code):
			ENUMS.ACCOUNT_GET_DOCUMENT_RESPONSE_CODE.NO_RESPONSE_FROM_SERVER:
				push_error("No response from server")
			ENUMS.ACCOUNT_GET_DOCUMENT_RESPONSE_CODE.DATA_CAP_REACHED:
				push_error("Data transfer cap has been reached.")
			ENUMS.ACCOUNT_GET_DOCUMENT_RESPONSE_CODE.RATE_LIMIT_EXCEEDED:
				push_error("Rate limit exceeded, please wait and try again.")
			ENUMS.ACCOUNT_GET_DOCUMENT_RESPONSE_CODE.NO_DATABASE:
				push_error("API key has no linked database.")
			ENUMS.ACCOUNT_GET_DOCUMENT_RESPONSE_CODE.NOT_LOGGED_IN:
				push_error("There is not valid login session.")
			ENUMS.ACCOUNT_GET_DOCUMENT_RESPONSE_CODE.DOESNT_EXIST:
				push_error("The specified path does not exist.")
  

Documents - Browsing

Collections can be browsed using GDSync.account_browse_collection(path : String). This function returns a dictionary in the defined format, along with a response code from ENUMS.ACCOUNT_BROWSE_COLLECTION_RESPONSE_CODE.

{
	"Code" : 0,
	"Result" :
		[
			{"ExternallyVisible": true, "Name": "profile", "Path": "saves/profile", "Type": "Document"},
			{"ExternallyVisible": false, "Name": "save1", "Path": "saves/save1", "Type": "Document"},
			{"ExternallyVisible": false, "Name": "save2", "Path": "saves/save2", "Type": "Document"},
			{"ExternallyVisible": false, "Name": "configs", "Path": "saves/configs", "Type": "Collection"}
		]
}
  
func _ready():
	var response : Dictionary = await GDSync.account_browse_collection("collection1")
	var response_code : int = response["Code"]
	
	if response_code == ENUMS.ACCOUNT_BROWSE_COLLECTION_RESPONSE_CODE.SUCCESS:
		var results : Array = response["Result"]
		
		print("Collection browsed!")
	else:
		match(response_code):
			ENUMS.ACCOUNT_BROWSE_COLLECTION_RESPONSE_CODE.NO_RESPONSE_FROM_SERVER:
				push_error("No response from server")
			ENUMS.ACCOUNT_BROWSE_COLLECTION_RESPONSE_CODE.DATA_CAP_REACHED:
				push_error("Data transfer cap has been reached.")
			ENUMS.ACCOUNT_BROWSE_COLLECTION_RESPONSE_CODE.RATE_LIMIT_EXCEEDED:
				push_error("Rate limit exceeded, please wait and try again.")
			ENUMS.ACCOUNT_BROWSE_COLLECTION_RESPONSE_CODE.NO_DATABASE:
				push_error("API key has no linked database.")
			ENUMS.ACCOUNT_BROWSE_COLLECTION_RESPONSE_CODE.NOT_LOGGED_IN:
				push_error("There is not valid login session.")
			ENUMS.ACCOUNT_BROWSE_COLLECTION_RESPONSE_CODE.DOESNT_EXIST:
				push_error("The specified path does not exist.")