From ada7d718554cf9cfae3c98d67476bdd429da8cbd Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Wed, 28 Feb 2024 06:30:45 +0100 Subject: [PATCH] Get lobby and player list working --- scenes/game.gd | 45 ++++++++++++++++++++++++++---- scenes/game.tscn | 3 ++ scenes/lobby_menu.gd | 9 ++++++ scenes/lobby_menu.tscn | 43 ++++++++++++++++++++++++++++ scenes/main.gd | 21 ++++++++++---- scenes/multiple_players_tracker.gd | 40 ++++++++++++++------------ scenes/player_color_picker.gd | 12 ++------ scenes/player_color_picker.tscn | 1 + scenes/player_label.gd | 8 ++++++ scenes/player_label.tscn | 7 +++++ scenes/player_name_input.gd | 16 ++--------- scenes/player_name_input.tscn | 1 + scenes/players_list.gd | 16 +++++++++++ scenes/players_list.tscn | 14 ++++++++++ scenes/server_options_menu.gd | 12 +------- scenes/server_options_menu.tscn | 2 +- scenes/single_player_tracker.gd | 33 ++++++++++------------ scenes/single_player_tracker.tscn | 23 ++------------- utils/log.gd | 6 ++++ 19 files changed, 209 insertions(+), 103 deletions(-) create mode 100644 scenes/lobby_menu.gd create mode 100644 scenes/lobby_menu.tscn create mode 100644 scenes/player_label.gd create mode 100644 scenes/player_label.tscn create mode 100644 scenes/players_list.gd create mode 100644 scenes/players_list.tscn create mode 100644 utils/log.gd diff --git a/scenes/game.gd b/scenes/game.gd index 2c4e4ef..ba8cb0e 100644 --- a/scenes/game.gd +++ b/scenes/game.gd @@ -2,6 +2,15 @@ extends Node class_name Game +signal trackers_changed(trackers: Dictionary) + +func _on_trackers_changed(trackers: Dictionary): + trackers_changed.emit(trackers) + + +@onready var mp_tracker: MultiplePlayersTracker = $"MultiplePlayersTracker" + + # This cannot be called in _ready because the multiplayer node is set *after* adding the node to the tree. func init_signals(): print("[Game] Initializing signals...") @@ -12,17 +21,43 @@ func init_signals(): multiplayer.peer_disconnected.connect(_on_peer_disconnected) +var local_player_name: String = "Player" +var local_player_color: Color = Color.WHITE + +func init_identity(player_name: String, player_color: Color): + local_player_name = player_name + local_player_color = player_color + + func _on_connected_to_server(): - print("{", multiplayer.multiplayer_peer.get_unique_id(), "} Connected to server!") + Log.peer(self, "Connected to server!") func _on_server_disconnected(): - print("{", multiplayer.multiplayer_peer.get_unique_id(), "} Server disconnected...") + Log.peer(self, "Server disconnected...") func _on_connection_failed(): - print("{", multiplayer.multiplayer_peer.get_unique_id(), "} Connection failed...") + Log.peer(self, "Connection failed...") func _on_peer_connected(peer_id: int): - print("{", multiplayer.multiplayer_peer.get_unique_id(), "} Peer connected: ", peer_id) + Log.peer(self, "Peer connected: " + str(peer_id)) + if multiplayer.is_server(): + assert(peer_id != 1, "This is a server, but the remote peer_id is 1.") + Log.peer(self, "Initializing tracker for: " + str(peer_id)) + mp_tracker.spawn(peer_id) func _on_peer_disconnected(peer_id: int): - print("{", multiplayer.multiplayer_peer.get_unique_id(), "} Peer disconnected: ", peer_id) + Log.peer(self, "Peer disconnected: " + str(peer_id)) + if multiplayer.is_server(): + assert(peer_id != 1, "This is a server, but the remote peer_id is 1.") + Log.peer(self, "Deinitializing tracker for: " + str(peer_id)) + mp_tracker.mark_disconnected.rpc(peer_id) + +func _on_single_player_tracker_spawned(spawned_tracker: SinglePlayerTracker) -> void: + # If we spawned ourselves, set our own identity + if spawned_tracker.get_multiplayer_authority() == multiplayer.multiplayer_peer.get_unique_id(): + spawned_tracker.update_identity.rpc(local_player_name, local_player_color) + # If another player spawned, and they connected before us, send them our identity + else: + var self_tracker = mp_tracker.find(multiplayer.multiplayer_peer.get_unique_id()) + if self_tracker != null: + self_tracker.notify_identity(spawned_tracker.get_multiplayer_authority()) diff --git a/scenes/game.tscn b/scenes/game.tscn index 2b1163b..97fcb7f 100644 --- a/scenes/game.tscn +++ b/scenes/game.tscn @@ -7,3 +7,6 @@ script = ExtResource("1_cdtng") [node name="MultiplePlayersTracker" parent="." instance=ExtResource("2_f2gy2")] + +[connection signal="spawned" from="MultiplePlayersTracker" to="." method="_on_single_player_tracker_spawned"] +[connection signal="trackers_changed" from="MultiplePlayersTracker" to="." method="_on_trackers_changed"] diff --git a/scenes/lobby_menu.gd b/scenes/lobby_menu.gd new file mode 100644 index 0000000..157e522 --- /dev/null +++ b/scenes/lobby_menu.gd @@ -0,0 +1,9 @@ +extends Control +class_name LobbyMenu + + +@onready var players_list: PlayersList = $"Layout/PlayersList" + + +func _on_trackers_changed(trackers: Dictionary): + players_list._on_trackers_changed(trackers) diff --git a/scenes/lobby_menu.tscn b/scenes/lobby_menu.tscn new file mode 100644 index 0000000..92365fd --- /dev/null +++ b/scenes/lobby_menu.tscn @@ -0,0 +1,43 @@ +[gd_scene load_steps=3 format=3 uid="uid://cxpn0653ssa53"] + +[ext_resource type="Script" path="res://scenes/lobby_menu.gd" id="1_egicy"] +[ext_resource type="PackedScene" uid="uid://cpyclix18d3it" path="res://scenes/players_list.tscn" id="2_o2f1d"] + +[node name="LobbyMenu" type="Control"] +layout_mode = 3 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +script = ExtResource("1_egicy") + +[node name="Layout" type="VBoxContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 + +[node name="Title" type="RichTextLabel" parent="Layout"] +layout_mode = 2 +bbcode_enabled = true +text = "[center][font_size=32px][b]Nanogolf[/b][/font_size] +Stanza multigiocatore[/center]" +fit_content = true + +[node name="Padding" type="Control" parent="Layout"] +custom_minimum_size = Vector2(0, 16) +layout_mode = 2 + +[node name="PlayersList" parent="Layout" instance=ExtResource("2_o2f1d")] +layout_mode = 2 + +[node name="Padding2" type="Control" parent="Layout"] +custom_minimum_size = Vector2(0, 16) +layout_mode = 2 + +[node name="Button" type="Button" parent="Layout"] +layout_mode = 2 +text = "Avvia partita" diff --git a/scenes/main.gd b/scenes/main.gd index 8b651a8..43b226a 100644 --- a/scenes/main.gd +++ b/scenes/main.gd @@ -12,6 +12,8 @@ const game_scene: PackedScene = preload("res://scenes/game.tscn") var server_game_instance: Game = null var client_game_instance: Game = null +const lobby_menu_scene: PackedScene = preload("res://scenes/lobby_menu.tscn") +var lobby_menu_instance: LobbyMenu = null func init_main_menu(): main_menu_instance = main_menu_scene.instantiate() @@ -27,8 +29,6 @@ func init_server_game(server_port: int): server_game_instance.name = "Server" add_child(server_game_instance, true) - server_game_instance.init_signals() - print("[Main] Creating server at: *:", server_port) var smp: SceneMultiplayer = SceneMultiplayer.new() var peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new() @@ -38,6 +38,7 @@ func init_server_game(server_port: int): return scene_tree.set_multiplayer(smp, ^"/root/Main/Server") + server_game_instance.init_signals() smp.set_multiplayer_peer(peer) func deinit_server_game(): @@ -52,8 +53,6 @@ func init_client_game(player_name: String, player_color: Color, server_address: client_game_instance.name = "Client" add_child(client_game_instance, true) - client_game_instance.init_signals() - print("[Main] Creating client connecting to: ", server_address, ":", server_port) var smp = SceneMultiplayer.new() var peer: ENetMultiplayerPeer = ENetMultiplayerPeer.new() @@ -63,6 +62,8 @@ func init_client_game(player_name: String, player_color: Color, server_address: return scene_tree.set_multiplayer(smp, ^"/root/Main/Client") + client_game_instance.init_signals() + client_game_instance.init_identity(player_name, player_color) smp.set_multiplayer_peer(peer) func deinit_client_game(): @@ -72,6 +73,12 @@ func deinit_client_game(): scene_tree.set_multiplayer(multiplayer, ^"/root/Main/Client") client_game_instance.queue_free() +func init_lobby_menu(): + lobby_menu_instance = lobby_menu_scene.instantiate() + interface_instance.add_child(lobby_menu_instance) + +func deinit_lobby_menu(): + lobby_menu_instance.queue_free() func _ready(): init_main_menu() @@ -79,8 +86,12 @@ func _ready(): func _on_hosting_confirmed(player_name: String, player_color: Color, server_port: int): deinit_main_menu() init_server_game(server_port) - # init_client_game(player_name, player_color, "127.0.0.1", server_port) + init_client_game(player_name, player_color, "127.0.0.1", server_port) + init_lobby_menu() + client_game_instance.trackers_changed.connect(lobby_menu_instance._on_trackers_changed) func _on_connecting_confirmed(player_name: String, player_color: Color, server_address: String, server_port: int): deinit_main_menu() init_client_game(player_name, player_color, server_address, server_port) + init_lobby_menu() + client_game_instance.trackers_changed.connect(lobby_menu_instance._on_trackers_changed) diff --git a/scenes/multiple_players_tracker.gd b/scenes/multiple_players_tracker.gd index 915b5ed..199e501 100644 --- a/scenes/multiple_players_tracker.gd +++ b/scenes/multiple_players_tracker.gd @@ -3,32 +3,36 @@ class_name MultiplePlayersTracker # Requires the peer_id as data for the spawn function. +signal trackers_changed(trackers: Dictionary) -func get_tracker_by_peer(peer_id: int) -> SinglePlayerTracker: - for child in find_children("", "SinglePlayerTracker", false): - if child.peer_id == peer_id: - return child - return null +func emit_trackers_changed(): + trackers_changed.emit(trackers_by_peer_id) -func init_tracker(peer_id: int) -> SinglePlayerTracker: - var existing_tracker: SinglePlayerTracker = get_tracker_by_peer(peer_id) - if existing_tracker != null: - return existing_tracker - var single_tracker_instance = spawn(peer_id) - return single_tracker_instance +var trackers_by_peer_id: Dictionary = {} + + +func find(peer_id: int) -> SinglePlayerTracker: + return trackers_by_peer_id.get(peer_id) + +@rpc("authority", "call_local", "reliable") +func mark_disconnected(peer_id: int): + var single_tracker_instance = find(peer_id) + single_tracker_instance.set_multiplayer_authority(1) + single_tracker_instance.peer_connected = false + emit_trackers_changed() func _ready(): spawn_function = _spawn_tracker -func _spawn_tracker(data: Variant) -> Node: - print("Spawning ", data) +func _spawn_tracker(peer_id: int) -> Node: var single_tracker_scene: PackedScene = load(get_spawnable_scene(0)) var single_tracker_instance: SinglePlayerTracker = single_tracker_scene.instantiate() - single_tracker_instance.peer_id = data + single_tracker_instance.set_multiplayer_authority(peer_id) + single_tracker_instance.identity_updated.connect(_on_tracker_identity_updated) + trackers_by_peer_id[peer_id] = single_tracker_instance + emit_trackers_changed() return single_tracker_instance - -func _process(delta): - if multiplayer.is_server() and Input.is_action_just_pressed("ui_accept"): - spawn(1) +func _on_tracker_identity_updated(_player_name: String, _player_color: Color): + emit_trackers_changed() diff --git a/scenes/player_color_picker.gd b/scenes/player_color_picker.gd index fd472d1..3e0e5e2 100644 --- a/scenes/player_color_picker.gd +++ b/scenes/player_color_picker.gd @@ -4,18 +4,12 @@ class_name PlayerColorPicker signal color_confirmed(selected_color: Color) -var selected_color: Color = Color.WHITE: - get: - return selected_color - set(value): - selected_color = value - preview_texture.modulate = value - +@onready var color_picker: ColorPicker = $"Layout/ColorPicker" @onready var preview_texture: TextureRect = $"Layout/PreviewContainer/PreviewTexture" func _on_color_picker_color_changed(color: Color): - selected_color = color + preview_texture.modulate = color func _on_button_pressed(): - color_confirmed.emit(selected_color) + color_confirmed.emit(color_picker.color) diff --git a/scenes/player_color_picker.tscn b/scenes/player_color_picker.tscn index ac6aca7..9f635f7 100644 --- a/scenes/player_color_picker.tscn +++ b/scenes/player_color_picker.tscn @@ -21,6 +21,7 @@ fit_content = true [node name="ColorPicker" type="ColorPicker" parent="Layout"] layout_mode = 2 +color = Color(1, 0.996078, 0, 1) picker_shape = 1 can_add_swatches = false sampler_visible = false diff --git a/scenes/player_label.gd b/scenes/player_label.gd new file mode 100644 index 0000000..d613824 --- /dev/null +++ b/scenes/player_label.gd @@ -0,0 +1,8 @@ +extends Label +class_name PlayerLabel + + +func update_from_tracker(tracker: SinglePlayerTracker): + text = tracker.player_name + add_theme_color_override("font_color", tracker.player_color) + modulate.a = 1.0 if tracker.peer_connected else 0.3 diff --git a/scenes/player_label.tscn b/scenes/player_label.tscn new file mode 100644 index 0000000..32bc80f --- /dev/null +++ b/scenes/player_label.tscn @@ -0,0 +1,7 @@ +[gd_scene load_steps=2 format=3 uid="uid://dbj7jomrsn41h"] + +[ext_resource type="Script" path="res://scenes/player_label.gd" id="1_p6mii"] + +[node name="PlayerLabel" type="Label"] +text = "Player" +script = ExtResource("1_p6mii") diff --git a/scenes/player_name_input.gd b/scenes/player_name_input.gd index c4c8427..107bda1 100644 --- a/scenes/player_name_input.gd +++ b/scenes/player_name_input.gd @@ -4,23 +4,11 @@ class_name PlayerNameInput signal name_confirmed(selected_name: String) -var selected_name: String = "": - get: - return selected_name - set(value): - selected_name = value - @onready var line_edit: LineEdit = $"Layout/LineEdit" -func _on_line_edit_text_changed(new_text: String): - selected_name = new_text - - func _on_button_pressed(): - name_confirmed.emit(selected_name) - + name_confirmed.emit(line_edit.text) func _on_line_edit_text_submitted(new_text: String): - selected_name = new_text - name_confirmed.emit(selected_name) + name_confirmed.emit(line_edit.text) diff --git a/scenes/player_name_input.tscn b/scenes/player_name_input.tscn index 55ceac3..eae8bcc 100644 --- a/scenes/player_name_input.tscn +++ b/scenes/player_name_input.tscn @@ -18,6 +18,7 @@ fit_content = true [node name="LineEdit" type="LineEdit" parent="Layout"] layout_mode = 2 +text = "Steffo" placeholder_text = "Garasino Garasotti" [node name="PaddingEnd" type="Control" parent="Layout"] diff --git a/scenes/players_list.gd b/scenes/players_list.gd new file mode 100644 index 0000000..0619cab --- /dev/null +++ b/scenes/players_list.gd @@ -0,0 +1,16 @@ +extends PanelContainer +class_name PlayersList + + +@onready var layout = $"Scrollable/Layout" + +const player_label_scene = preload("res://scenes/player_label.tscn") + + +func _on_trackers_changed(trackers: Dictionary): + for child in layout.get_children(): + child.queue_free() + for tracker in trackers.values(): + var player_label_instance = player_label_scene.instantiate() + player_label_instance.update_from_tracker(tracker) + layout.add_child(player_label_instance) diff --git a/scenes/players_list.tscn b/scenes/players_list.tscn new file mode 100644 index 0000000..0a64e5c --- /dev/null +++ b/scenes/players_list.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=2 format=3 uid="uid://cpyclix18d3it"] + +[ext_resource type="Script" path="res://scenes/players_list.gd" id="1_45xu7"] + +[node name="PlayersList" type="PanelContainer"] +size_flags_vertical = 3 +script = ExtResource("1_45xu7") + +[node name="Scrollable" type="ScrollContainer" parent="."] +layout_mode = 2 + +[node name="Layout" type="VBoxContainer" parent="Scrollable"] +layout_mode = 2 +size_flags_vertical = 3 diff --git a/scenes/server_options_menu.gd b/scenes/server_options_menu.gd index 3358fc9..4ff190f 100644 --- a/scenes/server_options_menu.gd +++ b/scenes/server_options_menu.gd @@ -7,21 +7,11 @@ class_name ServerOptionsMenu signal hosting_confirmed(port: int) signal connecting_confirmed(address: String, port: int) -var selected_address: String = "": - get: - return selected_address - set(value): - selected_address = value - @onready var line_edit: LineEdit = $"Layout/LineEdit" - -func _on_line_edit_text_changed(new_text): - selected_address = new_text - func _on_host_button_pressed(): hosting_confirmed.emit(port) func _on_connect_button_pressed(): - connecting_confirmed.emit(selected_address, port) + connecting_confirmed.emit(line_edit.text, port) diff --git a/scenes/server_options_menu.tscn b/scenes/server_options_menu.tscn index 9c1895f..f4ff937 100644 --- a/scenes/server_options_menu.tscn +++ b/scenes/server_options_menu.tscn @@ -35,6 +35,7 @@ horizontal_alignment = 1 [node name="LineEdit" type="LineEdit" parent="Layout"] layout_mode = 2 +text = "127.0.0.1" placeholder_text = "127.0.0.1" [node name="ConnectButton" type="Button" parent="Layout"] @@ -42,5 +43,4 @@ layout_mode = 2 text = "Connettiti al server" [connection signal="pressed" from="Layout/HostButton" to="." method="_on_host_button_pressed"] -[connection signal="text_changed" from="Layout/LineEdit" to="." method="_on_line_edit_text_changed"] [connection signal="pressed" from="Layout/ConnectButton" to="." method="_on_connect_button_pressed"] diff --git a/scenes/single_player_tracker.gd b/scenes/single_player_tracker.gd index f9b2164..efebe00 100644 --- a/scenes/single_player_tracker.gd +++ b/scenes/single_player_tracker.gd @@ -1,28 +1,12 @@ -extends MultiplayerSynchronizer +extends Node class_name SinglePlayerTracker -## Emitted when the peer represented by this object connects. -signal peer_has_connected -## Emitted when the peer represented by this object connects. -signal peer_has_disconnected +signal identity_updated(player_name: String, player_color: Color) -## The peer ID that this object represents. -var peer_id: int = 0 - ## Whether the peer is connected or not. -var peer_connected: bool = false: - get: - return peer_connected - set(value): - var pvalue = peer_connected - peer_connected = value - if value != pvalue: - if value: - peer_has_connected.emit() - else: - peer_has_disconnected.emit() +var peer_connected: bool = true ## The player's name. var player_name: String = "Player" @@ -32,3 +16,14 @@ var player_color: Color = Color.WHITE ## This player's score, with an item per hole played. var strokes_per_hole: Array[int] = [] + + +@rpc("authority", "call_local", "reliable") +func update_identity(new_player_name: String, new_player_color: Color): + player_name = new_player_name + player_color = new_player_color + identity_updated.emit(player_name, player_color) + +func notify_identity(peer_id: int): + Log.peer(self, "Notifying of our identity: " + str(peer_id)) + update_identity.rpc_id(peer_id, player_name, player_color) diff --git a/scenes/single_player_tracker.tscn b/scenes/single_player_tracker.tscn index 5e47aa3..ec5116e 100644 --- a/scenes/single_player_tracker.tscn +++ b/scenes/single_player_tracker.tscn @@ -1,25 +1,6 @@ -[gd_scene load_steps=3 format=3 uid="uid://drccgvtcng3ju"] +[gd_scene load_steps=2 format=3 uid="uid://drccgvtcng3ju"] [ext_resource type="Script" path="res://scenes/single_player_tracker.gd" id="1_jwlkv"] -[sub_resource type="SceneReplicationConfig" id="SceneReplicationConfig_aosye"] -properties/0/path = NodePath(".:peer_id") -properties/0/spawn = true -properties/0/replication_mode = 2 -properties/1/path = NodePath(".:peer_connected") -properties/1/spawn = true -properties/1/replication_mode = 2 -properties/2/path = NodePath(".:player_name") -properties/2/spawn = true -properties/2/replication_mode = 2 -properties/3/path = NodePath(".:player_color") -properties/3/spawn = true -properties/3/replication_mode = 2 -properties/4/path = NodePath(".:strokes_per_hole") -properties/4/spawn = true -properties/4/replication_mode = 2 - -[node name="SinglePlayerTracker" type="MultiplayerSynchronizer"] -root_path = NodePath(".") -replication_config = SubResource("SceneReplicationConfig_aosye") +[node name="SinglePlayerTracker" type="Node"] script = ExtResource("1_jwlkv") diff --git a/utils/log.gd b/utils/log.gd new file mode 100644 index 0000000..6e13b6d --- /dev/null +++ b/utils/log.gd @@ -0,0 +1,6 @@ +extends Node +class_name Log + + +static func peer(this: Node, string: String): + print("{", this.multiplayer.multiplayer_peer.get_unique_id(), "} ", string)