Initial commit
This commit is contained in:
parent
308f09916b
commit
b915552a64
11 changed files with 557 additions and 49 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@ export_presets.cfg
|
|||
*.translation
|
||||
.mono
|
||||
data_*/
|
||||
/webrtc/
|
||||
|
|
64
client_ui.gd
Normal file
64
client_ui.gd
Normal file
|
@ -0,0 +1,64 @@
|
|||
extends Control
|
||||
|
||||
onready var client = $Client
|
||||
|
||||
func _ready():
|
||||
client.connect("lobby_joined", self, "_lobby_joined")
|
||||
client.connect("lobby_sealed", self, "_lobby_sealed")
|
||||
client.connect("connected", self, "_connected")
|
||||
client.connect("disconnected", self, "_disconnected")
|
||||
client.rtc_mp.connect("peer_connected", self, "_mp_peer_connected")
|
||||
client.rtc_mp.connect("peer_disconnected", self, "_mp_peer_disconnected")
|
||||
client.rtc_mp.connect("server_disconnected", self, "_mp_server_disconnect")
|
||||
client.rtc_mp.connect("connection_succeeded", self, "_mp_connected")
|
||||
|
||||
func _process(delta):
|
||||
client.rtc_mp.poll()
|
||||
while client.rtc_mp.get_available_packet_count() > 0:
|
||||
_log(client.rtc_mp.get_packet().get_string_from_utf8())
|
||||
|
||||
func _connected(id):
|
||||
_log("Signaling server connected with ID: %d" % id)
|
||||
|
||||
func _disconnected():
|
||||
_log("Signaling server disconnected: %d - %s" % [client.code, client.reason])
|
||||
|
||||
func _lobby_joined(lobby):
|
||||
_log("Joined lobby %s" % lobby)
|
||||
|
||||
func _lobby_sealed():
|
||||
_log("Lobby has been sealed")
|
||||
|
||||
func _mp_connected():
|
||||
_log("Multiplayer is connected (I am %d)" % client.rtc_mp.get_unique_id())
|
||||
|
||||
func _mp_server_disconnect():
|
||||
_log("Multiplayer is disconnected (I am %d)" % client.rtc_mp.get_unique_id())
|
||||
|
||||
func _mp_peer_connected(id: int):
|
||||
_log("Multiplayer peer %d connected" % id)
|
||||
|
||||
func _mp_peer_disconnected(id: int):
|
||||
_log("Multiplayer peer %d disconnected" % id)
|
||||
|
||||
func _log(msg):
|
||||
print(msg)
|
||||
$VBoxContainer/TextEdit.text += str(msg) + "\n"
|
||||
|
||||
func ping():
|
||||
_log(client.rtc_mp.put_packet("ping".to_utf8()))
|
||||
|
||||
func _on_Peers_pressed():
|
||||
var d = client.rtc_mp.get_peers()
|
||||
_log(d)
|
||||
for k in d:
|
||||
_log(client.rtc_mp.get_peer(k))
|
||||
|
||||
func start():
|
||||
client.start($VBoxContainer/Connect/Host.text, $VBoxContainer/Connect/RoomSecret.text)
|
||||
|
||||
func _on_Seal_pressed():
|
||||
client.seal_lobby()
|
||||
|
||||
func stop():
|
||||
client.stop()
|
107
client_ui.tscn
Normal file
107
client_ui.tscn
Normal file
|
@ -0,0 +1,107 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://client_ui.gd" type="Script" id=1]
|
||||
[ext_resource path="res://multiplayer_client.gd" type="Script" id=2]
|
||||
|
||||
[node name="ClientUI" type="Control"]
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 600.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": true
|
||||
}
|
||||
|
||||
[node name="Client" type="Node" parent="."]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
custom_constants/separation = 8
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Connect" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 24.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/Connect"]
|
||||
margin_top = 5.0
|
||||
margin_right = 73.0
|
||||
margin_bottom = 19.0
|
||||
text = "Connect to:"
|
||||
|
||||
[node name="Host" type="LineEdit" parent="VBoxContainer/Connect"]
|
||||
margin_left = 77.0
|
||||
margin_right = 921.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
text = "ws://localhost:9080"
|
||||
|
||||
[node name="Room" type="Label" parent="VBoxContainer/Connect"]
|
||||
margin_left = 925.0
|
||||
margin_right = 962.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_vertical = 5
|
||||
text = "Room"
|
||||
valign = 1
|
||||
|
||||
[node name="RoomSecret" type="LineEdit" parent="VBoxContainer/Connect"]
|
||||
margin_left = 966.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 24.0
|
||||
placeholder_text = "secret"
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 32.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 52.0
|
||||
custom_constants/separation = 10
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Start" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_right = 41.0
|
||||
margin_bottom = 20.0
|
||||
text = "Start"
|
||||
|
||||
[node name="Stop" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_left = 51.0
|
||||
margin_right = 91.0
|
||||
margin_bottom = 20.0
|
||||
text = "Stop"
|
||||
|
||||
[node name="Seal" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_left = 101.0
|
||||
margin_right = 139.0
|
||||
margin_bottom = 20.0
|
||||
text = "Seal"
|
||||
|
||||
[node name="Ping" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_left = 149.0
|
||||
margin_right = 188.0
|
||||
margin_bottom = 20.0
|
||||
text = "Ping"
|
||||
|
||||
[node name="Peers" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_left = 198.0
|
||||
margin_right = 280.0
|
||||
margin_bottom = 20.0
|
||||
text = "Print peers"
|
||||
|
||||
[node name="TextEdit" type="TextEdit" parent="VBoxContainer"]
|
||||
margin_top = 60.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 600.0
|
||||
size_flags_vertical = 3
|
||||
readonly = true
|
||||
|
||||
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Start" to="." method="start"]
|
||||
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Stop" to="." method="stop"]
|
||||
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Seal" to="." method="_on_Seal_pressed"]
|
||||
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Ping" to="." method="ping"]
|
||||
[connection signal="pressed" from="VBoxContainer/HBoxContainer/Peers" to="." method="_on_Peers_pressed"]
|
|
@ -1,5 +1,7 @@
|
|||
[gd_resource type="Environment" load_steps=2 format=2]
|
||||
|
||||
[sub_resource type="ProceduralSky" id=1]
|
||||
|
||||
[resource]
|
||||
background_mode = 2
|
||||
background_sky = SubResource( 1 )
|
||||
|
|
14
main.gd
Normal file
14
main.gd
Normal file
|
@ -0,0 +1,14 @@
|
|||
extends Control
|
||||
|
||||
func _ready():
|
||||
if OS.get_name() == "HTML5":
|
||||
$VBoxContainer/Signaling.hide()
|
||||
|
||||
func _on_listen_toggled(button_pressed):
|
||||
if button_pressed:
|
||||
$Server.listen(int($VBoxContainer/Signaling/Port.value))
|
||||
else:
|
||||
$Server.stop()
|
||||
|
||||
func _on_LinkButton_pressed():
|
||||
OS.shell_open("https://github.com/godotengine/webrtc-native/releases")
|
98
main.tscn
Normal file
98
main.tscn
Normal file
|
@ -0,0 +1,98 @@
|
|||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://main.gd" type="Script" id=1]
|
||||
[ext_resource path="res://client_ui.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="Control" type="Control"]
|
||||
anchor_left = 0.0136719
|
||||
anchor_top = 0.0166667
|
||||
anchor_right = 0.986328
|
||||
anchor_bottom = 0.983333
|
||||
margin_top = 4.32134e-07
|
||||
margin_bottom = -9.53674e-06
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": true
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
custom_constants/separation = 50
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": true
|
||||
}
|
||||
|
||||
[node name="Signaling" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_right = 995.0
|
||||
margin_bottom = 24.0
|
||||
|
||||
[node name="Label" type="Label" parent="VBoxContainer/Signaling"]
|
||||
margin_top = 5.0
|
||||
margin_right = 104.0
|
||||
margin_bottom = 19.0
|
||||
text = "Signaling server:"
|
||||
|
||||
[node name="Port" type="SpinBox" parent="VBoxContainer/Signaling"]
|
||||
margin_left = 108.0
|
||||
margin_right = 182.0
|
||||
margin_bottom = 24.0
|
||||
min_value = 1025.0
|
||||
max_value = 65535.0
|
||||
value = 9080.0
|
||||
|
||||
[node name="ListenButton" type="Button" parent="VBoxContainer/Signaling"]
|
||||
margin_left = 186.0
|
||||
margin_right = 237.0
|
||||
margin_bottom = 24.0
|
||||
toggle_mode = true
|
||||
text = "Listen"
|
||||
|
||||
[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/Signaling"]
|
||||
margin_left = 241.0
|
||||
margin_right = 995.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="LinkButton" type="LinkButton" parent="VBoxContainer/Signaling/CenterContainer"]
|
||||
margin_left = 104.0
|
||||
margin_top = 5.0
|
||||
margin_right = 650.0
|
||||
margin_bottom = 19.0
|
||||
text = "Make sure to download the GDNative WebRTC Plugin and place it in the project folder"
|
||||
|
||||
[node name="Clients" type="GridContainer" parent="VBoxContainer"]
|
||||
margin_top = 74.0
|
||||
margin_right = 995.0
|
||||
margin_bottom = 579.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
custom_constants/vseparation = 15
|
||||
custom_constants/hseparation = 15
|
||||
columns = 2
|
||||
|
||||
[node name="ClientUI" parent="VBoxContainer/Clients" instance=ExtResource( 2 )]
|
||||
margin_right = 490.0
|
||||
margin_bottom = 245.0
|
||||
|
||||
[node name="ClientUI2" parent="VBoxContainer/Clients" instance=ExtResource( 2 )]
|
||||
margin_left = 505.0
|
||||
margin_right = 995.0
|
||||
margin_bottom = 245.0
|
||||
|
||||
[node name="ClientUI3" parent="VBoxContainer/Clients" instance=ExtResource( 2 )]
|
||||
margin_top = 260.0
|
||||
margin_right = 490.0
|
||||
margin_bottom = 505.0
|
||||
|
||||
[node name="ClientUI4" parent="VBoxContainer/Clients" instance=ExtResource( 2 )]
|
||||
margin_left = 505.0
|
||||
margin_top = 260.0
|
||||
margin_right = 995.0
|
||||
margin_bottom = 505.0
|
||||
|
||||
[node name="Server" type="Node" parent="."]
|
||||
|
||||
[connection signal="toggled" from="VBoxContainer/Signaling/ListenButton" to="." method="_on_listen_toggled"]
|
||||
[connection signal="pressed" from="VBoxContainer/Signaling/CenterContainer/LinkButton" to="." method="_on_LinkButton_pressed"]
|
86
multiplayer_client.gd
Normal file
86
multiplayer_client.gd
Normal file
|
@ -0,0 +1,86 @@
|
|||
extends "ws_webrtc_client.gd"
|
||||
|
||||
var rtc_mp: WebRTCMultiplayer = WebRTCMultiplayer.new()
|
||||
var sealed = false
|
||||
|
||||
func _init():
|
||||
connect("connected", self, "connected")
|
||||
connect("disconnected", self, "disconnected")
|
||||
|
||||
connect("offer_received", self, "offer_received")
|
||||
connect("answer_received", self, "answer_received")
|
||||
connect("candidate_received", self, "candidate_received")
|
||||
|
||||
connect("lobby_joined", self, "lobby_joined")
|
||||
connect("lobby_sealed", self, "lobby_sealed")
|
||||
connect("peer_connected", self, "peer_connected")
|
||||
connect("peer_disconnected", self, "peer_disconnected")
|
||||
|
||||
func start(url, lobby = ""):
|
||||
stop()
|
||||
sealed = false
|
||||
self.lobby = lobby
|
||||
connect_to_url(url)
|
||||
|
||||
func stop():
|
||||
rtc_mp.close()
|
||||
close()
|
||||
|
||||
func _create_peer(id):
|
||||
var peer: WebRTCPeerConnection = WebRTCPeerConnection.new()
|
||||
peer.initialize({
|
||||
"iceServers": [ { "urls": ["stun:stun.l.google.com:19302"] } ]
|
||||
})
|
||||
peer.connect("session_description_created", self, "_offer_created", [id])
|
||||
peer.connect("ice_candidate_created", self, "_new_ice_candidate", [id])
|
||||
rtc_mp.add_peer(peer, id)
|
||||
if id > rtc_mp.get_unique_id():
|
||||
peer.create_offer()
|
||||
return peer
|
||||
|
||||
func _new_ice_candidate(mid_name, index_name, sdp_name, id):
|
||||
send_candidate(id, mid_name, index_name, sdp_name)
|
||||
|
||||
func _offer_created(type, data, id):
|
||||
if not rtc_mp.has_peer(id):
|
||||
return
|
||||
print("created", type)
|
||||
rtc_mp.get_peer(id).connection.set_local_description(type, data)
|
||||
if type == "offer": send_offer(id, data)
|
||||
else: send_answer(id, data)
|
||||
|
||||
func connected(id):
|
||||
print("Connected %d" % id)
|
||||
rtc_mp.initialize(id, true)
|
||||
|
||||
func lobby_joined(lobby):
|
||||
self.lobby = lobby
|
||||
|
||||
func lobby_sealed():
|
||||
sealed = true
|
||||
|
||||
func disconnected():
|
||||
print("Disconnected: %d: %s" % [code, reason])
|
||||
if not sealed:
|
||||
stop() # Unexpected disconnect
|
||||
|
||||
func peer_connected(id):
|
||||
print("Peer connected %d" % id)
|
||||
_create_peer(id)
|
||||
|
||||
func peer_disconnected(id):
|
||||
if rtc_mp.has_peer(id): rtc_mp.remove_peer(id)
|
||||
|
||||
func offer_received(id, offer):
|
||||
print("Got offer: %d" % id)
|
||||
if rtc_mp.has_peer(id):
|
||||
rtc_mp.get_peer(id).connection.set_remote_description("offer", offer)
|
||||
|
||||
func answer_received(id, answer):
|
||||
print("Got answer: %d" % id)
|
||||
if rtc_mp.has_peer(id):
|
||||
rtc_mp.get_peer(id).connection.set_remote_description("answer", answer)
|
||||
|
||||
func candidate_received(id, mid, index, sdp):
|
||||
if rtc_mp.has_peer(id):
|
||||
rtc_mp.get_peer(id).connection.add_ice_candidate(mid, index, sdp)
|
|
@ -11,8 +11,13 @@ config_version=4
|
|||
[application]
|
||||
|
||||
config/name="kdt"
|
||||
run/main_scene="res://main.tscn"
|
||||
config/icon="res://icon.png"
|
||||
|
||||
[gdnative]
|
||||
|
||||
singletons=[ "res://webrtc/webrtc.tres" ]
|
||||
|
||||
[physics]
|
||||
|
||||
common/enable_pause_aware_picking=true
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
# Setup
|
||||
|
||||
- Download the latest WebRTC GDNative plugin from https://github.com/godotengine/webrtc-native/releases and extract it in the project root.
|
||||
|
||||
# Signalling Server
|
||||
|
||||
deno run -A server.ts
|
||||
|
|
109
server.ts
109
server.ts
|
@ -101,10 +101,14 @@ class Lobby {
|
|||
const assigned = this.getPeerId(peer);
|
||||
const close = assigned === 1;
|
||||
this.peers.forEach((p) => {
|
||||
// Room host disconnected, must close.
|
||||
if (close) p.ws.close(4000, STR_HOST_DISCONNECTED);
|
||||
// Notify peer disconnect.
|
||||
else p.ws.send(`D: ${assigned}\n`);
|
||||
try {
|
||||
// Room host disconnected, must close.
|
||||
if (close) p.ws.close(4000, STR_HOST_DISCONNECTED);
|
||||
// Notify peer disconnect.
|
||||
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) {
|
||||
|
@ -217,50 +221,57 @@ function parseMsg(peer: Peer, msg: string) {
|
|||
}
|
||||
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
const conn = Deno.listen({ port: PORT });
|
||||
const httpConn = Deno.serveHttp(await conn.accept());
|
||||
const e = await httpConn.nextRequest();
|
||||
if (e) {
|
||||
const { socket, response } = Deno.upgradeWebSocket(e.request);
|
||||
const id = randomId();
|
||||
const peer = new Peer(id, socket);
|
||||
socket.onopen = (_ev) => {
|
||||
if (peersCount >= MAX_PEERS) {
|
||||
socket.close(4000, STR_TOO_MANY_PEERS);
|
||||
return;
|
||||
const server = Deno.listen({ port: PORT });
|
||||
for await (const conn of server) {
|
||||
(async () => {
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
for await (const requestEvent of httpConn) {
|
||||
if (requestEvent) {
|
||||
const { socket, response } = Deno.upgradeWebSocket(
|
||||
requestEvent.request,
|
||||
);
|
||||
const id = randomId();
|
||||
const peer = new Peer(id, socket);
|
||||
socket.onopen = (_ev) => {
|
||||
if (peersCount >= MAX_PEERS) {
|
||||
socket.close(4000, STR_TOO_MANY_PEERS);
|
||||
return;
|
||||
}
|
||||
peersCount++;
|
||||
};
|
||||
socket.onmessage = (ev) => {
|
||||
try {
|
||||
parseMsg(peer, ev.data);
|
||||
} catch (e) {
|
||||
const code = e.code || 4000;
|
||||
console.log(`Error parsing message from ${id}:\n` + ev.data);
|
||||
socket.close(code, e.message);
|
||||
}
|
||||
};
|
||||
socket.onclose = (ev) => {
|
||||
peersCount--;
|
||||
console.log(
|
||||
`Connection with peer ${peer.id} closed ` +
|
||||
`with reason: ${ev.reason}`,
|
||||
);
|
||||
if (
|
||||
peer.lobby &&
|
||||
lobbies.has(peer.lobby) &&
|
||||
lobbies.get(peer.lobby).leave(peer)
|
||||
) {
|
||||
lobbies.delete(peer.lobby);
|
||||
console.log(`Deleted lobby ${peer.lobby}`);
|
||||
console.log(`Open lobbies: ${lobbies.size}`);
|
||||
peer.lobby = "";
|
||||
}
|
||||
if (peer.timeout >= 0) {
|
||||
clearTimeout(peer.timeout);
|
||||
peer.timeout = -1;
|
||||
}
|
||||
};
|
||||
socket.onerror = (e) => console.error("WebSocket error:", e);
|
||||
requestEvent.respondWith(response);
|
||||
}
|
||||
}
|
||||
peersCount++;
|
||||
};
|
||||
socket.onmessage = (ev) => {
|
||||
try {
|
||||
parseMsg(peer, ev.data);
|
||||
} catch (e) {
|
||||
const code = e.code || 4000;
|
||||
console.log(`Error parsing message from ${id}:\n` + ev.data);
|
||||
socket.close(code, e.message);
|
||||
}
|
||||
};
|
||||
socket.onclose = (ev) => {
|
||||
peersCount--;
|
||||
console.log(
|
||||
`Connection with peer ${peer.id} closed ` +
|
||||
`with reason: ${ev.reason}`,
|
||||
);
|
||||
if (
|
||||
peer.lobby &&
|
||||
lobbies.has(peer.lobby) &&
|
||||
lobbies.get(peer.lobby).leave(peer)
|
||||
) {
|
||||
lobbies.delete(peer.lobby);
|
||||
console.log(`Deleted lobby ${peer.lobby}`);
|
||||
console.log(`Open lobbies: ${lobbies.size}`);
|
||||
peer.lobby = "";
|
||||
}
|
||||
if (peer.timeout >= 0) {
|
||||
clearTimeout(peer.timeout);
|
||||
peer.timeout = -1;
|
||||
}
|
||||
};
|
||||
socket.onerror = (e) => console.error("WebSocket error:", e);
|
||||
e.respondWith(response);
|
||||
})();
|
||||
}
|
||||
|
|
116
ws_webrtc_client.gd
Normal file
116
ws_webrtc_client.gd
Normal file
|
@ -0,0 +1,116 @@
|
|||
extends Node
|
||||
|
||||
export var autojoin = true
|
||||
export var lobby = "" # Will create a new lobby if empty.
|
||||
|
||||
var client: WebSocketClient = WebSocketClient.new()
|
||||
var code = 1000
|
||||
var reason = "Unknown"
|
||||
|
||||
signal lobby_joined(lobby)
|
||||
signal connected(id)
|
||||
signal disconnected()
|
||||
signal peer_connected(id)
|
||||
signal peer_disconnected(id)
|
||||
signal offer_received(id, offer)
|
||||
signal answer_received(id, answer)
|
||||
signal candidate_received(id, mid, index, sdp)
|
||||
signal lobby_sealed()
|
||||
|
||||
func _init():
|
||||
client.connect("data_received", self, "_parse_msg")
|
||||
client.connect("connection_established", self, "_connected")
|
||||
client.connect("connection_closed", self, "_closed")
|
||||
client.connect("connection_error", self, "_closed")
|
||||
client.connect("server_close_request", self, "_close_request")
|
||||
|
||||
func connect_to_url(url):
|
||||
close()
|
||||
code = 1000
|
||||
reason = "Unknown"
|
||||
client.connect_to_url(url)
|
||||
|
||||
func close():
|
||||
client.disconnect_from_host()
|
||||
|
||||
func _closed(was_clean = false):
|
||||
emit_signal("disconnected")
|
||||
|
||||
func _close_request(code, reason):
|
||||
self.code = code
|
||||
self.reason = reason
|
||||
|
||||
func _connected(protocol = ""):
|
||||
client.get_peer(1).set_write_mode(WebSocketPeer.WRITE_MODE_TEXT)
|
||||
if autojoin:
|
||||
join_lobby(lobby)
|
||||
|
||||
func _parse_msg():
|
||||
var pkt_str: String = client.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: "):
|
||||
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: "):
|
||||
emit_signal("connected", src_id)
|
||||
elif type.begins_with("N: "):
|
||||
# Client 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
|
||||
emit_signal("offer_received", src_id, req[1])
|
||||
elif type.begins_with("A: "):
|
||||
# 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
|
||||
emit_signal("candidate_received", src_id, candidate[0], int(candidate[1]), candidate[2])
|
||||
|
||||
func join_lobby(lobby):
|
||||
return client.get_peer(1).put_packet(("J: %s\n" % lobby).to_utf8())
|
||||
|
||||
func seal_lobby():
|
||||
return client.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 client.get_peer(1).put_packet(("%s: %d\n%s" % [type, id, data]).to_utf8())
|
||||
|
||||
func _process(delta):
|
||||
var status: int = client.get_connection_status()
|
||||
if status == WebSocketClient.CONNECTION_CONNECTING or status == WebSocketClient.CONNECTION_CONNECTED:
|
||||
client.poll()
|
Loading…
Reference in a new issue