Signup form
This commit is contained in:
@ -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
|
Reference in New Issue
Block a user