Current section
Files
Jump to
Current section
Files
priv/static/libow.gd
extends Node
class_name OverworldClient
const Ow_pb = preload('ow_pb.gd')
var ws = WebSocketClient.new()
export(Dictionary) var session
var debug = false
###########################################################################
# Constants
###########################################################################
# These are merely aliases for convenience. We should not leak Protobuf
# details to the consumer of the library
# via overworld_pb
enum gen_response_status {
OK = Overworld_pb.gen_response.status.OK,
ERROR = Overworld_pb.gen_response.status.ERROR,
}
# via ow_pb
enum gen_response_status {
OK = Ow_pb.gen_response.status.OK,
ERROR = Ow_pb.gen_response.status.ERROR,
}
###########################################################################
# Signals
###########################################################################
signal connection(status)
signal session_id(id)
signal session_beacon(id)
signal session_pong(latency)
signal session_log(color,msg)
signal gen_response(msg,status)
###########################################################################
# OpCodes
###########################################################################
func bytepack(opcode):
var buf = StreamPeerBuffer.new()
buf.big_endian=true
buf.put_16(opcode)
return buf.data_array
var OpCode = {
VERSION = bytepack(16),
SESSION_ID_REQ = bytepack(21),
SESSION_ID = bytepack(22),
SESSION_BEACON = bytepack(25),
SESSION_PING = bytepack(32),
SESSION_PONG = bytepack(33),
SESSION_LOG = bytepack(80),
ACCOUNT_NEW = bytepack(256),
ACCOUNT_LOGIN = bytepack(272),
}
###########################################################################
# Router
###########################################################################
func route(packet):
var opcode = packet.subarray(0,1)
var hex_opcode = str(opcode.hex_encode())
var payload = []
if packet.size() > 2:
payload = packet.subarray(2,-1)
match opcode:
OpCode.ACCOUNT_LOGIN:
server_account_login(payload)
OpCode.ACCOUNT_NEW:
server_account_new(payload)
OpCode.SESSION_LOG:
server_session_log(payload)
OpCode.SESSION_PONG:
server_session_pong(payload)
OpCode.SESSION_PING:
server_session_ping(payload)
OpCode.SESSION_BEACON:
server_session_beacon(payload)
OpCode.SESSION_ID:
server_session_id(payload)
OpCode.SESSION_ID_REQ:
server_session_id_req(payload)
OpCode.VERSION:
server_version(payload)
_:
print("[WARNING] Unknown opcode from the server:" + hex_opcode)
###########################################################################
# Payload unmarshalling (server packets)
###########################################################################
func unpack_gen_response(object):
if typeof(object) == TYPE_ARRAY and object != []:
var array = []
for obj in object:
var msg = obj.get_msg()
var status = obj.get_status()
var dict = {'status': status, 'msg': msg, }
array.append(dict)
return array
elif typeof(object) == TYPE_ARRAY and object == []:
return []
else:
var msg = object.get_msg()
var status = object.get_status()
var dict = {'status': status, 'msg': msg, }
return dict
func unpack_account_new(object):
if typeof(object) == TYPE_ARRAY and object != []:
var array = []
for obj in object:
var password = obj.get_password()
var email = obj.get_email()
var dict = {'email': email, 'password': password, }
array.append(dict)
return array
elif typeof(object) == TYPE_ARRAY and object == []:
return []
else:
var password = object.get_password()
var email = object.get_email()
var dict = {'email': email, 'password': password, }
return dict
func unpack_account_login(object):
if typeof(object) == TYPE_ARRAY and object != []:
var array = []
for obj in object:
var password = obj.get_password()
var email = obj.get_email()
var dict = {'email': email, 'password': password, }
array.append(dict)
return array
elif typeof(object) == TYPE_ARRAY and object == []:
return []
else:
var password = object.get_password()
var email = object.get_email()
var dict = {'email': email, 'password': password, }
return dict
func unpack_session_log(object):
if typeof(object) == TYPE_ARRAY and object != []:
var array = []
for obj in object:
var color = obj.get_color()
var msg = obj.get_msg()
var dict = {'msg': msg, 'color': color, }
array.append(dict)
return array
elif typeof(object) == TYPE_ARRAY and object == []:
return []
else:
var color = object.get_color()
var msg = object.get_msg()
var dict = {'msg': msg, 'color': color, }
return dict
func unpack_session_beacon(object):
if typeof(object) == TYPE_ARRAY and object != []:
var array = []
for obj in object:
var id = obj.get_id()
var dict = {'id': id, }
array.append(dict)
return array
elif typeof(object) == TYPE_ARRAY and object == []:
return []
else:
var id = object.get_id()
var dict = {'id': id, }
return dict
func unpack_session_ping(object):
if typeof(object) == TYPE_ARRAY and object != []:
var array = []
for obj in object:
var id = obj.get_id()
var dict = {'id': id, }
array.append(dict)
return array
elif typeof(object) == TYPE_ARRAY and object == []:
return []
else:
var id = object.get_id()
var dict = {'id': id, }
return dict
func unpack_session_pong(object):
if typeof(object) == TYPE_ARRAY and object != []:
var array = []
for obj in object:
var latency = obj.get_latency()
var dict = {'latency': latency, }
array.append(dict)
return array
elif typeof(object) == TYPE_ARRAY and object == []:
return []
else:
var latency = object.get_latency()
var dict = {'latency': latency, }
return dict
func unpack_session_id(object):
if typeof(object) == TYPE_ARRAY and object != []:
var array = []
for obj in object:
var id = obj.get_id()
var dict = {'id': id, }
array.append(dict)
return array
elif typeof(object) == TYPE_ARRAY and object == []:
return []
else:
var id = object.get_id()
var dict = {'id': id, }
return dict
func server_account_login(packet):
if debug:
print('[DEBUG] Processing a account_login packet')
var m = Ow_pb.gen_response.new()
var result_code = m.from_bytes(packet)
if result_code != Ow_pb.PB_ERR.NO_ERRORS:
print('[CRITICAL] Error decoding new account_login packet')
return
var d = unpack_gen_response(m)
emit_signal('gen_response',d['msg'],d['status'])
func server_account_new(packet):
if debug:
print('[DEBUG] Processing a account_new packet')
var m = Ow_pb.gen_response.new()
var result_code = m.from_bytes(packet)
if result_code != Ow_pb.PB_ERR.NO_ERRORS:
print('[CRITICAL] Error decoding new account_new packet')
return
var d = unpack_gen_response(m)
emit_signal('gen_response',d['msg'],d['status'])
func server_session_log(packet):
if debug:
print('[DEBUG] Processing a session_log packet')
var m = Ow_pb.session_log.new()
var result_code = m.from_bytes(packet)
if result_code != Ow_pb.PB_ERR.NO_ERRORS:
print('[CRITICAL] Error decoding new session_log packet')
return
var d = unpack_session_log(m)
emit_signal('session_log',d['color'],d['msg'])
func server_session_pong(packet):
if debug:
print('[DEBUG] Processing a session_pong packet')
var m = Ow_pb.session_pong.new()
var result_code = m.from_bytes(packet)
if result_code != Ow_pb.PB_ERR.NO_ERRORS:
print('[CRITICAL] Error decoding new session_pong packet')
return
var d = unpack_session_pong(m)
emit_signal('session_pong',d['latency'])
func server_session_ping(_packet):
print('[WARN] Received a session_ping packet')
return
func server_session_beacon(packet):
if debug:
print('[DEBUG] Processing a session_beacon packet')
var m = Ow_pb.session_beacon.new()
var result_code = m.from_bytes(packet)
if result_code != Ow_pb.PB_ERR.NO_ERRORS:
print('[CRITICAL] Error decoding new session_beacon packet')
return
var d = unpack_session_beacon(m)
emit_signal('session_beacon',d['id'])
func server_session_id(packet):
if debug:
print('[DEBUG] Processing a session_id packet')
var m = Ow_pb.session_id.new()
var result_code = m.from_bytes(packet)
if result_code != Ow_pb.PB_ERR.NO_ERRORS:
print('[CRITICAL] Error decoding new session_id packet')
return
var d = unpack_session_id(m)
emit_signal('session_id',d['id'])
func server_session_id_req(_packet):
print('[WARN] Received a session_id_req packet')
return
func server_version(_packet):
print('[WARN] Received a version packet')
return
###########################################################################
# Payload marshalling (client packets)
###########################################################################
func pack_session_id(obj, ref):
ref.set_id(obj.id)
func pack_session_pong(obj, ref):
ref.set_latency(obj.latency)
func pack_session_ping(obj, ref):
ref.set_id(obj.id)
func pack_session_beacon(obj, ref):
ref.set_id(obj.id)
func pack_session_log(obj, ref):
ref.set_color(obj.color)
ref.set_msg(obj.msg)
func pack_account_login(obj, ref):
ref.set_password(obj.password)
ref.set_email(obj.email)
func pack_account_new(obj, ref):
ref.set_password(obj.password)
ref.set_email(obj.email)
func pack_gen_response(obj, ref):
ref.set_msg(obj.msg)
ref.set_status(obj.status)
func version():
send_message([], OpCode.VERSION)
if debug:
print('[INFO] Sent a version packet')
func session_id_req():
send_message([], OpCode.SESSION_ID_REQ)
if debug:
print('[INFO] Sent a session_id_req packet')
func session_ping(id: int):
var m = Ow_pb.session_ping.new()
m.set_id(id)
var payload = m.to_bytes()
send_message(payload, OpCode.SESSION_PING)
if debug:
print('[INFO] Sent a session_ping packet')
func account_new(email: String, password: String):
var m = Ow_pb.account_new.new()
m.set_password(password)
m.set_email(email)
var payload = m.to_bytes()
send_message(payload, OpCode.ACCOUNT_NEW)
if debug:
print('[INFO] Sent a account_new packet')
func account_login(email: String, password: String):
var m = Ow_pb.account_login.new()
m.set_password(password)
m.set_email(email)
var payload = m.to_bytes()
send_message(payload, OpCode.ACCOUNT_LOGIN)
if debug:
print('[INFO] Sent a account_login packet')
############################################################################
# Various other utility and initialization functions
############################################################################
func send_message(payload, opcode):
# Create a new packet starting with opcode, append the message if it exists,
# then send it across the websocket.
var packet = opcode
if payload.empty() == true:
# Message is empty, just send the bare opcode
ws.get_peer(1).put_packet(packet)
else:
packet.append_array(payload)
ws.get_peer(1).put_packet(packet)
############################################################################
# Signal Handlers
############################################################################
func _ready():
ws.connect("data_received", self, "_on_data")
# Take the host and whether or not its a TLS conncetion
func ws_connect(url: String, tls: bool):
ws.set_verify_ssl_enabled(tls)
print("[INFO] Attempting to connect to ", url)
ws.connect_to_url(url+"/ws")
func ws_disconnect():
ws.disconnect_from_host(1000,"Goodbye")
func _process(_delta):
# Poll the socket for new data
if ws.get_connection_status() == ws.CONNECTION_CONNECTING || ws.get_connection_status() == ws.CONNECTION_CONNECTED:
ws.poll()
func _on_data():
var packet = ws.get_peer(1).get_packet()
route(packet)
func _connection_established(_protocol):
print("[INFO] Connection established")
emit_signal("connection", "established")
func _connection_closed(msg):
print("[INFO] Connection closed: ", msg)
emit_signal("connection", "closed")
func _connection_error():
print("[INFO] Connection error")
emit_signal("connection", "error")
print(ws.get_peer(1))