Update WebSocket Minimal demo for Godot 4.1 (#990)

This commit is contained in:
Alex
2023-10-30 18:44:30 +01:00
committed by GitHub
parent 232eb35acf
commit 7af99c55ef
5 changed files with 122 additions and 95 deletions

View File

@@ -6,7 +6,74 @@
[node name="Main" type="Node"]
[node name="Server" type="Node" parent="."]
script = ExtResource( "1" )
script = ExtResource("1")
[node name="Client" type="Node" parent="."]
script = ExtResource( "2" )
script = ExtResource("2")
[node name="Control" type="Control" parent="."]
layout_mode = 3
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="HBoxContainer" type="HBoxContainer" parent="Control"]
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
grow_horizontal = 2
grow_vertical = 2
[node name="ServerContainer" type="VBoxContainer" parent="Control/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="LabelServer" type="Label" parent="Control/HBoxContainer/ServerContainer"]
layout_mode = 2
size_flags_horizontal = 4
theme_override_colors/font_color = Color(0.666667, 0.666667, 0.666667, 1)
theme_override_font_sizes/font_size = 30
text = "Server"
[node name="ButtonPong" type="Button" parent="Control/HBoxContainer/ServerContainer"]
layout_mode = 2
size_flags_horizontal = 4
theme_override_font_sizes/font_size = 30
text = "Send Pong"
[node name="TextServer" type="RichTextLabel" parent="Control/HBoxContainer/ServerContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
bbcode_enabled = true
scroll_following = true
[node name="ClientContainer" type="VBoxContainer" parent="Control/HBoxContainer"]
layout_mode = 2
size_flags_horizontal = 3
[node name="LabelClient" type="Label" parent="Control/HBoxContainer/ClientContainer"]
layout_mode = 2
size_flags_horizontal = 4
theme_override_colors/font_color = Color(0.666667, 0.666667, 0.666667, 1)
theme_override_font_sizes/font_size = 30
text = "Client"
[node name="ButtonPing" type="Button" parent="Control/HBoxContainer/ClientContainer"]
layout_mode = 2
size_flags_horizontal = 4
theme_override_font_sizes/font_size = 30
text = "Send Ping"
[node name="TextClient" type="RichTextLabel" parent="Control/HBoxContainer/ClientContainer"]
unique_name_in_owner = true
layout_mode = 2
size_flags_vertical = 3
bbcode_enabled = true
scroll_following = true
[connection signal="pressed" from="Control/HBoxContainer/ServerContainer/ButtonPong" to="Server" method="_on_button_pong_pressed"]
[connection signal="pressed" from="Control/HBoxContainer/ClientContainer/ButtonPing" to="Client" method="_on_button_ping_pressed"]

View File

@@ -4,6 +4,6 @@ This is a minimal sample of connecting two peers to each other using websockets.
Language: GDScript
Renderer: GLES 2
Renderer: Forward+
Check out this demo on the asset library: https://godotengine.org/asset-library/asset/539

View File

@@ -1,56 +1,32 @@
extends Node
# The URL we will connect to.
@export var websocket_url = "ws://localhost:9080"
var websocket_url = "ws://localhost:9080"
var socket := WebSocketPeer.new()
func log_message(message):
var time = "[color=#aaaaaa] %s [/color]" % Time.get_time_string_from_system()
%TextClient.text += time + message + "\n"
# Our WebSocketClient instance.
var _client = WebSocketClient.new()
func _ready():
# Connect base signals to get notified of connection open, close, and errors.
_client.connection_closed.connect(self._closed)
_client.connection_error.connect(self._closed)
_client.connection_established.connect(self._connected)
# This signal is emitted when not using the Multiplayer API every time
# a full packet is received.
# Alternatively, you could check get_peer(1).get_available_packets() in a loop.
_client.data_received.connect(self._on_data)
# Initiate connection to the given URL.
var err = _client.connect_to_url(websocket_url)
if err != OK:
push_error("Unable to connect.")
if socket.connect_to_url(websocket_url) != OK:
log_message("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)
print("Connected with protocol: ", proto)
# You MUST always use get_peer(1).put_packet to send data to server,
# and not put_packet directly when not using the MultiplayerAPI.
_client.get_peer(1).put_packet("Test packet".to_utf8_buffer())
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()
socket.poll()
if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
while socket.get_available_packet_count():
log_message(socket.get_packet().get_string_from_ascii())
func _exit_tree():
_client.disconnect_from_host()
socket.close()
func _on_button_ping_pressed():
socket.send_text("Ping")

View File

@@ -12,9 +12,14 @@ config_version=5
config/name="WebSocket Minimal Demo"
config/description="This is a minimal sample of connecting two peers to each other using websockets."
run/main_scene="res://Main.tscn"
config/features=PackedStringArray("4.0")
config/tags=PackedStringArray("demo", "network", "official")
run/main_scene="res://Main.tscn"
config/features=PackedStringArray("4.1")
[display]
window/size/viewport_width=600
window/size/viewport_height=300
[rendering]

View File

@@ -2,59 +2,38 @@ extends Node
# The port we will listen to.
const PORT = 9080
# Our WebSocketServer instance.
var _server = WebSocketServer.new()
var tcp_server := TCPServer.new()
var socket := WebSocketPeer.new()
func log_message(message):
var time = "[color=#aaaaaa] %s [/color]" % Time.get_time_string_from_system()
%TextServer.text += time + message + "\n"
func _ready():
# Connect base signals to get notified of new client connections,
# disconnections, and disconnect requests.
_server.client_connected.connect(self._connected)
_server.client_disconnected.connect(self._disconnected)
_server.client_close_request.connect(self._close_request)
# This signal is emitted when not using the Multiplayer API every time a
# full packet is received.
# Alternatively, you could check get_peer(PEER_ID).get_available_packets()
# in a loop for each connected peer.
_server.data_received.connect(self._on_data)
# Start listening on the given port.
var err = _server.listen(PORT)
if err != OK:
push_error("Unable to start server.")
if tcp_server.listen(PORT) != OK:
log_message("Unable to start server.")
set_process(false)
func _connected(id, proto, rname):
# 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_rich("Client [b]%d[/b] [color=green]connected[/color] with protocol [b]%s[/b] and resource name [b]%s[/b]" % [id, proto, rname])
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_rich("Client [b]%d[/b] [color=yellow]disconnecting[/color] with code: [b]%d[/b], reason: [b]%s[/b]" % [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_rich("Client [b]%d[/b] [color=red]disconnected[/color], clean: [b]%s[/b]" % [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.
var pkt = _server.get_peer(id).get_packet()
print("Got data from client [b]%d[/b]: [b]%s[/b] ... 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()
while tcp_server.is_connection_available():
var conn: StreamPeerTCP = tcp_server.take_connection()
assert(conn != null)
socket.accept_stream(conn)
socket.poll()
if socket.get_ready_state() == WebSocketPeer.STATE_OPEN:
while socket.get_available_packet_count():
log_message(socket.get_packet().get_string_from_ascii())
func _exit_tree():
_server.stop()
socket.close()
tcp_server.stop()
func _on_button_pong_pressed():
socket.send_text("Pong")