mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2026-01-04 15:00:09 +01:00
Update other networking demos, with style fixes
This commit is contained in:
@@ -1,35 +1,39 @@
|
||||
# An example p2p chat client
|
||||
extends Node
|
||||
# An example p2p chat client.
|
||||
|
||||
var peer = WebRTCPeerConnection.new()
|
||||
|
||||
# Create negotiated data channel
|
||||
# Create negotiated data channel.
|
||||
var channel = peer.create_data_channel("chat", {"negotiated": true, "id": 1})
|
||||
|
||||
func _ready():
|
||||
# Connect all functions
|
||||
# Connect all functions.
|
||||
peer.connect("ice_candidate_created", self, "_on_ice_candidate")
|
||||
peer.connect("session_description_created", self, "_on_session")
|
||||
|
||||
# Register to the local signaling server (see below for the implementation)
|
||||
# Register to the local signaling server (see below for the implementation).
|
||||
Signaling.register(get_path())
|
||||
|
||||
|
||||
func _on_ice_candidate(mid, index, sdp):
|
||||
# Send the ICE candidate to the other peer via signaling server
|
||||
# Send the ICE candidate to the other peer via signaling server.
|
||||
Signaling.send_candidate(get_path(), mid, index, sdp)
|
||||
|
||||
|
||||
func _on_session(type, sdp):
|
||||
# Send the session to other peer via signaling server
|
||||
# Send the session to other peer via signaling server.
|
||||
Signaling.send_session(get_path(), type, sdp)
|
||||
# Set generated description as local
|
||||
# Set generated description as local.
|
||||
peer.set_local_description(type, sdp)
|
||||
|
||||
|
||||
func _process(delta):
|
||||
# Always poll the connection frequently
|
||||
# Always poll the connection frequently.
|
||||
peer.poll()
|
||||
if channel.get_ready_state() == WebRTCDataChannel.STATE_OPEN:
|
||||
while channel.get_available_packet_count() > 0:
|
||||
print(get_path(), " received: ", channel.get_packet().get_string_from_utf8())
|
||||
|
||||
|
||||
func send_message(message):
|
||||
channel.put_packet(message.to_utf8())
|
||||
channel.put_packet(message.to_utf8())
|
||||
|
||||
@@ -10,10 +10,10 @@ func _on_LinkButton_pressed():
|
||||
OS.shell_open(\"https://github.com/godotengine/webrtc-native/releases\")
|
||||
"
|
||||
|
||||
[node name="main" type="Node"]
|
||||
[node name="Main" type="Node"]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="minimal" parent="." instance=ExtResource( 1 )]
|
||||
[node name="Minimal" parent="." instance=ExtResource( 1 )]
|
||||
|
||||
[node name="CenterContainer" type="CenterContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
|
||||
@@ -1,35 +1,37 @@
|
||||
# Main scene
|
||||
extends Node
|
||||
# Main scene.
|
||||
|
||||
# Create the two peers
|
||||
# Create the two peers.
|
||||
var p1 = WebRTCPeerConnection.new()
|
||||
var p2 = WebRTCPeerConnection.new()
|
||||
var ch1 = p1.create_data_channel("chat", {"id": 1, "negotiated": true})
|
||||
var ch2 = p2.create_data_channel("chat", {"id": 1, "negotiated": true})
|
||||
|
||||
func _ready():
|
||||
# Connect P1 session created to itself to set local description
|
||||
print(p1.create_data_channel("chat", {"id": 1, "negotiated": true}))
|
||||
# Connect P1 session created to itself to set local description.
|
||||
p1.connect("session_description_created", p1, "set_local_description")
|
||||
# Connect P1 session and ICE created to p2 set remote description and candidates
|
||||
# Connect P1 session and ICE created to p2 set remote description and candidates.
|
||||
p1.connect("session_description_created", p2, "set_remote_description")
|
||||
p1.connect("ice_candidate_created", p2, "add_ice_candidate")
|
||||
|
||||
# Same for P2
|
||||
# Same for P2.
|
||||
p2.connect("session_description_created", p2, "set_local_description")
|
||||
p2.connect("session_description_created", p1, "set_remote_description")
|
||||
p2.connect("ice_candidate_created", p1, "add_ice_candidate")
|
||||
|
||||
# Let P1 create the offer
|
||||
# Let P1 create the offer.
|
||||
p1.create_offer()
|
||||
|
||||
# Wait a second and send message from P1
|
||||
# Wait a second and send message from P1.
|
||||
yield(get_tree().create_timer(1), "timeout")
|
||||
ch1.put_packet("Hi from P1".to_utf8())
|
||||
|
||||
# Wait a second and send message from P2
|
||||
# Wait a second and send message from P2.
|
||||
yield(get_tree().create_timer(1), "timeout")
|
||||
ch2.put_packet("Hi from P2".to_utf8())
|
||||
|
||||
|
||||
func _process(delta):
|
||||
p1.poll()
|
||||
p2.poll()
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
[ext_resource path="res://minimal.gd" type="Script" id=1]
|
||||
|
||||
[node name="minimal" type="Node"]
|
||||
[node name="Minimal" type="Node"]
|
||||
script = ExtResource( 1 )
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
extends "ws_webrtc_client.gd"
|
||||
|
||||
var rtc_mp : WebRTCMultiplayer = WebRTCMultiplayer.new()
|
||||
var rtc_mp: WebRTCMultiplayer = WebRTCMultiplayer.new()
|
||||
var sealed = false
|
||||
|
||||
func _init():
|
||||
@@ -16,17 +16,20 @@ func _init():
|
||||
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 : int):
|
||||
|
||||
func _create_peer(id):
|
||||
var peer : WebRTCPeerConnection = WebRTCPeerConnection.new()
|
||||
peer.initialize({
|
||||
"iceServers": [ { "urls": ["stun:stun.l.google.com:19302"] } ]
|
||||
@@ -38,10 +41,12 @@ func _create_peer(id : int):
|
||||
peer.create_offer()
|
||||
return peer
|
||||
|
||||
func _new_ice_candidate(mid_name : String, index_name : int, sdp_name : String, id : int):
|
||||
|
||||
func _new_ice_candidate(mid_name, index_name, sdp_name, id):
|
||||
send_candidate(id, mid_name, index_name, sdp_name)
|
||||
|
||||
func _offer_created(type : String, data : String, id : int):
|
||||
|
||||
func _offer_created(type, data, id):
|
||||
if not rtc_mp.has_peer(id):
|
||||
return
|
||||
print("created", type)
|
||||
@@ -49,38 +54,47 @@ func _offer_created(type : String, data : String, id : int):
|
||||
if type == "offer": send_offer(id, data)
|
||||
else: send_answer(id, data)
|
||||
|
||||
func connected(id : int):
|
||||
|
||||
func connected(id):
|
||||
print("Connected %d" % id)
|
||||
rtc_mp.initialize(id, true)
|
||||
|
||||
func lobby_joined(lobby : String):
|
||||
|
||||
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 : int):
|
||||
|
||||
func peer_connected(id):
|
||||
print("Peer connected %d" % id)
|
||||
_create_peer(id)
|
||||
|
||||
func peer_disconnected(id : int):
|
||||
|
||||
func peer_disconnected(id):
|
||||
if rtc_mp.has_peer(id): rtc_mp.remove_peer(id)
|
||||
|
||||
func offer_received(id : int, offer : String):
|
||||
|
||||
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 : int, answer : String):
|
||||
|
||||
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 : int, mid : String, index : int, sdp : String):
|
||||
|
||||
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)
|
||||
rtc_mp.get_peer(id).connection.add_ice_candidate(mid, index, sdp)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
extends Node
|
||||
|
||||
export var autojoin = true
|
||||
export var lobby = "" # Will create a new lobby if empty
|
||||
export var lobby = "" # Will create a new lobby if empty.
|
||||
|
||||
var client : WebSocketClient = WebSocketClient.new()
|
||||
var client: WebSocketClient = WebSocketClient.new()
|
||||
var code = 1000
|
||||
var reason = "Unknown"
|
||||
|
||||
@@ -24,27 +24,33 @@ func _init():
|
||||
client.connect("connection_error", self, "_closed")
|
||||
client.connect("server_close_request", self, "_close_request")
|
||||
|
||||
func connect_to_url(url : String):
|
||||
|
||||
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 : bool = false):
|
||||
|
||||
func _closed(was_clean = false):
|
||||
emit_signal("disconnected")
|
||||
|
||||
func _close_request(code : int, reason : String):
|
||||
|
||||
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()
|
||||
|
||||
@@ -92,25 +98,32 @@ func _parse_msg():
|
||||
return
|
||||
emit_signal("candidate_received", src_id, candidate[0], int(candidate[1]), candidate[2])
|
||||
|
||||
func join_lobby(lobby : String):
|
||||
|
||||
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 : int, mid : String, index : int, sdp : String) -> int:
|
||||
|
||||
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 : int, offer : String) -> int:
|
||||
|
||||
func send_offer(id, offer) -> int:
|
||||
return _send_msg("O", id, offer)
|
||||
|
||||
func send_answer(id : int, answer : String) -> int:
|
||||
|
||||
func send_answer(id, answer) -> int:
|
||||
return _send_msg("A", id, answer)
|
||||
|
||||
func _send_msg(type : String, id : int, data : String) -> int:
|
||||
|
||||
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()
|
||||
client.poll()
|
||||
|
||||
@@ -12,53 +12,68 @@ func _ready():
|
||||
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)
|
||||
$vbox/TextEdit.text += str(msg) + "\n"
|
||||
$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($vbox/connect/host.text, $vbox/connect/RoomSecret.text)
|
||||
client.start($VBoxContainer/Connect/Host.text, $VBoxContainer/Connect/RoomSecret.text)
|
||||
|
||||
|
||||
func _on_Seal_pressed():
|
||||
client.seal_lobby()
|
||||
|
||||
|
||||
func stop():
|
||||
client.stop()
|
||||
|
||||
@@ -16,7 +16,7 @@ __meta__ = {
|
||||
[node name="Client" type="Node" parent="."]
|
||||
script = ExtResource( 2 )
|
||||
|
||||
[node name="vbox" type="VBoxContainer" parent="."]
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
custom_constants/separation = 8
|
||||
@@ -24,24 +24,24 @@ __meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="connect" type="HBoxContainer" parent="vbox"]
|
||||
[node name="Connect" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 24.0
|
||||
|
||||
[node name="Label" type="Label" parent="vbox/connect"]
|
||||
[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="vbox/connect"]
|
||||
[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="vbox/connect"]
|
||||
[node name="Room" type="Label" parent="VBoxContainer/Connect"]
|
||||
margin_left = 925.0
|
||||
margin_right = 962.0
|
||||
margin_bottom = 24.0
|
||||
@@ -49,13 +49,13 @@ size_flags_vertical = 5
|
||||
text = "Room"
|
||||
valign = 1
|
||||
|
||||
[node name="RoomSecret" type="LineEdit" parent="vbox/connect"]
|
||||
[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="vbox"]
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_top = 32.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 52.0
|
||||
@@ -64,43 +64,43 @@ __meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Start" type="Button" parent="vbox/HBoxContainer"]
|
||||
[node name="Start" type="Button" parent="VBoxContainer/HBoxContainer"]
|
||||
margin_right = 41.0
|
||||
margin_bottom = 20.0
|
||||
text = "Start"
|
||||
|
||||
[node name="Stop" type="Button" parent="vbox/HBoxContainer"]
|
||||
[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="vbox/HBoxContainer"]
|
||||
[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="vbox/HBoxContainer"]
|
||||
[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="vbox/HBoxContainer"]
|
||||
[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="vbox"]
|
||||
[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="vbox/HBoxContainer/Start" to="." method="start"]
|
||||
[connection signal="pressed" from="vbox/HBoxContainer/Stop" to="." method="stop"]
|
||||
[connection signal="pressed" from="vbox/HBoxContainer/Seal" to="." method="_on_Seal_pressed"]
|
||||
[connection signal="pressed" from="vbox/HBoxContainer/Ping" to="." method="ping"]
|
||||
[connection signal="pressed" from="vbox/HBoxContainer/Peers" to="." method="_on_Peers_pressed"]
|
||||
[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"]
|
||||
|
||||
@@ -2,13 +2,15 @@ extends Control
|
||||
|
||||
func _ready():
|
||||
if OS.get_name() == "HTML5":
|
||||
$vbox/Signaling.hide()
|
||||
$VBoxContainer/Signaling.hide()
|
||||
|
||||
|
||||
func _on_listen_toggled(button_pressed):
|
||||
if button_pressed:
|
||||
$Server.listen(int($vbox/Signaling/port.value))
|
||||
$Server.listen(int($VBoxContainer/Signaling/Port.value))
|
||||
else:
|
||||
$Server.stop()
|
||||
|
||||
|
||||
func _on_LinkButton_pressed():
|
||||
OS.shell_open("https://github.com/godotengine/webrtc-native/releases")
|
||||
|
||||
@@ -16,7 +16,7 @@ __meta__ = {
|
||||
"_edit_use_anchors_": true
|
||||
}
|
||||
|
||||
[node name="vbox" type="VBoxContainer" parent="."]
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
custom_constants/separation = 50
|
||||
@@ -24,17 +24,17 @@ __meta__ = {
|
||||
"_edit_use_anchors_": true
|
||||
}
|
||||
|
||||
[node name="Signaling" type="HBoxContainer" parent="vbox"]
|
||||
margin_right = 996.0
|
||||
[node name="Signaling" type="HBoxContainer" parent="VBoxContainer"]
|
||||
margin_right = 995.0
|
||||
margin_bottom = 24.0
|
||||
|
||||
[node name="Label" type="Label" parent="vbox/Signaling"]
|
||||
[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="vbox/Signaling"]
|
||||
[node name="Port" type="SpinBox" parent="VBoxContainer/Signaling"]
|
||||
margin_left = 108.0
|
||||
margin_right = 182.0
|
||||
margin_bottom = 24.0
|
||||
@@ -42,52 +42,52 @@ min_value = 1025.0
|
||||
max_value = 65535.0
|
||||
value = 9080.0
|
||||
|
||||
[node name="listen" type="Button" parent="vbox/Signaling"]
|
||||
[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="vbox/Signaling"]
|
||||
[node name="CenterContainer" type="CenterContainer" parent="VBoxContainer/Signaling"]
|
||||
margin_left = 241.0
|
||||
margin_right = 996.0
|
||||
margin_right = 995.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
|
||||
[node name="LinkButton" type="LinkButton" parent="vbox/Signaling/CenterContainer"]
|
||||
[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="vbox"]
|
||||
[node name="Clients" type="GridContainer" parent="VBoxContainer"]
|
||||
margin_top = 74.0
|
||||
margin_right = 996.0
|
||||
margin_bottom = 580.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="vbox/Clients" instance=ExtResource( 2 )]
|
||||
[node name="ClientUI" parent="VBoxContainer/Clients" instance=ExtResource( 2 )]
|
||||
margin_right = 490.0
|
||||
margin_bottom = 245.0
|
||||
|
||||
[node name="ClientUI2" parent="vbox/Clients" instance=ExtResource( 2 )]
|
||||
[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="vbox/Clients" instance=ExtResource( 2 )]
|
||||
[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="vbox/Clients" instance=ExtResource( 2 )]
|
||||
[node name="ClientUI4" parent="VBoxContainer/Clients" instance=ExtResource( 2 )]
|
||||
margin_left = 505.0
|
||||
margin_top = 260.0
|
||||
margin_right = 995.0
|
||||
@@ -95,5 +95,5 @@ margin_bottom = 505.0
|
||||
|
||||
[node name="Server" type="Node" parent="."]
|
||||
script = ExtResource( 3 )
|
||||
[connection signal="toggled" from="vbox/Signaling/listen" to="." method="_on_listen_toggled"]
|
||||
[connection signal="pressed" from="vbox/Signaling/CenterContainer/LinkButton" to="." method="_on_LinkButton_pressed"]
|
||||
[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"]
|
||||
|
||||
@@ -6,6 +6,11 @@ const ALFNUM = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
var _alfnum = ALFNUM.to_ascii()
|
||||
|
||||
var rand: RandomNumberGenerator = RandomNumberGenerator.new()
|
||||
var lobbies: Dictionary = {}
|
||||
var server: WebSocketServer = WebSocketServer.new()
|
||||
var peers: Dictionary = {}
|
||||
|
||||
class Peer extends Reference:
|
||||
var id = -1
|
||||
var lobby = ""
|
||||
@@ -14,6 +19,8 @@ class Peer extends Reference:
|
||||
func _init(peer_id):
|
||||
id = peer_id
|
||||
|
||||
|
||||
|
||||
class Lobby extends Reference:
|
||||
var peers : Array = []
|
||||
var host : int = -1
|
||||
@@ -23,7 +30,7 @@ class Lobby extends Reference:
|
||||
func _init(host_id : int):
|
||||
host = host_id
|
||||
|
||||
func join(peer_id : int, server : WebSocketServer) -> bool:
|
||||
func join(peer_id, server) -> bool:
|
||||
if sealed: return false
|
||||
if not server.has_peer(peer_id): return false
|
||||
var new_peer : WebSocketPeer = server.get_peer(peer_id)
|
||||
@@ -36,27 +43,29 @@ class Lobby extends Reference:
|
||||
peers.push_back(peer_id)
|
||||
return true
|
||||
|
||||
func leave(peer_id : int, server : WebSocketServer) -> bool:
|
||||
|
||||
func leave(peer_id, server) -> bool:
|
||||
if not peers.has(peer_id): return false
|
||||
peers.erase(peer_id)
|
||||
var close = false
|
||||
if peer_id == host:
|
||||
# The room host disconnected, will disconnect all peers
|
||||
# The room host disconnected, will disconnect all peers.
|
||||
close = true
|
||||
if sealed: return close
|
||||
# Notify other peers
|
||||
# Notify other peers.
|
||||
for p in peers:
|
||||
if not server.has_peer(p): return close
|
||||
if close:
|
||||
# Disconnect peers
|
||||
# Disconnect peers.
|
||||
server.disconnect_peer(p)
|
||||
else:
|
||||
# Notify disconnection
|
||||
# Notify disconnection.
|
||||
server.get_peer(p).put_packet(("D: %d\n" % peer_id).to_utf8())
|
||||
return close
|
||||
|
||||
func seal(peer_id : int, server : WebSocketServer) -> bool:
|
||||
# Only host can seal the room
|
||||
|
||||
func seal(peer_id, server) -> bool:
|
||||
# Only host can seal the room.
|
||||
if host != peer_id: return false
|
||||
sealed = true
|
||||
for p in peers:
|
||||
@@ -64,51 +73,54 @@ class Lobby extends Reference:
|
||||
time = OS.get_ticks_msec()
|
||||
return true
|
||||
|
||||
var rand : RandomNumberGenerator = RandomNumberGenerator.new()
|
||||
var lobbies : Dictionary = {}
|
||||
var server : WebSocketServer = WebSocketServer.new()
|
||||
var peers : Dictionary = {}
|
||||
|
||||
|
||||
func _init():
|
||||
server.connect("data_received", self, "_on_data")
|
||||
server.connect("client_connected", self, "_peer_connected")
|
||||
server.connect("client_disconnected", self, "_peer_disconnected")
|
||||
|
||||
|
||||
func _process(delta):
|
||||
poll()
|
||||
|
||||
func listen(port : int):
|
||||
|
||||
func listen(port):
|
||||
stop()
|
||||
rand.seed = OS.get_unix_time()
|
||||
server.listen(port)
|
||||
|
||||
|
||||
func stop():
|
||||
server.stop()
|
||||
peers.clear()
|
||||
|
||||
|
||||
func poll():
|
||||
if not server.is_listening():
|
||||
return
|
||||
|
||||
server.poll()
|
||||
|
||||
# Peers timeout
|
||||
# Peers timeout.
|
||||
for p in peers.values():
|
||||
if p.lobby == "" and OS.get_ticks_msec() - p.time > TIMEOUT:
|
||||
server.disconnect_peer(p.id)
|
||||
# Lobby seal
|
||||
# Lobby seal.
|
||||
for k in lobbies:
|
||||
if not lobbies[k].sealed:
|
||||
continue
|
||||
if lobbies[k].time + SEAL_TIME < OS.get_ticks_msec():
|
||||
# Close lobby
|
||||
# Close lobby.
|
||||
for p in lobbies[k].peers:
|
||||
server.disconnect_peer(p)
|
||||
|
||||
func _peer_connected(id : int, protocol = ""):
|
||||
|
||||
func _peer_connected(id, protocol = ""):
|
||||
peers[id] = Peer.new(id)
|
||||
|
||||
func _peer_disconnected(id : int, was_clean : bool = false):
|
||||
|
||||
func _peer_disconnected(id, was_clean = false):
|
||||
var lobby = peers[id].lobby
|
||||
print("Peer %d disconnected from lobby: '%s'" % [id, lobby])
|
||||
if lobby and lobbies.has(lobby):
|
||||
@@ -119,9 +131,10 @@ func _peer_disconnected(id : int, was_clean : bool = false):
|
||||
lobbies.erase(lobby)
|
||||
peers.erase(id)
|
||||
|
||||
func _join_lobby(peer, lobby : String) -> bool:
|
||||
|
||||
func _join_lobby(peer, lobby) -> bool:
|
||||
if lobby == "":
|
||||
for i in range(0, 32):
|
||||
for _i in range(0, 32):
|
||||
lobby += char(_alfnum[rand.randi_range(0, ALFNUM.length()-1)])
|
||||
lobbies[lobby] = Lobby.new(peer.id)
|
||||
elif not lobbies.has(lobby):
|
||||
@@ -133,19 +146,21 @@ func _join_lobby(peer, lobby : String) -> bool:
|
||||
print("Peer %d joined lobby: '%s'" % [peer.id, lobby])
|
||||
return true
|
||||
|
||||
func _on_data(id : int):
|
||||
|
||||
func _on_data(id):
|
||||
if not _parse_msg(id):
|
||||
print("Parse message failed from peer %d" % id)
|
||||
server.disconnect_peer(id)
|
||||
|
||||
func _parse_msg(id : int) -> bool:
|
||||
var pkt_str : String = server.get_peer(id).get_packet().get_string_from_utf8()
|
||||
|
||||
var req : PoolStringArray = pkt_str.split('\n', true, 1)
|
||||
func _parse_msg(id) -> bool:
|
||||
var pkt_str: String = server.get_peer(id).get_packet().get_string_from_utf8()
|
||||
|
||||
var req = pkt_str.split('\n', true, 1)
|
||||
if req.size() != 2: # Invalid request size
|
||||
return false
|
||||
|
||||
var type : String = req[0]
|
||||
var type = req[0]
|
||||
if type.length() < 3: # Invalid type size
|
||||
return false
|
||||
|
||||
@@ -192,4 +207,4 @@ func _parse_msg(id : int) -> bool:
|
||||
elif type.begins_with("C: "):
|
||||
# Client is making an answer
|
||||
server.get_peer(dest_id).put_packet(("C: %d\n%s" % [id, req[1]]).to_utf8())
|
||||
return true
|
||||
return true
|
||||
|
||||
@@ -19,30 +19,37 @@ func _init():
|
||||
_client.connect("connection_succeeded", self, "_client_connected", ["multiplayer_protocol"])
|
||||
_client.connect("connection_failed", self, "_client_disconnected")
|
||||
|
||||
|
||||
func _client_close_request(code, reason):
|
||||
Utils._log(_log_dest, "Close code: %d, reason: %s" % [code, reason])
|
||||
|
||||
|
||||
func _peer_connected(id):
|
||||
Utils._log(_log_dest, "%s: Client just connected" % id)
|
||||
last_connected_client = id
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
_client.disconnect_from_host(1001, "Bye bye!")
|
||||
|
||||
func _process(delta):
|
||||
|
||||
func _process(_delta):
|
||||
if _client.get_connection_status() == WebSocketClient.CONNECTION_DISCONNECTED:
|
||||
return
|
||||
|
||||
_client.poll()
|
||||
|
||||
|
||||
func _client_connected(protocol):
|
||||
Utils._log(_log_dest, "Client just connected with protocol: %s" % protocol)
|
||||
_client.get_peer(1).set_write_mode(_write_mode)
|
||||
|
||||
|
||||
func _client_disconnected(clean=true):
|
||||
Utils._log(_log_dest, "Client just disconnected. Was clean: %s" % clean)
|
||||
|
||||
func _client_received(p_id = 1):
|
||||
|
||||
func _client_received(_p_id = 1):
|
||||
if _use_multiplayer:
|
||||
var peer_id = _client.get_packet_peer()
|
||||
var packet = _client.get_packet()
|
||||
@@ -52,15 +59,18 @@ func _client_received(p_id = 1):
|
||||
var is_string = _client.get_peer(1).was_string_packet()
|
||||
Utils._log(_log_dest, "Received data. BINARY: %s: %s" % [not is_string, Utils.decode_data(packet, is_string)])
|
||||
|
||||
|
||||
func connect_to_url(host, protocols, multiplayer):
|
||||
_use_multiplayer = multiplayer
|
||||
if _use_multiplayer:
|
||||
_write_mode = WebSocketPeer.WRITE_MODE_BINARY
|
||||
return _client.connect_to_url(host, protocols, multiplayer)
|
||||
|
||||
|
||||
func disconnect_from_host():
|
||||
_client.disconnect_from_host(1000, "Bye bye!")
|
||||
|
||||
|
||||
func send_data(data, dest):
|
||||
_client.get_peer(1).set_write_mode(_write_mode)
|
||||
if _use_multiplayer:
|
||||
@@ -69,5 +79,6 @@ func send_data(data, dest):
|
||||
else:
|
||||
_client.get_peer(1).put_packet(Utils.encode_data(data, _write_mode))
|
||||
|
||||
|
||||
func set_write_mode(mode):
|
||||
_write_mode = mode
|
||||
|
||||
@@ -14,23 +14,14 @@ __meta__ = {
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Panel"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Connect" type="HBoxContainer" parent="Panel/VBoxContainer"]
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 24.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Host" type="LineEdit" parent="Panel/VBoxContainer/Connect"]
|
||||
margin_right = 956.0
|
||||
@@ -38,9 +29,6 @@ margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
text = "ws://localhost:8000/test/"
|
||||
placeholder_text = "ws://my.server/path/"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Connect" type="Button" parent="Panel/VBoxContainer/Connect"]
|
||||
margin_left = 960.0
|
||||
@@ -48,83 +36,53 @@ margin_right = 1024.0
|
||||
margin_bottom = 24.0
|
||||
toggle_mode = true
|
||||
text = "Connect"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Settings" type="HBoxContainer" parent="Panel/VBoxContainer"]
|
||||
margin_top = 28.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 52.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Mode" type="OptionButton" parent="Panel/VBoxContainer/Settings"]
|
||||
margin_right = 41.0
|
||||
margin_right = 29.0
|
||||
margin_bottom = 24.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Multiplayer" type="CheckBox" parent="Panel/VBoxContainer/Settings"]
|
||||
margin_left = 45.0
|
||||
margin_right = 171.0
|
||||
margin_left = 33.0
|
||||
margin_right = 159.0
|
||||
margin_bottom = 24.0
|
||||
pressed = true
|
||||
text = "Multiplayer API"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Destination" type="OptionButton" parent="Panel/VBoxContainer/Settings"]
|
||||
margin_left = 175.0
|
||||
margin_right = 216.0
|
||||
margin_left = 163.0
|
||||
margin_right = 192.0
|
||||
margin_bottom = 24.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Send" type="HBoxContainer" parent="Panel/VBoxContainer"]
|
||||
margin_top = 56.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 80.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="LineEdit" type="LineEdit" parent="Panel/VBoxContainer/Send"]
|
||||
margin_right = 977.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
placeholder_text = "Enter some text to send..."
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Send" type="Button" parent="Panel/VBoxContainer/Send"]
|
||||
margin_left = 981.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 24.0
|
||||
text = "Send"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="Panel/VBoxContainer"]
|
||||
margin_top = 84.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 600.0
|
||||
size_flags_vertical = 3
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Client" type="Node" parent="."]
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
[connection signal="toggled" from="Panel/VBoxContainer/Connect/Connect" to="." method="_on_Connect_toggled"]
|
||||
[connection signal="item_selected" from="Panel/VBoxContainer/Settings/Mode" to="." method="_on_Mode_item_selected"]
|
||||
[connection signal="pressed" from="Panel/VBoxContainer/Send/Send" to="." method="_on_Send_pressed"]
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
extends Control
|
||||
|
||||
onready var _client = get_node("Client")
|
||||
onready var _log_dest = get_node("Panel/VBoxContainer/RichTextLabel")
|
||||
onready var _line_edit = get_node("Panel/VBoxContainer/Send/LineEdit")
|
||||
onready var _host = get_node("Panel/VBoxContainer/Connect/Host")
|
||||
onready var _multiplayer = get_node("Panel/VBoxContainer/Settings/Multiplayer")
|
||||
onready var _write_mode = get_node("Panel/VBoxContainer/Settings/Mode")
|
||||
onready var _destination = get_node("Panel/VBoxContainer/Settings/Destination")
|
||||
onready var _client = $Client
|
||||
onready var _log_dest = $Panel/VBoxContainer/RichTextLabel
|
||||
onready var _line_edit = $Panel/VBoxContainer/Send/LineEdit
|
||||
onready var _host = $Panel/VBoxContainer/Connect/Host
|
||||
onready var _multiplayer = $Panel/VBoxContainer/Settings/Multiplayer
|
||||
onready var _write_mode = $Panel/VBoxContainer/Settings/Mode
|
||||
onready var _destination = $Panel/VBoxContainer/Settings/Destination
|
||||
|
||||
func _ready():
|
||||
_write_mode.clear()
|
||||
@@ -23,9 +23,11 @@ func _ready():
|
||||
_destination.set_item_metadata(2, -1)
|
||||
_destination.select(0)
|
||||
|
||||
func _on_Mode_item_selected( ID ):
|
||||
|
||||
func _on_Mode_item_selected(_id):
|
||||
_client.set_write_mode(_write_mode.get_selected_metadata())
|
||||
|
||||
|
||||
func _on_Send_pressed():
|
||||
if _line_edit.text == "":
|
||||
return
|
||||
@@ -40,6 +42,7 @@ func _on_Send_pressed():
|
||||
_client.send_data(_line_edit.text, dest)
|
||||
_line_edit.text = ""
|
||||
|
||||
|
||||
func _on_Connect_toggled( pressed ):
|
||||
if pressed:
|
||||
var multiplayer = _multiplayer.pressed
|
||||
|
||||
@@ -7,17 +7,11 @@
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
mouse_filter = 1
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Box" type="HBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
custom_constants/separation = 20
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="ServerControl" parent="Box" instance=ExtResource( 1 )]
|
||||
anchor_right = 0.0
|
||||
@@ -31,9 +25,6 @@ margin_left = 522.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 600.0
|
||||
size_flags_horizontal = 3
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Client" parent="Box/VBoxContainer" instance=ExtResource( 2 )]
|
||||
anchor_right = 0.0
|
||||
|
||||
@@ -18,29 +18,35 @@ func _init():
|
||||
_server.connect("peer_connected", self, "_client_connected", ["multiplayer_protocol"])
|
||||
_server.connect("peer_disconnected", self, "_client_disconnected")
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
_clients.clear()
|
||||
_server.stop()
|
||||
|
||||
func _process(delta):
|
||||
|
||||
func _process(_delta):
|
||||
if _server.is_listening():
|
||||
_server.poll()
|
||||
|
||||
|
||||
func _client_close_request(id, code, reason):
|
||||
print(reason == "Bye bye!")
|
||||
Utils._log(_log_dest, "Client %s close code: %d, reason: %s" % [id, code, reason])
|
||||
|
||||
|
||||
func _client_connected(id, protocol):
|
||||
_clients[id] = _server.get_peer(id)
|
||||
_clients[id].set_write_mode(_write_mode)
|
||||
last_connected_client = id
|
||||
Utils._log(_log_dest, "%s: Client connected with protocol %s" % [id, protocol])
|
||||
|
||||
|
||||
func _client_disconnected(id, clean = true):
|
||||
Utils._log(_log_dest, "Client %s disconnected. Was clean: %s" % [id, clean])
|
||||
if _clients.has(id):
|
||||
_clients.erase(id)
|
||||
|
||||
|
||||
func _client_receive(id):
|
||||
if _use_multiplayer:
|
||||
var peer_id = _server.get_packet_peer()
|
||||
@@ -51,6 +57,7 @@ func _client_receive(id):
|
||||
var is_string = _server.get_peer(id).was_string_packet()
|
||||
Utils._log(_log_dest, "Data from %s BINARY: %s: %s" % [id, not is_string, Utils.decode_data(packet, is_string)])
|
||||
|
||||
|
||||
func send_data(data, dest):
|
||||
if _use_multiplayer:
|
||||
_server.set_target_peer(dest)
|
||||
@@ -59,15 +66,18 @@ func send_data(data, dest):
|
||||
for id in _clients:
|
||||
_server.get_peer(id).put_packet(Utils.encode_data(data, _write_mode))
|
||||
|
||||
|
||||
func listen(port, supported_protocols, multiplayer):
|
||||
_use_multiplayer = multiplayer
|
||||
if _use_multiplayer:
|
||||
set_write_mode(WebSocketPeer.WRITE_MODE_BINARY)
|
||||
return _server.listen(port, supported_protocols, multiplayer)
|
||||
|
||||
|
||||
func stop():
|
||||
_server.stop()
|
||||
|
||||
|
||||
func set_write_mode(mode):
|
||||
_write_mode = mode
|
||||
for c in _clients:
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
extends Control
|
||||
|
||||
onready var _server = get_node("Server")
|
||||
onready var _port = get_node("Panel/VBoxContainer/HBoxContainer/Port")
|
||||
onready var _line_edit = get_node("Panel/VBoxContainer/HBoxContainer3/LineEdit")
|
||||
onready var _write_mode = get_node("Panel/VBoxContainer/HBoxContainer2/WriteMode")
|
||||
onready var _log_dest = get_node("Panel/VBoxContainer/RichTextLabel")
|
||||
onready var _multiplayer = get_node("Panel/VBoxContainer/HBoxContainer2/MPAPI")
|
||||
onready var _destination = get_node("Panel/VBoxContainer/HBoxContainer2/Destination")
|
||||
onready var _server = $Server
|
||||
onready var _port = $Panel/VBoxContainer/HBoxContainer/Port
|
||||
onready var _line_edit = $Panel/VBoxContainer/HBoxContainer3/LineEdit
|
||||
onready var _write_mode = $Panel/VBoxContainer/HBoxContainer2/WriteMode
|
||||
onready var _log_dest = $Panel/VBoxContainer/RichTextLabel
|
||||
onready var _multiplayer = $Panel/VBoxContainer/HBoxContainer2/MPAPI
|
||||
onready var _destination = $Panel/VBoxContainer/HBoxContainer2/Destination
|
||||
|
||||
func _ready():
|
||||
_write_mode.clear()
|
||||
@@ -24,7 +24,8 @@ func _ready():
|
||||
_destination.set_item_metadata(2, -1)
|
||||
_destination.select(0)
|
||||
|
||||
func _on_Listen_toggled( pressed ):
|
||||
|
||||
func _on_Listen_toggled(pressed):
|
||||
if pressed:
|
||||
var use_multiplayer = _multiplayer.pressed
|
||||
_multiplayer.disabled = true
|
||||
@@ -49,6 +50,7 @@ func _on_Listen_toggled( pressed ):
|
||||
_destination.disabled = false
|
||||
Utils._log(_log_dest, "Server stopped")
|
||||
|
||||
|
||||
func _on_Send_pressed():
|
||||
if _line_edit.text == "":
|
||||
return
|
||||
@@ -63,5 +65,6 @@ func _on_Send_pressed():
|
||||
_server.send_data(_line_edit.text, dest)
|
||||
_line_edit.text = ""
|
||||
|
||||
func _on_WriteMode_item_selected( ID ):
|
||||
|
||||
func _on_WriteMode_item_selected(_id):
|
||||
_server.set_write_mode(_write_mode.get_selected_metadata())
|
||||
|
||||
@@ -3,9 +3,11 @@ extends Node
|
||||
func encode_data(data, mode):
|
||||
return data.to_utf8() if mode == WebSocketPeer.WRITE_MODE_TEXT else var2bytes(data)
|
||||
|
||||
|
||||
func decode_data(data, is_string):
|
||||
return data.get_string_from_utf8() if is_string else bytes2var(data)
|
||||
|
||||
|
||||
func _log(node, msg):
|
||||
print(msg)
|
||||
node.add_text(str(msg) + "\n")
|
||||
|
||||
@@ -4,18 +4,9 @@
|
||||
[ext_resource path="res://client.gd" type="Script" id=2]
|
||||
|
||||
[node name="Main" type="Node"]
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Server" type="Node" parent="."]
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Client" type="Node" parent="."]
|
||||
script = ExtResource( 2 )
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
extends Node
|
||||
|
||||
# The URL we will connect to
|
||||
# The URL we will connect to.
|
||||
export var websocket_url = "ws://localhost:9080"
|
||||
|
||||
# Our WebSocketClient instance
|
||||
# Our WebSocketClient instance.
|
||||
var _client = WebSocketClient.new()
|
||||
|
||||
func _ready():
|
||||
@@ -22,12 +22,14 @@ func _ready():
|
||||
print("Unable to connect")
|
||||
set_process(false)
|
||||
|
||||
|
||||
func _closed(was_clean = false):
|
||||
# was_clean will tell you if the disconnection was correctly notified
|
||||
# by the remote peer before closing the socket.
|
||||
print("Closed, clean: ", was_clean)
|
||||
set_process(false)
|
||||
|
||||
|
||||
func _connected(proto = ""):
|
||||
# This is called on connection, "proto" will be the selected WebSocket
|
||||
# sub-protocol (which is optional)
|
||||
@@ -36,16 +38,19 @@ func _connected(proto = ""):
|
||||
# and not put_packet directly when not using the MultiplayerAPI.
|
||||
_client.get_peer(1).put_packet("Test packet".to_utf8())
|
||||
|
||||
|
||||
func _on_data():
|
||||
# Print the received packet, you MUST always use get_peer(1).get_packet
|
||||
# to receive data from server, and not get_packet directly when not
|
||||
# using the MultiplayerAPI.
|
||||
print("Got data from server: ", _client.get_peer(1).get_packet().get_string_from_utf8())
|
||||
|
||||
|
||||
func _process(delta):
|
||||
# Call this in _process or _physics_process. Data transfer, and signals
|
||||
# emission will only happen when calling this function.
|
||||
_client.poll()
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
_client.disconnect_from_host()
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
extends Node
|
||||
|
||||
# The port we will listen to
|
||||
# The port we will listen to.
|
||||
const PORT = 9080
|
||||
# Our WebSocketServer instance
|
||||
# Our WebSocketServer instance.
|
||||
var _server = WebSocketServer.new()
|
||||
|
||||
func _ready():
|
||||
@@ -22,22 +22,26 @@ func _ready():
|
||||
print("Unable to start server")
|
||||
set_process(false)
|
||||
|
||||
|
||||
func _connected(id, proto):
|
||||
# This is called when a new peer connects, "id" will be the assigned peer id,
|
||||
# "proto" will be the selected WebSocket sub-protocol (which is optional)
|
||||
print("Client %d connected with protocol: %s" % [id, proto])
|
||||
|
||||
|
||||
func _close_request(id, code, reason):
|
||||
# This is called when a client notifies that it wishes to close the connection,
|
||||
# providing a reason string and close code.
|
||||
print("Client %d disconnecting with code: %d, reason: %s" % [id, code, reason])
|
||||
|
||||
|
||||
func _disconnected(id, was_clean = false):
|
||||
# This is called when a client disconnects, "id" will be the one of the
|
||||
# disconnecting client, "was_clean" will tell you if the disconnection
|
||||
# was correctly notified by the remote peer before closing the socket.
|
||||
print("Client %d disconnected, clean: %s" % [id, str(was_clean)])
|
||||
|
||||
|
||||
func _on_data(id):
|
||||
# Print the received packet, you MUST always use get_peer(id).get_packet to receive data,
|
||||
# and not get_packet directly when not using the MultiplayerAPI.
|
||||
@@ -45,10 +49,12 @@ func _on_data(id):
|
||||
print("Got data from client %d: %s ... echoing" % [id, pkt.get_string_from_utf8()])
|
||||
_server.get_peer(id).put_packet(pkt)
|
||||
|
||||
|
||||
func _process(delta):
|
||||
# Call this in _process or _physics_process.
|
||||
# Data transfer, and signals emission will only happen when calling this function.
|
||||
_server.poll()
|
||||
|
||||
|
||||
func _exit_tree():
|
||||
_server.stop()
|
||||
|
||||
@@ -8,13 +8,7 @@ ground_bottom_color = Color( 0.101961, 0.145098, 0.188235, 1 )
|
||||
ground_horizon_color = Color( 0.482353, 0.788235, 0.952941, 1 )
|
||||
ground_curve = 0.01
|
||||
sun_energy = 16.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[resource]
|
||||
background_mode = 2
|
||||
background_sky = SubResource( 1 )
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
@@ -16,34 +16,22 @@ __meta__ = {
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="RichTextLabel" type="RichTextLabel" parent="HBoxContainer"]
|
||||
margin_right = 510.0
|
||||
margin_bottom = 600.0
|
||||
size_flags_horizontal = 3
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer"]
|
||||
margin_left = 514.0
|
||||
margin_right = 1024.0
|
||||
margin_bottom = 600.0
|
||||
size_flags_horizontal = 3
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="HBoxContainer/VBoxContainer"]
|
||||
margin_right = 510.0
|
||||
margin_bottom = 14.0
|
||||
text = "Players:"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="ItemList" type="ItemList" parent="HBoxContainer/VBoxContainer"]
|
||||
margin_top = 18.0
|
||||
@@ -52,9 +40,6 @@ margin_bottom = 576.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
same_column_width = true
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Action" type="Button" parent="HBoxContainer/VBoxContainer"]
|
||||
margin_top = 580.0
|
||||
@@ -62,7 +47,4 @@ margin_right = 510.0
|
||||
margin_bottom = 600.0
|
||||
disabled = true
|
||||
text = "Do Action!"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
[connection signal="pressed" from="HBoxContainer/VBoxContainer/Action" to="." method="_on_Action_pressed"]
|
||||
|
||||
@@ -3,20 +3,17 @@
|
||||
[ext_resource path="res://script/main.gd" type="Script" id=1]
|
||||
[ext_resource path="res://scene/game.tscn" type="PackedScene" id=2]
|
||||
|
||||
[node name="Control" type="Control"]
|
||||
[node name="Main" type="Control"]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Panel" type="Panel" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="Panel"]
|
||||
anchor_right = 1.0
|
||||
@@ -25,16 +22,10 @@ margin_left = 20.0
|
||||
margin_top = 20.0
|
||||
margin_right = -20.0
|
||||
margin_bottom = -20.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Panel/VBoxContainer"]
|
||||
margin_right = 984.0
|
||||
margin_bottom = 24.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Label" type="Label" parent="Panel/VBoxContainer/HBoxContainer"]
|
||||
margin_top = 5.0
|
||||
@@ -42,9 +33,6 @@ margin_right = 326.0
|
||||
margin_bottom = 19.0
|
||||
size_flags_horizontal = 3
|
||||
text = "Name"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="NameEdit" type="LineEdit" parent="Panel/VBoxContainer/HBoxContainer"]
|
||||
margin_left = 330.0
|
||||
@@ -53,51 +41,33 @@ margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "A Godot User"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="HBoxContainer2" type="HBoxContainer" parent="Panel/VBoxContainer"]
|
||||
margin_top = 28.0
|
||||
margin_right = 984.0
|
||||
margin_bottom = 52.0
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="HBoxContainer" type="HBoxContainer" parent="Panel/VBoxContainer/HBoxContainer2"]
|
||||
margin_right = 326.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Host" type="Button" parent="Panel/VBoxContainer/HBoxContainer2/HBoxContainer"]
|
||||
margin_right = 42.0
|
||||
margin_bottom = 24.0
|
||||
text = "Host"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Control" type="Control" parent="Panel/VBoxContainer/HBoxContainer2/HBoxContainer"]
|
||||
margin_left = 46.0
|
||||
margin_right = 241.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Connect" type="Button" parent="Panel/VBoxContainer/HBoxContainer2/HBoxContainer"]
|
||||
margin_left = 245.0
|
||||
margin_right = 326.0
|
||||
margin_bottom = 24.0
|
||||
text = "Connect to"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Disconnect" type="Button" parent="Panel/VBoxContainer/HBoxContainer2/HBoxContainer"]
|
||||
visible = false
|
||||
@@ -105,9 +75,6 @@ margin_left = 68.0
|
||||
margin_right = 152.0
|
||||
margin_bottom = 24.0
|
||||
text = "Disconnect"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Hostname" type="LineEdit" parent="Panel/VBoxContainer/HBoxContainer2"]
|
||||
margin_left = 330.0
|
||||
@@ -117,18 +84,12 @@ size_flags_horizontal = 3
|
||||
size_flags_stretch_ratio = 2.0
|
||||
text = "localhost"
|
||||
placeholder_text = "localhost"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Control" type="Control" parent="Panel/VBoxContainer"]
|
||||
margin_top = 56.0
|
||||
margin_right = 984.0
|
||||
margin_bottom = 76.0
|
||||
rect_min_size = Vector2( 0, 20 )
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
|
||||
[node name="Game" parent="Panel/VBoxContainer" instance=ExtResource( 2 )]
|
||||
anchor_right = 0.0
|
||||
@@ -147,9 +108,6 @@ margin_top = -100.0
|
||||
margin_right = 200.0
|
||||
margin_bottom = 100.0
|
||||
dialog_text = "Connection closed"
|
||||
__meta__ = {
|
||||
|
||||
}
|
||||
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Host" to="." method="_on_Host_pressed"]
|
||||
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Connect" to="." method="_on_Connect_pressed"]
|
||||
[connection signal="pressed" from="Panel/VBoxContainer/HBoxContainer2/HBoxContainer/Disconnect" to="." method="_on_Disconnect_pressed"]
|
||||
|
||||
@@ -12,11 +12,13 @@ master func set_player_name(name):
|
||||
var sender = get_tree().get_rpc_sender_id()
|
||||
rpc("update_player_name", sender, name)
|
||||
|
||||
|
||||
sync func update_player_name(player, name):
|
||||
var pos = _players.find(player)
|
||||
if pos != -1:
|
||||
_list.set_item_text(pos, name)
|
||||
|
||||
|
||||
master func request_action(action):
|
||||
var sender = get_tree().get_rpc_sender_id()
|
||||
if _players[_turn] != get_tree().get_rpc_sender_id():
|
||||
@@ -25,11 +27,13 @@ master func request_action(action):
|
||||
do_action(action)
|
||||
next_turn()
|
||||
|
||||
|
||||
sync func do_action(action):
|
||||
var name = _list.get_item_text(_turn)
|
||||
var val = randi() % 100
|
||||
rpc("_log", "%s: %ss %d" % [name, action, val])
|
||||
|
||||
|
||||
sync func set_turn(turn):
|
||||
_turn = turn
|
||||
if turn >= _players.size():
|
||||
@@ -41,6 +45,7 @@ sync func set_turn(turn):
|
||||
_list.set_item_icon(i, null)
|
||||
_action.disabled = _players[turn] != get_tree().get_network_unique_id()
|
||||
|
||||
|
||||
sync func del_player(id):
|
||||
var pos = _players.find(id)
|
||||
if pos == -1:
|
||||
@@ -52,6 +57,7 @@ sync func del_player(id):
|
||||
if get_tree().is_network_server():
|
||||
rpc("set_turn", _turn)
|
||||
|
||||
|
||||
sync func add_player(id, name=""):
|
||||
_players.append(id)
|
||||
if name == "":
|
||||
@@ -59,27 +65,32 @@ sync func add_player(id, name=""):
|
||||
else:
|
||||
_list.add_item(name, null, false)
|
||||
|
||||
|
||||
func get_player_name(pos):
|
||||
if pos < _list.get_item_count():
|
||||
return _list.get_item_text(pos)
|
||||
else:
|
||||
return "Error!"
|
||||
|
||||
|
||||
func next_turn():
|
||||
_turn += 1
|
||||
if _turn >= _players.size():
|
||||
_turn = 0
|
||||
rpc("set_turn", _turn)
|
||||
|
||||
|
||||
func start():
|
||||
set_turn(0)
|
||||
|
||||
|
||||
func stop():
|
||||
_players.clear()
|
||||
_list.clear()
|
||||
_turn = 0
|
||||
_action.disabled = true
|
||||
|
||||
|
||||
func on_peer_add(id):
|
||||
if not get_tree().is_network_server():
|
||||
return
|
||||
@@ -88,14 +99,17 @@ func on_peer_add(id):
|
||||
rpc("add_player", id)
|
||||
rpc_id(id, "set_turn", _turn)
|
||||
|
||||
|
||||
func on_peer_del(id):
|
||||
if not get_tree().is_network_server():
|
||||
return
|
||||
rpc("del_player", id)
|
||||
|
||||
|
||||
sync func _log(what):
|
||||
$HBoxContainer/RichTextLabel.add_text(what + "\n")
|
||||
|
||||
|
||||
func _on_Action_pressed():
|
||||
if get_tree().is_network_server():
|
||||
do_action("roll")
|
||||
|
||||
@@ -11,10 +11,18 @@ onready var _host_edit = $Panel/VBoxContainer/HBoxContainer2/Hostname
|
||||
onready var _game = $Panel/VBoxContainer/Game
|
||||
|
||||
func _ready():
|
||||
#warning-ignore-all:return_value_discarded
|
||||
get_tree().connect("network_peer_disconnected", self, "_peer_disconnected")
|
||||
get_tree().connect("network_peer_connected", self, "_peer_connected")
|
||||
$AcceptDialog.get_label().align = Label.ALIGN_CENTER
|
||||
$AcceptDialog.get_label().valign = Label.VALIGN_CENTER
|
||||
# Set the player name according to the system username. Fallback to the path.
|
||||
if OS.has_environment("USERNAME"):
|
||||
_name_edit.text = OS.get_environment("USERNAME")
|
||||
else:
|
||||
var desktop_path = OS.get_system_dir(0).replace("\\", "/").split("/")
|
||||
_name_edit.text = desktop_path[desktop_path.size() - 2]
|
||||
|
||||
|
||||
func start_game():
|
||||
_host_btn.disabled = true
|
||||
@@ -24,6 +32,7 @@ func start_game():
|
||||
_disconnect_btn.show()
|
||||
_game.start()
|
||||
|
||||
|
||||
func stop_game():
|
||||
_host_btn.disabled = false
|
||||
_name_edit.editable = true
|
||||
@@ -32,6 +41,7 @@ func stop_game():
|
||||
_connect_btn.show()
|
||||
_game.stop()
|
||||
|
||||
|
||||
func _close_network():
|
||||
if get_tree().is_connected("server_disconnected", self, "_close_network"):
|
||||
get_tree().disconnect("server_disconnected", self, "_close_network")
|
||||
@@ -44,15 +54,19 @@ func _close_network():
|
||||
$AcceptDialog.get_close_button().grab_focus()
|
||||
get_tree().set_network_peer(null)
|
||||
|
||||
|
||||
func _connected():
|
||||
_game.rpc("set_player_name", _name_edit.text)
|
||||
|
||||
|
||||
func _peer_connected(id):
|
||||
_game.on_peer_add(id)
|
||||
|
||||
|
||||
func _peer_disconnected(id):
|
||||
_game.on_peer_del(id)
|
||||
|
||||
|
||||
func _on_Host_pressed():
|
||||
var host = WebSocketServer.new()
|
||||
host.listen(DEF_PORT, PoolStringArray(["ludus"]), true)
|
||||
@@ -61,9 +75,11 @@ func _on_Host_pressed():
|
||||
_game.add_player(1, _name_edit.text)
|
||||
start_game()
|
||||
|
||||
|
||||
func _on_Disconnect_pressed():
|
||||
_close_network()
|
||||
|
||||
|
||||
func _on_Connect_pressed():
|
||||
var host = WebSocketClient.new()
|
||||
host.connect_to_url("ws://" + _host_edit.text + ":" + str(DEF_PORT), PoolStringArray([PROTO_NAME]), true)
|
||||
|
||||
Reference in New Issue
Block a user