wth is happening

This commit is contained in:
Daniel Flanagan 2021-11-17 16:24:00 -06:00
parent 724a351d96
commit 9c5b376852
Signed by: lytedev
GPG key ID: 5B2020A0F9921EF4
6 changed files with 147 additions and 122 deletions

View file

@ -5,7 +5,9 @@ const MultiplayerClient = preload("multiplayer_client.gd")
onready var client = MultiplayerClient.new() onready var client = MultiplayerClient.new()
func _ready(): func _ready():
# client.signaller.connect("websocket_connected", self, "signaller_disconnected")
add_child(client) add_child(client)
client.signaller.connect("websocket_connected", self, "_signaller_connected")
func goto_scene(scene_resource_name): func goto_scene(scene_resource_name):
var _result = get_tree().change_scene("res://%s.tscn" % scene_resource_name) var _result = get_tree().change_scene("res://%s.tscn" % scene_resource_name)
@ -18,9 +20,12 @@ func start_singleplayer_game():
client.close() client.close()
goto_scene("game") goto_scene("game")
func _signaller_connected():
goto_scene("multiplayer")
func lobby_browser(): func lobby_browser():
client.close() client.close()
goto_scene("multiplayer") Global.client.connect_to_signaller()
func lobby(): func lobby():
goto_scene("lobby") goto_scene("lobby")

View file

@ -7,8 +7,12 @@ func _ready():
Global.client.signaller.connect("peer_left", self, "_peer_left") Global.client.signaller.connect("peer_left", self, "_peer_left")
Global.client.signaller.connect("lobby_left", self, "_lobby_left") Global.client.signaller.connect("lobby_left", self, "_lobby_left")
$MarginContainer/Label.text = Global.client.signaller.lobby_id $MarginContainer/Label.text = Global.client.signaller.lobby_id
Global.client.signaller.connect("websocket_disconnected", self, "_signaller_disconnected")
Global.client.signaller.request_peer_list() Global.client.signaller.request_peer_list()
func _signaller_disconnected():
Global.main_menu()
func _draw(): func _draw():
pass pass
@ -19,7 +23,7 @@ func _peer_joined(joined_peers):
for i in range(len(joined_peers)): for i in range(len(joined_peers)):
var id = joined_peers[i]["id"] var id = joined_peers[i]["id"]
var name = joined_peers[i]["name"] var name = joined_peers[i]["name"]
print("New Peer ", id, name) print("New Lobby Peer ", id, name)
peers.add_item("%s" % name) peers.add_item("%s" % name)
peers.set_item_metadata(peers.get_item_count() - 1, { "id": id }) peers.set_item_metadata(peers.get_item_count() - 1, { "id": id })

View file

@ -9,18 +9,18 @@ func _ready():
Global.client.signaller.connect("lobby_delete", self, "_lobby_delete") Global.client.signaller.connect("lobby_delete", self, "_lobby_delete")
Global.client.signaller.connect("lobby_joined", self, "_lobby_joined") Global.client.signaller.connect("lobby_joined", self, "_lobby_joined")
Global.client.signaller.connect("lobby_left", self, "_lobby_left") Global.client.signaller.connect("lobby_left", self, "_lobby_left")
Global.client.signaller.connect("websocket_connected", self, "_signaller_connected") Global.client.signaller.connect("websocket_disconnected", self, "_signaller_disconnected")
Global.client.connect_to_signaller() Global.client.signaller.request_lobby_list()
func _lobby_joined(id): func _signaller_disconnected():
Global.main_menu()
func _lobby_joined(_id, _peerId):
Global.lobby() Global.lobby()
func _lobby_left(_id): func _lobby_left(_id):
Global.lobby_browser() Global.lobby_browser()
func _signaller_connected():
Global.client.signaller.request_lobby_list()
func _on_back_pressed(): func _on_back_pressed():
Global.main_menu() Global.main_menu()

View file

@ -15,16 +15,16 @@ onready var mp = WebRTCMultiplayer.new()
onready var signaller = SignallerClient.new() onready var signaller = SignallerClient.new()
func _ready(): func _ready():
# connect("connected", self, "connected") # signaller.connect("websocket_connected", self, "connected")
# connect("disconnected", self, "disconnected") # signaller.connect("websocket_disconnected", self, "disconnected")
# connect("offer_received", self, "offer_received") signaller.connect("offer_received", self, "offer_received")
# connect("answer_received", self, "answer_received") signaller.connect("answer_received", self, "answer_received")
# connect("candidate_received", self, "candidate_received") signaller.connect("candidate_received", self, "candidate_received")
# connect("lobby_joined", self, "lobby_joined") signaller.connect("lobby_joined", self, "_lobby_joined")
# connect("lobby_sealed", self, "lobby_sealed") # connect("lobby_sealed", self, "lobby_sealed")
# connect("peer_connected", self, "peer_connected") signaller.connect("peer_joined", self, "_peer_joined")
# connect("peer_disconnected", self, "peer_disconnected") # connect("peer_disconnected", self, "peer_disconnected")
add_child(signaller) add_child(signaller)
@ -36,26 +36,30 @@ func connect_to_signaller():
close() close()
signaller.connect_to_websocket_signaller(multiplayer_url) signaller.connect_to_websocket_signaller(multiplayer_url)
func _create_peer(id): func _create_peer(peer_id):
var peer: WebRTCPeerConnection = WebRTCPeerConnection.new() var peer: WebRTCPeerConnection = WebRTCPeerConnection.new()
peer.initialize({"iceServers": webrtc_ice_servers}) print("New Net Peer %s with peer_id %d" % [peer, peer_id])
peer.connect("session_description_created", self, "_offer_created", [id]) var _peer_init_results = peer.initialize({"iceServers": webrtc_ice_servers})
peer.connect("ice_candidate_created", self, "_new_ice_candidate", [id]) peer.connect("session_description_created", self, "_offer_created", [peer_id])
mp.add_peer(peer, id) peer.connect("ice_candidate_created", self, "_new_ice_candidate", [peer_id])
if id > mp.get_unique_id(): mp.add_peer(peer, peer_id)
# TODO: peer.create_offer() var uid = mp.get_unique_id()
pass if peer_id > uid:
var offer_result = peer.create_offer()
print("Create Offer Result: ", offer_result)
else:
print("Did not create offer: %d <= %d" % [peer_id, uid])
return peer return peer
func _new_ice_candidate(mid_name, index_name, sdp_name, id): func _new_ice_candidate(mid_name, index_name, sdp_name, peer_id):
print("New ICE Candidate: ", mid_name, index_name, sdp_name, id) print("New ICE Candidate: ", mid_name, index_name, sdp_name, peer_id)
# TODO: send_candidate(id, mid_name, index_name, sdp_name) signaller.send_candidate(peer_id, mid_name, index_name, sdp_name)
func _offer_created(type, data, id): func _offer_created(type, data, peer_id):
if not mp.has_peer(id): print("Offer Created", type, data, peer_id)
if not mp.has_peer(peer_id):
return return
print("created", type) mp.get_peer(peer_id).connection.set_local_description(type, data)
mp.get_peer(id).connection.set_local_description(type, data)
if type == "offer": if type == "offer":
# TODO: send_offer(id, data) # TODO: send_offer(id, data)
pass pass
@ -63,28 +67,35 @@ func _offer_created(type, data, id):
# TODO: send_answer(id, data) # TODO: send_answer(id, data)
pass pass
func connected(id): func _lobby_joined(id, peer_id):
print("Connected %d" % id) print("Connected to lobby %s as peer %d" % [id, peer_id])
mp.initialize(id, true) mp.initialize(peer_id, true)
func peer_connected(id): func _peer_joined(peers):
print("Peer connected %d" % id) for i in range(len(peers)):
_create_peer(id) var peer_id = peers[i]["peerId"]
if not mp.has_peer(peer_id):
_create_peer(peer_id)
func peer_disconnected(id): func peer_disconnected(id):
print("Peer disconnected ", id)
if mp.has_peer(id): if mp.has_peer(id):
mp.remove_peer(id) mp.remove_peer(id)
func offer_received(id, offer): func offer_received(data):
print("Got offer: %d" % id) print("Got offer: ", data)
var id = data["peerId"]
if mp.has_peer(id): if mp.has_peer(id):
mp.get_peer(id).connection.set_remote_description("offer", offer) mp.get_peer(id).connection.set_remote_description("offer", data["offer"])
func answer_received(id, answer): func answer_received(data):
print("Got answer: %d" % id) print("Got answer: ", data)
var id = data["peerId"]
if mp.has_peer(id): if mp.has_peer(id):
mp.get_peer(id).connection.set_remote_description("answer", answer) mp.get_peer(id).connection.set_remote_description("answer", data["offer"])
func candidate_received(id, mid, index, sdp): func candidate_received(data):
print("Candidate Received: ", data)
var id = data["peerId"]
if mp.has_peer(id): if mp.has_peer(id):
mp.get_peer(id).connection.add_ice_candidate(mid, index, sdp) mp.get_peer(id).connection.add_ice_candidate(data["mid"], data["index"], data["sdp"])

View file

@ -13,7 +13,8 @@ interface DataMessage {
type: string; type: string;
} }
type ServerData = Record<string, string | number | symbol> | string; type ServerDataObject = Record<string, string | number | symbol | null>;
type ServerData = ServerDataObject | string;
type Message = string | DataMessage; type Message = string | DataMessage;
const broadcast = (message: Message) => const broadcast = (message: Message) =>
@ -32,6 +33,7 @@ const buildMessage = (
class Client { class Client {
id: ID; id: ID;
peerId: number | null;
name: string; name: string;
socket: WebSocket; socket: WebSocket;
lobby: Lobby | null; lobby: Lobby | null;
@ -39,11 +41,10 @@ class Client {
constructor(socket: WebSocket) { constructor(socket: WebSocket) {
this.id = crypto.randomUUID(); this.id = crypto.randomUUID();
this.socket = socket; this.socket = socket;
this.peerId = null;
this.name = "Client"; this.name = "Client";
this.lobby = null; this.lobby = null;
this.send(buildMessage("your-id", this.id));
console.log(this); console.log(this);
allClients.set(this.id, this); allClients.set(this.id, this);
} }
@ -78,8 +79,10 @@ class Client {
clientList() { clientList() {
if (!this.lobby) return; if (!this.lobby) return;
const netClients: { id: ID; name: string }[] = []; const netClients: { id: ID; name: string; peerId: number | null }[] = [];
this.lobby.clients.forEach(({ id, name }) => netClients.push({ id, name })); this.lobby.clients.forEach(({ id, name, peerId }) =>
netClients.push({ id, name, peerId })
);
// TODO: chunk async? // TODO: chunk async?
this.send(buildMessage("peer_list", netClients)); this.send(buildMessage("peer_list", netClients));
} }
@ -118,8 +121,10 @@ class Client {
return; return;
} }
this.lobby = lobby; this.lobby = lobby;
this.send(buildMessage("lobby_joined", { id: lobby.id }));
lobby.addClient(this); lobby.addClient(this);
this.send(
buildMessage("lobby_joined", { id: lobby.id, peerId: this.peerId }),
);
} }
lobbyLeave() { lobbyLeave() {
@ -128,6 +133,7 @@ class Client {
this.send(`[info] cannot leave lobby (not in a lobby)`); this.send(`[info] cannot leave lobby (not in a lobby)`);
return; return;
} }
this.peerId = null;
this.lobby = null; this.lobby = null;
if (this.isConnected()) { if (this.isConnected()) {
this.send(buildMessage("lobby_left", { id: leavingLobby.id })); this.send(buildMessage("lobby_left", { id: leavingLobby.id }));
@ -149,6 +155,7 @@ class Lobby {
this.name = name || this.id; this.name = name || this.id;
allLobbies.set(this.id, this); allLobbies.set(this.id, this);
host.peerId = 1;
host.lobbyJoin(this); host.lobbyJoin(this);
allClients.forEach((client) => client.lobbyNew(this)); allClients.forEach((client) => client.lobbyNew(this));
} }
@ -166,10 +173,19 @@ class Lobby {
} }
addClient(client: Client) { addClient(client: Client) {
this.clients.set(client.id, client); if (!client.peerId) {
const arr = new Int32Array(1);
crypto.getRandomValues(arr);
client.peerId = Math.abs(arr[0]);
}
this.broadcast( this.broadcast(
buildMessage("peer_joined", { id: client.id, name: client.name }), buildMessage("peer_joined", {
id: client.id,
name: client.name,
peerId: client.peerId,
}),
); );
this.clients.set(client.id, client);
} }
removeClient({ id }: Client) { removeClient({ id }: Client) {
@ -182,10 +198,16 @@ class Lobby {
} }
} }
interface ClientMessage {
type: "candidate" | "offer" | "answer";
data: ServerDataObject;
}
// events // events
function onMessage(client: Client, ev: MessageEvent) { function onMessage(client: Client, ev: MessageEvent) {
// TODO: log who from? // TODO: log who from?
console.log("Client Message Received", ev.data); console.log("Client Message Received", ev.data);
if (ev.data === "init") client.send(buildMessage("your_id", client.id));
if (ev.data === "lobby_create") client.lobbyCreate(); if (ev.data === "lobby_create") client.lobbyCreate();
if (ev.data === "lobby_leave") client.lobbyLeave(); if (ev.data === "lobby_leave") client.lobbyLeave();
if (ev.data === "request_lobby_list") client.lobbyList(); if (ev.data === "request_lobby_list") client.lobbyList();
@ -196,6 +218,22 @@ function onMessage(client: Client, ev: MessageEvent) {
if (lobby) client.lobbyJoin(lobby); if (lobby) client.lobbyJoin(lobby);
else client.send(`[info] could not find lobby ${id}`); else client.send(`[info] could not find lobby ${id}`);
} }
if (ev.data.startsWith("json:")) {
const data: ClientMessage = JSON.parse(ev.data.substr(5));
if (data.type in ["candidate", "answer", "offer"]) {
if (typeof data.data === "object") {
const subdata = data.data;
if (typeof subdata["peerId"] === "number") {
const peerId: number = subdata["peerId"];
const payload = Object.assign({}, data);
payload.data.peerId = client.peerId;
for (const client of allClients.values()) {
client.send(ev.data);
}
}
}
}
}
} }
function onSocketOpen(_client: Client, _ev: Event) { function onSocketOpen(_client: Client, _ev: Event) {

View file

@ -8,16 +8,21 @@ expected to fully setup the peer connections.
signal lobby_new(lobbiesList) signal lobby_new(lobbiesList)
signal lobby_delete(id) signal lobby_delete(id)
signal lobby_joined(id) signal lobby_joined(id, peer_id)
signal lobby_left(id) signal lobby_left(id)
signal peer_joined(id) signal peer_joined(id)
signal peer_left(id) signal peer_left(id)
signal candidate_received(data)
signal offer_received(data)
signal answer_received(data)
signal websocket_connected signal websocket_connected
signal websocket_disconnected signal websocket_disconnected
onready var ws: WebSocketClient = WebSocketClient.new() onready var ws: WebSocketClient = WebSocketClient.new()
onready var client_id = null
onready var lobby_id = null onready var lobby_id = null
onready var peer_id = null
func _ready(): func _ready():
var _result = ws.connect("data_received", self, "_parse_msg") var _result = ws.connect("data_received", self, "_parse_msg")
@ -45,6 +50,7 @@ func _connected(protocol = ""):
print("WebSocket signaller connected via protocol ", protocol) print("WebSocket signaller connected via protocol ", protocol)
ws.get_peer(1).set_write_mode(WebSocketPeer.WRITE_MODE_TEXT) ws.get_peer(1).set_write_mode(WebSocketPeer.WRITE_MODE_TEXT)
emit_signal("websocket_connected") emit_signal("websocket_connected")
_send("init")
func _process(_delta: float): func _process(_delta: float):
var status: int = ws.get_connection_status() var status: int = ws.get_connection_status()
@ -78,89 +84,50 @@ func _parse_msg():
func handle_message(data: Dictionary): func handle_message(data: Dictionary):
match data["type"]: match data["type"]:
"your_id": client_id = data["data"]
"lobby_new": emit_signal("lobby_new", [{"id": data["id"], "name": data["name"]}]) "lobby_new": emit_signal("lobby_new", [{"id": data["id"], "name": data["name"]}])
"lobby_delete": emit_signal("lobby_delete", data["id"]) "lobby_delete": emit_signal("lobby_delete", data["id"])
"lobby_joined": "lobby_joined":
lobby_id = data["id"] lobby_id = data["id"]
emit_signal("lobby_joined", data["id"]) peer_id = data["peerId"]
emit_signal("lobby_joined", data["id"], data["peerId"])
"lobby_left": "lobby_left":
lobby_id = null lobby_id = null
emit_signal("lobby_left", data["id"]) emit_signal("lobby_left", data["id"])
"lobby_list": emit_signal("lobby_new", data["data"]) "lobby_list": emit_signal("lobby_new", data["data"])
"peer_list": emit_signal("peer_joined", data["data"]) "peer_list": emit_signal("peer_joined", data["data"])
"peer_joined": emit_signal("peer_joined", [{"id": data["id"], "name": data["name"]}]) "peer_joined": emit_signal("peer_joined", [{"id": data["id"], "name": data["name"], "peerId": data["peerId"]}])
"peer_left": emit_signal("peer_left", data["id"]) "peer_left": emit_signal("peer_left", data["id"])
"candidate":
print("Candidate received ", data["data"])
emit_signal("candidate_received", data["data"])
"offer":
print("Offer received ", data["data"])
emit_signal("offer_received", data["data"])
"answer":
print("Answer received ", data["data"])
emit_signal("answer_received", data["data"])
_: print("Unhandled Data Message: ", JSON.print(data)) _: print("Unhandled Data Message: ", JSON.print(data))
func send_candidate(peerId, mid, index, sdp) -> int:
return _send("json:%s" % JSON.print({
"type": "candidate",
"data": {
"peerId": peerId,
"mid": mid,
"index": index,
"sdp": sdp
}
}))
func send_offer(peerId, offer) -> int:
return _send("json:%s" % JSON.print({ "type": "offer", "data": {"peerId": peerId, "offer": offer }}))
func send_answer(peerId, answer) -> int:
return _send("json:%s" % JSON.print({ "type": "answer", "data": {"peerId": peerId, "answer": answer }}))
""" """
func _parse_msg():
var pkt_str: String = ws.get_peer(1).get_packet().get_string_from_utf8()
var req: PoolStringArray = pkt_str.split("\n", true, 1)
if req.size() != 2: # Invalid request size
return
var type: String = req[0]
if type.length() < 3: # Invalid type size
return
if type.begins_with("J: "):
print("Emitting lobby_joined")
emit_signal("lobby_joined", type.substr(3, type.length() - 3))
return
elif type.begins_with("S: "): elif type.begins_with("S: "):
emit_signal("lobby_sealed") emit_signal("lobby_sealed")
return return
var src_str: String = type.substr(3, type.length() - 3)
if not src_str.is_valid_integer(): # Source id is not an integer
return
var src_id: int = int(src_str)
if type.begins_with("I: "):
print("Emitting connected")
emit_signal("connected", src_id)
elif type.begins_with("N: "):
# Client connected
print("Emitting peer_connected")
emit_signal("peer_connected", src_id)
elif type.begins_with("D: "):
# Client connected
emit_signal("peer_disconnected", src_id)
elif type.begins_with("O: "):
# Offer received
print("Emitting offer_received")
emit_signal("offer_received", src_id, req[1])
elif type.begins_with("A: "):
# Answer received
print("Emitting answer_received")
emit_signal("answer_received", src_id, req[1])
elif type.begins_with("C: "):
# Candidate received
var candidate: PoolStringArray = req[1].split("\n", false)
if candidate.size() != 3:
return
if not candidate[1].is_valid_integer():
return
print("Emitting candidate_received")
emit_signal("candidate_received", src_id, candidate[0], int(candidate[1]), candidate[2])
func join_lobby(joined_lobby):
return ws.get_peer(1).put_packet(("J: %s\n" % joined_lobby).to_utf8())
func seal_lobby():
return ws.get_peer(1).put_packet("S: \n".to_utf8())
func send_candidate(id, mid, index, sdp) -> int:
return _send_msg("C", id, "\n%s\n%d\n%s" % [mid, index, sdp])
func send_offer(id, offer) -> int:
return _send_msg("O", id, offer)
func send_answer(id, answer) -> int:
return _send_msg("A", id, answer)
func _send_msg(type, id, data) -> int:
return ws.get_peer(1).put_packet(("%s: %d\n%s" % [type, id, data]).to_utf8())
""" """