Browse Source

Merge pull request #419 from aaronfranke/multiplayer

Update networking and multiplayer demos
Aaron Franke 5 years ago
parent
commit
5809089e9e
37 changed files with 537 additions and 471 deletions
  1. 7 3
      networking/multiplayer_bomber/bomb.gd
  2. 10 11
      networking/multiplayer_bomber/bomb.tscn
  3. 51 37
      networking/multiplayer_bomber/gamestate.gd
  4. 45 29
      networking/multiplayer_bomber/lobby.gd
  5. 17 17
      networking/multiplayer_bomber/lobby.tscn
  6. 15 0
      networking/multiplayer_bomber/project.godot
  7. 2 2
      networking/multiplayer_bomber/rock.gd
  8. 5 6
      networking/multiplayer_bomber/rock.tscn
  9. 8 4
      networking/multiplayer_bomber/score.gd
  10. 5 5
      networking/multiplayer_bomber/tile_scene.tscn
  11. 97 91
      networking/multiplayer_bomber/world.tscn
  12. 13 9
      networking/webrtc_minimal/chat.gd
  13. 2 2
      networking/webrtc_minimal/main.tscn
  14. 10 8
      networking/webrtc_minimal/minimal.gd
  15. 1 1
      networking/webrtc_minimal/minimal.tscn
  16. 26 12
      networking/webrtc_signaling/client/multiplayer_client.gd
  17. 24 11
      networking/webrtc_signaling/client/ws_webrtc_client.gd
  18. 17 2
      networking/webrtc_signaling/demo/client_ui.gd
  19. 18 18
      networking/webrtc_signaling/demo/client_ui.tscn
  20. 4 2
      networking/webrtc_signaling/demo/main.gd
  21. 18 18
      networking/webrtc_signaling/demo/main.tscn
  22. 41 26
      networking/webrtc_signaling/server/ws_webrtc_server.gd
  23. 13 2
      networking/websocket_chat/client/client.gd
  24. 5 47
      networking/websocket_chat/client/client.tscn
  25. 11 8
      networking/websocket_chat/client/client_ui.gd
  26. 0 9
      networking/websocket_chat/combo/combo.tscn
  27. 11 1
      networking/websocket_chat/server/server.gd
  28. 12 9
      networking/websocket_chat/server/server_ui.gd
  29. 2 0
      networking/websocket_chat/utils.gd
  30. 0 9
      networking/websocket_minimal/Main.tscn
  31. 7 2
      networking/websocket_minimal/client.gd
  32. 8 2
      networking/websocket_minimal/server.gd
  33. 0 6
      networking/websocket_multiplayer/default_env.tres
  34. 0 18
      networking/websocket_multiplayer/scene/game.tscn
  35. 2 44
      networking/websocket_multiplayer/scene/main.tscn
  36. 14 0
      networking/websocket_multiplayer/script/game.gd
  37. 16 0
      networking/websocket_multiplayer/script/main.gd

+ 7 - 3
networking/multiplayer_bomber/bomb.gd

@@ -3,21 +3,25 @@ extends Area2D
 var in_area = []
 var from_player
 
-# Called from the animation
+# Called from the animation.
 func explode():
 	if not is_network_master():
-		# But will call explosion only on master
+		# Explode only on master.
 		return
 	for p in in_area:
 		if p.has_method("exploded"):
-			p.rpc("exploded", from_player) # Exploded has a master keyword, so it will only be received by the master
+			# Exploded has a master keyword, so it will only be received by the master.
+			p.rpc("exploded", from_player)
+
 
 func done():
 	queue_free()
 
+
 func _on_bomb_body_enter(body):
 	if not body in in_area:
 		in_area.append(body)
 
+
 func _on_bomb_body_exit(body):
 	in_area.erase(body)

+ 10 - 11
networking/multiplayer_bomber/bomb.tscn

@@ -32,7 +32,7 @@ scale_curve = SubResource( 4 )
 [sub_resource type="Animation" id=6]
 length = 4.0
 tracks/0/type = "value"
-tracks/0/path = NodePath("sprite:self_modulate")
+tracks/0/path = NodePath("Sprite:self_modulate")
 tracks/0/interp = 1
 tracks/0/loop_wrap = true
 tracks/0/imported = false
@@ -61,7 +61,7 @@ tracks/1/keys = {
 } ]
 }
 tracks/2/type = "value"
-tracks/2/path = NodePath("explosion1:emitting")
+tracks/2/path = NodePath("Explosion1:emitting")
 tracks/2/interp = 1
 tracks/2/loop_wrap = true
 tracks/2/imported = false
@@ -73,7 +73,7 @@ tracks/2/keys = {
 "values": [ false, true ]
 }
 tracks/3/type = "value"
-tracks/3/path = NodePath("explosion2:emitting")
+tracks/3/path = NodePath("Explosion2:emitting")
 tracks/3/interp = 1
 tracks/3/loop_wrap = true
 tracks/3/imported = false
@@ -85,22 +85,22 @@ tracks/3/keys = {
 "values": [ false, true ]
 }
 
-[node name="bomb" type="Area2D"]
+[node name="Bomb" type="Area2D"]
 script = ExtResource( 1 )
 
-[node name="sprite" type="Sprite" parent="."]
+[node name="Sprite" type="Sprite" parent="."]
 position = Vector2( -2.92606, -2.92606 )
 texture = ExtResource( 2 )
 region_enabled = true
 region_rect = Rect2( 144, 0, 48, 48 )
 
-[node name="shape1" type="CollisionShape2D" parent="."]
+[node name="Shape1" type="CollisionShape2D" parent="."]
 shape = SubResource( 1 )
 
-[node name="shape2" type="CollisionShape2D" parent="."]
+[node name="Shape2" type="CollisionShape2D" parent="."]
 shape = SubResource( 2 )
 
-[node name="explosion1" type="Particles2D" parent="."]
+[node name="Explosion1" type="Particles2D" parent="."]
 emitting = false
 lifetime = 0.5
 one_shot = true
@@ -108,7 +108,7 @@ explosiveness = 0.95
 process_material = SubResource( 5 )
 texture = ExtResource( 3 )
 
-[node name="explosion2" type="Particles2D" parent="."]
+[node name="Explosion2" type="Particles2D" parent="."]
 rotation = 1.57162
 emitting = false
 one_shot = true
@@ -116,9 +116,8 @@ explosiveness = 0.95
 process_material = SubResource( 5 )
 texture = ExtResource( 3 )
 
-[node name="anim" type="AnimationPlayer" parent="."]
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
 autoplay = "anim"
 anims/anim = SubResource( 6 )
-
 [connection signal="body_entered" from="." to="." method="_on_bomb_body_enter"]
 [connection signal="body_exited" from="." to="." method="_on_bomb_body_exit"]

+ 51 - 37
networking/multiplayer_bomber/gamestate.gd

@@ -1,55 +1,61 @@
 extends Node
 
-# Default game port
+# Default game port. Can be any number between 1024 and 49151.
 const DEFAULT_PORT = 10567
 
-# Max number of players
+# Max number of players.
 const MAX_PEERS = 12
 
-# Name for my player
+# Name for my player.
 var player_name = "The Warrior"
 
-# Names for remote players in id:name format
+# Names for remote players in id:name format.
 var players = {}
+var players_ready = []
 
-# Signals to let lobby GUI know what's going on
+# Signals to let lobby GUI know what's going on.
 signal player_list_changed()
 signal connection_failed()
 signal connection_succeeded()
 signal game_ended()
 signal game_error(what)
 
-# Callback from SceneTree
+# Callback from SceneTree.
 func _player_connected(id):
-	# Registration of a client beings here, tell the connected player that we are here
+	# Registration of a client beings here, tell the connected player that we are here.
 	rpc_id(id, "register_player", player_name)
 
-# Callback from SceneTree
+
+# Callback from SceneTree.
 func _player_disconnected(id):
-	if has_node("/root/world"): # Game is in progress
+	if has_node("/root/World"): # Game is in progress.
 		if get_tree().is_network_server():
 			emit_signal("game_error", "Player " + players[id] + " disconnected")
 			end_game()
-	else: # Game is not in progress
-		# Unregister this player
+	else: # Game is not in progress.
+		# Unregister this player.
 		unregister_player(id)
 
-# Callback from SceneTree, only for clients (not server)
+
+# Callback from SceneTree, only for clients (not server).
 func _connected_ok():
 	# We just connected to a server
 	emit_signal("connection_succeeded")
 
-# Callback from SceneTree, only for clients (not server)
+
+# Callback from SceneTree, only for clients (not server).
 func _server_disconnected():
 	emit_signal("game_error", "Server disconnected")
 	end_game()
 
-# Callback from SceneTree, only for clients (not server)
+
+# Callback from SceneTree, only for clients (not server).
 func _connected_fail():
 	get_tree().set_network_peer(null) # Remove peer
 	emit_signal("connection_failed")
 
-# Lobby management functions
+
+# Lobby management functions.
 
 remote func register_player(new_player_name):
 	var id = get_tree().get_rpc_sender_id()
@@ -57,51 +63,53 @@ remote func register_player(new_player_name):
 	players[id] = new_player_name
 	emit_signal("player_list_changed")
 
+
 func unregister_player(id):
 	players.erase(id)
 	emit_signal("player_list_changed")
 
+
 remote func pre_start_game(spawn_points):
-	# Change scene
+	# Change scene.
 	var world = load("res://world.tscn").instance()
 	get_tree().get_root().add_child(world)
 
-	get_tree().get_root().get_node("lobby").hide()
+	get_tree().get_root().get_node("Lobby").hide()
 
 	var player_scene = load("res://player.tscn")
 
 	for p_id in spawn_points:
-		var spawn_pos = world.get_node("spawn_points/" + str(spawn_points[p_id])).position
+		var spawn_pos = world.get_node("SpawnPoints/" + str(spawn_points[p_id])).position
 		var player = player_scene.instance()
 
-		player.set_name(str(p_id)) # Use unique ID as node name
+		player.set_name(str(p_id)) # Use unique ID as node name.
 		player.position=spawn_pos
-		player.set_network_master(p_id) #set unique id as master
+		player.set_network_master(p_id) #set unique id as master.
 
 		if p_id == get_tree().get_network_unique_id():
-			# If node for this peer id, set name
+			# If node for this peer id, set name.
 			player.set_player_name(player_name)
 		else:
-			# Otherwise set name from peer
+			# Otherwise set name from peer.
 			player.set_player_name(players[p_id])
 
-		world.get_node("players").add_child(player)
+		world.get_node("Players").add_child(player)
 
-	# Set up score
-	world.get_node("score").add_player(get_tree().get_network_unique_id(), player_name)
+	# Set up score.
+	world.get_node("Score").add_player(get_tree().get_network_unique_id(), player_name)
 	for pn in players:
-		world.get_node("score").add_player(pn, players[pn])
+		world.get_node("Score").add_player(pn, players[pn])
 
 	if not get_tree().is_network_server():
-		# Tell server we are ready to start
+		# Tell server we are ready to start.
 		rpc_id(1, "ready_to_start", get_tree().get_network_unique_id())
 	elif players.size() == 0:
 		post_start_game()
 
+
 remote func post_start_game():
 	get_tree().set_pause(false) # Unpause and unleash the game!
 
-var players_ready = []
 
 remote func ready_to_start(id):
 	assert(get_tree().is_network_server())
@@ -114,48 +122,54 @@ remote func ready_to_start(id):
 			rpc_id(p, "post_start_game")
 		post_start_game()
 
+
 func host_game(new_player_name):
 	player_name = new_player_name
 	var host = NetworkedMultiplayerENet.new()
 	host.create_server(DEFAULT_PORT, MAX_PEERS)
 	get_tree().set_network_peer(host)
 
+
 func join_game(ip, new_player_name):
 	player_name = new_player_name
-	var host = NetworkedMultiplayerENet.new()
-	host.create_client(ip, DEFAULT_PORT)
-	get_tree().set_network_peer(host)
+	var client = NetworkedMultiplayerENet.new()
+	client.create_client(ip, DEFAULT_PORT)
+	get_tree().set_network_peer(client)
+
 
 func get_player_list():
 	return players.values()
 
+
 func get_player_name():
 	return player_name
 
+
 func begin_game():
 	assert(get_tree().is_network_server())
 
-	# Create a dictionary with peer id and respective spawn points, could be improved by randomizing
+	# Create a dictionary with peer id and respective spawn points, could be improved by randomizing.
 	var spawn_points = {}
-	spawn_points[1] = 0 # Server in spawn point 0
+	spawn_points[1] = 0 # Server in spawn point 0.
 	var spawn_point_idx = 1
 	for p in players:
 		spawn_points[p] = spawn_point_idx
 		spawn_point_idx += 1
-	# Call to pre-start game with the spawn points
+	# Call to pre-start game with the spawn points.
 	for p in players:
 		rpc_id(p, "pre_start_game", spawn_points)
 
 	pre_start_game(spawn_points)
 
+
 func end_game():
-	if has_node("/root/world"): # Game is in progress
+	if has_node("/root/World"): # Game is in progress.
 		# End it
-		get_node("/root/world").queue_free()
+		get_node("/root/World").queue_free()
 
 	emit_signal("game_ended")
 	players.clear()
-	get_tree().set_network_peer(null) # End networking
+
 
 func _ready():
 	get_tree().connect("network_peer_connected", self, "_player_connected")

+ 45 - 29
networking/multiplayer_bomber/lobby.gd

@@ -7,66 +7,82 @@ func _ready():
 	gamestate.connect("player_list_changed", self, "refresh_lobby")
 	gamestate.connect("game_ended", self, "_on_game_ended")
 	gamestate.connect("game_error", self, "_on_game_error")
+	# Set the player name according to the system username. Fallback to the path.
+	if OS.has_environment("USERNAME"):
+		$Connect/Name.text = OS.get_environment("USERNAME")
+	else:
+		var desktop_path = OS.get_system_dir(0).replace("\\", "/").split("/")
+		$Connect/Name.text = desktop_path[desktop_path.size() - 2]
+
 
 func _on_host_pressed():
-	if get_node("connect/name").text == "":
-		get_node("connect/error_label").text = "Invalid name!"
+	if $Connect/Name.text == "":
+		$Connect/ErrorLabel.text = "Invalid name!"
 		return
 
-	get_node("connect").hide()
-	get_node("players").show()
-	get_node("connect/error_label").text = ""
+	$Connect.hide()
+	$Players.show()
+	$Connect/ErrorLabel.text = ""
 
-	var player_name = get_node("connect/name").text
+	var player_name = $Connect/Name.text
 	gamestate.host_game(player_name)
 	refresh_lobby()
 
+
 func _on_join_pressed():
-	if get_node("connect/name").text == "":
-		get_node("connect/error_label").text = "Invalid name!"
+	if $Connect/Name.text == "":
+		$Connect/ErrorLabel.text = "Invalid name!"
 		return
 
-	var ip = get_node("connect/ip").text
+	var ip = $Connect/IPAddress.text
 	if not ip.is_valid_ip_address():
-		get_node("connect/error_label").text = "Invalid IPv4 address!"
+		$Connect/ErrorLabel.text = "Invalid IP address!"
 		return
 
-	get_node("connect/error_label").text=""
-	get_node("connect/host").disabled = true
-	get_node("connect/join").disabled = true
+	$Connect/ErrorLabel.text = ""
+	$Connect/Host.disabled = true
+	$Connect/Join.disabled = true
 
-	var player_name = get_node("connect/name").text
+	var player_name = $Connect/Name.text
 	gamestate.join_game(ip, player_name)
-	# refresh_lobby() gets called by the player_list_changed signal
+
 
 func _on_connection_success():
-	get_node("connect").hide()
-	get_node("players").show()
+	$Connect.hide()
+	$Players.show()
+
 
 func _on_connection_failed():
-	get_node("connect/host").disabled = false
-	get_node("connect/join").disabled = false
-	get_node("connect/error_label").set_text("Connection failed.")
+	$Connect/Host.disabled = false
+	$Connect/Join.disabled = false
+	$Connect/ErrorLabel.set_text("Connection failed.")
+
 
 func _on_game_ended():
 	show()
-	get_node("connect").show()
-	get_node("players").hide()
-	get_node("connect/host").disabled = false
+	$Connect.show()
+	$Players.hide()
+	$Connect/Host.disabled = false
+	$Connect/Join.disabled = false
+
 
 func _on_game_error(errtxt):
-	get_node("error").dialog_text = errtxt
-	get_node("error").popup_centered_minsize()
+	$ErrorDialog.dialog_text = errtxt
+	$ErrorDialog.popup_centered_minsize()
+	$Connect/Host.disabled = false
+	$Connect/Join.disabled = false
+
 
 func refresh_lobby():
 	var players = gamestate.get_player_list()
 	players.sort()
-	get_node("players/list").clear()
-	get_node("players/list").add_item(gamestate.get_player_name() + " (You)")
+	$Players/List.clear()
+	$Players/List.add_item(gamestate.get_player_name() + " (You)")
 	for p in players:
-		get_node("players/list").add_item(p)
+		$Players/List.add_item(p)
+
+	$Players/Start.disabled = not get_tree().is_network_server()
 
-	get_node("players/start").disabled = not get_tree().is_network_server()
 
 func _on_start_pressed():
 	gamestate.begin_game()

+ 17 - 17
networking/multiplayer_bomber/lobby.tscn

@@ -2,7 +2,7 @@
 
 [ext_resource path="res://lobby.gd" type="Script" id=1]
 
-[node name="lobby" type="Control"]
+[node name="Lobby" type="Control"]
 anchor_right = 1.0
 anchor_bottom = 1.0
 size_flags_horizontal = 2
@@ -12,7 +12,7 @@ __meta__ = {
 "_edit_use_anchors_": false
 }
 
-[node name="players" type="Panel" parent="."]
+[node name="Players" type="Panel" parent="."]
 visible = false
 anchor_left = 0.5
 anchor_top = 0.5
@@ -25,7 +25,7 @@ margin_bottom = 177.5
 size_flags_horizontal = 2
 size_flags_vertical = 2
 
-[node name="label" type="Label" parent="players"]
+[node name="Label" type="Label" parent="Players"]
 margin_left = 26.0
 margin_top = 18.0
 margin_right = 142.0
@@ -34,7 +34,7 @@ size_flags_horizontal = 2
 size_flags_vertical = 0
 text = "Awaiting Players..."
 
-[node name="start" type="Button" parent="players"]
+[node name="Start" type="Button" parent="Players"]
 margin_left = 68.0
 margin_top = 307.0
 margin_right = 193.0
@@ -43,7 +43,7 @@ size_flags_horizontal = 2
 size_flags_vertical = 2
 text = "START!"
 
-[node name="list" type="ItemList" parent="players"]
+[node name="List" type="ItemList" parent="Players"]
 margin_left = 25.0
 margin_top = 37.0
 margin_right = 229.0
@@ -51,7 +51,7 @@ margin_bottom = 296.0
 size_flags_horizontal = 2
 size_flags_vertical = 2
 
-[node name="connect" type="Panel" parent="."]
+[node name="Connect" type="Panel" parent="."]
 anchor_left = 0.5
 anchor_top = 0.5
 anchor_right = 0.5
@@ -63,7 +63,7 @@ margin_bottom = 83.5
 size_flags_horizontal = 2
 size_flags_vertical = 2
 
-[node name="name_label" type="Label" parent="connect"]
+[node name="NameLabel" type="Label" parent="Connect"]
 margin_left = 14.0
 margin_top = 11.0
 margin_right = 56.0
@@ -72,7 +72,7 @@ size_flags_horizontal = 2
 size_flags_vertical = 0
 text = "Name:"
 
-[node name="name" type="LineEdit" parent="connect"]
+[node name="Name" type="LineEdit" parent="Connect"]
 margin_left = 17.0
 margin_top = 30.0
 margin_right = 173.0
@@ -81,7 +81,7 @@ size_flags_horizontal = 2
 size_flags_vertical = 2
 text = "The Warrior"
 
-[node name="ip_label" type="Label" parent="connect"]
+[node name="IPLabel" type="Label" parent="Connect"]
 margin_left = 15.0
 margin_top = 66.0
 margin_right = 57.0
@@ -90,7 +90,7 @@ size_flags_horizontal = 2
 size_flags_vertical = 0
 text = "IP:"
 
-[node name="ip" type="LineEdit" parent="connect"]
+[node name="IPAddress" type="LineEdit" parent="Connect"]
 margin_left = 17.0
 margin_top = 85.0
 margin_right = 173.0
@@ -99,7 +99,7 @@ size_flags_horizontal = 2
 size_flags_vertical = 2
 text = "127.0.0.1"
 
-[node name="host" type="Button" parent="connect"]
+[node name="Host" type="Button" parent="Connect"]
 margin_left = 181.0
 margin_top = 31.0
 margin_right = 246.0
@@ -108,7 +108,7 @@ size_flags_horizontal = 2
 size_flags_vertical = 2
 text = "Host"
 
-[node name="join" type="Button" parent="connect"]
+[node name="Join" type="Button" parent="Connect"]
 margin_left = 181.0
 margin_top = 87.0
 margin_right = 246.0
@@ -117,7 +117,7 @@ size_flags_horizontal = 2
 size_flags_vertical = 2
 text = "Join"
 
-[node name="error_label" type="Label" parent="connect"]
+[node name="ErrorLabel" type="Label" parent="Connect"]
 margin_left = 15.0
 margin_top = 125.0
 margin_right = 257.0
@@ -127,11 +127,11 @@ size_flags_vertical = 0
 custom_colors/font_color = Color( 0.820312, 0.291595, 0.291595, 1 )
 align = 1
 
-[node name="error" type="AcceptDialog" parent="."]
+[node name="ErrorDialog" type="AcceptDialog" parent="."]
 margin_right = 55.0
 margin_bottom = 58.0
 size_flags_horizontal = 2
 size_flags_vertical = 2
-[connection signal="pressed" from="players/start" to="." method="_on_start_pressed"]
-[connection signal="pressed" from="connect/host" to="." method="_on_host_pressed"]
-[connection signal="pressed" from="connect/join" to="." method="_on_join_pressed"]
+[connection signal="pressed" from="Players/Start" to="." method="_on_start_pressed"]
+[connection signal="pressed" from="Connect/Host" to="." method="_on_host_pressed"]
+[connection signal="pressed" from="Connect/Join" to="." method="_on_join_pressed"]

+ 15 - 0
networking/multiplayer_bomber/project.godot

@@ -46,25 +46,40 @@ gen_mipmaps=false
 move_down={
 "deadzone": 0.5,
 "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"unicode":0,"echo":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":1.0,"script":null)
+, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null)
  ]
 }
 move_left={
 "deadzone": 0.5,
 "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"unicode":0,"echo":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":-1.0,"script":null)
+, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null)
  ]
 }
 move_right={
 "deadzone": 0.5,
 "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"unicode":0,"echo":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":0,"axis_value":1.0,"script":null)
+, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null)
  ]
 }
 move_up={
 "deadzone": 0.5,
 "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"unicode":0,"echo":false,"script":null)
+, Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"unicode":0,"echo":false,"script":null)
+, Object(InputEventJoypadMotion,"resource_local_to_scene":false,"resource_name":"","device":0,"axis":1,"axis_value":-1.0,"script":null)
+, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null)
  ]
 }
 set_bomb={
 "deadzone": 0.5,
 "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":32,"unicode":0,"echo":false,"script":null)
+, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":0,"pressure":0.0,"pressed":false,"script":null)
+, Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":1,"pressure":0.0,"pressed":false,"script":null)
+, Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"button_mask":0,"position":Vector2( 0, 0 ),"global_position":Vector2( 0, 0 ),"factor":1.0,"button_index":1,"pressed":false,"doubleclick":false,"script":null)
  ]
 }

+ 2 - 2
networking/multiplayer_bomber/rock.gd

@@ -2,10 +2,10 @@ extends KinematicBody2D
 
 # Sent to everyone else
 puppet func do_explosion():
-	get_node("anim").play("explode")
+	$"AnimationPlayer".play("explode")
 
 # Received by owner of the rock
 master func exploded(by_who):
 	rpc("do_explosion") # Re-sent to puppet rocks
-	get_node("../../score").rpc("increase_score", by_who)
+	$"../../Score".rpc("increase_score", by_who)
 	do_explosion()

+ 5 - 6
networking/multiplayer_bomber/rock.tscn

@@ -23,7 +23,7 @@ tracks/0/keys = {
 } ]
 }
 tracks/1/type = "value"
-tracks/1/path = NodePath("sprite:visible")
+tracks/1/path = NodePath("Sprite:visible")
 tracks/1/interp = 1
 tracks/1/loop_wrap = true
 tracks/1/imported = false
@@ -35,17 +35,16 @@ tracks/1/keys = {
 "values": [ false ]
 }
 
-[node name="rock" type="KinematicBody2D"]
+[node name="Rock" type="KinematicBody2D"]
 script = ExtResource( 1 )
 
-[node name="sprite" type="Sprite" parent="."]
+[node name="Sprite" type="Sprite" parent="."]
 texture = ExtResource( 2 )
 region_enabled = true
 region_rect = Rect2( 96, 0, 48, 48 )
 
-[node name="shape" type="CollisionShape2D" parent="."]
+[node name="Shape" type="CollisionShape2D" parent="."]
 shape = SubResource( 1 )
 
-[node name="anim" type="AnimationPlayer" parent="."]
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
 anims/explode = SubResource( 2 )
-

+ 8 - 4
networking/multiplayer_bomber/score.gd

@@ -3,7 +3,7 @@ extends HBoxContainer
 var player_labels = {}
 
 func _process(_delta):
-	var rocks_left = get_node("../rocks").get_child_count()
+	var rocks_left = $"../Rocks".get_child_count()
 	if rocks_left == 0:
 		var winner_name = ""
 		var winner_score = 0
@@ -12,8 +12,9 @@ func _process(_delta):
 				winner_score = player_labels[p].score
 				winner_name = player_labels[p].name
 
-		get_node("../winner").set_text("THE WINNER IS:\n" + winner_name)
-		get_node("../winner").show()
+		$"../Winner".set_text("THE WINNER IS:\n" + winner_name)
+		$"../Winner".show()
+
 
 sync func increase_score(for_who):
 	assert(for_who in player_labels)
@@ -21,6 +22,7 @@ sync func increase_score(for_who):
 	pl.score += 1
 	pl.label.set_text(pl.name + "\n" + str(pl.score))
 
+
 func add_player(id, new_player_name):
 	var l = Label.new()
 	l.set_align(Label.ALIGN_CENTER)
@@ -34,9 +36,11 @@ func add_player(id, new_player_name):
 
 	player_labels[id] = { name = new_player_name, label = l, score = 0 }
 
+
 func _ready():
-	get_node("../winner").hide()
+	$"../Winner".hide()
 	set_process(true)
 
+
 func _on_exit_game_pressed():
 	gamestate.end_game()

+ 5 - 5
networking/multiplayer_bomber/tile_scene.tscn

@@ -5,19 +5,19 @@
 [sub_resource type="RectangleShape2D" id=1]
 extents = Vector2( 24, 24 )
 
-[node name="Node2D" type="Node2D"]
+[node name="TileScene" type="Node2D"]
 
-[node name="wall" type="Sprite" parent="."]
+[node name="Wall" type="Sprite" parent="."]
 position = Vector2( 24, 24 )
 texture = ExtResource( 1 )
 region_rect = Rect2( 0, 0, 48, 48 )
 
-[node name="col" type="StaticBody2D" parent="wall"]
+[node name="StaticBody2D" type="StaticBody2D" parent="Wall"]
 
-[node name="CollisionShape2D" type="CollisionShape2D" parent="wall/col"]
+[node name="CollisionShape2D" type="CollisionShape2D" parent="Wall/StaticBody2D"]
 shape = SubResource( 1 )
 
-[node name="floor" type="Sprite" parent="."]
+[node name="Floor" type="Sprite" parent="."]
 position = Vector2( 72, 24 )
 texture = ExtResource( 1 )
 region_rect = Rect2( 48, 0, 48, 48 )

+ 97 - 91
networking/multiplayer_bomber/world.tscn

@@ -9,9 +9,9 @@
 size = 44
 font_data = ExtResource( 4 )
 
-[node name="world" type="Node2D"]
+[node name="World" type="Node2D"]
 
-[node name="map" type="TileMap" parent="."]
+[node name="TileMap" type="TileMap" parent="."]
 tile_set = ExtResource( 1 )
 cell_size = Vector2( 48, 48 )
 format = 1
@@ -20,266 +20,269 @@ __meta__ = {
 "_edit_lock_": true
 }
 
-[node name="spawn_points" type="Node2D" parent="."]
+[node name="SpawnPoints" type="Node2D" parent="."]
 
-[node name="0" type="Position2D" parent="spawn_points"]
+[node name="0" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 72, 72 )
 
-[node name="1" type="Position2D" parent="spawn_points"]
+[node name="1" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 264, 216 )
 
-[node name="2" type="Position2D" parent="spawn_points"]
+[node name="2" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 72, 456 )
 
-[node name="3" type="Position2D" parent="spawn_points"]
+[node name="3" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 360, 552 )
 
-[node name="4" type="Position2D" parent="spawn_points"]
+[node name="4" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 840, 360 )
 
-[node name="5" type="Position2D" parent="spawn_points"]
+[node name="5" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 456, 264 )
 
-[node name="6" type="Position2D" parent="spawn_points"]
+[node name="6" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 696, 264 )
 
-[node name="7" type="Position2D" parent="spawn_points"]
+[node name="7" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 744, 456 )
 
-[node name="8" type="Position2D" parent="spawn_points"]
+[node name="8" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 312, 456 )
 
-[node name="9" type="Position2D" parent="spawn_points"]
+[node name="9" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 696, 72 )
 
-[node name="10" type="Position2D" parent="spawn_points"]
+[node name="10" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 504, 72 )
 
-[node name="11" type="Position2D" parent="spawn_points"]
+[node name="11" type="Position2D" parent="SpawnPoints"]
 position = Vector2( 936, 72 )
 
-[node name="rocks" type="Node2D" parent="."]
+[node name="Rocks" type="Node2D" parent="."]
 
-[node name="rock" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock0" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 120, 72 )
 
-[node name="rock1" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock1" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 264, 168 )
 
-[node name="rock2" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock2" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 264, 120 )
 
-[node name="rock3" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock3" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 216, 72 )
 
-[node name="rock4" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock4" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 264, 72 )
 
-[node name="rock5" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock5" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 312, 72 )
 
-[node name="rock6" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock6" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 552, 168 )
 
-[node name="rock7" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock7" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 600, 168 )
 
-[node name="rock8" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock8" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 552, 216 )
 
-[node name="rock9" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock9" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 264, 312 )
 
-[node name="rock10" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock10" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 120, 360 )
 
-[node name="rock11" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock11" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 168, 360 )
 
-[node name="rock12" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock12" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 216, 360 )
 
-[node name="rock13" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock13" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 120, 264 )
 
-[node name="rock14" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock14" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 168, 216 )
 
-[node name="rock15" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock15" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 72, 360 )
 
-[node name="rock16" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock16" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 72, 312 )
 
-[node name="rock17" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock17" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 72, 264 )
 
-[node name="rock18" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock18" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 360, 360 )
 
-[node name="rock19" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock19" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 408, 360 )
 
-[node name="rock20" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock20" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 504, 360 )
 
-[node name="rock21" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock21" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 600, 360 )
 
-[node name="rock22" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock22" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 648, 360 )
 
-[node name="rock23" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock23" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 504, 456 )
 
-[node name="rock24" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock24" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 552, 456 )
 
-[node name="rock25" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock25" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 552, 408 )
 
-[node name="rock26" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock26" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 360, 456 )
 
-[node name="rock27" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock27" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 360, 504 )
 
-[node name="rock28" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock28" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 264, 504 )
 
-[node name="rock29" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock29" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 264, 552 )
 
-[node name="rock30" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock30" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 168, 456 )
 
-[node name="rock31" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock31" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 168, 504 )
 
-[node name="rock32" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock32" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 72, 552 )
 
-[node name="rock33" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock33" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 120, 552 )
 
-[node name="rock34" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock34" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 504, 552 )
 
-[node name="rock35" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock35" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 600, 552 )
 
-[node name="rock36" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock36" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 648, 552 )
 
-[node name="rock37" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock37" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 648, 504 )
 
-[node name="rock38" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock38" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 456, 216 )
 
-[node name="rock39" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock39" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 360, 216 )
 
-[node name="rock40" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock40" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 360, 168 )
 
-[node name="rock41" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock41" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 456, 120 )
 
-[node name="rock42" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock42" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 456, 408 )
 
-[node name="rock43" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock43" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 456, 456 )
 
-[node name="rock44" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock44" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 456, 504 )
 
-[node name="rock45" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock45" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 600, 264 )
 
-[node name="rock46" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock46" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 600, 72 )
 
-[node name="rock47" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock47" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 408, 72 )
 
-[node name="rock48" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock48" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 792, 168 )
 
-[node name="rock49" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock49" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 744, 168 )
 
-[node name="rock50" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock50" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 744, 264 )
 
-[node name="rock51" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock51" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 792, 264 )
 
-[node name="rock52" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock52" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 744, 360 )
 
-[node name="rock53" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock53" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 744, 408 )
 
-[node name="rock54" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock54" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 792, 552 )
 
-[node name="rock55" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock55" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 840, 552 )
 
-[node name="rock56" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock56" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 840, 504 )
 
-[node name="rock57" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock57" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 840, 312 )
 
-[node name="rock58" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock58" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 840, 264 )
 
-[node name="rock59" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock59" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 840, 216 )
 
-[node name="rock60" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock60" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 840, 120 )
 
-[node name="rock61" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock61" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 792, 72 )
 
-[node name="rock62" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock62" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 840, 72 )
 
-[node name="rock63" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock63" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 936, 216 )
 
-[node name="rock64" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock64" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 936, 264 )
 
-[node name="rock65" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock65" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 936, 408 )
 
-[node name="rock66" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock66" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 888, 456 )
 
-[node name="rock67" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock67" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 936, 456 )
 
-[node name="rock68" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock68" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 792, 456 )
 
-[node name="rock69" parent="rocks" instance=ExtResource( 2 )]
+[node name="Rock69" parent="Rocks" instance=ExtResource( 2 )]
 position = Vector2( 840, 456 )
 
-[node name="players" type="Node2D" parent="."]
+[node name="Players" type="Node2D" parent="."]
 
-[node name="score" type="HBoxContainer" parent="."]
+[node name="Score" type="HBoxContainer" parent="."]
 margin_right = 1024.0
 margin_bottom = 40.0
 size_flags_horizontal = 2
 size_flags_vertical = 2
 script = ExtResource( 3 )
+__meta__ = {
+"_edit_use_anchors_": false
+}
 
-[node name="winner" type="Label" parent="."]
+[node name="Winner" type="Label" parent="."]
 margin_right = 1031.0
 margin_bottom = 617.0
 size_flags_horizontal = 2
@@ -294,7 +297,7 @@ YOU"
 align = 1
 valign = 1
 
-[node name="exit_game" type="Button" parent="winner"]
+[node name="ExitGame" type="Button" parent="Winner"]
 margin_left = 384.0
 margin_top = 408.0
 margin_right = 649.0
@@ -303,8 +306,11 @@ size_flags_horizontal = 2
 size_flags_vertical = 2
 custom_fonts/font = SubResource( 1 )
 text = "EXIT GAME"
+__meta__ = {
+"_edit_use_anchors_": false
+}
 
 [node name="Camera2D" type="Camera2D" parent="."]
 offset = Vector2( 512, 300 )
 current = true
-[connection signal="pressed" from="winner/exit_game" to="score" method="_on_exit_game_pressed"]
+[connection signal="pressed" from="Winner/ExitGame" to="Score" method="_on_exit_game_pressed"]

+ 13 - 9
networking/webrtc_minimal/chat.gd

@@ -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())

+ 2 - 2
networking/webrtc_minimal/main.tscn

@@ -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

+ 10 - 8
networking/webrtc_minimal/minimal.gd

@@ -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()

+ 1 - 1
networking/webrtc_minimal/minimal.tscn

@@ -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 )

+ 26 - 12
networking/webrtc_signaling/client/multiplayer_client.gd

@@ -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)

+ 24 - 11
networking/webrtc_signaling/client/ws_webrtc_client.gd

@@ -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()

+ 17 - 2
networking/webrtc_signaling/demo/client_ui.gd

@@ -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()

+ 18 - 18
networking/webrtc_signaling/demo/client_ui.tscn

@@ -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"]

+ 4 - 2
networking/webrtc_signaling/demo/main.gd

@@ -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")

+ 18 - 18
networking/webrtc_signaling/demo/main.tscn

@@ -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"]

+ 41 - 26
networking/webrtc_signaling/server/ws_webrtc_server.gd

@@ -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

+ 13 - 2
networking/websocket_chat/client/client.gd

@@ -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

+ 5 - 47
networking/websocket_chat/client/client.tscn

@@ -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"]

+ 11 - 8
networking/websocket_chat/client/client_ui.gd

@@ -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

+ 0 - 9
networking/websocket_chat/combo/combo.tscn

@@ -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

+ 11 - 1
networking/websocket_chat/server/server.gd

@@ -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:

+ 12 - 9
networking/websocket_chat/server/server_ui.gd

@@ -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())

+ 2 - 0
networking/websocket_chat/utils.gd

@@ -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")

+ 0 - 9
networking/websocket_minimal/Main.tscn

@@ -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__ = {
-
-}

+ 7 - 2
networking/websocket_minimal/client.gd

@@ -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()

+ 8 - 2
networking/websocket_minimal/server.gd

@@ -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()

+ 0 - 6
networking/websocket_multiplayer/default_env.tres

@@ -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__ = {
-
-}

+ 0 - 18
networking/websocket_multiplayer/scene/game.tscn

@@ -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"]

+ 2 - 44
networking/websocket_multiplayer/scene/main.tscn

@@ -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"]

+ 14 - 0
networking/websocket_multiplayer/script/game.gd

@@ -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")

+ 16 - 0
networking/websocket_multiplayer/script/main.gd

@@ -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)