Signup form
This commit is contained in:
		
							
								
								
									
										58
									
								
								client/addons/com.heroiclabs.nakama/Nakama.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								client/addons/com.heroiclabs.nakama/Nakama.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,58 @@
 | 
			
		||||
tool
 | 
			
		||||
extends Node
 | 
			
		||||
 | 
			
		||||
# The default host address of the server.
 | 
			
		||||
const DEFAULT_HOST : String = "127.0.0.1"
 | 
			
		||||
 | 
			
		||||
# The default port number of the server.
 | 
			
		||||
const DEFAULT_PORT : int = 7350
 | 
			
		||||
 | 
			
		||||
# The default timeout for the connections.
 | 
			
		||||
const DEFAULT_TIMEOUT = 3
 | 
			
		||||
 | 
			
		||||
# The default protocol scheme for the client connection.
 | 
			
		||||
const DEFAULT_CLIENT_SCHEME : String = "http"
 | 
			
		||||
 | 
			
		||||
# The default protocol scheme for the socket connection.
 | 
			
		||||
const DEFAULT_SOCKET_SCHEME : String = "ws"
 | 
			
		||||
 | 
			
		||||
# The default log level for the Nakama logger.
 | 
			
		||||
const DEFAULT_LOG_LEVEL = NakamaLogger.LOG_LEVEL.DEBUG
 | 
			
		||||
 | 
			
		||||
var _http_adapter = null
 | 
			
		||||
var logger = NakamaLogger.new()
 | 
			
		||||
 | 
			
		||||
func get_client_adapter() -> NakamaHTTPAdapter:
 | 
			
		||||
	if _http_adapter == null:
 | 
			
		||||
		_http_adapter = NakamaHTTPAdapter.new()
 | 
			
		||||
		_http_adapter.logger = logger
 | 
			
		||||
		_http_adapter.name = "NakamaHTTPAdapter"
 | 
			
		||||
		add_child(_http_adapter)
 | 
			
		||||
	return _http_adapter
 | 
			
		||||
 | 
			
		||||
func create_socket_adapter() -> NakamaSocketAdapter:
 | 
			
		||||
	var adapter = NakamaSocketAdapter.new()
 | 
			
		||||
	adapter.name = "NakamaWebSocketAdapter"
 | 
			
		||||
	adapter.logger = logger
 | 
			
		||||
	add_child(adapter)
 | 
			
		||||
	return adapter
 | 
			
		||||
 | 
			
		||||
func create_client(p_server_key : String,
 | 
			
		||||
		p_host : String = DEFAULT_HOST,
 | 
			
		||||
		p_port : int = DEFAULT_PORT,
 | 
			
		||||
		p_scheme : String = DEFAULT_CLIENT_SCHEME,
 | 
			
		||||
		p_timeout : int = DEFAULT_TIMEOUT,
 | 
			
		||||
		p_log_level : int = DEFAULT_LOG_LEVEL) -> NakamaClient:
 | 
			
		||||
	logger._level = p_log_level
 | 
			
		||||
	return NakamaClient.new(get_client_adapter(), p_server_key, p_scheme, p_host, p_port, p_timeout)
 | 
			
		||||
 | 
			
		||||
func create_socket(p_host : String = DEFAULT_HOST,
 | 
			
		||||
		p_port : int = DEFAULT_PORT,
 | 
			
		||||
		p_scheme : String = DEFAULT_SOCKET_SCHEME) -> NakamaSocket:
 | 
			
		||||
	return NakamaSocket.new(create_socket_adapter(), p_host, p_port, p_scheme, true)
 | 
			
		||||
 | 
			
		||||
func create_socket_from(p_client : NakamaClient) -> NakamaSocket:
 | 
			
		||||
	var scheme = "ws"
 | 
			
		||||
	if p_client.scheme == "https":
 | 
			
		||||
		scheme = "wss"
 | 
			
		||||
	return NakamaSocket.new(create_socket_adapter(), p_client.host, p_client.port, scheme, true)
 | 
			
		||||
							
								
								
									
										4350
									
								
								client/addons/com.heroiclabs.nakama/api/NakamaAPI.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4350
									
								
								client/addons/com.heroiclabs.nakama/api/NakamaAPI.gd
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										576
									
								
								client/addons/com.heroiclabs.nakama/api/NakamaRTAPI.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										576
									
								
								client/addons/com.heroiclabs.nakama/api/NakamaRTAPI.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,576 @@
 | 
			
		||||
extends NakamaAsyncResult
 | 
			
		||||
 | 
			
		||||
class_name NakamaRTAPI
 | 
			
		||||
 | 
			
		||||
# A chat channel on the server.
 | 
			
		||||
class Channel extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"id": {"name": "id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"presences": {"name": "presences", "type": TYPE_ARRAY, "required": true, "content": "UserPresence"},
 | 
			
		||||
		"self": {"name": "self_presence", "type": "UserPresence", "required": true},
 | 
			
		||||
		"room_name": {"name": "room_name", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"group_id": {"name": "group_id", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"user_id_one": {"name": "user_id_one", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"user_id_two": {"name": "user_id_two", "type": TYPE_STRING, "required": false}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The server-assigned channel ID.
 | 
			
		||||
	var id : String
 | 
			
		||||
 | 
			
		||||
	# The presences visible on the chat channel.
 | 
			
		||||
	var presences : Array # of objects NakamaUserPresence
 | 
			
		||||
 | 
			
		||||
	# The presence of the current user. i.e. Your self.
 | 
			
		||||
	var self_presence : NakamaRTAPI.UserPresence
 | 
			
		||||
 | 
			
		||||
	# The name of the chat room, or an empty string if this message was not sent through a chat room.
 | 
			
		||||
	var room_name : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the group, or an empty string if this message was not sent through a group channel.
 | 
			
		||||
	var group_id : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the first DM user, or an empty string if this message was not sent through a DM chat.
 | 
			
		||||
	var user_id_one : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the second DM user, or an empty string if this message was not sent through a DM chat.
 | 
			
		||||
	var user_id_two : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "Channel<id=%s, presences=%s, self=%s, room_name=%s, group_id=%s, user_id_one=%s, user_id_two=%s>" % [
 | 
			
		||||
			id, presences, self_presence, room_name, group_id, user_id_one, user_id_two
 | 
			
		||||
		]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> Channel:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "Channel", p_dict), Channel) as Channel
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "channel"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ChannelMessageAck extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"channel_id": {"name": "channel_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"code": {"name": "code", "type": TYPE_INT, "required": true},
 | 
			
		||||
		"create_time": {"name": "create_time", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"message_id": {"name": "message_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"persistent": {"name": "persistent", "type": TYPE_BOOL, "required": false},
 | 
			
		||||
		"update_time": {"name": "update_time", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"username": {"name": "username", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"room_name": {"name": "room_name", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"group_id": {"name": "group_id", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"user_id_one": {"name": "user_id_one", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"user_id_two": {"name": "user_id_two", "type": TYPE_STRING, "required": false}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The server-assigned channel ID.
 | 
			
		||||
	var channel_id : String
 | 
			
		||||
 | 
			
		||||
	# A user-defined code for the chat message.
 | 
			
		||||
	var code : int
 | 
			
		||||
 | 
			
		||||
	# The UNIX time when the message was created.
 | 
			
		||||
	var create_time : String
 | 
			
		||||
 | 
			
		||||
	# A unique ID for the chat message.
 | 
			
		||||
	var message_id : String
 | 
			
		||||
 | 
			
		||||
	# True if the chat message has been stored in history.
 | 
			
		||||
	var persistent : bool
 | 
			
		||||
 | 
			
		||||
	# The UNIX time when the message was updated.
 | 
			
		||||
	var update_time : String
 | 
			
		||||
 | 
			
		||||
	# The username of the sender of the message.
 | 
			
		||||
	var username : String
 | 
			
		||||
 | 
			
		||||
	# The name of the chat room, or an empty string if this message was not sent through a chat room.
 | 
			
		||||
	var room_name : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the group, or an empty string if this message was not sent through a group channel.
 | 
			
		||||
	var group_id : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the first DM user, or an empty string if this message was not sent through a DM chat.
 | 
			
		||||
	var user_id_one : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the second DM user, or an empty string if this message was not sent through a DM chat.
 | 
			
		||||
	var user_id_two : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "ChannelMessageAck<channel_id=%s, code=%d, create_time=%s, message_id=%s, persistent=%s, update_time=%s, username=%s room_name=%s, group_id=%s, user_id_one=%s, user_id_two=%s>" % [
 | 
			
		||||
			channel_id, code, create_time, message_id, persistent, update_time, username, room_name, group_id, user_id_one, user_id_two
 | 
			
		||||
		]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> ChannelMessageAck:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "ChannelMessageAck", p_dict), ChannelMessageAck) as ChannelMessageAck
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "channel_message_ack"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A batch of join and leave presences on a chat channel.
 | 
			
		||||
class ChannelPresenceEvent extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"channel_id": {"name": "channel_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"joins": {"name": "joins", "type": TYPE_ARRAY, "required": false, "content" : "UserPresence"},
 | 
			
		||||
		"leaves": {"name": "leaves", "type": TYPE_ARRAY, "required": false, "content" : "UserPresence"},
 | 
			
		||||
		"room_name": {"name": "room_name", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"group_id": {"name": "group_id", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"user_id_one": {"name": "user_id_one", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"user_id_two": {"name": "user_id_two", "type": TYPE_STRING, "required": false}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The unique identifier of the chat channel.
 | 
			
		||||
	var channel_id : String
 | 
			
		||||
 | 
			
		||||
	# Presences of the users who joined the channel.
 | 
			
		||||
	var joins : Array # UserPresence
 | 
			
		||||
 | 
			
		||||
	# Presences of users who left the channel.
 | 
			
		||||
	var leaves : Array # UserPresence
 | 
			
		||||
 | 
			
		||||
	# The name of the chat room, or an empty string if this message was not sent through a chat room.
 | 
			
		||||
	var room_name : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the group, or an empty string if this message was not sent through a group channel.
 | 
			
		||||
	var group_id : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the first DM user, or an empty string if this message was not sent through a DM chat.
 | 
			
		||||
	var user_id_one : String
 | 
			
		||||
 | 
			
		||||
	# The ID of the second DM user, or an empty string if this message was not sent through a DM chat.
 | 
			
		||||
	var user_id_two : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "ChannelPresenceEvent<channel_id=%s, joins=%s, leaves=%s, room_name=%s, group_id=%s, user_id_one=%s, user_id_two=%s>" % [
 | 
			
		||||
			channel_id, joins, leaves, room_name, group_id, user_id_one, user_id_two
 | 
			
		||||
		]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> ChannelPresenceEvent:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "ChannelPresenceEvent", p_dict), ChannelPresenceEvent) as ChannelPresenceEvent
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "channel_presence_event"
 | 
			
		||||
 | 
			
		||||
# A multiplayer match.
 | 
			
		||||
class Match extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"authoritative": {"name": "authoritative", "type": TYPE_BOOL, "required": false},
 | 
			
		||||
		"match_id": {"name": "match_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"label": {"name": "label", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"presences": {"name": "presences", "type": TYPE_ARRAY, "required": false, "content": "UserPresence"},
 | 
			
		||||
		"size": {"name": "size", "type": TYPE_INT, "required": false},
 | 
			
		||||
		"self": {"name": "self_user", "type": "UserPresence", "required": true}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# If this match has an authoritative handler on the server.
 | 
			
		||||
	var authoritative : bool
 | 
			
		||||
 | 
			
		||||
	# The unique match identifier.
 | 
			
		||||
	var match_id : String
 | 
			
		||||
 | 
			
		||||
	# A label for the match which can be filtered on.
 | 
			
		||||
	var label : String
 | 
			
		||||
 | 
			
		||||
	# The presences already in the match.
 | 
			
		||||
	var presences : Array # UserPresence
 | 
			
		||||
 | 
			
		||||
	# The number of users currently in the match.
 | 
			
		||||
	var size : int
 | 
			
		||||
 | 
			
		||||
	# The current user in this match. i.e. Yourself.
 | 
			
		||||
	var self_user : UserPresence
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary):
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "Match", p_dict), Match) as Match
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "Match<authoritative=%s, match_id=%s, label=%s, presences=%s, size=%d, self=%s>" % [authoritative, match_id, label, presences, size, self_user]
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "match"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Some game state update in a match.
 | 
			
		||||
class MatchData extends NakamaAsyncResult:
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"match_id": {"name": "match_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"presence": {"name": "presence", "type": "UserPresence", "required": false},
 | 
			
		||||
		"op_code": {"name": "op_code", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"data": {"name": "data", "type": TYPE_STRING, "required": false}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The unique match identifier.
 | 
			
		||||
	var match_id : String
 | 
			
		||||
 | 
			
		||||
	# The operation code for the state change.
 | 
			
		||||
	# This value can be used to mark the type of the contents of the state.
 | 
			
		||||
	var op_code : int = 0
 | 
			
		||||
 | 
			
		||||
	# The user that sent this game state update.
 | 
			
		||||
	var presence : UserPresence
 | 
			
		||||
 | 
			
		||||
	# The byte contents of the state change.
 | 
			
		||||
	var data : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "MatchData<match_id=%s, op_code=%s, presence=%s, data=%s>" % [match_id, op_code, presence, data]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> MatchData:
 | 
			
		||||
		var out := _safe_ret(NakamaSerializer.deserialize(p_ns, "MatchData", p_dict), MatchData) as MatchData
 | 
			
		||||
		if out.data: # Decode base64 received data
 | 
			
		||||
			out.data = Marshalls.base64_to_utf8(out.data)
 | 
			
		||||
		return out
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "match_data"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A batch of join and leave presences for a match.
 | 
			
		||||
class MatchPresenceEvent extends NakamaAsyncResult:
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"match_id": {"name": "match_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"joins": {"name": "joins", "type": TYPE_ARRAY, "required": false, "content" : "UserPresence"},
 | 
			
		||||
		"leaves": {"name": "leaves", "type": TYPE_ARRAY, "required": false, "content" : "UserPresence"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# Presences of users who joined the match.
 | 
			
		||||
	var joins : Array
 | 
			
		||||
 | 
			
		||||
	# Presences of users who left the match.
 | 
			
		||||
	var leaves : Array
 | 
			
		||||
 | 
			
		||||
	# The unique match identifier.
 | 
			
		||||
	var match_id : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "MatchPresenceEvent<match_id=%s, joins=%s, leaves=%s>" % [match_id, joins, leaves]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> MatchPresenceEvent:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "MatchPresenceEvent", p_dict), MatchPresenceEvent) as MatchPresenceEvent
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "match_presence_event"
 | 
			
		||||
 | 
			
		||||
# The result of a successful matchmaker operation sent to the server.
 | 
			
		||||
class MatchmakerMatched extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"match_id": {"name": "match_id", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"ticket": {"name": "ticket", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"token": {"name": "token", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"users": {"name": "users", "type": TYPE_ARRAY, "required": false, "content": "MatchmakerUser"},
 | 
			
		||||
		"self": {"name": "self_user", "type": "MatchmakerUser", "required": true}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The id used to join the match.
 | 
			
		||||
	# A match ID used to join the match.
 | 
			
		||||
	var match_id : String
 | 
			
		||||
 | 
			
		||||
	# The ticket sent by the server when the user requested to matchmake for other players.
 | 
			
		||||
	var ticket : String
 | 
			
		||||
 | 
			
		||||
	# The token used to join a match.
 | 
			
		||||
	var token : String
 | 
			
		||||
 | 
			
		||||
	# The other users matched with this user and the parameters they sent.
 | 
			
		||||
	var users : Array # MatchmakerUser
 | 
			
		||||
	
 | 
			
		||||
	# The current user who matched with opponents.
 | 
			
		||||
	var self_user : MatchmakerUser
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "<MatchmakerMatched match_id=%s, ticket=%s, token=%s, users=%s, self=%s>" % [
 | 
			
		||||
			match_id, ticket, token, users, self_user
 | 
			
		||||
		]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> MatchmakerMatched:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "MatchmakerMatched", p_dict), MatchmakerMatched) as MatchmakerMatched
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "matchmaker_matched"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# The matchmaker ticket received from the server.
 | 
			
		||||
class MatchmakerTicket extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"ticket": {"name": "ticket", "type": TYPE_STRING, "required": true}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The ticket generated by the matchmaker.
 | 
			
		||||
	var ticket : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> MatchmakerTicket:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "MatchmakerTicket", p_dict), MatchmakerTicket) as MatchmakerTicket
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "<MatchmakerTicket ticket=%s>" % ticket
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "matchmaker_ticket"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# The user with the parameters they sent to the server when asking for opponents.
 | 
			
		||||
class MatchmakerUser extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"numeric_properties": {"name": "numeric_properties", "type": TYPE_DICTIONARY, "required": false, "content": TYPE_REAL},
 | 
			
		||||
		"string_properties": {"name": "string_properties", "type": TYPE_DICTIONARY, "required": false, "content": TYPE_STRING},
 | 
			
		||||
		"presence": {"name": "presence", "type": "UserPresence", "required": true}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The numeric properties which this user asked to matchmake with.
 | 
			
		||||
	var numeric_properties : Dictionary
 | 
			
		||||
 | 
			
		||||
	# The presence of the user.
 | 
			
		||||
	var presence : UserPresence
 | 
			
		||||
 | 
			
		||||
	# The string properties which this user asked to matchmake with.
 | 
			
		||||
	var string_properties : Dictionary
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "<MatchmakerUser presence=%s, numeric_properties=%s, string_properties=%s>" % [
 | 
			
		||||
			presence, numeric_properties, string_properties]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> MatchmakerUser:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "MatchmakerUser", p_dict), MatchmakerUser) as MatchmakerUser
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "matchmaker_user"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Receive status updates for users.
 | 
			
		||||
class Status extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"presences": {"name": "presences", "type": TYPE_ARRAY, "required": true, "content": "UserPresence"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The status events for the users followed.
 | 
			
		||||
	var presences := Array()
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> Status:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "Status", p_dict), Status) as Status
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "<Status presences=%s>" % [presences]
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "status"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A status update event about other users who've come online or gone offline.
 | 
			
		||||
class StatusPresenceEvent extends NakamaAsyncResult:
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"joins": {"name": "joins", "type": TYPE_ARRAY, "required": false, "content" : "UserPresence"},
 | 
			
		||||
		"leaves": {"name": "leaves", "type": TYPE_ARRAY, "required": false, "content" : "UserPresence"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# Presences of users who joined the server.
 | 
			
		||||
	# This join information is in response to a subscription made to be notified when a user comes online.
 | 
			
		||||
	var joins : Array
 | 
			
		||||
 | 
			
		||||
	# Presences of users who left the server.
 | 
			
		||||
	# This leave information is in response to a subscription made to be notified when a user goes offline.
 | 
			
		||||
	var leaves : Array
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "StatusPresenceEvent<joins=%s, leaves=%s>" % [joins, leaves]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> StatusPresenceEvent:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "StatusPresenceEvent", p_dict), StatusPresenceEvent) as StatusPresenceEvent
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "status_presence_event"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A realtime socket stream on the server.
 | 
			
		||||
class Stream extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"mode": {"name": "mode", "type": TYPE_INT, "required": true},
 | 
			
		||||
		"subject": {"name": "subject", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"subcontext": {"name": "subcontext", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"label": {"name": "label", "type": TYPE_STRING, "required": false},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The mode of the stream.
 | 
			
		||||
	var mode : int
 | 
			
		||||
 | 
			
		||||
	# The subject of the stream. This is usually a user id.
 | 
			
		||||
	var subject : String
 | 
			
		||||
 | 
			
		||||
	# The descriptor of the stream. Used with direct chat messages and contains a second user id.
 | 
			
		||||
	var subcontext : String
 | 
			
		||||
 | 
			
		||||
	# Identifies streams which have a context across users like a chat channel room.
 | 
			
		||||
	var label : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "Stream<mode=%s, subject=%s, subcontext=%s, label=%s>" % [mode, subject, subcontext, label]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> Stream:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "Stream", p_dict), Stream) as Stream
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "stream"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A batch of joins and leaves on the low level stream.
 | 
			
		||||
# Streams are built on to provide abstractions for matches, chat channels, etc. In most cases you'll never need to
 | 
			
		||||
# interact with the low level stream itself.
 | 
			
		||||
class StreamPresenceEvent extends NakamaAsyncResult:
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"stream": {"name": "stream", "type": "Stream", "required": true},
 | 
			
		||||
		"joins": {"name": "joins", "type": TYPE_ARRAY, "required": false, "content" : "UserPresence"},
 | 
			
		||||
		"leaves": {"name": "leaves", "type": TYPE_ARRAY, "required": false, "content" : "UserPresence"},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# Presences of users who left the stream.
 | 
			
		||||
	var joins : Array
 | 
			
		||||
 | 
			
		||||
	# Presences of users who joined the stream.
 | 
			
		||||
	var leaves : Array
 | 
			
		||||
 | 
			
		||||
	# The identifier for the stream.
 | 
			
		||||
	var stream : Stream = null
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "StreamPresenceEvent<stream=%s, joins=%s, leaves=%s>" % [stream, joins, leaves]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> StreamPresenceEvent:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "StreamPresenceEvent", p_dict), StreamPresenceEvent) as StreamPresenceEvent
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "stream_presence_event"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A state change received from a stream.
 | 
			
		||||
class StreamData extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"stream": {"name": "stream", "type": "Stream", "required": true},
 | 
			
		||||
		"sender": {"name": "sender", "type": "UserPresence", "required": false},
 | 
			
		||||
		"data": {"name": "state", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"reliable": {"name": "reliable", "type": TYPE_BOOL, "required": false},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# The user who sent the state change. May be `null`.
 | 
			
		||||
	var sender : UserPresence = null
 | 
			
		||||
 | 
			
		||||
	# The contents of the state change.
 | 
			
		||||
	var state : String
 | 
			
		||||
 | 
			
		||||
	# The identifier for the stream.
 | 
			
		||||
	var stream : Stream
 | 
			
		||||
 | 
			
		||||
	# True if this data was delivered reliably, false otherwise.
 | 
			
		||||
	var reliable : bool
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "StreamData<sender=%s, state=%s, stream=%s>" % [sender, state, stream]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> StreamData:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "StreamData", p_dict), StreamData) as StreamData
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "stream_data"
 | 
			
		||||
 | 
			
		||||
# An object which represents a connected user in the server.
 | 
			
		||||
# The server allows the same user to be connected with multiple sessions. To uniquely identify them a tuple of
 | 
			
		||||
# `{ node_id, user_id, session_id }` is used which is exposed as this object.
 | 
			
		||||
class UserPresence extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"persistence": {"name": "persistence", "type": TYPE_BOOL, "required": false},
 | 
			
		||||
		"session_id": {"name": "session_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"status": {"name": "status", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"username": {"name": "username", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"user_id": {"name": "user_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# If this presence generates stored events like persistent chat messages or notifications.
 | 
			
		||||
	var persistence : bool
 | 
			
		||||
 | 
			
		||||
	# The session id of the user.
 | 
			
		||||
	var session_id : String
 | 
			
		||||
 | 
			
		||||
	# The status of the user with the presence on the server.
 | 
			
		||||
	var status : String
 | 
			
		||||
 | 
			
		||||
	# The username for the user.
 | 
			
		||||
	var username : String
 | 
			
		||||
 | 
			
		||||
	# The id of the user.
 | 
			
		||||
	var user_id : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex = null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		if is_exception(): return get_exception()._to_string()
 | 
			
		||||
		return "UserPresence<persistence=%s, session_id=%s, status=%s, username=%s, user_id=%s>" % [
 | 
			
		||||
			persistence, session_id, status, username, user_id]
 | 
			
		||||
 | 
			
		||||
	static func create(p_ns : GDScript, p_dict : Dictionary) -> UserPresence:
 | 
			
		||||
		return _safe_ret(NakamaSerializer.deserialize(p_ns, "UserPresence", p_dict), UserPresence) as UserPresence
 | 
			
		||||
 | 
			
		||||
	static func get_result_key() -> String:
 | 
			
		||||
		return "user_presence"
 | 
			
		||||
							
								
								
									
										363
									
								
								client/addons/com.heroiclabs.nakama/api/NakamaRTMessage.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										363
									
								
								client/addons/com.heroiclabs.nakama/api/NakamaRTMessage.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,363 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
class_name NakamaRTMessage
 | 
			
		||||
 | 
			
		||||
# Send a channel join message to the server.
 | 
			
		||||
class ChannelJoin:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"persistence": {"name": "persistence", "type": TYPE_BOOL, "required": true},
 | 
			
		||||
		"hidden": {"name": "hidden", "type": TYPE_BOOL, "required": true},
 | 
			
		||||
		"target": {"name": "target", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"type": {"name": "type", "type": TYPE_INT, "required": true},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	enum ChannelType {
 | 
			
		||||
		# A chat room which can be created dynamically with a name.
 | 
			
		||||
		Room = 1,
 | 
			
		||||
		# A private chat between two users.
 | 
			
		||||
		DirectMessage = 2,
 | 
			
		||||
		# A chat within a group on the server.
 | 
			
		||||
		Group = 3
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var persistence : bool
 | 
			
		||||
	var hidden : bool
 | 
			
		||||
	var target : String
 | 
			
		||||
	var type : int
 | 
			
		||||
 | 
			
		||||
	func _init(p_target : String, p_type : int, p_persistence : bool, p_hidden : bool):
 | 
			
		||||
		persistence = p_persistence
 | 
			
		||||
		hidden = p_hidden
 | 
			
		||||
		target = p_target
 | 
			
		||||
		type = p_type if p_type >= ChannelType.Room and p_type <= ChannelType.Group else 0 # Will cause error server side
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "channel_join"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "ChannelJoin<persistence=%s, hidden=%s, target=%s, type=%d>" % [persistence, hidden, target, type]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A leave message for a match on the server.
 | 
			
		||||
class ChannelLeave extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"channel_id": {"name": "channel_id", "type": TYPE_STRING, "required": true}
 | 
			
		||||
	}
 | 
			
		||||
	var channel_id : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_channel_id : String):
 | 
			
		||||
		channel_id = p_channel_id
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "channel_leave"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "ChannelLeave<channel_id=%s>" % [channel_id]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ChannelMessageRemove extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"channel_id": {"name": "channel_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"message_id": {"name": "message_id", "type": TYPE_STRING, "required": true}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var channel_id : String
 | 
			
		||||
	var message_id : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_channel_id : String, p_message_id):
 | 
			
		||||
		channel_id = p_channel_id
 | 
			
		||||
		message_id = p_message_id
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "channel_message_remove"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "ChannelMessageRemove<channel_id=%s, message_id=%s>" % [channel_id, message_id]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Send a chat message to a channel on the server.
 | 
			
		||||
class ChannelMessageSend extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"channel_id": {"name": "channel_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"content": {"name": "content", "type": TYPE_STRING, "required": true}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var channel_id : String
 | 
			
		||||
	var content : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_channel_id : String, p_content):
 | 
			
		||||
		channel_id = p_channel_id
 | 
			
		||||
		content = p_content
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "channel_message_send"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "ChannelMessageSend<channel_id=%s, content=%s>" % [channel_id, content]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class ChannelMessageUpdate extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"channel_id": {"name": "channel_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"message_id": {"name": "message_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"content": {"name": "content", "type": TYPE_STRING, "required": true}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var channel_id : String
 | 
			
		||||
	var message_id : String
 | 
			
		||||
	var content : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_channel_id : String, p_message_id, p_content : String):
 | 
			
		||||
		channel_id = p_channel_id
 | 
			
		||||
		message_id = p_message_id
 | 
			
		||||
		content = p_content
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "channel_message_update"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "ChannelMessageUpdate<channel_id=%s, message_id=%s, content=%s>" % [channel_id, message_id, content]
 | 
			
		||||
 | 
			
		||||
# A create message for a match on the server.
 | 
			
		||||
class MatchCreate extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {}
 | 
			
		||||
 | 
			
		||||
	func _init():
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func serialize():
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "match_create"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "MatchCreate<>"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A join message for a match on the server.
 | 
			
		||||
class MatchJoin extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"match_id": {"name": "match_id", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"token": {"name": "token", "type": TYPE_STRING, "required": false},
 | 
			
		||||
		"metadata": {"name": "metadata", "type": TYPE_DICTIONARY, "required": false, "content": TYPE_STRING},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	# These two are mutually exclusive and set manually by socket for now, so use null.
 | 
			
		||||
	var match_id = null
 | 
			
		||||
	var token = null
 | 
			
		||||
	var metadata = null
 | 
			
		||||
 | 
			
		||||
	func _init(p_ex=null).(p_ex):
 | 
			
		||||
		pass
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "match_join"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "MatchJoin<match_id=%s, token=%s, metadata=%s>" % [match_id, token, metadata]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# A leave message for a match on the server.
 | 
			
		||||
class MatchLeave extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"match_id": {"name": "match_id", "type": TYPE_STRING, "required": true}
 | 
			
		||||
	}
 | 
			
		||||
	var match_id : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_match_id : String):
 | 
			
		||||
		match_id = p_match_id
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "match_leave"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "MatchLeave<match_id=%s>" % [match_id]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Send new state to a match on the server.
 | 
			
		||||
class MatchDataSend extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"match_id": {"name": "match_id", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"op_code": {"name": "op_code", "type": TYPE_INT, "required": true},
 | 
			
		||||
		"presences": {"name": "presences", "type": TYPE_ARRAY, "required": false, "content": "UserPresences"},
 | 
			
		||||
		"data": {"name": "data", "type": TYPE_STRING, "required": true},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var match_id : String
 | 
			
		||||
	var presences = null
 | 
			
		||||
	var op_code : int
 | 
			
		||||
	var data : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_match_id : String, p_op_code : int, p_data : String, p_presences):
 | 
			
		||||
		match_id = p_match_id
 | 
			
		||||
		presences = p_presences
 | 
			
		||||
		op_code = p_op_code
 | 
			
		||||
		data = p_data
 | 
			
		||||
 | 
			
		||||
	func serialize():
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key():
 | 
			
		||||
		return "match_data_send"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "MatchDataSend<match_id=%s, op_code=%s, presences=%s, data=%s>" % [match_id, op_code, presences, data]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Add the user to the matchmaker pool with properties.
 | 
			
		||||
class MatchmakerAdd extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"query": {"name": "query", "type": TYPE_STRING, "required": true},
 | 
			
		||||
		"max_count": {"name": "max_count", "type": TYPE_INT, "required": true},
 | 
			
		||||
		"min_count": {"name": "min_count", "type": TYPE_INT, "required": true},
 | 
			
		||||
		"numeric_properties": {"name": "numeric_properties", "type": TYPE_DICTIONARY, "required": false, "content": TYPE_REAL},
 | 
			
		||||
		"string_properties": {"name": "string_properties", "type": TYPE_DICTIONARY, "required": false, "content": TYPE_STRING},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var query : String = "*"
 | 
			
		||||
	var max_count : int = 8
 | 
			
		||||
	var min_count : int = 2
 | 
			
		||||
	var string_properties : Dictionary
 | 
			
		||||
	var numeric_properties : Dictionary
 | 
			
		||||
 | 
			
		||||
	func _no_set(_val):
 | 
			
		||||
		return
 | 
			
		||||
 | 
			
		||||
	func _init(p_query : String = "*", p_min_count : int = 2, p_max_count : int = 8,
 | 
			
		||||
			p_string_props : Dictionary = Dictionary(), p_numeric_props : Dictionary = Dictionary()):
 | 
			
		||||
		query = p_query
 | 
			
		||||
		min_count = p_min_count
 | 
			
		||||
		max_count = p_max_count
 | 
			
		||||
		string_properties = p_string_props
 | 
			
		||||
		numeric_properties = p_numeric_props
 | 
			
		||||
 | 
			
		||||
	func serialize() -> Dictionary:
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "matchmaker_add"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "MatchmakerAdd<query=%s, max_count=%d, min_count=%d, numeric_properties=%s, string_properties=%s>" % [query, max_count, min_count, numeric_properties, string_properties]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Remove the user from the matchmaker pool by ticket.
 | 
			
		||||
class MatchmakerRemove extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"ticket": {"name": "ticket", "type": TYPE_STRING, "required": true}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var ticket : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_ticket : String):
 | 
			
		||||
		ticket = p_ticket
 | 
			
		||||
 | 
			
		||||
	func serialize():
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "matchmaker_remove"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "MatchmakerRemove<ticket=%s>" % [ticket]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Follow one or more other users for status updates.
 | 
			
		||||
class StatusFollow extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"user_ids": {"name": "user_ids", "type": TYPE_DICTIONARY, "required": false, "content": TYPE_STRING},
 | 
			
		||||
		"usernames": {"name": "usernames", "type": TYPE_DICTIONARY, "required": false, "content": TYPE_STRING},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var user_ids := PoolStringArray()
 | 
			
		||||
	var usernames := PoolStringArray()
 | 
			
		||||
 | 
			
		||||
	func _init(p_ids : PoolStringArray, p_usernames : PoolStringArray):
 | 
			
		||||
		user_ids = p_ids
 | 
			
		||||
		usernames = p_usernames
 | 
			
		||||
 | 
			
		||||
	func serialize():
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "status_follow"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "StatusFollow<user_ids=%s, usernames=%s>" % [user_ids, usernames]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Unfollow one or more users on the server.
 | 
			
		||||
class StatusUnfollow extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"user_ids": {"name": "user_ids", "type": TYPE_DICTIONARY, "required": false, "content": TYPE_STRING},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var user_ids := PoolStringArray()
 | 
			
		||||
 | 
			
		||||
	func _init(p_ids : PoolStringArray):
 | 
			
		||||
		user_ids = p_ids
 | 
			
		||||
 | 
			
		||||
	func serialize():
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "status_unfollow"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "StatusUnfollow<user_ids=%s>" % [user_ids]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Unfollow one or more users on the server.
 | 
			
		||||
class StatusUpdate extends NakamaAsyncResult:
 | 
			
		||||
 | 
			
		||||
	const _SCHEMA = {
 | 
			
		||||
		"status": {"name": "status", "type": TYPE_STRING, "required": true},
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var status : String
 | 
			
		||||
 | 
			
		||||
	func _init(p_status : String):
 | 
			
		||||
		status = p_status
 | 
			
		||||
 | 
			
		||||
	func serialize():
 | 
			
		||||
		return NakamaSerializer.serialize(self)
 | 
			
		||||
 | 
			
		||||
	func get_msg_key() -> String:
 | 
			
		||||
		return "status_update"
 | 
			
		||||
 | 
			
		||||
	func _to_string():
 | 
			
		||||
		return "StatusUpdate<status=%s>" % [status]
 | 
			
		||||
							
								
								
									
										64
									
								
								client/addons/com.heroiclabs.nakama/api/NakamaSession.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								client/addons/com.heroiclabs.nakama/api/NakamaSession.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
			
		||||
extends NakamaAsyncResult
 | 
			
		||||
class_name NakamaSession
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var created : bool = false setget _no_set
 | 
			
		||||
var token : String = "" setget _no_set
 | 
			
		||||
var create_time : int = 0 setget _no_set
 | 
			
		||||
var expire_time : int = 0 setget _no_set
 | 
			
		||||
var expired : bool = true setget _no_set, is_expired
 | 
			
		||||
var vars : Dictionary = {} setget _no_set
 | 
			
		||||
var username : String = "" setget _no_set
 | 
			
		||||
var user_id : String = "" setget _no_set
 | 
			
		||||
var valid : bool = false setget _no_set, is_valid
 | 
			
		||||
 | 
			
		||||
func _no_set(v):
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
func is_expired() -> bool:
 | 
			
		||||
	return expire_time < OS.get_unix_time()
 | 
			
		||||
 | 
			
		||||
func is_valid():
 | 
			
		||||
	return valid
 | 
			
		||||
 | 
			
		||||
func _init(p_token = null, p_created : bool = false, p_exception = null).(p_exception):
 | 
			
		||||
	if p_token:
 | 
			
		||||
		var unpacked = _jwt_unpack(p_token)
 | 
			
		||||
		var decoded = {}
 | 
			
		||||
		if not validate_json(unpacked):
 | 
			
		||||
			decoded = parse_json(unpacked)
 | 
			
		||||
			valid = true
 | 
			
		||||
		if typeof(decoded) != TYPE_DICTIONARY:
 | 
			
		||||
			decoded = {}
 | 
			
		||||
		if decoded.empty():
 | 
			
		||||
			valid = false
 | 
			
		||||
			if p_exception == null:
 | 
			
		||||
				_ex = NakamaException.new("Unable to unpack token")
 | 
			
		||||
 | 
			
		||||
		token = p_token
 | 
			
		||||
		created = p_created
 | 
			
		||||
		create_time = OS.get_unix_time()
 | 
			
		||||
		expire_time = int(decoded.get("exp", 0))
 | 
			
		||||
		username = str(decoded.get("usn", ""))
 | 
			
		||||
		user_id = str(decoded.get("uid", ""))
 | 
			
		||||
		if decoded.has("vrs") and typeof(decoded["vrs"]) == TYPE_DICTIONARY:
 | 
			
		||||
			for k in decoded["vrs"]:
 | 
			
		||||
				vars[k] = decoded["vrs"][k]
 | 
			
		||||
 | 
			
		||||
func _to_string():
 | 
			
		||||
	if is_exception():
 | 
			
		||||
		return get_exception()._to_string()
 | 
			
		||||
	return "Session<created=%s, token=%s, create_time=%d, username=%s, user_id=%s, vars=%s>" % [
 | 
			
		||||
		created, token, create_time, username, user_id, str(vars)]
 | 
			
		||||
 | 
			
		||||
func _jwt_unpack(p_token : String) -> String:
 | 
			
		||||
	# Hack decode JSON payload from JWT.
 | 
			
		||||
	if p_token.find(".") == -1:
 | 
			
		||||
		return ""
 | 
			
		||||
	var payload = p_token.split('.')[1];
 | 
			
		||||
	var pad_length = ceil(payload.length() / 4.0) * 4;
 | 
			
		||||
	# Pad base64
 | 
			
		||||
	for i in range(0, pad_length - payload.length()):
 | 
			
		||||
		payload += "="
 | 
			
		||||
	payload = payload.replace("-", "+").replace("_", "/")
 | 
			
		||||
	return Marshalls.base64_to_utf8(payload)
 | 
			
		||||
@ -0,0 +1,34 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
class_name NakamaStorageObjectId
 | 
			
		||||
 | 
			
		||||
# The collection which stores the object.
 | 
			
		||||
var collection : String
 | 
			
		||||
 | 
			
		||||
# The key of the object within the collection.
 | 
			
		||||
var key : String
 | 
			
		||||
 | 
			
		||||
# The user owner of the object.
 | 
			
		||||
var user_id : String
 | 
			
		||||
 | 
			
		||||
# The version hash of the object.
 | 
			
		||||
var version : String
 | 
			
		||||
 | 
			
		||||
func _init(p_collection, p_key, p_user_id = "", p_version = ""):
 | 
			
		||||
	collection = p_collection
 | 
			
		||||
	key = p_key
 | 
			
		||||
	user_id = p_user_id
 | 
			
		||||
	version = p_version
 | 
			
		||||
 | 
			
		||||
func as_delete():
 | 
			
		||||
	return NakamaAPI.ApiDeleteStorageObjectId.create(NakamaAPI, {
 | 
			
		||||
		"collection": collection,
 | 
			
		||||
		"key": key,
 | 
			
		||||
		"version": version
 | 
			
		||||
	})
 | 
			
		||||
 | 
			
		||||
func as_read():
 | 
			
		||||
	return NakamaAPI.ApiReadStorageObjectId.create(NakamaAPI, {
 | 
			
		||||
		"collection": collection,
 | 
			
		||||
		"key": key,
 | 
			
		||||
		"user_id": user_id
 | 
			
		||||
	})
 | 
			
		||||
@ -0,0 +1,28 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
class_name NakamaWriteStorageObject
 | 
			
		||||
 | 
			
		||||
var collection : String
 | 
			
		||||
var key : String
 | 
			
		||||
var permission_read : int = 0
 | 
			
		||||
var permission_write : int = 0
 | 
			
		||||
var value : String
 | 
			
		||||
var version : String
 | 
			
		||||
 | 
			
		||||
func _init(p_collection : String, p_key : String, p_permission_read : int,
 | 
			
		||||
		p_permission_write : int, p_value : String, p_version : String):
 | 
			
		||||
	collection = p_collection
 | 
			
		||||
	key = p_key
 | 
			
		||||
	permission_read = p_permission_read
 | 
			
		||||
	permission_write = p_permission_write
 | 
			
		||||
	value = p_value
 | 
			
		||||
	version = p_version
 | 
			
		||||
 | 
			
		||||
func as_write():
 | 
			
		||||
	return NakamaAPI.ApiWriteStorageObject.create(NakamaAPI, {
 | 
			
		||||
		"collection": collection,
 | 
			
		||||
		"key": key,
 | 
			
		||||
		"permission_read": permission_read,
 | 
			
		||||
		"permission_write": permission_write,
 | 
			
		||||
		"value": value,
 | 
			
		||||
		"version": version
 | 
			
		||||
	})
 | 
			
		||||
							
								
								
									
										795
									
								
								client/addons/com.heroiclabs.nakama/client/NakamaClient.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										795
									
								
								client/addons/com.heroiclabs.nakama/client/NakamaClient.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,795 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
 | 
			
		||||
# A client for the API in Nakama server.
 | 
			
		||||
class_name NakamaClient
 | 
			
		||||
 | 
			
		||||
const ChannelType = NakamaRTMessage.ChannelJoin.ChannelType
 | 
			
		||||
 | 
			
		||||
func _no_set(_p):
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
func _no_get():
 | 
			
		||||
	return null
 | 
			
		||||
 | 
			
		||||
# The host address of the server. Defaults to "127.0.0.1".
 | 
			
		||||
var host : String setget _no_set
 | 
			
		||||
 | 
			
		||||
# The port number of the server. Defaults to 7350.
 | 
			
		||||
var port : int setget _no_set
 | 
			
		||||
 | 
			
		||||
# The protocol scheme used to connect with the server. Must be either "http" or "https".
 | 
			
		||||
var scheme : String setget _no_set
 | 
			
		||||
 | 
			
		||||
# The key used to authenticate with the server without a session. Defaults to "defaultkey".
 | 
			
		||||
var server_key : String = "defaultkey" setget _no_set
 | 
			
		||||
 | 
			
		||||
# Set the timeout in seconds on requests sent to the server.
 | 
			
		||||
var timeout : int
 | 
			
		||||
 | 
			
		||||
var logger : NakamaLogger = null
 | 
			
		||||
 | 
			
		||||
var _api_client := NakamaAPI.ApiClient.new("", NakamaAPI, null) setget _no_set, _no_get
 | 
			
		||||
 | 
			
		||||
func _init(p_adapter : NakamaHTTPAdapter,
 | 
			
		||||
		p_server_key : String,
 | 
			
		||||
		p_scheme : String,
 | 
			
		||||
		p_host : String,
 | 
			
		||||
		p_port : int,
 | 
			
		||||
		p_timeout : int):
 | 
			
		||||
 | 
			
		||||
	server_key = p_server_key
 | 
			
		||||
	scheme = p_scheme
 | 
			
		||||
	host = p_host
 | 
			
		||||
	port = p_port
 | 
			
		||||
	timeout = p_timeout
 | 
			
		||||
	logger = p_adapter.logger
 | 
			
		||||
	_api_client = NakamaAPI.ApiClient.new(scheme + "://" + host + ":" + str(port), p_adapter, NakamaAPI, p_timeout)
 | 
			
		||||
 | 
			
		||||
# Restore a session from the auth token.
 | 
			
		||||
# A `null` or empty authentication token will return `null`.
 | 
			
		||||
# @param authToken - The authentication token to restore as a session.
 | 
			
		||||
# Returns a session.
 | 
			
		||||
static func restore_session(auth_token : String):
 | 
			
		||||
	return NakamaSession.new(auth_token, false)
 | 
			
		||||
 | 
			
		||||
func _to_string():
 | 
			
		||||
	return "Client(Host='%s', Port=%s, Scheme='%s', ServerKey='%s', Timeout=%s)" % [
 | 
			
		||||
		host, port, scheme, server_key, timeout
 | 
			
		||||
	]
 | 
			
		||||
 | 
			
		||||
func _parse_auth(p_session) -> NakamaSession:
 | 
			
		||||
	if p_session.is_exception():
 | 
			
		||||
		return NakamaSession.new(null, false, p_session.get_exception())
 | 
			
		||||
	return NakamaSession.new(p_session.token, p_session.created)
 | 
			
		||||
 | 
			
		||||
# Add one or more friends by id or username.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_ids - The ids of the users to add or invite as friends.
 | 
			
		||||
# @param p_usernames - The usernames of the users to add as friends.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func add_friends_async(p_session : NakamaSession, p_ids = null, p_usernames = null) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.add_friends_async(p_session.token, p_ids, p_usernames)
 | 
			
		||||
 | 
			
		||||
# Add one or more users to the group.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_group_id - The id of the group to add users into.
 | 
			
		||||
# @param p_ids - The ids of the users to add or invite to the group.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func add_group_users_async(p_session : NakamaSession, p_group_id : String, p_ids : PoolStringArray) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.add_group_users_async(p_session.token, p_group_id, p_ids);
 | 
			
		||||
 | 
			
		||||
# Authenticate a user with a custom id.
 | 
			
		||||
# @param p_id - A custom identifier usually obtained from an external authentication service.
 | 
			
		||||
# @param p_username - A username used to create the user. May be `null`.
 | 
			
		||||
# @param p_create - If the user should be created when authenticated.
 | 
			
		||||
# @param p_vars - Extra information that will be bundled in the session token.
 | 
			
		||||
# Returns a task which resolves to a session object.
 | 
			
		||||
func authenticate_custom_async(p_id : String, p_username = null, p_create : bool = true, p_vars = null) -> NakamaSession:
 | 
			
		||||
	return _parse_auth(yield(_api_client.authenticate_custom_async(server_key, "",
 | 
			
		||||
		NakamaAPI.ApiAccountCustom.create(NakamaAPI, {
 | 
			
		||||
			"id": p_id,
 | 
			
		||||
			"vars": p_vars
 | 
			
		||||
		}), p_create, p_username), "completed"))
 | 
			
		||||
 | 
			
		||||
# Authenticate a user with a device id.
 | 
			
		||||
# @param p_id - A device identifier usually obtained from a platform API.
 | 
			
		||||
# @param p_username - A username used to create the user. May be `null`.
 | 
			
		||||
# @param p_create - If the user should be created when authenticated.
 | 
			
		||||
# @param p_vars - Extra information that will be bundled in the session token.
 | 
			
		||||
# Returns a task which resolves to a session object.
 | 
			
		||||
func authenticate_device_async(p_id : String, p_username = null, p_create : bool = true, p_vars = null) -> NakamaSession:
 | 
			
		||||
	return _parse_auth(yield(_api_client.authenticate_device_async(server_key, "",
 | 
			
		||||
		NakamaAPI.ApiAccountDevice.create(NakamaAPI, {
 | 
			
		||||
			"id": p_id,
 | 
			
		||||
			"vars": p_vars
 | 
			
		||||
		}), p_create, p_username), "completed"))
 | 
			
		||||
 | 
			
		||||
# Authenticate a user with an email and password.
 | 
			
		||||
# @param p_email - The email address of the user.
 | 
			
		||||
# @param p_password - The password for the user.
 | 
			
		||||
# @param p_username - A username used to create the user. May be `null`.
 | 
			
		||||
# @param p_create - If the user should be created when authenticated.
 | 
			
		||||
# @param p_vars - Extra information that will be bundled in the session token.
 | 
			
		||||
# Returns a task which resolves to a session object.
 | 
			
		||||
func authenticate_email_async(p_email : String, p_password : String, p_username = null, p_create : bool = true, p_vars = null) -> NakamaSession:
 | 
			
		||||
	return _parse_auth(yield(_api_client.authenticate_email_async(server_key, "",
 | 
			
		||||
		NakamaAPI.ApiAccountEmail.create(NakamaAPI, {
 | 
			
		||||
			"email": p_email,
 | 
			
		||||
			"password": p_password,
 | 
			
		||||
			"vars": p_vars
 | 
			
		||||
		}), p_create, p_username), "completed"))
 | 
			
		||||
 | 
			
		||||
# Authenticate a user with a Facebook auth token.
 | 
			
		||||
# @param p_token - An OAuth access token from the Facebook SDK.
 | 
			
		||||
# @param p_username - A username used to create the user. May be `null`.
 | 
			
		||||
# @param p_create - If the user should be created when authenticated.
 | 
			
		||||
# @param p_import - If the Facebook friends should be imported.
 | 
			
		||||
# @param p_vars - Extra information that will be bundled in the session token.
 | 
			
		||||
# Returns a task which resolves to a session object.
 | 
			
		||||
func authenticate_facebook_async(p_token : String, p_username = null, p_create : bool = true, p_import : bool = true, p_vars = null) -> NakamaSession:
 | 
			
		||||
	return _parse_auth(yield(_api_client.authenticate_facebook_async(server_key, "",
 | 
			
		||||
		NakamaAPI.ApiAccountFacebook.create(NakamaAPI, {
 | 
			
		||||
			"token": p_token,
 | 
			
		||||
			"vars": p_vars
 | 
			
		||||
		}), p_create, p_username, p_import), "completed"))
 | 
			
		||||
 | 
			
		||||
# Authenticate a user with a Facebook Instant Game token against the server.
 | 
			
		||||
# @param p_signed_player_info - Facebook Instant Game signed info from Facebook SDK.
 | 
			
		||||
# @param p_username - A username used to create the user. May be `null`.
 | 
			
		||||
# @param p_create - If the user should be created when authenticated.
 | 
			
		||||
# @param p_import - If the Facebook friends should be imported.
 | 
			
		||||
# @param p_vars - Extra information that will be bundled in the session token.
 | 
			
		||||
# Returns a task which resolves to a session object.
 | 
			
		||||
func authenticate_facebook_instant_game_async(p_signed_player_info : String, p_username = null, p_create : bool = true, p_vars = null) -> NakamaSession:
 | 
			
		||||
		return _parse_auth(yield(_api_client.authenticate_facebook_instant_game_async(server_key, "",
 | 
			
		||||
				NakamaAPI.ApiAccountFacebookInstantGame.create(NakamaAPI, {
 | 
			
		||||
						"signed_player_info": p_signed_player_info,
 | 
			
		||||
						"vars": p_vars
 | 
			
		||||
				}), p_create, p_username), "completed"))
 | 
			
		||||
 | 
			
		||||
# Authenticate a user with Apple Game Center.
 | 
			
		||||
# @param p_bundle_id - The bundle id of the Game Center application.
 | 
			
		||||
# @param p_player_id - The player id of the user in Game Center.
 | 
			
		||||
# @param p_public_key_url - The URL for the public encryption key.
 | 
			
		||||
# @param p_salt - A random `NSString` used to compute the hash and keep it randomized.
 | 
			
		||||
# @param p_signature - The verification signature data generated.
 | 
			
		||||
# @param p_timestamp_seconds - The date and time that the signature was created.
 | 
			
		||||
# @param p_username - A username used to create the user. May be `null`.
 | 
			
		||||
# @param p_create - If the user should be created when authenticated.
 | 
			
		||||
# @param p_vars - Extra information that will be bundled in the session token.
 | 
			
		||||
# Returns a task which resolves to a session object.
 | 
			
		||||
func authenticate_game_center_async(p_bundle_id : String, p_player_id : String, p_public_key_url : String,
 | 
			
		||||
		p_salt : String, p_signature : String, p_timestamp_seconds : String, p_username = null, p_create : bool = true, p_vars = null) -> NakamaSession:
 | 
			
		||||
	return _parse_auth(yield(_api_client.authenticate_game_center_async(server_key, "",
 | 
			
		||||
		NakamaAPI.ApiAccountGameCenter.create(NakamaAPI, {
 | 
			
		||||
			"bundle_id": p_bundle_id,
 | 
			
		||||
			"player_id": p_player_id,
 | 
			
		||||
			"public_key_url": p_public_key_url,
 | 
			
		||||
			"salt": p_salt,
 | 
			
		||||
			"signature": p_signature,
 | 
			
		||||
			"timestamp_seconds": p_timestamp_seconds,
 | 
			
		||||
			"vars": p_vars
 | 
			
		||||
		}), p_create, p_username), "completed"))
 | 
			
		||||
 | 
			
		||||
# Authenticate a user with a Google auth token.
 | 
			
		||||
# @param p_token - An OAuth access token from the Google SDK.
 | 
			
		||||
# @param p_username - A username used to create the user. May be `null`.
 | 
			
		||||
# @param p_create - If the user should be created when authenticated.
 | 
			
		||||
# @param p_vars - Extra information that will be bundled in the session token.
 | 
			
		||||
# Returns a task which resolves to a session object.
 | 
			
		||||
func authenticate_google_async(p_token : String, p_username = null, p_create : bool = true, p_vars = null) -> NakamaSession:
 | 
			
		||||
	return _parse_auth(yield(_api_client.authenticate_google_async(server_key, "",
 | 
			
		||||
		NakamaAPI.ApiAccountGoogle.create(NakamaAPI, {
 | 
			
		||||
			"token": p_token,
 | 
			
		||||
			"vars": p_vars
 | 
			
		||||
		}), p_create, p_username), "completed"))
 | 
			
		||||
 | 
			
		||||
# Authenticate a user with a Steam auth token.
 | 
			
		||||
# @param p_token - An authentication token from the Steam network.
 | 
			
		||||
# @param p_username - A username used to create the user. May be `null`.
 | 
			
		||||
# @param p_create - If the user should be created when authenticated.
 | 
			
		||||
# @param p_vars - Extra information that will be bundled in the session token.
 | 
			
		||||
# Returns a task which resolves to a session object.
 | 
			
		||||
func authenticate_steam_async(p_token : String, p_username = null, p_create : bool = true, p_vars = null) -> NakamaSession:
 | 
			
		||||
	return _parse_auth(yield(_api_client.authenticate_steam_async(server_key, "",
 | 
			
		||||
		NakamaAPI.ApiAccountSteam.create(NakamaAPI, {
 | 
			
		||||
			"token": p_token,
 | 
			
		||||
			"vars": p_vars
 | 
			
		||||
		}), p_create, p_username), "completed"))
 | 
			
		||||
 | 
			
		||||
# Block one or more friends by id or username.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_ids - The ids of the users to block.
 | 
			
		||||
# @param p_usernames - The usernames of the users to block.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func block_friends_async(p_session : NakamaSession, p_ids : PoolStringArray, p_usernames = null) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.block_friends_async(p_session.token, p_ids, p_usernames);
 | 
			
		||||
 | 
			
		||||
# Create a group.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_name - The name for the group.
 | 
			
		||||
# @param p_description - A description for the group.
 | 
			
		||||
# @param p_avatar_url - An avatar url for the group.
 | 
			
		||||
# @param p_lang_tag - A language tag in BCP-47 format for the group.
 | 
			
		||||
# @param p_open - If the group should have open membership.
 | 
			
		||||
# @param p_max_count - The maximum number of members allowed.
 | 
			
		||||
# Returns a task which resolves to a new group object.
 | 
			
		||||
func create_group_async(p_session : NakamaSession, p_name : String, p_description : String = "",
 | 
			
		||||
		p_avatar_url = null, p_lang_tag = null, p_open : bool = true, p_max_count : int = 100): # -> NakamaAPI.ApiGroup:
 | 
			
		||||
	return _api_client.create_group_async(p_session.token,
 | 
			
		||||
		NakamaAPI.ApiCreateGroupRequest.create(NakamaAPI, {
 | 
			
		||||
			"avatar_url": p_avatar_url,
 | 
			
		||||
			"description": p_description,
 | 
			
		||||
			"lang_tag": p_lang_tag,
 | 
			
		||||
			"max_count": p_max_count,
 | 
			
		||||
			"name": p_name,
 | 
			
		||||
			"open": p_open
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Delete one more or users by id or username from friends.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_ids - The user ids to remove as friends.
 | 
			
		||||
# @param p_usernames - The usernames to remove as friends.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func delete_friends_async(p_session : NakamaSession, p_ids : PoolStringArray, p_usernames = null) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.delete_friends_async(p_session.token, p_ids, p_usernames)
 | 
			
		||||
 | 
			
		||||
# Delete a group by id.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_group_id - The group id to to remove.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func delete_group_async(p_session : NakamaSession, p_group_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.delete_group_async(p_session.token, p_group_id)
 | 
			
		||||
 | 
			
		||||
# Delete a leaderboard record.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_leaderboard_id - The id of the leaderboard with the record to be deleted.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func delete_leaderboard_record_async(p_session : NakamaSession, p_leaderboard_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.delete_leaderboard_record_async(p_session.token, p_leaderboard_id)
 | 
			
		||||
 | 
			
		||||
# Delete one or more notifications by id.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_ids - The notification ids to remove.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func delete_notifications_async(p_session : NakamaSession, p_ids : PoolStringArray) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.delete_notifications_async(p_session.token, p_ids)
 | 
			
		||||
 | 
			
		||||
# Delete one or more storage objects.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_ids - The ids of the objects to delete.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func delete_storage_objects_async(p_session : NakamaSession, p_ids : Array) -> NakamaAsyncResult:
 | 
			
		||||
	var ids : Array = []
 | 
			
		||||
	for id in p_ids:
 | 
			
		||||
		if not id is NakamaStorageObjectId:
 | 
			
		||||
			continue # TODO Exceptions
 | 
			
		||||
		var obj_id : NakamaStorageObjectId = id
 | 
			
		||||
		ids.append(obj_id.as_delete().serialize())
 | 
			
		||||
	return _api_client.delete_storage_objects_async(p_session.token,
 | 
			
		||||
		NakamaAPI.ApiDeleteStorageObjectsRequest.create(NakamaAPI, {
 | 
			
		||||
			"object_ids": ids
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Fetch the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# Returns a task which resolves to the account object.
 | 
			
		||||
func get_account_async(p_session : NakamaSession): # -> NakamaAPI.ApiAccount:
 | 
			
		||||
	return _api_client.get_account_async(p_session.token)
 | 
			
		||||
 | 
			
		||||
# Fetch one or more users by id, usernames, and Facebook ids.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_ids - The IDs of the users to retrieve.
 | 
			
		||||
# @param p_usernames - The usernames of the users to retrieve.
 | 
			
		||||
# @param p_facebook_ids - The facebook IDs of the users to retrieve.
 | 
			
		||||
# Returns a task which resolves to a collection of user objects.
 | 
			
		||||
func get_users_async(p_session : NakamaSession, p_ids : PoolStringArray, p_usernames = null, p_facebook_ids = null): # -> NakamaAPI.ApiUsers:
 | 
			
		||||
	return _api_client.get_users_async(p_session.token, p_ids, p_usernames, p_facebook_ids)
 | 
			
		||||
 | 
			
		||||
# Import Facebook friends and add them to the user's account.
 | 
			
		||||
# The server will import friends when the user authenticates with Facebook. This function can be used to be
 | 
			
		||||
# explicit with the import operation.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An OAuth access token from the Facebook SDK.
 | 
			
		||||
# @param p_reset - If the Facebook friend import for the user should be reset.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func import_facebook_friends_async(p_session : NakamaSession, p_token : String, p_reset = null) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.import_facebook_friends_async(p_session.token,
 | 
			
		||||
		NakamaAPI.ApiAccountFacebook.create(NakamaAPI, {
 | 
			
		||||
			"token": p_token
 | 
			
		||||
		}), p_reset)
 | 
			
		||||
 | 
			
		||||
# Join a group if it has open membership or request to join it.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_group_id - The ID of the group to join.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func join_group_async(p_session : NakamaSession, p_group_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.join_group_async(p_session.token, p_group_id)
 | 
			
		||||
 | 
			
		||||
# Join a tournament by ID.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_tournament_id - The ID of the tournament to join.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func join_tournament_async(p_session : NakamaSession, p_tournament_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.join_tournament_async(p_session.token, p_tournament_id)
 | 
			
		||||
 | 
			
		||||
# Kick one or more users from the group.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_group_id - The ID of the group.
 | 
			
		||||
# @param p_ids - The IDs of the users to kick.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func kick_group_users_async(p_session : NakamaSession, p_group_id : String, p_ids : PoolStringArray) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.kick_group_users_async(p_session.token, p_group_id, p_ids)
 | 
			
		||||
 | 
			
		||||
# Leave a group by ID.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_group_id - The ID of the group to leave.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func leave_group_async(p_session : NakamaSession, p_group_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.leave_group_async(p_session.token, p_group_id)
 | 
			
		||||
 | 
			
		||||
# Link a custom ID to the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_id - A custom identifier usually obtained from an external authentication service.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func link_custom_async(p_session : NakamaSession, p_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.link_custom_async(p_session.token, NakamaAPI.ApiAccountCustom.create(NakamaAPI, {
 | 
			
		||||
		"id": p_id
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Link a device ID to the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_id - A device identifier usually obtained from a platform API.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func link_device_async(p_session : NakamaSession, p_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.link_device_async(p_session.token, NakamaAPI.ApiAccountDevice.create(NakamaAPI, {
 | 
			
		||||
		"id": p_id
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Link an email with password to the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_email - The email address of the user.
 | 
			
		||||
# @param p_password - The password for the user.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func link_email_async(p_session : NakamaSession, p_email : String, p_password : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.link_email_async(p_session.token, NakamaAPI.ApiAccountEmail.create(NakamaAPI, {
 | 
			
		||||
		"email": p_email,
 | 
			
		||||
		"password": p_password
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Link a Facebook profile to a user account.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An OAuth access token from the Facebook SDK.
 | 
			
		||||
# @param p_import - If the Facebook friends should be imported.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func link_facebook_async(p_session : NakamaSession, p_token : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.link_facebook_async(p_session.token, NakamaAPI.ApiAccountFacebook.create(NakamaAPI, {
 | 
			
		||||
		"token": p_token
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Add Facebook Instant Game to the social profiles on the current user's account.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An OAuth access token from the Facebook SDK.
 | 
			
		||||
# @param p_import - If the Facebook friends should be imported.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func link_facebook_instant_game_async(p_session : NakamaSession, p_signed_player_info : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.link_facebook_instant_game_async(
 | 
			
		||||
		p_session.token,
 | 
			
		||||
		NakamaAPI.ApiAccountFacebookInstantGame.create(
 | 
			
		||||
			NakamaAPI, {
 | 
			
		||||
				"signed_player_info": p_signed_player_info
 | 
			
		||||
			})
 | 
			
		||||
		)
 | 
			
		||||
 | 
			
		||||
# Link a Game Center profile to a user account.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_bundle_id - The bundle ID of the Game Center application.
 | 
			
		||||
# @param p_player_id - The player ID of the user in Game Center.
 | 
			
		||||
# @param p_public_key_url - The URL for the public encryption key.
 | 
			
		||||
# @param p_salt - A random `NSString` used to compute the hash and keep it randomized.
 | 
			
		||||
# @param p_signature - The verification signature data generated.
 | 
			
		||||
# @param p_timestamp_seconds - The date and time that the signature was created.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func link_game_center_async(p_session : NakamaSession,
 | 
			
		||||
		p_bundle_id : String, p_player_id : String, p_public_key_url : String, p_salt : String, p_signature : String, p_timestamp_seconds) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.link_game_center_async(p_session.token,
 | 
			
		||||
		NakamaAPI.ApiAccountGameCenter.create(NakamaAPI, {
 | 
			
		||||
			"bundle_id": p_bundle_id,
 | 
			
		||||
			"player_id": p_player_id,
 | 
			
		||||
			"public_key_url": p_public_key_url,
 | 
			
		||||
			"salt": p_salt,
 | 
			
		||||
			"signature": p_signature,
 | 
			
		||||
			"timestamp_seconds": p_timestamp_seconds,
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Link a Google profile to a user account.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An OAuth access token from the Google SDK.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func link_google_async(p_session : NakamaSession, p_token : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.link_google_async(p_session.token, NakamaAPI.ApiAccountGoogle.create(NakamaAPI, {
 | 
			
		||||
		"token": p_token
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Link a Steam profile to a user account.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An authentication token from the Steam network.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func link_steam_async(p_session : NakamaSession, p_token : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.link_steam_async(p_session.token, NakamaAPI.ApiAccountSteam.create(NakamaAPI, {
 | 
			
		||||
		"token": p_token
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# List messages from a chat channel.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_channel_id - The id of the chat channel.
 | 
			
		||||
# @param p_limit - The number of chat messages to list.
 | 
			
		||||
# @param forward - Fetch messages forward from the current cursor (or the start).
 | 
			
		||||
# @param p_cursor - A cursor for the current position in the messages history to list.
 | 
			
		||||
# Returns a task which resolves to the channel message list object.
 | 
			
		||||
func list_channel_messages_async(p_session : NakamaSession, p_channel_id : String, limit : int = 1,
 | 
			
		||||
		forward : bool = true, cursor = null): # -> NakamaAPI.ApiChannelMessageList:
 | 
			
		||||
	return _api_client.list_channel_messages_async(p_session.token, p_channel_id, limit, forward, cursor)
 | 
			
		||||
 | 
			
		||||
# List of friends of the current user.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_state - Filter by friendship state.
 | 
			
		||||
# @param p_limit - The number of friends to list.
 | 
			
		||||
# @param p_cursor - A cursor for the current position in the friends list.
 | 
			
		||||
# Returns a task which resolves to the friend objects.
 | 
			
		||||
func list_friends_async(p_session : NakamaSession, p_state = null, p_limit = null, p_cursor = null): # -> NakamaAPI.ApiFriendList:
 | 
			
		||||
	return _api_client.list_friends_async(p_session.token, p_limit, p_state, p_cursor)
 | 
			
		||||
 | 
			
		||||
# List all users part of the group.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_group_id - The ID of the group.
 | 
			
		||||
# @param p_state - Filter by group membership state.
 | 
			
		||||
# @param p_limit - The number of groups to list.
 | 
			
		||||
# @param p_cursor - A cursor for the current position in the group listing.
 | 
			
		||||
# Returns a task which resolves to the group user objects.
 | 
			
		||||
func list_group_users_async(p_session : NakamaSession, p_group_id : String, p_state = null, p_limit = null, p_cursor = null): # -> NakamaAPI.ApiGroupUserList:
 | 
			
		||||
	return _api_client.list_group_users_async(p_session.token, p_group_id, p_limit, p_state, p_cursor)
 | 
			
		||||
 | 
			
		||||
# List groups on the server.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_name - The name filter to apply to the group list.
 | 
			
		||||
# @param p_limit - The number of groups to list.
 | 
			
		||||
# @param p_cursor - A cursor for the current position in the groups to list.
 | 
			
		||||
# Returns a task to resolve group objects.
 | 
			
		||||
func list_groups_async(p_session : NakamaSession, p_name = null, p_limit : int = 10, p_cursor = null): # -> NakamaAPI.ApiGroupList:
 | 
			
		||||
	return _api_client.list_groups_async(p_session.token, p_name, p_cursor, p_limit)
 | 
			
		||||
 | 
			
		||||
# List records from a leaderboard.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_leaderboard_id - The ID of the leaderboard to list.
 | 
			
		||||
# @param p_owner_ids - Record owners to fetch with the list of records.
 | 
			
		||||
# @param p_expiry - Expiry in seconds (since epoch) to begin fetching records from. Optional. 0 means from current time.
 | 
			
		||||
# @param p_limit - The number of records to list.
 | 
			
		||||
# @param p_cursor - A cursor for the current position in the leaderboard records to list.
 | 
			
		||||
# Returns a task which resolves to the leaderboard record objects.
 | 
			
		||||
func list_leaderboard_records_async(p_session : NakamaSession,
 | 
			
		||||
		p_leaderboard_id : String, p_owner_ids = null, p_expiry = null, p_limit : int = 10, p_cursor = null): # -> NakamaAPI.ApiLeaderboardRecordList:
 | 
			
		||||
	return _api_client.list_leaderboard_records_async(p_session.token,
 | 
			
		||||
		p_leaderboard_id, p_owner_ids, p_limit, p_cursor, p_expiry)
 | 
			
		||||
 | 
			
		||||
# List leaderboard records that belong to a user.
 | 
			
		||||
# @param p_session - The session for the user.
 | 
			
		||||
# @param p_leaderboard_id - The ID of the leaderboard to list.
 | 
			
		||||
# @param p_owner_id - The ID of the user to list around.
 | 
			
		||||
# @param p_expiry - Expiry in seconds (since epoch) to begin fetching records from. Optional. 0 means from current time.
 | 
			
		||||
# @param p_limit - The limit of the listings.
 | 
			
		||||
# Returns a task which resolves to the leaderboard record objects.
 | 
			
		||||
func list_leaderboard_records_around_owner_async(p_session : NakamaSession,
 | 
			
		||||
		p_leaderboar_id : String, p_owner_id : String, p_expiry = null, p_limit : int = 10): # -> NakamaAPI.ApiLeaderboardRecordList:
 | 
			
		||||
	return _api_client.list_leaderboard_records_around_owner_async(p_session.token,
 | 
			
		||||
		p_leaderboar_id, p_owner_id, p_limit, p_expiry)
 | 
			
		||||
 | 
			
		||||
# Fetch a list of matches active on the server.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_min - The minimum number of match participants.
 | 
			
		||||
# @param p_max - The maximum number of match participants.
 | 
			
		||||
# @param p_limit - The number of matches to list.
 | 
			
		||||
# @param p_authoritative - If authoritative matches should be included.
 | 
			
		||||
# @param p_label - The label to filter the match list on.
 | 
			
		||||
# @param p_query - A query for the matches to filter.
 | 
			
		||||
# Returns a task which resolves to the match list object.
 | 
			
		||||
func list_matches_async(p_session : NakamaSession, p_min : int, p_max : int, p_limit : int, p_authoritative : bool,
 | 
			
		||||
		p_label : String, p_query : String): # -> NakamaAPI.ApiMatchList:
 | 
			
		||||
	return _api_client.list_matches_async(p_session.token, p_limit, p_authoritative, p_label, p_min, p_max, p_query)
 | 
			
		||||
 | 
			
		||||
# List notifications for the user with an optional cursor.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_limit - The number of notifications to list.
 | 
			
		||||
# @param p_cacheable_cursor - A cursor for the current position in notifications to list.
 | 
			
		||||
# Returns a task to resolve notifications objects.
 | 
			
		||||
func list_notifications_async(p_session : NakamaSession, p_limit : int = 10, p_cacheable_cursor = null): # -> NakamaAPI.ApiNotificationList:
 | 
			
		||||
	return _api_client.list_notifications_async(p_session.token, p_limit, p_cacheable_cursor)
 | 
			
		||||
 | 
			
		||||
# List storage objects in a collection which have public read access.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_collection - The collection to list over.
 | 
			
		||||
# @param p_user_id - The id of the user that owns the objects.
 | 
			
		||||
# @param p_limit - The number of objects to list.
 | 
			
		||||
# @param p_cursor - A cursor to paginate over the collection.
 | 
			
		||||
# Returns a task which resolves to the storage object list.
 | 
			
		||||
func list_storage_objects_async(p_session : NakamaSession, p_collection : String, p_user_id : String = "", p_limit : int = 10, p_cursor = null): # -> NakamaAPI.ApiStorageObjectList:
 | 
			
		||||
# List tournament records around the owner.
 | 
			
		||||
	return _api_client.list_storage_objects_async(p_session.token, p_collection, p_user_id, p_limit, p_cursor)
 | 
			
		||||
 | 
			
		||||
# List tournament records around the owner.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_tournament_id - The ID of the tournament.
 | 
			
		||||
# @param p_owner_id - The ID of the owner to pivot around.
 | 
			
		||||
# @param p_expiry - Expiry in seconds (since epoch) to begin fetching records from.
 | 
			
		||||
# @param p_limit - The number of records to list.
 | 
			
		||||
# Returns a task which resolves to the tournament record list object.
 | 
			
		||||
func list_tournament_records_around_owner_async(p_session : NakamaSession,
 | 
			
		||||
		p_tournament_id : String, p_owner_id : String, p_limit : int = 10, p_expiry = null): # -> NakamaAPI.ApiTournamentRecordList:
 | 
			
		||||
	return _api_client.list_tournament_records_around_owner_async(p_session.token, p_tournament_id, p_owner_id, p_limit, p_expiry)
 | 
			
		||||
 | 
			
		||||
# List records from a tournament.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_tournament_id - The ID of the tournament.
 | 
			
		||||
# @param p_owner_ids - The IDs of the record owners to return in the result.
 | 
			
		||||
# @param p_expiry - Expiry in seconds (since epoch) to begin fetching records from.
 | 
			
		||||
# @param p_limit - The number of records to list.
 | 
			
		||||
# @param p_cursor - An optional cursor for the next page of tournament records.
 | 
			
		||||
# Returns a task which resolves to the list of tournament records.
 | 
			
		||||
func list_tournament_records_async(p_session : NakamaSession, p_tournament_id : String,
 | 
			
		||||
		p_owner_ids = null, p_limit : int = 10, p_cursor = null, p_expiry = null): # -> NakamaAPI.ApiTournamentRecordList:
 | 
			
		||||
	return _api_client.list_tournament_records_async(p_session.token, p_tournament_id, p_owner_ids, p_limit, p_cursor, p_expiry)
 | 
			
		||||
 | 
			
		||||
# List current or upcoming tournaments.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_category_start - The start of the category of tournaments to include.
 | 
			
		||||
# @param p_category_end - The end of the category of tournaments to include.
 | 
			
		||||
# @param p_start_time - The start time of the tournaments. (UNIX timestamp)
 | 
			
		||||
# @param p_end_time - The end time of the tournaments. (UNIX timestamp)
 | 
			
		||||
# @param p_limit - The number of tournaments to list.
 | 
			
		||||
# @param p_cursor - An optional cursor for the next page of tournaments.
 | 
			
		||||
# Returns a task which resolves to the list of tournament objects.
 | 
			
		||||
func list_tournaments_async(p_session : NakamaSession, p_category_start : int, p_category_end : int,
 | 
			
		||||
		p_start_time : int, p_end_time : int, p_limit : int = 10, p_cursor = null): # -> NakamaAPI.ApiTournamentList:
 | 
			
		||||
	return _api_client.list_tournaments_async(p_session.token,
 | 
			
		||||
		p_category_start, p_category_end, p_start_time, p_end_time, p_limit, p_cursor)
 | 
			
		||||
 | 
			
		||||
# List of groups the current user is a member of.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_user_id - The ID of the user whose groups to list.
 | 
			
		||||
# @param p_state - Filter by group membership state.
 | 
			
		||||
# @param p_limit - The number of records to list.
 | 
			
		||||
# @param p_cursor - A cursor for the current position in the listing.
 | 
			
		||||
# Returns a task which resolves to the group list object.
 | 
			
		||||
func list_user_groups_async(p_session : NakamaSession, p_user_id : String, p_state = null, p_limit = null, p_cursor = null): # -> NakamaAPI.ApiUserGroupList:
 | 
			
		||||
	return _api_client.list_user_groups_async(p_session.token, p_user_id, p_limit, p_state, p_cursor)
 | 
			
		||||
 | 
			
		||||
# List storage objects in a collection which belong to a specific user and have public read access.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_collection - The collection to list over.
 | 
			
		||||
# @param p_user_id - The user ID of the user to list objects for.
 | 
			
		||||
# @param p_limit - The number of objects to list.
 | 
			
		||||
# @param p_cursor - A cursor to paginate over the collection.
 | 
			
		||||
# Returns a task which resolves to the storage object list.
 | 
			
		||||
func list_users_storage_objects_async(p_session : NakamaSession,
 | 
			
		||||
		p_collection : String, p_user_id : String, p_limit : int, p_cursor : String): # -> NakamaAPI.ApiStorageObjectList:
 | 
			
		||||
	return _api_client.list_storage_objects2_async(p_session.token, p_collection, p_user_id, p_limit, p_cursor)
 | 
			
		||||
 | 
			
		||||
# Promote one or more users in the group.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_group_id - The ID of the group to promote users into.
 | 
			
		||||
# @param p_ids - The IDs of the users to promote.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func promote_group_users_async(p_session : NakamaSession, p_group_id : String, p_ids : PoolStringArray) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.promote_group_users_async(p_session.token, p_group_id, p_ids)
 | 
			
		||||
 | 
			
		||||
# Read one or more objects from the storage engine.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_ids - The objects to read.
 | 
			
		||||
# Returns a task which resolves to the storage batch object.
 | 
			
		||||
func read_storage_objects_async(p_session : NakamaSession, p_ids : Array): # -> NakamaAPI.ApiStorageObjects:
 | 
			
		||||
	var ids = []
 | 
			
		||||
	for id in p_ids:
 | 
			
		||||
		if not id is NakamaStorageObjectId:
 | 
			
		||||
			continue # TODO Exceptions
 | 
			
		||||
		var obj_id : NakamaStorageObjectId = id
 | 
			
		||||
		ids.append(obj_id.as_read().serialize())
 | 
			
		||||
	return _api_client.read_storage_objects_async(p_session.token,
 | 
			
		||||
		NakamaAPI.ApiReadStorageObjectsRequest.create(NakamaAPI, {
 | 
			
		||||
			"object_ids": ids
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Execute a function with an input payload on the server.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_id - The ID of the function to execute on the server.
 | 
			
		||||
# @param p_payload - The payload to send with the function call.
 | 
			
		||||
# Returns a task which resolves to the RPC response.
 | 
			
		||||
func rpc_async(p_session : NakamaSession, p_id : String, p_payload : String = ""): # -> NakamaAPI.ApiRpc:
 | 
			
		||||
	return _api_client.rpc_func_async(p_session.token, p_id, p_payload)
 | 
			
		||||
 | 
			
		||||
# Execute a function on the server without a session.
 | 
			
		||||
# This function is usually used with server side code. DO NOT USE client side.
 | 
			
		||||
# @param p_http_key - The secure HTTP key used to authenticate.
 | 
			
		||||
# @param p_id - The id of the function to execute on the server.
 | 
			
		||||
# @param p_payload - A payload to send with the function call.
 | 
			
		||||
# Returns a task to resolve an RPC response.
 | 
			
		||||
func rpc_async_with_key(p_http_key : String, p_id : String, p_payload = null): # -> NakamaAPI.ApiRpc:
 | 
			
		||||
	return _api_client.rpc_func2_async("", p_id, p_payload, p_http_key)
 | 
			
		||||
 | 
			
		||||
# Unlink a custom ID from the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_id - A custom identifier usually obtained from an external authentication service.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unlink_custom_async(p_session : NakamaSession, p_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.unlink_custom_async(p_session.token, NakamaAPI.ApiAccountCustom.create(NakamaAPI, {
 | 
			
		||||
		"id": p_id
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Unlink a device ID from the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_id - A device identifier usually obtained from a platform API.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unlink_device_async(p_session : NakamaSession, p_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.unlink_device_async(p_session.token, NakamaAPI.ApiAccountDevice.create(NakamaAPI, {
 | 
			
		||||
		"id": p_id
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Unlink an email with password from the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_email - The email address of the user.
 | 
			
		||||
# @param p_password - The password for the user.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unlink_email_async(p_session : NakamaSession, p_email : String, p_password : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.unlink_email_async(p_session.token, NakamaAPI.ApiAccountEmail.create(NakamaAPI, {
 | 
			
		||||
		"email": p_email,
 | 
			
		||||
		"password": p_password
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Unlink a Facebook profile from the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An OAuth access token from the Facebook SDK.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unlink_facebook_async(p_session : NakamaSession, p_token : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.unlink_facebook_async(p_session.token, NakamaAPI.ApiAccountFacebook.create(NakamaAPI, {
 | 
			
		||||
		"token": p_token
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Unlink a Facebook profile from the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An OAuth access token from the Facebook SDK.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unlink_facebook_instant_game_async(p_session : NakamaSession, p_signed_player_info : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.unlink_facebook_instant_game_async(
 | 
			
		||||
		p_session.token,
 | 
			
		||||
		NakamaAPI.ApiAccountFacebookInstantGame.create(NakamaAPI, {
 | 
			
		||||
			"signed_player_info": p_signed_player_info
 | 
			
		||||
		})
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
# Unlink a Game Center profile from the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_bundle_id - The bundle ID of the Game Center application.
 | 
			
		||||
# @param p_player_id - The player ID of the user in Game Center.
 | 
			
		||||
# @param p_public_key_url - The URL for the public encryption key.
 | 
			
		||||
# @param p_salt - A random `NSString` used to compute the hash and keep it randomized.
 | 
			
		||||
# @param p_signature - The verification signature data generated.
 | 
			
		||||
# @param p_timestamp_seconds - The date and time that the signature was created.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unlink_game_center_async(p_session : NakamaSession,
 | 
			
		||||
		p_bundle_id : String, p_player_id : String, p_public_key_url : String, p_salt : String, p_signature : String, p_timestamp_seconds) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.unlink_game_center_async(p_session.token,
 | 
			
		||||
		NakamaAPI.ApiAccountGameCenter.create(NakamaAPI, {
 | 
			
		||||
			"bundle_id": p_bundle_id,
 | 
			
		||||
			"player_id": p_player_id,
 | 
			
		||||
			"public_key_url": p_public_key_url,
 | 
			
		||||
			"salt": p_salt,
 | 
			
		||||
			"signature": p_signature,
 | 
			
		||||
			"timestamp_seconds": p_timestamp_seconds,
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Unlink a Google profile from the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An OAuth access token from the Google SDK.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unlink_google_async(p_session : NakamaSession, p_token : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.unlink_google_async(p_session.token, NakamaAPI.ApiAccountGoogle.create(NakamaAPI, {
 | 
			
		||||
		"token": p_token
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Unlink a Steam profile from the user account owned by the session.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_token - An authentication token from the Steam network.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unlink_steam_async(p_session : NakamaSession, p_token : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.unlink_steam_async(p_session.token, NakamaAPI.ApiAccountSteam.create(NakamaAPI, {
 | 
			
		||||
		"token": p_token
 | 
			
		||||
	}))
 | 
			
		||||
 | 
			
		||||
# Update the current user's account on the server.
 | 
			
		||||
# @param p_session - The session for the user.
 | 
			
		||||
# @param p_username - The new username for the user.
 | 
			
		||||
# @param p_display_name - A new display name for the user.
 | 
			
		||||
# @param p_avatar_url - A new avatar url for the user.
 | 
			
		||||
# @param p_lang_tag - A new language tag in BCP-47 format for the user.
 | 
			
		||||
# @param p_location - A new location for the user.
 | 
			
		||||
# @param p_timezone - New timezone information for the user.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func update_account_async(p_session : NakamaSession, p_username = null, p_display_name = null,
 | 
			
		||||
		p_avatar_url = null, p_lang_tag = null, p_location = null, p_timezone = null) -> NakamaAsyncResult:
 | 
			
		||||
	return _api_client.update_account_async(p_session.token,
 | 
			
		||||
		NakamaAPI.ApiUpdateAccountRequest.create(NakamaAPI, {
 | 
			
		||||
			"avatar_url": p_avatar_url,
 | 
			
		||||
			"display_name": p_display_name,
 | 
			
		||||
			"lang_tag": p_lang_tag,
 | 
			
		||||
			"location": p_location,
 | 
			
		||||
			"timezone": p_timezone,
 | 
			
		||||
			"username": p_username
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Update a group.
 | 
			
		||||
# The user must have the correct access permissions for the group.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_group_id - The ID of the group to update.
 | 
			
		||||
# @param p_name - A new name for the group.
 | 
			
		||||
# @param p_open - If the group should have open membership.
 | 
			
		||||
# @param p_description - A new description for the group.
 | 
			
		||||
# @param p_avatar_url - A new avatar url for the group.
 | 
			
		||||
# @param p_lang_tag - A new language tag in BCP-47 format for the group.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func update_group_async(p_session : NakamaSession,
 | 
			
		||||
		p_group_id : String, p_name = null, p_description = null, p_avatar_url = null, p_lang_tag = null, p_open = null) -> NakamaAsyncResult:
 | 
			
		||||
	return  _api_client.update_group_async(p_session.token, p_group_id,
 | 
			
		||||
		NakamaAPI.ApiUpdateGroupRequest.create(NakamaAPI, {
 | 
			
		||||
			"name": p_name,
 | 
			
		||||
			"open": p_open,
 | 
			
		||||
			"avatar_url": p_avatar_url,
 | 
			
		||||
			"description": p_description,
 | 
			
		||||
			"lang_tag": p_lang_tag
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Write a record to a leaderboard.
 | 
			
		||||
# @param p_session - The session for the user.
 | 
			
		||||
# @param p_leaderboard_id - The ID of the leaderboard to write.
 | 
			
		||||
# @param p_score - The score for the leaderboard record.
 | 
			
		||||
# @param p_subscore - The subscore for the leaderboard record.
 | 
			
		||||
# @param p_metadata - The metadata for the leaderboard record.
 | 
			
		||||
# Returns a task which resolves to the leaderboard record object written.
 | 
			
		||||
func write_leaderboard_record_async(p_session : NakamaSession,
 | 
			
		||||
		p_leaderboard_id : String, p_score : int, p_subscore : int = 0, p_metadata = null): # -> NakamaAPI.ApiLeaderboardRecord:
 | 
			
		||||
	return _api_client.write_leaderboard_record_async(p_session.token, p_leaderboard_id,
 | 
			
		||||
		NakamaAPI.WriteLeaderboardRecordRequestLeaderboardRecordWrite.create(NakamaAPI, {
 | 
			
		||||
			"metadata": p_metadata,
 | 
			
		||||
			"score": str(p_score),
 | 
			
		||||
			"subscore": str(p_subscore)
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Write objects to the storage engine.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_objects - The objects to write.
 | 
			
		||||
# Returns a task which resolves to the storage write acknowledgements.
 | 
			
		||||
func write_storage_objects_async(p_session : NakamaSession, p_objects : Array): # -> NakamaAPI.ApiStorageObjectAcks:
 | 
			
		||||
	var writes : Array = []
 | 
			
		||||
	for obj in p_objects:
 | 
			
		||||
		if not obj is NakamaWriteStorageObject:
 | 
			
		||||
			continue # TODO Exceptions
 | 
			
		||||
		var write_obj : NakamaWriteStorageObject = obj
 | 
			
		||||
		writes.append(write_obj.as_write().serialize())
 | 
			
		||||
	return _api_client.write_storage_objects_async(p_session.token,
 | 
			
		||||
		NakamaAPI.ApiWriteStorageObjectsRequest.create(NakamaAPI, {
 | 
			
		||||
			"objects": writes
 | 
			
		||||
		}))
 | 
			
		||||
 | 
			
		||||
# Write a record to a tournament.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_tournament_id - The ID of the tournament to write.
 | 
			
		||||
# @param p_score - The score of the tournament record.
 | 
			
		||||
# @param p_subscore - The subscore for the tournament record.
 | 
			
		||||
# @param p_metadata - The metadata for the tournament record.
 | 
			
		||||
# Returns a task which resolves to the tournament record object written.
 | 
			
		||||
func write_tournament_record_async(p_session : NakamaSession,
 | 
			
		||||
		p_tournament_id : String, p_score : int, p_subscore : int = 0, p_metadata = null): # -> NakamaAPI.ApiLeaderboardRecord:
 | 
			
		||||
	return _api_client.write_tournament_record_async(p_session.token, p_tournament_id,
 | 
			
		||||
		NakamaAPI.WriteTournamentRecordRequestTournamentRecordWrite.create(NakamaAPI, {
 | 
			
		||||
			"metadata": p_metadata,
 | 
			
		||||
			"score": str(p_score),
 | 
			
		||||
			"subscore": str(p_subscore)
 | 
			
		||||
		}))
 | 
			
		||||
							
								
								
									
										116
									
								
								client/addons/com.heroiclabs.nakama/client/NakamaHTTPAdapter.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										116
									
								
								client/addons/com.heroiclabs.nakama/client/NakamaHTTPAdapter.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,116 @@
 | 
			
		||||
tool
 | 
			
		||||
extends Node
 | 
			
		||||
 | 
			
		||||
# An adapter which implements the HTTP protocol.
 | 
			
		||||
class_name NakamaHTTPAdapter
 | 
			
		||||
 | 
			
		||||
# The logger to use with the adapter.
 | 
			
		||||
var logger : Reference = NakamaLogger.new()
 | 
			
		||||
 | 
			
		||||
var _pending = {}
 | 
			
		||||
var id : int = 0
 | 
			
		||||
 | 
			
		||||
# Send a HTTP request.
 | 
			
		||||
# @param method - HTTP method to use for this request.
 | 
			
		||||
# @param uri - The fully qualified URI to use.
 | 
			
		||||
# @param headers - Request headers to set.
 | 
			
		||||
# @param body - Request content body to set.
 | 
			
		||||
# @param timeoutSec - Request timeout.
 | 
			
		||||
# Returns a task which resolves to the contents of the response.
 | 
			
		||||
func send_async(p_method : String, p_uri : String, p_headers : Dictionary, p_body : PoolByteArray, p_timeout : int = 3):
 | 
			
		||||
	var req = HTTPRequest.new()
 | 
			
		||||
	if OS.get_name() != 'HTML5':
 | 
			
		||||
		req.use_threads = true # Threads not available nor needed on the web.
 | 
			
		||||
 | 
			
		||||
	# Parse method
 | 
			
		||||
	var method = HTTPClient.METHOD_GET
 | 
			
		||||
	if p_method == "POST":
 | 
			
		||||
		method = HTTPClient.METHOD_POST
 | 
			
		||||
	elif p_method == "PUT":
 | 
			
		||||
		method = HTTPClient.METHOD_PUT
 | 
			
		||||
	elif p_method == "DELETE":
 | 
			
		||||
		method = HTTPClient.METHOD_DELETE
 | 
			
		||||
	elif p_method == "HEAD":
 | 
			
		||||
		method = HTTPClient.METHOD_HEAD
 | 
			
		||||
	var headers = PoolStringArray()
 | 
			
		||||
 | 
			
		||||
	# Parse headers
 | 
			
		||||
	headers.append("Accept: application/json")
 | 
			
		||||
	for k in p_headers:
 | 
			
		||||
		headers.append("%s: %s" % [k, p_headers[k]])
 | 
			
		||||
 | 
			
		||||
	# Handle timeout for 3.1 compatibility
 | 
			
		||||
	id += 1
 | 
			
		||||
	_pending[id] = [req, OS.get_ticks_msec() + (p_timeout * 1000)]
 | 
			
		||||
 | 
			
		||||
	logger.debug("Sending request [ID: %d, Method: %s, Uri: %s, Headers: %s, Body: %s, Timeout: %d]" % [
 | 
			
		||||
		id, p_method, p_uri, p_headers, p_body.get_string_from_utf8(), p_timeout
 | 
			
		||||
	])
 | 
			
		||||
 | 
			
		||||
	add_child(req)
 | 
			
		||||
	return _send_async(req, p_uri, headers, method, p_body, id, _pending, logger)
 | 
			
		||||
 | 
			
		||||
func _process(delta):
 | 
			
		||||
	# Handle timeout for 3.1 compatibility
 | 
			
		||||
	var ids = _pending.keys()
 | 
			
		||||
	for id in ids:
 | 
			
		||||
		var p = _pending[id]
 | 
			
		||||
		if p[0].is_queued_for_deletion():
 | 
			
		||||
			_pending.erase(id)
 | 
			
		||||
			continue
 | 
			
		||||
		if p[1] < OS.get_ticks_msec():
 | 
			
		||||
			logger.debug("Request %d timed out" % id)
 | 
			
		||||
			p[0].cancel_request()
 | 
			
		||||
			_pending.erase(id)
 | 
			
		||||
			p[0].emit_signal("request_completed", HTTPRequest.RESULT_REQUEST_FAILED, 0, PoolStringArray(), PoolByteArray())
 | 
			
		||||
 | 
			
		||||
static func _send_async(request : HTTPRequest, p_uri : String, p_headers : PoolStringArray,
 | 
			
		||||
		p_method : int, p_body : PoolByteArray, p_id : int, p_pending : Dictionary, logger : NakamaLogger):
 | 
			
		||||
 | 
			
		||||
	var err = request.request(p_uri, p_headers, true, p_method, p_body.get_string_from_utf8())
 | 
			
		||||
	if err != OK:
 | 
			
		||||
		yield(request.get_tree(), "idle_frame")
 | 
			
		||||
		logger.debug("Request %d failed to start, error: %d" % [p_id, err])
 | 
			
		||||
		request.queue_free()
 | 
			
		||||
		return NakamaException.new("Request failed")
 | 
			
		||||
 | 
			
		||||
	var args = yield(request, "request_completed")
 | 
			
		||||
	var result = args[0]
 | 
			
		||||
	var response_code = args[1]
 | 
			
		||||
	var _headers = args[2]
 | 
			
		||||
	var body = args[3]
 | 
			
		||||
 | 
			
		||||
	# Will be deleted next frame
 | 
			
		||||
	if not request.is_queued_for_deletion():
 | 
			
		||||
		request.queue_free()
 | 
			
		||||
		p_pending.erase(p_id)
 | 
			
		||||
 | 
			
		||||
	if result != HTTPRequest.RESULT_SUCCESS:
 | 
			
		||||
		logger.debug("Request %d failed with result: %d, response code: %d" % [
 | 
			
		||||
			p_id, result, response_code
 | 
			
		||||
		])
 | 
			
		||||
		return NakamaException.new("HTTPRequest failed!", result)
 | 
			
		||||
 | 
			
		||||
	var json : JSONParseResult = JSON.parse(body.get_string_from_utf8())
 | 
			
		||||
	if json.error != OK:
 | 
			
		||||
		logger.debug("Unable to parse request %d response. JSON error: %d, response code: %d" % [
 | 
			
		||||
			p_id, json.error, response_code
 | 
			
		||||
		])
 | 
			
		||||
		return NakamaException.new("Failed to decode JSON response", response_code)
 | 
			
		||||
 | 
			
		||||
	if response_code != HTTPClient.RESPONSE_OK:
 | 
			
		||||
		var error = ""
 | 
			
		||||
		var code = -1
 | 
			
		||||
		if typeof(json.result) == TYPE_DICTIONARY:
 | 
			
		||||
			error = json.result["error"] if "error" in json.result else str(json.result)
 | 
			
		||||
			code = json.result["code"] if "code" in json.result else -1
 | 
			
		||||
		else:
 | 
			
		||||
			error = str(json.result)
 | 
			
		||||
		if typeof(error) == TYPE_DICTIONARY:
 | 
			
		||||
			error = JSON.print(error)
 | 
			
		||||
		logger.debug("Request %d returned response code: %d, RPC code: %d, error: %s" % [
 | 
			
		||||
			p_id, response_code, code, error
 | 
			
		||||
		])
 | 
			
		||||
		return NakamaException.new(error, response_code, code)
 | 
			
		||||
 | 
			
		||||
	return json.result
 | 
			
		||||
							
								
								
									
										433
									
								
								client/addons/com.heroiclabs.nakama/socket/NakamaSocket.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										433
									
								
								client/addons/com.heroiclabs.nakama/socket/NakamaSocket.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,433 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
 | 
			
		||||
# A socket to interact with Nakama server.
 | 
			
		||||
class_name NakamaSocket
 | 
			
		||||
 | 
			
		||||
const ChannelType = NakamaRTMessage.ChannelJoin.ChannelType
 | 
			
		||||
 | 
			
		||||
# Emitted when a socket is closed.
 | 
			
		||||
signal closed()
 | 
			
		||||
 | 
			
		||||
# Emitted when a socket is connected.
 | 
			
		||||
signal connected()
 | 
			
		||||
 | 
			
		||||
# Emitted when a chat channel message is received
 | 
			
		||||
signal received_channel_message(p_channel_message) # ApiChannelMessage
 | 
			
		||||
 | 
			
		||||
# Emitted when receiving a presence change for joins and leaves with users in a chat channel.
 | 
			
		||||
signal received_channel_presence(p_channel_presence) # ChannelPresenceEvent
 | 
			
		||||
 | 
			
		||||
# Emitted when an error occurs on the socket.
 | 
			
		||||
signal received_error(p_error)
 | 
			
		||||
 | 
			
		||||
# Emitted when receiving a matchmaker matched message.
 | 
			
		||||
signal received_matchmaker_matched(p_matchmaker_matched) # MatchmakerMatched
 | 
			
		||||
 | 
			
		||||
# Emitted when receiving a message from a multiplayer match.
 | 
			
		||||
signal received_match_state(p_match_state) # MatchData
 | 
			
		||||
 | 
			
		||||
# Emitted when receiving a presence change for joins and leaves of users in a multiplayer match.
 | 
			
		||||
signal received_match_presence(p_match_presence_event) # MatchPresenceEvent
 | 
			
		||||
 | 
			
		||||
# Emitted when receiving a notification for the current user.
 | 
			
		||||
signal received_notification(p_api_notification) # ApiNotification
 | 
			
		||||
 | 
			
		||||
# Emitted when receiving a presence change for when a user updated their online status.
 | 
			
		||||
signal received_status_presence(p_status_presence_event) # StatusPresenceEvent
 | 
			
		||||
 | 
			
		||||
# Emitted when receiving a presence change for joins and leaves on a realtime stream.
 | 
			
		||||
signal received_stream_presence(p_stream_presence_event) # StreamPresenceEvent
 | 
			
		||||
 | 
			
		||||
# Emitted when receiving a message from a realtime stream.
 | 
			
		||||
signal received_stream_state(p_stream_state) # StreamState
 | 
			
		||||
 | 
			
		||||
var _adapter : NakamaSocketAdapter
 | 
			
		||||
var _free_adapter : bool = false
 | 
			
		||||
var _weak_ref : WeakRef
 | 
			
		||||
var _base_uri : String
 | 
			
		||||
var _responses : Dictionary
 | 
			
		||||
var _last_id : int = 1
 | 
			
		||||
var _conn : GDScriptFunctionState = null
 | 
			
		||||
var logger : NakamaLogger = null
 | 
			
		||||
 | 
			
		||||
func _resume_conn(p_err : int):
 | 
			
		||||
	if _conn:
 | 
			
		||||
		if p_err: # Exception
 | 
			
		||||
			logger.warning("Connection error: %d" % p_err)
 | 
			
		||||
			_conn.resume(NakamaAsyncResult.new(NakamaException.new()))
 | 
			
		||||
		else:
 | 
			
		||||
			logger.info("Connected!")
 | 
			
		||||
			_conn.resume(NakamaAsyncResult.new())
 | 
			
		||||
		call_deferred("_survive", _conn)
 | 
			
		||||
		_conn = null
 | 
			
		||||
 | 
			
		||||
func _init(p_adapter : NakamaSocketAdapter,
 | 
			
		||||
		p_host : String,
 | 
			
		||||
		p_port : int,
 | 
			
		||||
		p_scheme : String,
 | 
			
		||||
		p_free_adapter : bool = false):
 | 
			
		||||
	logger = p_adapter.logger
 | 
			
		||||
	_adapter = p_adapter
 | 
			
		||||
	_weak_ref = weakref(_adapter)
 | 
			
		||||
	var port = ""
 | 
			
		||||
	if (p_scheme == "ws" and p_port != 80) or (p_scheme == "wss" and p_port != 443):
 | 
			
		||||
		port = ":%d" % p_port
 | 
			
		||||
	_base_uri = "%s://%s%s" % [p_scheme, p_host, port]
 | 
			
		||||
	_free_adapter = p_free_adapter
 | 
			
		||||
	_adapter.connect("closed", self, "_closed")
 | 
			
		||||
	_adapter.connect("connected", self, "_connected")
 | 
			
		||||
	_adapter.connect("received_error", self, "_error")
 | 
			
		||||
	_adapter.connect("received", self, "_received")
 | 
			
		||||
 | 
			
		||||
func _notification(what):
 | 
			
		||||
	if what == NOTIFICATION_PREDELETE:
 | 
			
		||||
		# Is this a bug? Why can't I call a function? self is null...
 | 
			
		||||
#		_clear_responses()
 | 
			
		||||
#		_resume_conn(ERR_FILE_EOF)
 | 
			
		||||
		var keys = _responses.keys()
 | 
			
		||||
		for k in keys:
 | 
			
		||||
			_responses[k].resume(NakamaException.new("Cancelled!"))
 | 
			
		||||
		if _conn != null:
 | 
			
		||||
			_conn.resume(ERR_FILE_EOF)
 | 
			
		||||
			call_deferred("_survive", _conn)
 | 
			
		||||
		_conn = null
 | 
			
		||||
		if _weak_ref.get_ref() == null:
 | 
			
		||||
			return
 | 
			
		||||
		_adapter.close()
 | 
			
		||||
		if _free_adapter:
 | 
			
		||||
			_adapter.queue_free()
 | 
			
		||||
 | 
			
		||||
func _closed(p_error = null):
 | 
			
		||||
	emit_signal("closed")
 | 
			
		||||
	_resume_conn(ERR_CANT_CONNECT)
 | 
			
		||||
	_clear_responses()
 | 
			
		||||
 | 
			
		||||
func _error(p_error):
 | 
			
		||||
	emit_signal("received_error", p_error)
 | 
			
		||||
	_resume_conn(p_error)
 | 
			
		||||
	_clear_responses()
 | 
			
		||||
 | 
			
		||||
func _connected():
 | 
			
		||||
	emit_signal("connected")
 | 
			
		||||
	_resume_conn(OK)
 | 
			
		||||
 | 
			
		||||
func _received(p_bytes : PoolByteArray):
 | 
			
		||||
	var json_str = p_bytes.get_string_from_utf8()
 | 
			
		||||
	var json := JSON.parse(json_str)
 | 
			
		||||
	if json.error != OK or typeof(json.result) != TYPE_DICTIONARY:
 | 
			
		||||
		logger.error("Unable to parse response: %s" % json_str)
 | 
			
		||||
		return
 | 
			
		||||
	var dict : Dictionary = json.result
 | 
			
		||||
	var cid = dict.get("cid")
 | 
			
		||||
	if cid:
 | 
			
		||||
		if _responses.has(cid):
 | 
			
		||||
			_resume_response(cid, dict)
 | 
			
		||||
		else:
 | 
			
		||||
			logger.error("Invalid call id received %s" % dict)
 | 
			
		||||
	else:
 | 
			
		||||
		if dict.has("channel_message"):
 | 
			
		||||
			var res = NakamaAPI.ApiChannelMessage.create(NakamaAPI, dict["channel_message"])
 | 
			
		||||
			emit_signal("received_channel_message", res)
 | 
			
		||||
		elif dict.has("channel_presence_event"):
 | 
			
		||||
			var res = NakamaRTAPI.ChannelPresenceEvent.create(NakamaRTAPI, dict["channel_presence_event"])
 | 
			
		||||
			emit_signal("received_channel_presence", res)
 | 
			
		||||
		elif dict.has("match_data"):
 | 
			
		||||
			var res = NakamaRTAPI.MatchData.create(NakamaRTAPI, dict["match_data"])
 | 
			
		||||
			emit_signal("received_match_state", res)
 | 
			
		||||
		elif dict.has("match_presence_event"):
 | 
			
		||||
			var res = NakamaRTAPI.MatchPresenceEvent.create(NakamaRTAPI, dict["match_presence_event"])
 | 
			
		||||
			emit_signal("received_match_presence", res)
 | 
			
		||||
		elif dict.has("matchmaker_matched"):
 | 
			
		||||
			var res = NakamaRTAPI.MatchmakerMatched.create(NakamaRTAPI, dict["matchmaker_matched"])
 | 
			
		||||
			emit_signal("received_matchmaker_matched", res)
 | 
			
		||||
		elif dict.has("notifications"):
 | 
			
		||||
			var res = NakamaAPI.ApiNotificationList.create(NakamaAPI, dict["notifications"])
 | 
			
		||||
			for n in res.notifications:
 | 
			
		||||
				emit_signal("received_notification", n)
 | 
			
		||||
		elif dict.has("status_presence_event"):
 | 
			
		||||
			var res = NakamaRTAPI.StatusPresenceEvent.create(NakamaRTAPI, dict["status_presence_event"])
 | 
			
		||||
			emit_signal("received_status_presence", res)
 | 
			
		||||
		elif dict.has("stream_presence_event"):
 | 
			
		||||
			var res = NakamaRTAPI.StreamPresenceEvent.create(NakamaRTAPI, dict["stream_presence_event"])
 | 
			
		||||
			emit_signal("received_stream_presence", res)
 | 
			
		||||
		elif dict.has("stream_data"):
 | 
			
		||||
			var res = NakamaRTAPI.StreamData.create(NakamaRTAPI, dict["stream_data"])
 | 
			
		||||
			emit_signal("received_stream_state", res)
 | 
			
		||||
		else:
 | 
			
		||||
			logger.warning("Unhandled response: %s" % dict)
 | 
			
		||||
 | 
			
		||||
func _resume_response(p_id : String, p_data):
 | 
			
		||||
	if _responses.has(p_id):
 | 
			
		||||
		logger.debug("Resuming response: %s: %s" % [p_id, p_data])
 | 
			
		||||
		_responses[p_id].resume(p_data)
 | 
			
		||||
	else:
 | 
			
		||||
		logger.warning("Trying to resume missing response: %s: %s" % [p_id, p_data])
 | 
			
		||||
 | 
			
		||||
func _cancel_response(p_id : String):
 | 
			
		||||
	logger.debug("Cancelling response: %s" % [p_id])
 | 
			
		||||
	_resume_response(p_id, NakamaException.new("Request cancelled."))
 | 
			
		||||
 | 
			
		||||
func _clear_responses():
 | 
			
		||||
	var ids = _responses.keys()
 | 
			
		||||
	for id in ids:
 | 
			
		||||
		_cancel_response(id)
 | 
			
		||||
 | 
			
		||||
func _survive(p_ref):
 | 
			
		||||
	pass
 | 
			
		||||
 | 
			
		||||
func _parse_result(p_responses : Dictionary, p_id : String, p_type, p_ns : GDScript, p_result_key = null):
 | 
			
		||||
 | 
			
		||||
	# Specifically defined key, or default for objject
 | 
			
		||||
	var result_key = p_result_key
 | 
			
		||||
	if p_type != NakamaAsyncResult and result_key == null:
 | 
			
		||||
		result_key = p_type.get_result_key()
 | 
			
		||||
 | 
			
		||||
	# Here we yield and wait
 | 
			
		||||
	var data = yield() # Manually resumed
 | 
			
		||||
	call_deferred("_survive", p_responses[p_id])
 | 
			
		||||
	p_responses.erase(p_id) # Remove this request from the list of responses
 | 
			
		||||
 | 
			
		||||
	# We got an exception, maybe the task was cancelled?
 | 
			
		||||
	if data is NakamaException:
 | 
			
		||||
		return p_type.new(data as NakamaException)
 | 
			
		||||
	# Error from server
 | 
			
		||||
	if data.has("error"):
 | 
			
		||||
		var err = data["error"]
 | 
			
		||||
		var code = -1
 | 
			
		||||
		var msg = str(err)
 | 
			
		||||
		if typeof(err) == TYPE_DICTIONARY:
 | 
			
		||||
			msg = err.get("message", "")
 | 
			
		||||
			code = err.get("code", -1)
 | 
			
		||||
		logger.warning("Error response from server: %s" % err)
 | 
			
		||||
		return p_type.new(NakamaException.new(msg, code))
 | 
			
		||||
	# Simple ack response
 | 
			
		||||
	elif p_type == NakamaAsyncResult:
 | 
			
		||||
		return NakamaAsyncResult.new()
 | 
			
		||||
	# Missing expected result key
 | 
			
		||||
	elif not data.has(result_key):
 | 
			
		||||
		logger.warning("Missing expected result key: %s" % result_key)
 | 
			
		||||
		return p_type.new(NakamaException.new("Missing expected result key: %s" % result_key))
 | 
			
		||||
	# All good, proceed with parsing
 | 
			
		||||
	else:
 | 
			
		||||
		return p_type.create(p_ns, data.get(result_key))
 | 
			
		||||
 | 
			
		||||
func _send_async(p_message, p_parse_type = NakamaAsyncResult, p_ns = NakamaRTAPI, p_msg_key = null, p_result_key = null):
 | 
			
		||||
	logger.debug("Sending async request: %s" % p_message)
 | 
			
		||||
	# For messages coming from the API which does not have a key defined, so we can override it
 | 
			
		||||
	var msg = p_msg_key
 | 
			
		||||
	# For regular RT messages
 | 
			
		||||
	if msg == null:
 | 
			
		||||
		msg = p_message.get_msg_key()
 | 
			
		||||
	var id = str(_last_id)
 | 
			
		||||
	_last_id += 1
 | 
			
		||||
	_responses[id] = _parse_result(_responses, id, p_parse_type, p_ns, p_result_key)
 | 
			
		||||
	var json := JSON.print({
 | 
			
		||||
		"cid": id,
 | 
			
		||||
		msg: p_message.serialize()
 | 
			
		||||
	})
 | 
			
		||||
	var err = _adapter.send(json.to_utf8())
 | 
			
		||||
	if err != OK:
 | 
			
		||||
		call_deferred("_cancel_response", id)
 | 
			
		||||
	return _responses[id]
 | 
			
		||||
 | 
			
		||||
func _connect_function():
 | 
			
		||||
	return yield() # Manually resumed
 | 
			
		||||
 | 
			
		||||
# If the socket is connected.
 | 
			
		||||
func is_connected_to_host():
 | 
			
		||||
	return _adapter.is_connected_to_host()
 | 
			
		||||
 | 
			
		||||
# If the socket is connecting.
 | 
			
		||||
func is_connecting_to_host():
 | 
			
		||||
	return _adapter.is_connecting_to_host()
 | 
			
		||||
 | 
			
		||||
# Close the socket connection to the server.
 | 
			
		||||
func close():
 | 
			
		||||
	_adapter.close()
 | 
			
		||||
 | 
			
		||||
# Connect to the server.
 | 
			
		||||
# @param p_session - The session of the user.
 | 
			
		||||
# @param p_appear_online - If the user who appear online to other users.
 | 
			
		||||
# @param p_connect_timeout - The time allowed for the socket connection to be established.
 | 
			
		||||
# Returns a task to represent the asynchronous operation.
 | 
			
		||||
func connect_async(p_session : NakamaSession, p_appear_online : bool = false, p_connect_timeout : int = 3):
 | 
			
		||||
	var uri = "%s/ws?lang=en&status=%s&token=%s" % [_base_uri, str(p_appear_online).to_lower(), p_session.token]
 | 
			
		||||
	logger.debug("Connecting to host: %s" % uri)
 | 
			
		||||
	_adapter.connect_to_host(uri, p_connect_timeout)
 | 
			
		||||
	_conn = _connect_function()
 | 
			
		||||
	return _conn
 | 
			
		||||
 | 
			
		||||
# Join the matchmaker pool and search for opponents on the server.
 | 
			
		||||
# @param p_query - The matchmaker query to search for opponents.
 | 
			
		||||
# @param p_min_count - The minimum number of players to compete against in a match.
 | 
			
		||||
# @param p_max_count - The maximum number of players to compete against in a match.
 | 
			
		||||
# @param p_string_properties - A set of key/value properties to provide to searches.
 | 
			
		||||
# @param p_numeric_properties - A set of key/value numeric properties to provide to searches.
 | 
			
		||||
# Returns a task which resolves to a matchmaker ticket object.
 | 
			
		||||
func add_matchmaker_async(p_query : String = "*", p_min_count : int = 2, p_max_count : int = 8,
 | 
			
		||||
		p_string_props : Dictionary = {}, p_numeric_props : Dictionary = {}) -> NakamaRTAPI.MatchmakerTicket:
 | 
			
		||||
	return _send_async(
 | 
			
		||||
		NakamaRTMessage.MatchmakerAdd.new(p_query, p_min_count, p_max_count, p_string_props, p_numeric_props),
 | 
			
		||||
		NakamaRTAPI.MatchmakerTicket
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
## <summary>
 | 
			
		||||
## Create a multiplayer match on the server.
 | 
			
		||||
## </summary>
 | 
			
		||||
## Returns a task to represent the asynchronous operation.
 | 
			
		||||
func create_match_async():
 | 
			
		||||
	return _send_async(NakamaRTMessage.MatchCreate.new(), NakamaRTAPI.Match)
 | 
			
		||||
 | 
			
		||||
# Subscribe to one or more users for their status updates.
 | 
			
		||||
# @param p_user_ids - The IDs of users.
 | 
			
		||||
# @param p_usernames - The usernames of the users.
 | 
			
		||||
# Returns a task which resolves to the current statuses for the users.
 | 
			
		||||
func follow_users_async(p_ids : PoolStringArray, p_usernames : PoolStringArray = []) -> NakamaRTAPI.Status:
 | 
			
		||||
	return _send_async(NakamaRTMessage.StatusFollow.new(p_ids, p_usernames), NakamaRTAPI.Status)
 | 
			
		||||
 | 
			
		||||
# Join a chat channel on the server.
 | 
			
		||||
# @param p_target - The target channel to join.
 | 
			
		||||
# @param p_type - The type of channel to join.
 | 
			
		||||
# @param p_persistence - If chat messages should be stored.
 | 
			
		||||
# @param p_hidden - If the current user should be hidden on the channel.
 | 
			
		||||
# Returns a task which resolves to a chat channel object.
 | 
			
		||||
func join_chat_async(p_target : String, p_type : int, p_persistence : bool = false, p_hidden : bool = false) -> NakamaRTAPI.Channel:
 | 
			
		||||
	return _send_async(
 | 
			
		||||
		NakamaRTMessage.ChannelJoin.new(p_target, p_type, p_persistence, p_hidden),
 | 
			
		||||
		NakamaRTAPI.Channel
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
# Join a multiplayer match with the matchmaker matched object.
 | 
			
		||||
# @param p_matched - A matchmaker matched object.
 | 
			
		||||
# Returns a task which resolves to a multiplayer match.
 | 
			
		||||
func join_matched_async(p_matched):
 | 
			
		||||
	var msg := NakamaRTMessage.MatchJoin.new()
 | 
			
		||||
	if p_matched.match_id:
 | 
			
		||||
		msg.match_id = p_matched.match_id
 | 
			
		||||
	else:
 | 
			
		||||
		msg.token = p_matched.token
 | 
			
		||||
	return _send_async(msg, NakamaRTAPI.Match)
 | 
			
		||||
 | 
			
		||||
# Join a multiplayer match by ID.
 | 
			
		||||
# @param p_match_id - The ID of the match to attempt to join.
 | 
			
		||||
# @param p_metadata - An optional set of key-value metadata pairs to be passed to the match handler.
 | 
			
		||||
# Returns a task which resolves to a multiplayer match.
 | 
			
		||||
func join_match_async(p_match_id : String, p_metadata = null):
 | 
			
		||||
	var msg := NakamaRTMessage.MatchJoin.new()
 | 
			
		||||
	msg.match_id = p_match_id
 | 
			
		||||
	return _send_async(msg, NakamaRTAPI.Match)
 | 
			
		||||
 | 
			
		||||
# Leave a chat channel on the server.
 | 
			
		||||
## @param p_channel_id - The ID of the chat channel to leave.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func leave_chat_async(p_channel_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _send_async(NakamaRTMessage.ChannelLeave.new(p_channel_id))
 | 
			
		||||
 | 
			
		||||
# Leave a multiplayer match on the server.
 | 
			
		||||
# @param p_match_id - The multiplayer match to leave.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func leave_match_async(p_match_id : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _send_async(NakamaRTMessage.MatchLeave.new(p_match_id))
 | 
			
		||||
 | 
			
		||||
# Remove a chat message from a chat channel on the server.
 | 
			
		||||
# @param p_channel - The chat channel with the message to remove.
 | 
			
		||||
# @param p_message_id - The ID of the chat message to remove.
 | 
			
		||||
# Returns a task which resolves to an acknowledgement of the removed message.
 | 
			
		||||
func remove_chat_message_async(p_channel_id : String, p_message_id : String):
 | 
			
		||||
	return _send_async(
 | 
			
		||||
		NakamaRTMessage.ChannelMessageRemove.new(p_channel_id, p_message_id),
 | 
			
		||||
		NakamaRTAPI.ChannelMessageAck
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
# Leave the matchmaker pool with the ticket.
 | 
			
		||||
# @param p_ticket - The ticket returned by the matchmaker on join.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func remove_matchmaker_async(p_ticket : String) -> NakamaAsyncResult:
 | 
			
		||||
	return _send_async(NakamaRTMessage.MatchmakerRemove.new(p_ticket))
 | 
			
		||||
 | 
			
		||||
# Execute an RPC function to the server.
 | 
			
		||||
# @param p_func_id - The ID of the function to execute.
 | 
			
		||||
# @param p_payload - An (optional) String payload to send to the server.
 | 
			
		||||
# Returns a task which resolves to the RPC function response object.
 | 
			
		||||
func rpc_async(p_func_id : String, p_payload = null) -> NakamaAPI.ApiRpc:
 | 
			
		||||
	var payload = p_payload
 | 
			
		||||
	match typeof(p_payload):
 | 
			
		||||
		TYPE_NIL, TYPE_STRING:
 | 
			
		||||
			pass
 | 
			
		||||
		_:
 | 
			
		||||
			payload = JSON.print(p_payload)
 | 
			
		||||
	return _send_async(NakamaAPI.ApiRpc.create(NakamaAPI, {
 | 
			
		||||
		"id": p_func_id,
 | 
			
		||||
		"payload": payload
 | 
			
		||||
	}), NakamaAPI.ApiRpc, NakamaAPI, "rpc", "rpc")
 | 
			
		||||
 | 
			
		||||
# Send input to a multiplayer match on the server.
 | 
			
		||||
# When no presences are supplied the new match state will be sent to all presences.
 | 
			
		||||
# @param p_match_id - The ID of the match.
 | 
			
		||||
# @param p_op_code - An operation code for the input.
 | 
			
		||||
# @param p_data - The input data to send.
 | 
			
		||||
# @param p_presences - The presences in the match who should receive the input.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func send_match_state_async(p_match_id, p_op_code : int, p_data : String, p_presences = null):
 | 
			
		||||
	var req = _send_async(NakamaRTMessage.MatchDataSend.new(
 | 
			
		||||
		p_match_id,
 | 
			
		||||
		p_op_code,
 | 
			
		||||
		Marshalls.utf8_to_base64(p_data),
 | 
			
		||||
		p_presences
 | 
			
		||||
	))
 | 
			
		||||
	# This do not return a response from server, you don't really need to wait for it.
 | 
			
		||||
	req.call_deferred("resume", {})
 | 
			
		||||
	call_deferred("_survive", req)
 | 
			
		||||
	return req
 | 
			
		||||
 | 
			
		||||
# Send input to a multiplayer match on the server.
 | 
			
		||||
# When no presences are supplied the new match state will be sent to all presences.
 | 
			
		||||
# @param p_match_id - The ID of the match.
 | 
			
		||||
# @param p_op_code - An operation code for the input.
 | 
			
		||||
# @param p_data - The input data to send.
 | 
			
		||||
# @param p_presences - The presences in the match who should receive the input.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func send_match_state_raw_async(p_match_id, p_op_code : int, p_data : PoolByteArray, p_presences = null):
 | 
			
		||||
	var req = _send_async(NakamaRTMessage.MatchDataSend.new(
 | 
			
		||||
		p_match_id,
 | 
			
		||||
		p_op_code,
 | 
			
		||||
		Marshalls.raw_to_base64(p_data),
 | 
			
		||||
		p_presences
 | 
			
		||||
	))
 | 
			
		||||
	# This do not return a response from server, you don't really need to wait for it.
 | 
			
		||||
	req.call_deferred("resume", {})
 | 
			
		||||
	call_deferred("_survive", req)
 | 
			
		||||
	return req
 | 
			
		||||
 | 
			
		||||
# Unfollow one or more users from their status updates.
 | 
			
		||||
# @param p_user_ids - An array of user ids to unfollow.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func unfollow_users_async(p_ids : PoolStringArray):
 | 
			
		||||
	return _send_async(NakamaRTMessage.StatusUnfollow.new(p_ids))
 | 
			
		||||
 | 
			
		||||
# Update a chat message on a chat channel in the server.
 | 
			
		||||
# @param p_channel_id - The ID of the chat channel with the message to update.
 | 
			
		||||
# @param p_message_id - The ID of the message to update.
 | 
			
		||||
# @param p_content - The new contents of the chat message.
 | 
			
		||||
# Returns a task which resolves to an acknowledgement of the updated message.
 | 
			
		||||
func update_chat_message_async(p_channel_id : String, p_message_id : String, p_content : Dictionary):
 | 
			
		||||
	return _send_async(
 | 
			
		||||
		NakamaRTMessage.ChannelMessageUpdate.new(p_channel_id, p_message_id, JSON.print(p_content)),
 | 
			
		||||
		NakamaRTAPI.ChannelMessageAck
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
# Update the status for the current user online.
 | 
			
		||||
# @param p_status - The new status for the user.
 | 
			
		||||
# Returns a task which represents the asynchronous operation.
 | 
			
		||||
func update_status_async(p_status : String):
 | 
			
		||||
	return _send_async(NakamaRTMessage.StatusUpdate.new(p_status))
 | 
			
		||||
 | 
			
		||||
# Send a chat message to a chat channel on the server.
 | 
			
		||||
# @param p_channel_id - The ID of the chat channel to send onto.
 | 
			
		||||
# @param p_content - The contents of the message to send.
 | 
			
		||||
# Returns a task which resolves to the acknowledgement of the chat message write.
 | 
			
		||||
func write_chat_message_async(p_channel_id : String, p_content : Dictionary):
 | 
			
		||||
	return _send_async(
 | 
			
		||||
		NakamaRTMessage.ChannelMessageSend.new(p_channel_id, JSON.print(p_content)),
 | 
			
		||||
		NakamaRTAPI.ChannelMessageAck
 | 
			
		||||
	)
 | 
			
		||||
@ -0,0 +1,82 @@
 | 
			
		||||
tool
 | 
			
		||||
extends Node
 | 
			
		||||
 | 
			
		||||
# An adapter which implements a socket with a protocol supported by Nakama.
 | 
			
		||||
class_name NakamaSocketAdapter
 | 
			
		||||
 | 
			
		||||
var _ws := WebSocketClient.new()
 | 
			
		||||
var _timeout : int = 30
 | 
			
		||||
var _start : int = 0
 | 
			
		||||
var logger = NakamaLogger.new()
 | 
			
		||||
 | 
			
		||||
# A signal emitted when the socket is connected.
 | 
			
		||||
signal connected()
 | 
			
		||||
 | 
			
		||||
# A signal emitted when the socket is disconnected.
 | 
			
		||||
signal closed()
 | 
			
		||||
 | 
			
		||||
# A signal emitted when the socket has an error when connected.
 | 
			
		||||
signal received_error(p_exception)
 | 
			
		||||
 | 
			
		||||
# A signal emitted when the socket receives a message.
 | 
			
		||||
signal received(p_bytes) # PoolByteArray
 | 
			
		||||
 | 
			
		||||
# If the socket is connected.
 | 
			
		||||
func is_connected_to_host():
 | 
			
		||||
	return _ws.get_connection_status() == WebSocketClient.CONNECTION_CONNECTED
 | 
			
		||||
 | 
			
		||||
# If the socket is connecting.
 | 
			
		||||
func is_connecting_to_host():
 | 
			
		||||
	return _ws.get_connection_status() == WebSocketClient.CONNECTION_CONNECTING
 | 
			
		||||
 | 
			
		||||
# Close the socket with an asynchronous operation.
 | 
			
		||||
func close():
 | 
			
		||||
	_ws.disconnect_from_host()
 | 
			
		||||
 | 
			
		||||
# Connect to the server with an asynchronous operation.
 | 
			
		||||
# @param p_uri - The URI of the server.
 | 
			
		||||
# @param p_timeout - The timeout for the connect attempt on the socket.
 | 
			
		||||
func connect_to_host(p_uri : String, p_timeout : int):
 | 
			
		||||
	_ws.disconnect_from_host()
 | 
			
		||||
	_timeout = p_timeout
 | 
			
		||||
	_start = OS.get_unix_time()
 | 
			
		||||
	var err = _ws.connect_to_url(p_uri)
 | 
			
		||||
	if err != OK:
 | 
			
		||||
		logger.debug("Error connecting to host %s" % p_uri)
 | 
			
		||||
		call_deferred("emit_signal", "received_error", err)
 | 
			
		||||
 | 
			
		||||
# Send data to the server with an asynchronous operation.
 | 
			
		||||
# @param p_buffer - The buffer with the message to send.
 | 
			
		||||
# @param p_reliable - If the message should be sent reliably (will be ignored by some protocols).
 | 
			
		||||
func send(p_buffer : PoolByteArray, p_reliable : bool = true) -> int:
 | 
			
		||||
	return _ws.get_peer(1).put_packet(p_buffer)
 | 
			
		||||
 | 
			
		||||
func _process(delta):
 | 
			
		||||
	if _ws.get_connection_status() == WebSocketClient.CONNECTION_CONNECTING:
 | 
			
		||||
		if _start + _timeout < OS.get_unix_time():
 | 
			
		||||
			logger.debug("Timeout when connecting to socket")
 | 
			
		||||
			emit_signal("received_error", ERR_TIMEOUT)
 | 
			
		||||
			_ws.disconnect_from_host()
 | 
			
		||||
		else:
 | 
			
		||||
			_ws.poll()
 | 
			
		||||
	if _ws.get_connection_status() != WebSocketClient.CONNECTION_DISCONNECTED:
 | 
			
		||||
		_ws.poll()
 | 
			
		||||
 | 
			
		||||
func _init():
 | 
			
		||||
	_ws.connect("data_received", self, "_received")
 | 
			
		||||
	_ws.connect("connection_established", self, "_connected")
 | 
			
		||||
	_ws.connect("connection_error", self, "_error")
 | 
			
		||||
	_ws.connect("connection_closed", self, "_closed")
 | 
			
		||||
 | 
			
		||||
func _received():
 | 
			
		||||
	emit_signal("received", _ws.get_peer(1).get_packet())
 | 
			
		||||
 | 
			
		||||
func _connected(p_protocol : String):
 | 
			
		||||
	_ws.get_peer(1).set_write_mode(WebSocketPeer.WRITE_MODE_TEXT)
 | 
			
		||||
	emit_signal("connected")
 | 
			
		||||
 | 
			
		||||
func _error():
 | 
			
		||||
	emit_signal("received_error", FAILED)
 | 
			
		||||
 | 
			
		||||
func _closed(p_clean : bool):
 | 
			
		||||
	emit_signal("closed")
 | 
			
		||||
@ -0,0 +1,29 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
class_name NakamaAsyncResult
 | 
			
		||||
 | 
			
		||||
var exception : NakamaException setget _no_set, get_exception
 | 
			
		||||
var _ex = null
 | 
			
		||||
 | 
			
		||||
func _no_set(v):
 | 
			
		||||
	return
 | 
			
		||||
 | 
			
		||||
func _init(p_ex = null):
 | 
			
		||||
	_ex = p_ex
 | 
			
		||||
 | 
			
		||||
func is_exception():
 | 
			
		||||
	return get_exception() != null
 | 
			
		||||
 | 
			
		||||
func get_exception() -> NakamaException:
 | 
			
		||||
	return _ex as NakamaException
 | 
			
		||||
 | 
			
		||||
func _to_string():
 | 
			
		||||
	if is_exception():
 | 
			
		||||
		return get_exception()._to_string()
 | 
			
		||||
	return "NakamaAsyncResult<>"
 | 
			
		||||
 | 
			
		||||
static func _safe_ret(p_obj, p_type : GDScript):
 | 
			
		||||
	if p_obj is p_type:
 | 
			
		||||
		return p_obj # Correct type
 | 
			
		||||
	elif p_obj is NakamaException:
 | 
			
		||||
		return p_type.new(p_obj) # It's an exception. Incapsulate it
 | 
			
		||||
	return p_type.new(NakamaException.new()) # It's something else. generate an exception
 | 
			
		||||
							
								
								
									
										20
									
								
								client/addons/com.heroiclabs.nakama/utils/NakamaException.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								client/addons/com.heroiclabs.nakama/utils/NakamaException.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,20 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
 | 
			
		||||
# An exception generated during a request.
 | 
			
		||||
# Usually contains at least an error message.
 | 
			
		||||
class_name NakamaException
 | 
			
		||||
 | 
			
		||||
var status_code : int = -1 setget _no_set
 | 
			
		||||
var grpc_status_code : int = -1 setget _no_set
 | 
			
		||||
var message : String = "" setget _no_set
 | 
			
		||||
 | 
			
		||||
func _no_set(_p):
 | 
			
		||||
	pass
 | 
			
		||||
 | 
			
		||||
func _init(p_message : String = "", p_status_code : int = -1, p_grpc_status_code : int = -1):
 | 
			
		||||
	status_code = p_status_code
 | 
			
		||||
	grpc_status_code = p_grpc_status_code
 | 
			
		||||
	message = p_message
 | 
			
		||||
 | 
			
		||||
func _to_string() -> String:
 | 
			
		||||
	return "NakamaException(StatusCode={%s}, Message='{%s}', GrpcStatusCode={%s})" % [status_code, message, grpc_status_code]
 | 
			
		||||
							
								
								
									
										38
									
								
								client/addons/com.heroiclabs.nakama/utils/NakamaLogger.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								client/addons/com.heroiclabs.nakama/utils/NakamaLogger.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
class_name NakamaLogger
 | 
			
		||||
 | 
			
		||||
enum LOG_LEVEL {NONE, ERROR, WARNING, INFO, VERBOSE, DEBUG}
 | 
			
		||||
 | 
			
		||||
var _level = LOG_LEVEL.ERROR
 | 
			
		||||
var _module = "Nakama"
 | 
			
		||||
 | 
			
		||||
func _init(p_module : String = "Nakama", p_level : int = LOG_LEVEL.ERROR):
 | 
			
		||||
	_level = p_level
 | 
			
		||||
	_module = p_module
 | 
			
		||||
 | 
			
		||||
func _log(level : int, msg):
 | 
			
		||||
	if level <= _level:
 | 
			
		||||
		if level == LOG_LEVEL.ERROR:
 | 
			
		||||
			printerr("=== %s : ERROR === %s" % [_module, str(msg)])
 | 
			
		||||
		else:
 | 
			
		||||
			var what = "=== UNKNOWN === "
 | 
			
		||||
			for k in LOG_LEVEL:
 | 
			
		||||
				if level == LOG_LEVEL[k]:
 | 
			
		||||
					what = "=== %s : %s === " % [_module, k]
 | 
			
		||||
					break
 | 
			
		||||
			print(what + str(msg))
 | 
			
		||||
 | 
			
		||||
func error(msg):
 | 
			
		||||
	_log(LOG_LEVEL.ERROR, msg)
 | 
			
		||||
 | 
			
		||||
func warning(msg):
 | 
			
		||||
	_log(LOG_LEVEL.WARNING, msg)
 | 
			
		||||
 | 
			
		||||
func info(msg):
 | 
			
		||||
	_log(LOG_LEVEL.INFO, msg)
 | 
			
		||||
 | 
			
		||||
func verbose(msg):
 | 
			
		||||
	_log(LOG_LEVEL.VERBOSE, msg)
 | 
			
		||||
 | 
			
		||||
func debug(msg):
 | 
			
		||||
	_log(LOG_LEVEL.DEBUG, msg)
 | 
			
		||||
							
								
								
									
										145
									
								
								client/addons/com.heroiclabs.nakama/utils/NakamaSerializer.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								client/addons/com.heroiclabs.nakama/utils/NakamaSerializer.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,145 @@
 | 
			
		||||
extends Reference
 | 
			
		||||
class_name NakamaSerializer
 | 
			
		||||
 | 
			
		||||
static func serialize(p_obj : Object) -> Dictionary:
 | 
			
		||||
	var out = {}
 | 
			
		||||
	var schema = p_obj.get("_SCHEMA")
 | 
			
		||||
	if schema == null:
 | 
			
		||||
		return {} # No schema defined
 | 
			
		||||
	for k in schema:
 | 
			
		||||
		var prop = schema[k]
 | 
			
		||||
		var val = p_obj.get(prop["name"])
 | 
			
		||||
		if val == null:
 | 
			
		||||
			continue
 | 
			
		||||
		var type = prop["type"]
 | 
			
		||||
		var content = prop.get("content", TYPE_NIL)
 | 
			
		||||
		if typeof(content) == TYPE_STRING:
 | 
			
		||||
			content = TYPE_OBJECT
 | 
			
		||||
		var val_type = typeof(val)
 | 
			
		||||
		match val_type:
 | 
			
		||||
			TYPE_OBJECT: # Simple objects
 | 
			
		||||
				out[k] = serialize(val)
 | 
			
		||||
			TYPE_ARRAY: # Array of objects
 | 
			
		||||
				var arr = []
 | 
			
		||||
				for e in val:
 | 
			
		||||
					if typeof(e) != TYPE_OBJECT:
 | 
			
		||||
						continue
 | 
			
		||||
					arr.append(serialize(e))
 | 
			
		||||
				out[k] = arr
 | 
			
		||||
			TYPE_INT_ARRAY, TYPE_STRING_ARRAY: # Array of ints, bools, or strings
 | 
			
		||||
				var arr = []
 | 
			
		||||
				for e in val:
 | 
			
		||||
					if content == TYPE_BOOL:
 | 
			
		||||
						e = bool(e)
 | 
			
		||||
					if typeof(e) != content:
 | 
			
		||||
						continue
 | 
			
		||||
					arr.append(e)
 | 
			
		||||
				out[k] = arr
 | 
			
		||||
			TYPE_DICTIONARY: # Maps
 | 
			
		||||
				var dict = {}
 | 
			
		||||
				if content == TYPE_OBJECT: # Map of objects
 | 
			
		||||
					for l in val:
 | 
			
		||||
						if val_type != TYPE_OBJECT:
 | 
			
		||||
							continue
 | 
			
		||||
						dict[l] = serialize(val)
 | 
			
		||||
				else: # Map of simple types
 | 
			
		||||
					for l in val:
 | 
			
		||||
						if val_type != content:
 | 
			
		||||
							continue
 | 
			
		||||
						dict[l] = val
 | 
			
		||||
			_:
 | 
			
		||||
				out[k] = val
 | 
			
		||||
	return out
 | 
			
		||||
 | 
			
		||||
static func deserialize(p_ns : GDScript, p_cls_name : String, p_dict : Dictionary) -> Object:
 | 
			
		||||
	var cls : GDScript = p_ns.get(p_cls_name)
 | 
			
		||||
	var schema = cls.get("_SCHEMA")
 | 
			
		||||
	if schema == null:
 | 
			
		||||
		return NakamaException.new() # No schema defined
 | 
			
		||||
	var obj = cls.new()
 | 
			
		||||
	for k in schema:
 | 
			
		||||
		var prop = schema[k]
 | 
			
		||||
		var pname = prop["name"]
 | 
			
		||||
		var type = prop["type"]
 | 
			
		||||
		var required = prop["required"]
 | 
			
		||||
		var content = prop.get("content", TYPE_NIL)
 | 
			
		||||
		var type_cmp = type
 | 
			
		||||
		if typeof(type) == TYPE_STRING: # A class
 | 
			
		||||
			type_cmp = TYPE_DICTIONARY
 | 
			
		||||
		if type_cmp == TYPE_STRING_ARRAY or type_cmp == TYPE_INT_ARRAY: # A specialized array
 | 
			
		||||
			type_cmp = TYPE_ARRAY
 | 
			
		||||
 | 
			
		||||
		var content_cmp = content
 | 
			
		||||
		if typeof(content) == TYPE_STRING: # A dictionary or array of classes
 | 
			
		||||
			content_cmp = TYPE_DICTIONARY
 | 
			
		||||
 | 
			
		||||
		var val = p_dict.get(k, null)
 | 
			
		||||
 | 
			
		||||
		# Ints might and up being recognized as floats. Change that if needed
 | 
			
		||||
		if typeof(val) == TYPE_REAL and type_cmp == TYPE_INT:
 | 
			
		||||
			val = int(val)
 | 
			
		||||
 | 
			
		||||
		if typeof(val) == type_cmp:
 | 
			
		||||
			if typeof(type) == TYPE_STRING:
 | 
			
		||||
				obj.set(pname, deserialize(p_ns, type, val))
 | 
			
		||||
			elif type_cmp == TYPE_DICTIONARY:
 | 
			
		||||
				var v = {}
 | 
			
		||||
				for l in val:
 | 
			
		||||
					if typeof(content) == TYPE_STRING:
 | 
			
		||||
						v[l] = deserialize(p_ns, content, val[l])
 | 
			
		||||
					elif content == TYPE_INT:
 | 
			
		||||
						v[l] = int(val[l])
 | 
			
		||||
					elif content == TYPE_BOOL:
 | 
			
		||||
						v[l] = bool(val[l])
 | 
			
		||||
					else:
 | 
			
		||||
						v[l] = str(val[l])
 | 
			
		||||
				obj.set(pname, v)
 | 
			
		||||
			elif type_cmp == TYPE_ARRAY:
 | 
			
		||||
				var v
 | 
			
		||||
				match content:
 | 
			
		||||
					TYPE_INT, TYPE_BOOL: v = PoolIntArray()
 | 
			
		||||
					TYPE_STRING: v = PoolStringArray()
 | 
			
		||||
					_: v = Array()
 | 
			
		||||
				for e in val:
 | 
			
		||||
					if typeof(content) == TYPE_STRING:
 | 
			
		||||
						v.append(deserialize(p_ns, content, e))
 | 
			
		||||
					elif content == TYPE_INT:
 | 
			
		||||
						v.append(int(e))
 | 
			
		||||
					elif content == TYPE_BOOL:
 | 
			
		||||
						v.append(bool(e))
 | 
			
		||||
					else:
 | 
			
		||||
						v.append(str(e))
 | 
			
		||||
				obj.set(pname, v)
 | 
			
		||||
			else:
 | 
			
		||||
				obj.set(pname, val)
 | 
			
		||||
		elif required:
 | 
			
		||||
			obj._ex = NakamaException.new("ERROR [%s]: Missing or invalid required prop %s = %s:\n\t%s" % [p_cls_name, prop, p_dict.get(k), p_dict])
 | 
			
		||||
			return obj
 | 
			
		||||
	return obj
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
###
 | 
			
		||||
# Compatibility with Godot 3.1 which does not expose String.http_escape
 | 
			
		||||
###
 | 
			
		||||
const HEX = ["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"]
 | 
			
		||||
 | 
			
		||||
static func escape_http(p_str : String) -> String:
 | 
			
		||||
	var out : String = ""
 | 
			
		||||
	for o in p_str:
 | 
			
		||||
		if (o == '.' or o == '-' or o == '_' or o == '~' or
 | 
			
		||||
			(o >= 'a' and o <= 'z') or
 | 
			
		||||
			(o >= 'A' and o <= 'Z') or
 | 
			
		||||
			(o >= '0' and o <= '9')):
 | 
			
		||||
			out += o
 | 
			
		||||
		else:
 | 
			
		||||
			for b in o.to_utf8():
 | 
			
		||||
				out += "%%%s" % to_hex(b)
 | 
			
		||||
	return out
 | 
			
		||||
 | 
			
		||||
static func to_hex(p_val : int) -> String:
 | 
			
		||||
	var v := p_val
 | 
			
		||||
	var o := ""
 | 
			
		||||
	while v != 0:
 | 
			
		||||
		o = HEX[v % 16] + o
 | 
			
		||||
		v /= 16
 | 
			
		||||
	return o
 | 
			
		||||
@ -8,17 +8,105 @@
 | 
			
		||||
 | 
			
		||||
config_version=4
 | 
			
		||||
 | 
			
		||||
_global_script_classes=[  ]
 | 
			
		||||
_global_script_classes=[ {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaAPI",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/api/NakamaAPI.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaAsyncResult",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/utils/NakamaAsyncResult.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaClient",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/client/NakamaClient.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaException",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/utils/NakamaException.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Node",
 | 
			
		||||
"class": "NakamaHTTPAdapter",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/client/NakamaHTTPAdapter.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaLogger",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/utils/NakamaLogger.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "NakamaAsyncResult",
 | 
			
		||||
"class": "NakamaRTAPI",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/api/NakamaRTAPI.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaRTMessage",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/api/NakamaRTMessage.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaSerializer",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/utils/NakamaSerializer.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "NakamaAsyncResult",
 | 
			
		||||
"class": "NakamaSession",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/api/NakamaSession.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaSocket",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/socket/NakamaSocket.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Node",
 | 
			
		||||
"class": "NakamaSocketAdapter",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/socket/NakamaSocketAdapter.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaStorageObjectId",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/api/NakamaStorageObjectId.gd"
 | 
			
		||||
}, {
 | 
			
		||||
"base": "Reference",
 | 
			
		||||
"class": "NakamaWriteStorageObject",
 | 
			
		||||
"language": "GDScript",
 | 
			
		||||
"path": "res://addons/com.heroiclabs.nakama/api/NakamaWriteStorageObject.gd"
 | 
			
		||||
} ]
 | 
			
		||||
_global_script_class_icons={
 | 
			
		||||
 | 
			
		||||
"NakamaAPI": "",
 | 
			
		||||
"NakamaAsyncResult": "",
 | 
			
		||||
"NakamaClient": "",
 | 
			
		||||
"NakamaException": "",
 | 
			
		||||
"NakamaHTTPAdapter": "",
 | 
			
		||||
"NakamaLogger": "",
 | 
			
		||||
"NakamaRTAPI": "",
 | 
			
		||||
"NakamaRTMessage": "",
 | 
			
		||||
"NakamaSerializer": "",
 | 
			
		||||
"NakamaSession": "",
 | 
			
		||||
"NakamaSocket": "",
 | 
			
		||||
"NakamaSocketAdapter": "",
 | 
			
		||||
"NakamaStorageObjectId": "",
 | 
			
		||||
"NakamaWriteStorageObject": ""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[application]
 | 
			
		||||
 | 
			
		||||
config/name="Family"
 | 
			
		||||
run/main_scene="res://default.tscn"
 | 
			
		||||
run/main_scene="res://scenes/AuthScene.tscn"
 | 
			
		||||
config/icon="res://icon.png"
 | 
			
		||||
 | 
			
		||||
[autoload]
 | 
			
		||||
 | 
			
		||||
Nakama="*res://addons/com.heroiclabs.nakama/Nakama.gd"
 | 
			
		||||
ServerConnection="*res://scripts/singletons/ServerConnection.gd"
 | 
			
		||||
 | 
			
		||||
[rendering]
 | 
			
		||||
 | 
			
		||||
quality/driver/driver_name="GLES2"
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										22
									
								
								client/scenes/AuthScene.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								client/scenes/AuthScene.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,22 @@
 | 
			
		||||
extends Node
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Declare member variables here. Examples:
 | 
			
		||||
# var a = 2
 | 
			
		||||
# var b = "text"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Called when the node enters the scene tree for the first time.
 | 
			
		||||
func _ready():
 | 
			
		||||
	return
 | 
			
		||||
	var result : int
 | 
			
		||||
	result = yield(ServerConnection.authenticate_async("j@cloudsumu.com", "Learning12!"), "completed")
 | 
			
		||||
	if result == null:
 | 
			
		||||
		print("Logged In")
 | 
			
		||||
	else:
 | 
			
		||||
		print("Auth failed! Error code: %d" % result)
 | 
			
		||||
		result = yield(ServerConnection.signup_async("j@cloudsumu.com", "Learing12!"), "completed")
 | 
			
		||||
		if result == null:
 | 
			
		||||
			print("Registered!")
 | 
			
		||||
		else:
 | 
			
		||||
			print("Signup failed! Error code: %d" % result)
 | 
			
		||||
							
								
								
									
										153
									
								
								client/scenes/AuthScene.tscn
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								client/scenes/AuthScene.tscn
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,153 @@
 | 
			
		||||
[gd_scene load_steps=3 format=2]
 | 
			
		||||
 | 
			
		||||
[ext_resource path="res://scenes/AuthScene.gd" type="Script" id=1]
 | 
			
		||||
[ext_resource path="res://scripts/menus/signup_form.gd" type="Script" id=2]
 | 
			
		||||
 | 
			
		||||
[node name="AuthScene" type="Control"]
 | 
			
		||||
anchor_right = 1.0
 | 
			
		||||
anchor_bottom = 1.0
 | 
			
		||||
script = ExtResource( 1 )
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="SignupDialog" type="WindowDialog" parent="."]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_top = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
anchor_bottom = 0.5
 | 
			
		||||
margin_left = -256.0
 | 
			
		||||
margin_top = -140.0
 | 
			
		||||
margin_right = 256.0
 | 
			
		||||
margin_bottom = 140.0
 | 
			
		||||
window_title = "Registration"
 | 
			
		||||
script = ExtResource( 2 )
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
usernamePath = NodePath("UsernameEdit")
 | 
			
		||||
passwordPath = NodePath("PasswordEdit")
 | 
			
		||||
confirmPasswordPath = NodePath("CPasswordEdit")
 | 
			
		||||
buttonPath = NodePath("SignupButton")
 | 
			
		||||
errorPath = NodePath("ErrorLabel")
 | 
			
		||||
 | 
			
		||||
[node name="MessageLabel" type="Label" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
margin_left = -208.0
 | 
			
		||||
margin_top = 16.0
 | 
			
		||||
margin_right = 208.0
 | 
			
		||||
margin_bottom = 46.0
 | 
			
		||||
text = "Welcome to the family!"
 | 
			
		||||
align = 1
 | 
			
		||||
valign = 1
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="ErrorLabel" type="Label" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
margin_left = -232.0
 | 
			
		||||
margin_top = 48.0
 | 
			
		||||
margin_right = 228.0
 | 
			
		||||
margin_bottom = 62.0
 | 
			
		||||
custom_colors/font_color = Color( 1, 0, 0, 1 )
 | 
			
		||||
text = "[Errors go here]"
 | 
			
		||||
align = 1
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="UsernameLabel" type="Label" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
margin_left = -232.0
 | 
			
		||||
margin_top = 72.0
 | 
			
		||||
margin_right = -193.0
 | 
			
		||||
margin_bottom = 86.0
 | 
			
		||||
text = "Email:"
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="UsernameEdit" type="LineEdit" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
margin_left = -232.0
 | 
			
		||||
margin_top = 88.0
 | 
			
		||||
margin_right = 232.0
 | 
			
		||||
margin_bottom = 112.0
 | 
			
		||||
 | 
			
		||||
[node name="PasswordLabel" type="Label" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
margin_left = -232.0
 | 
			
		||||
margin_top = 128.0
 | 
			
		||||
margin_right = -168.0
 | 
			
		||||
margin_bottom = 142.0
 | 
			
		||||
text = "Password:"
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="PasswordEdit" type="LineEdit" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
margin_left = -232.0
 | 
			
		||||
margin_top = 144.0
 | 
			
		||||
margin_right = 232.0
 | 
			
		||||
margin_bottom = 168.0
 | 
			
		||||
secret = true
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="CPasswordLabel" type="Label" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
margin_left = -232.0
 | 
			
		||||
margin_top = 176.0
 | 
			
		||||
margin_right = -168.0
 | 
			
		||||
margin_bottom = 190.0
 | 
			
		||||
text = "Confirm Password:"
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="CPasswordEdit" type="LineEdit" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
margin_left = -232.0
 | 
			
		||||
margin_top = 192.0
 | 
			
		||||
margin_right = 232.0
 | 
			
		||||
margin_bottom = 216.0
 | 
			
		||||
secret = true
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="SignupButton" type="Button" parent="SignupDialog"]
 | 
			
		||||
anchor_left = 0.5
 | 
			
		||||
anchor_top = 1.0
 | 
			
		||||
anchor_right = 0.5
 | 
			
		||||
anchor_bottom = 1.0
 | 
			
		||||
margin_left = 136.0
 | 
			
		||||
margin_top = -44.0
 | 
			
		||||
margin_right = 228.0
 | 
			
		||||
margin_bottom = -16.0
 | 
			
		||||
disabled = true
 | 
			
		||||
text = "Sign Up!"
 | 
			
		||||
__meta__ = {
 | 
			
		||||
"_edit_use_anchors_": false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[node name="Button" type="Button" parent="."]
 | 
			
		||||
anchor_left = 1.0
 | 
			
		||||
anchor_top = 1.0
 | 
			
		||||
anchor_right = 1.0
 | 
			
		||||
anchor_bottom = 1.0
 | 
			
		||||
margin_left = -109.0
 | 
			
		||||
margin_top = -20.0
 | 
			
		||||
text = "Create Account"
 | 
			
		||||
[connection signal="button_down" from="Button" to="SignupDialog" method="popup_centered"]
 | 
			
		||||
							
								
								
									
										64
									
								
								client/scripts/menus/signup_form.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								client/scripts/menus/signup_form.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,64 @@
 | 
			
		||||
extends Popup
 | 
			
		||||
 | 
			
		||||
export(NodePath) var usernamePath
 | 
			
		||||
export(NodePath) var passwordPath
 | 
			
		||||
export(NodePath) var confirmPasswordPath
 | 
			
		||||
export(NodePath) var buttonPath
 | 
			
		||||
export(NodePath) var errorPath
 | 
			
		||||
 | 
			
		||||
var usernameEdit : LineEdit
 | 
			
		||||
var passwordEdit : LineEdit
 | 
			
		||||
var cPasswordEdit : LineEdit
 | 
			
		||||
var errorLabel : Label
 | 
			
		||||
var button : Button
 | 
			
		||||
 | 
			
		||||
const MIN_PASSWORD_LENGTH = 8
 | 
			
		||||
 | 
			
		||||
func _ready():
 | 
			
		||||
	# Get nodes
 | 
			
		||||
	usernameEdit = get_node(usernamePath)
 | 
			
		||||
	passwordEdit = get_node(passwordPath)
 | 
			
		||||
	cPasswordEdit = get_node(confirmPasswordPath)
 | 
			
		||||
	errorLabel = get_node(errorPath)
 | 
			
		||||
	button = get_node(buttonPath)
 | 
			
		||||
	
 | 
			
		||||
	# Set forms to validate on value chagne
 | 
			
		||||
	usernameEdit.connect("text_changed", self, "validate_fields")
 | 
			
		||||
	passwordEdit.connect("text_changed", self, "validate_fields")
 | 
			
		||||
	cPasswordEdit.connect("text_changed", self, "validate_fields")
 | 
			
		||||
	
 | 
			
		||||
	# Connect submission button
 | 
			
		||||
	button.connect("button_down", self, "signup")
 | 
			
		||||
	
 | 
			
		||||
	# Clear error message
 | 
			
		||||
	errorLabel.text = ""
 | 
			
		||||
 | 
			
		||||
func signup():
 | 
			
		||||
	var error : NakamaException = yield(ServerConnection.signup_async(usernameEdit.text, passwordEdit.text), "completed")
 | 
			
		||||
	
 | 
			
		||||
	# Check for error
 | 
			
		||||
	if error:
 | 
			
		||||
		errorLabel.text = error.message
 | 
			
		||||
	else:
 | 
			
		||||
		print("Signed up successfully!")
 | 
			
		||||
		# Close signup form
 | 
			
		||||
		hide()
 | 
			
		||||
 | 
			
		||||
func validate_fields(_text=""):
 | 
			
		||||
	var valid : bool = check_email(usernameEdit.text) and passwords_valid(passwordEdit.text, cPasswordEdit.text)
 | 
			
		||||
	button.disabled = !valid
 | 
			
		||||
	return valid
 | 
			
		||||
 | 
			
		||||
func passwords_valid(password, cpassword):
 | 
			
		||||
	return password == cpassword and len(password) >= MIN_PASSWORD_LENGTH
 | 
			
		||||
 | 
			
		||||
func check_email(email) -> bool:
 | 
			
		||||
	# Use regex to validate email
 | 
			
		||||
	var regex = RegEx.new()
 | 
			
		||||
	regex.compile("[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,6}")
 | 
			
		||||
 | 
			
		||||
	var result = regex.search(email)
 | 
			
		||||
 | 
			
		||||
	if result:
 | 
			
		||||
		return true
 | 
			
		||||
	return false
 | 
			
		||||
							
								
								
									
										31
									
								
								client/scripts/singletons/ServerConnection.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								client/scripts/singletons/ServerConnection.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,31 @@
 | 
			
		||||
extends Node
 | 
			
		||||
 | 
			
		||||
const KEY := "defaultkey"
 | 
			
		||||
const SERVER_ENDPOINT := "nakama.cloudsumu.com"
 | 
			
		||||
 | 
			
		||||
var _session : NakamaSession
 | 
			
		||||
var _client : NakamaClient = Nakama.create_client(KEY, SERVER_ENDPOINT, 7350, "http")
 | 
			
		||||
 | 
			
		||||
func authenticate_async(email : String, password : String) -> NakamaException:
 | 
			
		||||
	var result : NakamaException = null
 | 
			
		||||
	
 | 
			
		||||
	var new_session : NakamaSession = yield(_client.authenticate_email_async(email, password, null, false), "completed")
 | 
			
		||||
	
 | 
			
		||||
	if not new_session.is_exception():
 | 
			
		||||
		_session = new_session
 | 
			
		||||
	else:
 | 
			
		||||
		result = new_session.get_exception()
 | 
			
		||||
		
 | 
			
		||||
	return result
 | 
			
		||||
	
 | 
			
		||||
func signup_async(email : String, password : String) -> NakamaException:
 | 
			
		||||
	var result : NakamaException = null
 | 
			
		||||
	
 | 
			
		||||
	var new_session : NakamaSession = yield(_client.authenticate_email_async(email, password, null, true), "completed")
 | 
			
		||||
	
 | 
			
		||||
	if not new_session.is_exception():
 | 
			
		||||
		_session = new_session
 | 
			
		||||
	else:
 | 
			
		||||
		result = new_session.get_exception()
 | 
			
		||||
		
 | 
			
		||||
	return result
 | 
			
		||||
@ -1,4 +0,0 @@
 | 
			
		||||
extends "res://addons/gut/test.gd"
 | 
			
		||||
 | 
			
		||||
func test_example():
 | 
			
		||||
    assert_true(true)
 | 
			
		||||
							
								
								
									
										55
									
								
								client/tests/test_signup_form.gd
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								client/tests/test_signup_form.gd
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,55 @@
 | 
			
		||||
extends "res://addons/gut/test.gd"
 | 
			
		||||
 | 
			
		||||
var signup_form = load("res://scripts/menus/signup_form.gd")
 | 
			
		||||
 | 
			
		||||
# Test Object
 | 
			
		||||
var form = signup_form.new()
 | 
			
		||||
 | 
			
		||||
#------------
 | 
			
		||||
# Email Test
 | 
			
		||||
#------------
 | 
			
		||||
var valid_email_list = [
 | 
			
		||||
		"untitled@gmail.com",
 | 
			
		||||
		"test@cloudsumu.com",
 | 
			
		||||
		"cool.game@tetraforce.io",
 | 
			
		||||
		"ExampleName@yahoo.com"
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
var invalid_email_list = [
 | 
			
		||||
	"test the test",
 | 
			
		||||
	"test",
 | 
			
		||||
	"test@test",
 | 
			
		||||
	"gmail.com",
 | 
			
		||||
	"google.com",
 | 
			
		||||
	"@amazon.com",
 | 
			
		||||
	"test@_.com",
 | 
			
		||||
	"test@test.",
 | 
			
		||||
	"Hello World!"
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
func test_check_email_with_valid_email():
 | 
			
		||||
	for email in valid_email_list:
 | 
			
		||||
		assert_true(form.check_email(email))
 | 
			
		||||
 | 
			
		||||
func test_check_email_with_invalid_email():
 | 
			
		||||
	for email in invalid_email_list:
 | 
			
		||||
		assert_false(form.check_email(email))
 | 
			
		||||
 | 
			
		||||
#---------------
 | 
			
		||||
# Password Test
 | 
			
		||||
#---------------
 | 
			
		||||
var valid_passwords = [
 | 
			
		||||
	"Testing123!",
 | 
			
		||||
	"gR8$cuP8kJ8%qk*t",
 | 
			
		||||
	"GVa9%BZHh",
 | 
			
		||||
	"2Uw@2*5Qb$Gflb@c",
 | 
			
		||||
	"iL3DINd@hRaBlevo"
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
func test_passwords_valid_do_match():
 | 
			
		||||
	for password in valid_passwords:
 | 
			
		||||
		assert_true(form.passwords_valid(password, password))
 | 
			
		||||
 | 
			
		||||
func test_passwords_valid_do_not_match():
 | 
			
		||||
	for password in valid_passwords:
 | 
			
		||||
		assert_false(form.passwords_valid(password, null))
 | 
			
		||||
		Reference in New Issue
	
	Block a user