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()
func _ready():
# client.signaller.connect("websocket_connected", self, "signaller_disconnected")
add_child(client)
client.signaller.connect("websocket_connected", self, "_signaller_connected")
func goto_scene(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()
goto_scene("game")
func _signaller_connected():
goto_scene("multiplayer")
func lobby_browser():
client.close()
goto_scene("multiplayer")
Global.client.connect_to_signaller()
func 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("lobby_left", self, "_lobby_left")
$MarginContainer/Label.text = Global.client.signaller.lobby_id
Global.client.signaller.connect("websocket_disconnected", self, "_signaller_disconnected")
Global.client.signaller.request_peer_list()
func _signaller_disconnected():
Global.main_menu()
func _draw():
pass
@ -19,7 +23,7 @@ func _peer_joined(joined_peers):
for i in range(len(joined_peers)):
var id = joined_peers[i]["id"]
var name = joined_peers[i]["name"]
print("New Peer ", id, name)
print("New Lobby Peer ", id, name)
peers.add_item("%s" % name)
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_joined", self, "_lobby_joined")
Global.client.signaller.connect("lobby_left", self, "_lobby_left")
Global.client.signaller.connect("websocket_connected", self, "_signaller_connected")
Global.client.connect_to_signaller()
Global.client.signaller.connect("websocket_disconnected", self, "_signaller_disconnected")
Global.client.signaller.request_lobby_list()
func _lobby_joined(id):
func _signaller_disconnected():
Global.main_menu()
func _lobby_joined(_id, _peerId):
Global.lobby()
func _lobby_left(_id):
Global.lobby_browser()
func _signaller_connected():
Global.client.signaller.request_lobby_list()
func _on_back_pressed():
Global.main_menu()

View file

@ -15,16 +15,16 @@ onready var mp = WebRTCMultiplayer.new()
onready var signaller = SignallerClient.new()
func _ready():
# connect("connected", self, "connected")
# connect("disconnected", self, "disconnected")
# signaller.connect("websocket_connected", self, "connected")
# signaller.connect("websocket_disconnected", self, "disconnected")
# connect("offer_received", self, "offer_received")
# connect("answer_received", self, "answer_received")
# connect("candidate_received", self, "candidate_received")
signaller.connect("offer_received", self, "offer_received")
signaller.connect("answer_received", self, "answer_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("peer_connected", self, "peer_connected")
signaller.connect("peer_joined", self, "_peer_joined")
# connect("peer_disconnected", self, "peer_disconnected")
add_child(signaller)
@ -36,26 +36,30 @@ func connect_to_signaller():
close()
signaller.connect_to_websocket_signaller(multiplayer_url)
func _create_peer(id):
func _create_peer(peer_id):
var peer: WebRTCPeerConnection = WebRTCPeerConnection.new()
peer.initialize({"iceServers": webrtc_ice_servers})
peer.connect("session_description_created", self, "_offer_created", [id])
peer.connect("ice_candidate_created", self, "_new_ice_candidate", [id])
mp.add_peer(peer, id)
if id > mp.get_unique_id():
# TODO: peer.create_offer()
pass
print("New Net Peer %s with peer_id %d" % [peer, peer_id])
var _peer_init_results = peer.initialize({"iceServers": webrtc_ice_servers})
peer.connect("session_description_created", self, "_offer_created", [peer_id])
peer.connect("ice_candidate_created", self, "_new_ice_candidate", [peer_id])
mp.add_peer(peer, peer_id)
var uid = mp.get_unique_id()
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
func _new_ice_candidate(mid_name, index_name, sdp_name, id):
print("New ICE Candidate: ", mid_name, index_name, sdp_name, id)
# TODO: send_candidate(id, mid_name, index_name, sdp_name)
func _new_ice_candidate(mid_name, index_name, sdp_name, peer_id):
print("New ICE Candidate: ", mid_name, index_name, sdp_name, peer_id)
signaller.send_candidate(peer_id, mid_name, index_name, sdp_name)
func _offer_created(type, data, id):
if not mp.has_peer(id):
func _offer_created(type, data, peer_id):
print("Offer Created", type, data, peer_id)
if not mp.has_peer(peer_id):
return
print("created", type)
mp.get_peer(id).connection.set_local_description(type, data)
mp.get_peer(peer_id).connection.set_local_description(type, data)
if type == "offer":
# TODO: send_offer(id, data)
pass
@ -63,28 +67,35 @@ func _offer_created(type, data, id):
# TODO: send_answer(id, data)
pass
func connected(id):
print("Connected %d" % id)
mp.initialize(id, true)
func _lobby_joined(id, peer_id):
print("Connected to lobby %s as peer %d" % [id, peer_id])
mp.initialize(peer_id, true)
func peer_connected(id):
print("Peer connected %d" % id)
_create_peer(id)
func _peer_joined(peers):
for i in range(len(peers)):
var peer_id = peers[i]["peerId"]
if not mp.has_peer(peer_id):
_create_peer(peer_id)
func peer_disconnected(id):
print("Peer disconnected ", id)
if mp.has_peer(id):
mp.remove_peer(id)
func offer_received(id, offer):
print("Got offer: %d" % id)
func offer_received(data):
print("Got offer: ", data)
var id = data["peerId"]
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):
print("Got answer: %d" % id)
func answer_received(data):
print("Got answer: ", data)
var id = data["peerId"]
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):
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 ServerData = Record<string, string | number | symbol> | string;
type ServerDataObject = Record<string, string | number | symbol | null>;
type ServerData = ServerDataObject | string;
type Message = string | DataMessage;
const broadcast = (message: Message) =>
@ -32,6 +33,7 @@ const buildMessage = (
class Client {
id: ID;
peerId: number | null;
name: string;
socket: WebSocket;
lobby: Lobby | null;
@ -39,11 +41,10 @@ class Client {
constructor(socket: WebSocket) {
this.id = crypto.randomUUID();
this.socket = socket;
this.peerId = null;
this.name = "Client";
this.lobby = null;
this.send(buildMessage("your-id", this.id));
console.log(this);
allClients.set(this.id, this);
}
@ -78,8 +79,10 @@ class Client {
clientList() {
if (!this.lobby) return;
const netClients: { id: ID; name: string }[] = [];
this.lobby.clients.forEach(({ id, name }) => netClients.push({ id, name }));
const netClients: { id: ID; name: string; peerId: number | null }[] = [];
this.lobby.clients.forEach(({ id, name, peerId }) =>
netClients.push({ id, name, peerId })
);
// TODO: chunk async?
this.send(buildMessage("peer_list", netClients));
}
@ -118,8 +121,10 @@ class Client {
return;
}
this.lobby = lobby;
this.send(buildMessage("lobby_joined", { id: lobby.id }));
lobby.addClient(this);
this.send(
buildMessage("lobby_joined", { id: lobby.id, peerId: this.peerId }),
);
}
lobbyLeave() {
@ -128,6 +133,7 @@ class Client {
this.send(`[info] cannot leave lobby (not in a lobby)`);
return;
}
this.peerId = null;
this.lobby = null;
if (this.isConnected()) {
this.send(buildMessage("lobby_left", { id: leavingLobby.id }));
@ -149,6 +155,7 @@ class Lobby {
this.name = name || this.id;
allLobbies.set(this.id, this);
host.peerId = 1;
host.lobbyJoin(this);
allClients.forEach((client) => client.lobbyNew(this));
}
@ -166,10 +173,19 @@ class Lobby {
}
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(
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) {
@ -182,10 +198,16 @@ class Lobby {
}
}
interface ClientMessage {
type: "candidate" | "offer" | "answer";
data: ServerDataObject;
}
// events
function onMessage(client: Client, ev: MessageEvent) {
// TODO: log who from?
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_leave") client.lobbyLeave();
if (ev.data === "request_lobby_list") client.lobbyList();
@ -196,6 +218,22 @@ function onMessage(client: Client, ev: MessageEvent) {
if (lobby) client.lobbyJoin(lobby);
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) {

View file

@ -8,16 +8,21 @@ expected to fully setup the peer connections.
signal lobby_new(lobbiesList)
signal lobby_delete(id)
signal lobby_joined(id)
signal lobby_joined(id, peer_id)
signal lobby_left(id)
signal peer_joined(id)
signal peer_left(id)
signal candidate_received(data)
signal offer_received(data)
signal answer_received(data)
signal websocket_connected
signal websocket_disconnected
onready var ws: WebSocketClient = WebSocketClient.new()
onready var client_id = null
onready var lobby_id = null
onready var peer_id = null
func _ready():
var _result = ws.connect("data_received", self, "_parse_msg")
@ -45,6 +50,7 @@ func _connected(protocol = ""):
print("WebSocket signaller connected via protocol ", protocol)
ws.get_peer(1).set_write_mode(WebSocketPeer.WRITE_MODE_TEXT)
emit_signal("websocket_connected")
_send("init")
func _process(_delta: float):
var status: int = ws.get_connection_status()
@ -78,89 +84,50 @@ func _parse_msg():
func handle_message(data: Dictionary):
match data["type"]:
"your_id": client_id = data["data"]
"lobby_new": emit_signal("lobby_new", [{"id": data["id"], "name": data["name"]}])
"lobby_delete": emit_signal("lobby_delete", data["id"])
"lobby_joined":
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_id = null
emit_signal("lobby_left", data["id"])
"lobby_list": emit_signal("lobby_new", 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"])
"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))
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: "):
emit_signal("lobby_sealed")
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())
"""