Stuff
This commit is contained in:
parent
9c5b376852
commit
292bf5ba5c
|
@ -0,0 +1 @@
|
|||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
[gd_resource type="DynamicFont" load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://assets/fonts/iosevkalyte/iosevkalyte-regular.ttf" type="DynamicFontData" id=1]
|
||||
|
||||
[resource]
|
||||
font_data = ExtResource( 1 )
|
40
lobby.gd
40
lobby.gd
|
@ -1,31 +1,41 @@
|
|||
extends Node2D
|
||||
|
||||
onready var peers = $MarginContainer/peers
|
||||
onready var cursors = {}
|
||||
|
||||
func _ready():
|
||||
Global.client.signaller.connect("peer_joined", self, "_peer_joined")
|
||||
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
|
||||
$MarginContainer/Label.text = "%s (%s)" % [Global.client.signaller.lobby_id, get_tree().get_network_unique_id()]
|
||||
Global.client.signaller.connect("websocket_disconnected", self, "_signaller_disconnected")
|
||||
Global.client.signaller.request_peer_list()
|
||||
|
||||
_peer_joined([{
|
||||
"id": Global.client.signaller.client_id,
|
||||
"peerId": Global.client.signaller.peer_id,
|
||||
"name": "You!",
|
||||
}])
|
||||
|
||||
func _signaller_disconnected():
|
||||
Global.main_menu()
|
||||
|
||||
func _draw():
|
||||
pass
|
||||
|
||||
func _process(_delta):
|
||||
pass
|
||||
$text.text = JSON.print(Global.client.signaller)
|
||||
|
||||
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 Lobby Peer ", id, name)
|
||||
peers.add_item("%s" % name)
|
||||
peers.set_item_metadata(peers.get_item_count() - 1, { "id": id })
|
||||
var exists = false
|
||||
for j in range(peers.get_item_count()):
|
||||
if id == peers.get_item_metadata(j)["id"]:
|
||||
exists = true
|
||||
break
|
||||
if !exists:
|
||||
var peerId = joined_peers[i]["peerId"]
|
||||
var name = joined_peers[i]["name"]
|
||||
print("New Lobby Peer ID: %s, Name: %s, PeerID: %s" % [id, name, peerId])
|
||||
peers.add_item("%s (%s)" % [name, peerId])
|
||||
peers.set_item_metadata(peers.get_item_count() - 1, { "id": id })
|
||||
|
||||
func _peer_left(id):
|
||||
for i in range(peers.get_item_count()):
|
||||
|
@ -34,7 +44,15 @@ func _peer_left(id):
|
|||
return
|
||||
|
||||
func _on_Button_pressed():
|
||||
Global.lobby_browser()
|
||||
rpc("shift_cursor")
|
||||
# move cursor a bit
|
||||
|
||||
remotesync func shift_cursor():
|
||||
print("Shifting cursor...")
|
||||
$shifter.rect_position.x += 10
|
||||
|
||||
func _lobby_left(_id):
|
||||
Global.lobby_browser()
|
||||
|
||||
func _on_leave_button_pressed():
|
||||
Global.lobby_browser()
|
||||
|
|
49
lobby.tscn
49
lobby.tscn
|
@ -1,10 +1,41 @@
|
|||
[gd_scene load_steps=2 format=2]
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://lobby.gd" type="Script" id=1]
|
||||
[ext_resource path="res://iosevkalyte.tres" type="DynamicFont" id=2]
|
||||
|
||||
[node name="Node2D" type="Node2D"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="text" type="TextEdit" parent="."]
|
||||
margin_left = 208.0
|
||||
margin_top = 162.0
|
||||
margin_right = 739.0
|
||||
margin_bottom = 453.0
|
||||
custom_fonts/font = ExtResource( 2 )
|
||||
text = "information goes in here"
|
||||
readonly = true
|
||||
highlight_current_line = true
|
||||
syntax_highlighting = true
|
||||
show_line_numbers = true
|
||||
draw_tabs = true
|
||||
draw_spaces = true
|
||||
smooth_scrolling = true
|
||||
wrap_enabled = true
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="shifter" type="Label" parent="."]
|
||||
margin_left = 678.0
|
||||
margin_top = 10.0
|
||||
margin_right = 718.0
|
||||
margin_bottom = 26.0
|
||||
text = "ping"
|
||||
autowrap = true
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="MarginContainer" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
|
@ -22,16 +53,26 @@ __meta__ = {
|
|||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Button" type="Button" parent="MarginContainer"]
|
||||
[node name="leave_button" type="Button" parent="MarginContainer"]
|
||||
margin_top = 18.0
|
||||
margin_right = 669.0
|
||||
margin_bottom = 38.0
|
||||
text = "Leave"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="peers" type="ItemList" parent="MarginContainer"]
|
||||
[node name="Button" type="Button" parent="MarginContainer"]
|
||||
margin_top = 42.0
|
||||
margin_right = 669.0
|
||||
margin_bottom = 51.0
|
||||
margin_bottom = 62.0
|
||||
text = "Shift"
|
||||
|
||||
[node name="peers" type="ItemList" parent="MarginContainer"]
|
||||
margin_top = 66.0
|
||||
margin_right = 669.0
|
||||
margin_bottom = 75.0
|
||||
auto_height = true
|
||||
|
||||
[connection signal="pressed" from="MarginContainer/leave_button" to="." method="_on_leave_button_pressed"]
|
||||
[connection signal="pressed" from="MarginContainer/Button" to="." method="_on_Button_pressed"]
|
||||
|
|
|
@ -6,7 +6,8 @@ This module sets up WebRTC peer connections.
|
|||
|
||||
var multiplayer_url = "ws://localhost:8888"
|
||||
var webrtc_ice_servers = [
|
||||
{ "urls": ["stun:stun.l.google.com:19302"] }
|
||||
{ "urls": ["stun:stun.l.google.com:19302"] },
|
||||
# { "urls": ["stun:localhost:3478"] }
|
||||
]
|
||||
|
||||
const SignallerClient = preload("signaller_client.gd")
|
||||
|
@ -37,6 +38,8 @@ func connect_to_signaller():
|
|||
signaller.connect_to_websocket_signaller(multiplayer_url)
|
||||
|
||||
func _create_peer(peer_id):
|
||||
print("_create_peer: %d" % peer_id)
|
||||
if peer_id == signaller.peer_id: return
|
||||
var peer: WebRTCPeerConnection = WebRTCPeerConnection.new()
|
||||
print("New Net Peer %s with peer_id %d" % [peer, peer_id])
|
||||
var _peer_init_results = peer.initialize({"iceServers": webrtc_ice_servers})
|
||||
|
@ -46,30 +49,29 @@ func _create_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)
|
||||
print("Create Offer Result: %s" % 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, peer_id):
|
||||
print("New ICE Candidate: ", mid_name, index_name, sdp_name, peer_id)
|
||||
print("New ICE Candidate - MID: %s, Index: %s, SDP: %s, PeerID: %s" % [mid_name, index_name, sdp_name, peer_id])
|
||||
signaller.send_candidate(peer_id, mid_name, index_name, sdp_name)
|
||||
|
||||
func _offer_created(type, data, peer_id):
|
||||
print("Offer Created", type, data, peer_id)
|
||||
print("Offer created - Type: %s, PeerID: %s, Data: %s" % [type, peer_id, JSON.print(data)])
|
||||
if not mp.has_peer(peer_id):
|
||||
return
|
||||
mp.get_peer(peer_id).connection.set_local_description(type, data)
|
||||
if type == "offer":
|
||||
# TODO: send_offer(id, data)
|
||||
pass
|
||||
signaller.send_offer(peer_id, data)
|
||||
else:
|
||||
# TODO: send_answer(id, data)
|
||||
pass
|
||||
signaller.send_answer(peer_id, data)
|
||||
|
||||
func _lobby_joined(id, peer_id):
|
||||
print("Connected to lobby %s as peer %d" % [id, peer_id])
|
||||
mp.initialize(peer_id, true)
|
||||
get_tree().network_peer = mp
|
||||
|
||||
func _peer_joined(peers):
|
||||
for i in range(len(peers)):
|
||||
|
@ -78,24 +80,26 @@ func _peer_joined(peers):
|
|||
_create_peer(peer_id)
|
||||
|
||||
func peer_disconnected(id):
|
||||
print("Peer disconnected ", id)
|
||||
print("Peer %s disconnected" % id)
|
||||
if mp.has_peer(id):
|
||||
mp.remove_peer(id)
|
||||
|
||||
func offer_received(data):
|
||||
print("Got offer: ", data)
|
||||
var id = data["peerId"]
|
||||
if mp.has_peer(id):
|
||||
print("Setting offer remote description: %s" % JSON.print(data))
|
||||
mp.get_peer(id).connection.set_remote_description("offer", data["offer"])
|
||||
|
||||
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", data["offer"])
|
||||
print("Setting answer remote description: %s" % JSON.print(data))
|
||||
mp.get_peer(id).connection.set_remote_description("answer", data["answer"])
|
||||
|
||||
func candidate_received(data):
|
||||
print("Candidate Received: ", data)
|
||||
var id = data["peerId"]
|
||||
if mp.has_peer(id):
|
||||
print("Adding ice candidate: %s" % JSON.print(data))
|
||||
mp.get_peer(id).connection.add_ice_candidate(data["mid"], data["index"], data["sdp"])
|
||||
else:
|
||||
print("Received candidate for non-existant peer %s" % id)
|
||||
|
|
154
server.ts
154
server.ts
|
@ -1,4 +1,4 @@
|
|||
import { randomInt } from "./deps.ts";
|
||||
// import { randomInt } from "./deps.ts";
|
||||
|
||||
const SERVER_VERSION = "0.1.0";
|
||||
// TODO: version comparison
|
||||
|
@ -45,7 +45,6 @@ class Client {
|
|||
this.name = "Client";
|
||||
this.lobby = null;
|
||||
|
||||
console.log(this);
|
||||
allClients.set(this.id, this);
|
||||
}
|
||||
|
||||
|
@ -84,7 +83,6 @@ class Client {
|
|||
netClients.push({ id, name, peerId })
|
||||
);
|
||||
// TODO: chunk async?
|
||||
this.send(buildMessage("peer_list", netClients));
|
||||
}
|
||||
|
||||
lobbyList() {
|
||||
|
@ -178,6 +176,7 @@ class Lobby {
|
|||
crypto.getRandomValues(arr);
|
||||
client.peerId = Math.abs(arr[0]);
|
||||
}
|
||||
client.send(buildMessage("your_peer_id", client.peerId.toString()));
|
||||
this.broadcast(
|
||||
buildMessage("peer_joined", {
|
||||
id: client.id,
|
||||
|
@ -185,6 +184,13 @@ class Lobby {
|
|||
peerId: client.peerId,
|
||||
}),
|
||||
);
|
||||
this.clients.forEach((c) =>
|
||||
c.send(buildMessage("peer_joined", {
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
peerId: c.peerId,
|
||||
}))
|
||||
);
|
||||
this.clients.set(client.id, client);
|
||||
}
|
||||
|
||||
|
@ -215,20 +221,29 @@ function onMessage(client: Client, ev: MessageEvent) {
|
|||
if (ev.data.startsWith("lobby_join:")) {
|
||||
const id = ev.data.substr(11);
|
||||
const lobby = allLobbies.get(id);
|
||||
if (lobby) client.lobbyJoin(lobby);
|
||||
else client.send(`[info] could not find lobby ${id}`);
|
||||
if (lobby) {
|
||||
client.lobbyJoin(lobby);
|
||||
client.clientList();
|
||||
} 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 (["candidate", "answer", "offer"].includes(data.type)) {
|
||||
console.log("Received WebRTC Negotiation Message...");
|
||||
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);
|
||||
// const payload = Object.assign({}, data);
|
||||
// payload.data.peerId = client.peerId;
|
||||
for (const iClient of client.lobby?.clients.values() || []) {
|
||||
if (iClient.peerId == peerId) {
|
||||
console.log(
|
||||
`Forwarding WebRTC Negotiation Message from peer ${client.peerId} to peer ${peerId}...`,
|
||||
);
|
||||
iClient.send(ev.data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -236,8 +251,8 @@ function onMessage(client: Client, ev: MessageEvent) {
|
|||
}
|
||||
}
|
||||
|
||||
function onSocketOpen(_client: Client, _ev: Event) {
|
||||
console.log("New Client");
|
||||
function onSocketOpen(client: Client, _ev: Event) {
|
||||
console.log("New Client", client.id);
|
||||
}
|
||||
|
||||
function onClientLeave(client: Client) {
|
||||
|
@ -264,7 +279,7 @@ for await (const conn of listener) {
|
|||
for await (const { respondWith, request } of server) {
|
||||
// console.debug("HTTP Request Received", request);
|
||||
try {
|
||||
console.warn(JSON.stringify([allClients, allLobbies]));
|
||||
// console.warn(JSON.stringify([allClients, allLobbies]));
|
||||
const { socket, response } = Deno.upgradeWebSocket(request);
|
||||
const client = new Client(socket);
|
||||
socket.onmessage = (ev) => onMessage(client, ev);
|
||||
|
@ -284,116 +299,3 @@ for await (const conn of listener) {
|
|||
}
|
||||
})();
|
||||
}
|
||||
|
||||
/*
|
||||
function peerCreatesLobby(peer: Peer, lobbyName: string) {
|
||||
// TODO: ensure we can create a lobby
|
||||
lobbies.add({
|
||||
})
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
function peerJoinsLobby(peer: Peer, lobby: Lobby) {
|
||||
lobbyName = randomSecret();
|
||||
lobbies.set(lobbyName, new Lobby(lobbyName, this.id));
|
||||
console.log(`Peer ${this.id} created lobby ${lobbyName}`);
|
||||
console.log(`Open lobbies: ${lobbies.size}`);
|
||||
}
|
||||
const lobby = lobbies.get(lobbyName);
|
||||
if (!lobby) throw new ProtoError(4000, STR_LOBBY_DOES_NOT_EXIST);
|
||||
if (lobby.sealed) throw new ProtoError(4000, STR_LOBBY_IS_SEALED);
|
||||
this.lobby = lobbyName;
|
||||
console.log(
|
||||
`Peer ${this.id} joining lobby ${lobbyName} ` +
|
||||
`with ${lobby.peers.length} peers`,
|
||||
);
|
||||
lobby.join(this);
|
||||
this.ws.send(`J: ${lobbyName}\n`);
|
||||
}
|
||||
// TODO: ensure peer not already in a lobby
|
||||
const assigned = this.getPeerId(peer);
|
||||
peer.ws.send(`I: ${assigned}\n`);
|
||||
this.peers.forEach((p) => {
|
||||
p.ws.send(`N: ${assigned}\n`);
|
||||
peer.ws.send(`N: ${this.getPeerId(p)}\n`);
|
||||
});
|
||||
this.peers.push(peer);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
function peerLeavesLobby(peer: Peer) {
|
||||
const idx = this.peers.findIndex((p) => peer === p);
|
||||
if (idx === -1) return false;
|
||||
const assigned = this.getPeerId(peer);
|
||||
const close = assigned === 1;
|
||||
this.peers.forEach((p) => {
|
||||
try {
|
||||
// room host disconnected
|
||||
if (close) p.ws.close(4000, STR_HOST_DISCONNECTED);
|
||||
// notify peers
|
||||
else p.ws.send(`D: ${assigned}\n`);
|
||||
} catch (e) {
|
||||
console.error(`Error when leaving: ${e}`);
|
||||
}
|
||||
});
|
||||
this.peers.splice(idx, 1);
|
||||
if (close && this.closeTimer >= 0) {
|
||||
// we are closing already.
|
||||
clearTimeout(this.closeTimer);
|
||||
this.closeTimer = -1;
|
||||
}
|
||||
return close;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
function graduateLobby(lobby: Lobby) {
|
||||
// only host can seal
|
||||
if (peer.id !== this.host) {
|
||||
throw new ProtoError(4000, STR_ONLY_HOST_CAN_SEAL);
|
||||
}
|
||||
this.sealed = true;
|
||||
this.peers.forEach((p) => {
|
||||
p.ws.send("S: \n");
|
||||
});
|
||||
console.log(
|
||||
`Peer ${peer.id} sealed lobby ${this.name} ` +
|
||||
`with ${this.peers.length} peers`,
|
||||
);
|
||||
this.closeTimer = setTimeout(() => {
|
||||
// close peer connection to host (and thus the lobby)
|
||||
this.peers.forEach((p) => {
|
||||
p.ws.close(1000, STR_SEAL_COMPLETE);
|
||||
});
|
||||
}, SEAL_CLOSE_TIMEOUT);
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
function parseMsg(peer: Peer, msg: string) {
|
||||
// TODO: modify this?
|
||||
// O: Client is sending an offer.
|
||||
// A: Client is sending an answer.
|
||||
// C: Client is sending a candidate.
|
||||
let destId = parseInt(cmd.substr(3).trim());
|
||||
// Dest is not an ID.
|
||||
if (!destId) throw new ProtoError(4000, STR_INVALID_DEST);
|
||||
if (destId === 1) destId = lobby.host;
|
||||
const dest = lobby.peers.find((p: Peer) => p.id === destId);
|
||||
// Dest is not in this room.
|
||||
if (!dest) throw new ProtoError(4000, STR_INVALID_DEST);
|
||||
|
||||
function isCmd(what: string) {
|
||||
return cmd.startsWith(`${what}: `);
|
||||
}
|
||||
if (isCmd("O") || isCmd("A") || isCmd("C")) {
|
||||
dest.ws.send(cmd[0] + ": " + lobby.getPeerId(peer) + data);
|
||||
return;
|
||||
}
|
||||
throw new ProtoError(4000, STR_INVALID_CMD);
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -35,19 +35,19 @@ func close():
|
|||
ws.disconnect_from_host()
|
||||
|
||||
func connect_to_websocket_signaller(url: String):
|
||||
print(ws)
|
||||
print("WebSocket: %s" % ws)
|
||||
close()
|
||||
print("Attempting to connect to WebSocket signalling server at ", url)
|
||||
print("Attempting to connect to WebSocket signalling server at %s" % url)
|
||||
var _result = ws.connect_to_url(url)
|
||||
|
||||
func _closed(_unknown):
|
||||
emit_signal("websocket_disconnected")
|
||||
|
||||
func _close_request(code: int, reason: String):
|
||||
print("Received WebSocket close request from signalling server ", code, reason)
|
||||
print("Received WebSocket close request from signalling server - Code: %s, Reason: %s" % [code, reason])
|
||||
|
||||
func _connected(protocol = ""):
|
||||
print("WebSocket signaller connected via protocol ", protocol)
|
||||
print("WebSocket signaller connected via protocol %s" % protocol)
|
||||
ws.get_peer(1).set_write_mode(WebSocketPeer.WRITE_MODE_TEXT)
|
||||
emit_signal("websocket_connected")
|
||||
_send("init")
|
||||
|
@ -74,17 +74,18 @@ func _send(s: String):
|
|||
|
||||
func _parse_msg():
|
||||
var msg: String = ws.get_peer(1).get_packet().get_string_from_utf8()
|
||||
print("Signaller sent: ", msg)
|
||||
print("Signaller received message: %s" % msg)
|
||||
if msg.begins_with("json:"):
|
||||
var data = JSON.parse(msg.substr(5))
|
||||
if data.error == OK:
|
||||
handle_message(data.result)
|
||||
else:
|
||||
print("Unhandled Message: ", msg)
|
||||
print("Unhandled message: %s" % msg)
|
||||
|
||||
func handle_message(data: Dictionary):
|
||||
match data["type"]:
|
||||
"your_id": client_id = data["data"]
|
||||
"your_peer_id": peer_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":
|
||||
|
@ -99,15 +100,15 @@ func handle_message(data: Dictionary):
|
|||
"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"])
|
||||
print("Candidate received - Data: %s" % JSON.print(data["data"]))
|
||||
emit_signal("candidate_received", data["data"])
|
||||
"offer":
|
||||
print("Offer received ", data["data"])
|
||||
print("Offer received - Data: %s" % JSON.print(data["data"]))
|
||||
emit_signal("offer_received", data["data"])
|
||||
"answer":
|
||||
print("Answer received ", data["data"])
|
||||
print("Answer received - Data: %s" % JSON.print(data["data"]))
|
||||
emit_signal("answer_received", data["data"])
|
||||
_: print("Unhandled Data Message: ", JSON.print(data))
|
||||
_: print("Unhandled Message - Data: %s" % JSON.print(data))
|
||||
|
||||
func send_candidate(peerId, mid, index, sdp) -> int:
|
||||
return _send("json:%s" % JSON.print({
|
||||
|
|
Loading…
Reference in New Issue