From 2c51d84bbce3e24eccb10129b0fead82955cc9c5 Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Sat, 9 Mar 2024 05:48:31 +0100 Subject: [PATCH] Actually make some progress --- scenes/game.gd | 79 +--------------------------- scenes/multiple_players_tracker.gd | 69 ------------------------ scenes/multiple_players_tracker.tscn | 6 --- scenes/peernode.gd | 13 +++++ scenes/peernode.tscn | 6 +++ scenes/peernode_directory.gd | 51 ++++++++++++++++++ scenes/peernode_directory.tscn | 6 +++ scenes/playernode.gd | 5 ++ scenes/playernode.tscn | 6 +++ scenes/playernode_directory.gd | 44 ++++++++++++++++ scenes/playernode_directory.tscn | 6 +++ scenes/single_peer_tracker.gd | 12 ----- scenes/single_peer_tracker.tscn | 6 --- scenes/single_player_tracker.gd | 37 ------------- scenes/single_player_tracker.tscn | 6 --- 15 files changed, 139 insertions(+), 213 deletions(-) delete mode 100644 scenes/multiple_players_tracker.gd delete mode 100644 scenes/multiple_players_tracker.tscn create mode 100644 scenes/peernode.gd create mode 100644 scenes/peernode.tscn create mode 100644 scenes/peernode_directory.gd create mode 100644 scenes/peernode_directory.tscn create mode 100644 scenes/playernode.gd create mode 100644 scenes/playernode.tscn create mode 100644 scenes/playernode_directory.gd create mode 100644 scenes/playernode_directory.tscn delete mode 100644 scenes/single_peer_tracker.gd delete mode 100644 scenes/single_peer_tracker.tscn delete mode 100644 scenes/single_player_tracker.gd delete mode 100644 scenes/single_player_tracker.tscn diff --git a/scenes/game.gd b/scenes/game.gd index 2353a2e..d809432 100644 --- a/scenes/game.gd +++ b/scenes/game.gd @@ -2,80 +2,5 @@ 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...") - multiplayer.connected_to_server.connect(_on_connected_to_server) - multiplayer.server_disconnected.connect(_on_server_disconnected) - multiplayer.connection_failed.connect(_on_connection_failed) - multiplayer.peer_connected.connect(_on_peer_connected) - 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(): - Log.peer(self, "Connected to server!") - -func _on_server_disconnected(): - Log.peer(self, "Server disconnected...") - -func _on_connection_failed(): - Log.peer(self, "Connection failed...") - -func _on_peer_connected(peer_id: int): - 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.create(peer_id) - # Log.peer(self, "Setting multiplayer authority: " + str(peer_id)) - # var sp_tracker = mp_tracker.find(peer_id) - # sp_tracker.set_multiplayer_authority(peer_id) - -func _on_peer_disconnected(peer_id: int): - 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) - # Log.peer(self, "Unsetting multiplayer authority: " + str(peer_id)) - # var sp_tracker = mp_tracker.find(peer_id) - # sp_tracker.set_multiplayer_authority(1) - -func _on_single_player_tracker_created(spawned_tracker: SinglePlayerTracker) -> void: - # If we spawned ourselves, set our own identity - if spawned_tracker.get_multiplayer_authority() == multiplayer.multiplayer_peer.get_unique_id(): - Log.peer(self, "Checking if we should notify our identity to everybody else...") - spawned_tracker.update_identity.rpc(local_player_name, local_player_color) - # If another player spawned, and they connected before us, send them our identity - elif not multiplayer.is_server(): - Log.peer(self, "Checking if we should notify our identity to: " + str(spawned_tracker.get_multiplayer_authority())) - 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()) - # If we're the server, broadcast information about disconnected players - else: - Log.peer(self, "Checking if we should notify identity for disconnected peers...") - for tracker in mp_tracker.find_children("", "SinglePlayerTracker", true, false): - Log.peer(self, str(tracker)) - if tracker.get_multiplayer_authority() == 1: - Log.peer(self, "I'm the authority, do notify.") - tracker.notify_identity(spawned_tracker.get_multiplayer_authority()) - else: - Log.peer(self, "I'm not the authority, do not notify.") +func _on_peernode_identified(peernode: PeerNode, player_name: String) -> void: + pass # Replace with function body. diff --git a/scenes/multiple_players_tracker.gd b/scenes/multiple_players_tracker.gd deleted file mode 100644 index e090d57..0000000 --- a/scenes/multiple_players_tracker.gd +++ /dev/null @@ -1,69 +0,0 @@ -extends Node -class_name MultiplePlayersTracker - -## Manager of all the instances of [SinglePlayerTracker] for a given multiplayer room. -## -## Authority of this object is always given to the server (1). -## -## The server uses its authority to assign authority to the child [SinglePlayerTracker]s. - -## Emitted when a new [SinglePlayerTracker] is created. -signal created(tracker: SinglePlayerTracker) - -## Emitted when any [SinglePlayerTracker] has changed. -signal changed(all_trackers: Array[SinglePlayerTracker]) - -## Emitted when any [SinglePlayerTracker] is about to be destroyed. -signal before_destroyed(tracker: SinglePlayerTracker) - -## The scene to be instantiated. -const tracker_scene = preload("res://scenes/single_player_tracker.tscn") - -## Return the [Array] of [SinglePlayerTrackers] managed by this object. -func find_all() -> Array[SinglePlayerTracker]: - return find_children("", "SinglePlayerTracker", false, false) as Array[SinglePlayerTracker] - -## Find the first [SinglePlayerTracker] over which the given peer id has authority. -func find_id(peer_id: int) -> SinglePlayerTracker: - for tracker in find_all(): - if tracker.get_multiplayer_authority() == peer_id: - return tracker - return null - -## Find the first [SinglePlayerTracker] over which the running instance has authority. -func find_self() -> SinglePlayerTracker: - var self_id = multiplayer.multiplayer_peer.get_unique_id() - return find_id(self_id) - -## Find the first [SinglePlayerTracker] representing a player with the given name. -func find_name(player_name: String) -> SinglePlayerTracker: - for tracker in find_all(): - if tracker.player_name == player_name: - return tracker - return null - - -## Create a new [SinglePlayerTracker] for the given peer id, or return the one that already exists. -@rpc("authority", "call_local", "reliable") -func create(peer_id: int) -> SinglePlayerTracker: - var tracker = find_id(peer_id) - if tracker != null: - return tracker - Log.peer(self, "Creating tracker for peer: %d" % peer_id) - tracker = tracker_scene.instantiate() - tracker.set_multiplayer_authority(peer_id) - created.emit(tracker) - var trackers = find_all() - changed.emit(trackers) - return tracker - -## Destroy the [SinglePlayerTracker] for the given peer id, or do nothing if it already exists. -func destroy(peer_id: int) -> void: - var tracker = find_id(peer_id) - if tracker == null: - return - Log.peer(self, "Destroying tracker for peer: %d" % peer_id) - before_destroyed.emit(tracker) - tracker.queue_free() - var trackers = find_all() - changed.emit(trackers) diff --git a/scenes/multiple_players_tracker.tscn b/scenes/multiple_players_tracker.tscn deleted file mode 100644 index 2d7bb6b..0000000 --- a/scenes/multiple_players_tracker.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://cwj0fyj6obj6r"] - -[ext_resource type="Script" path="res://scenes/multiple_players_tracker.gd" id="1_fxysy"] - -[node name="MultiplePlayersTracker" type="Node"] -script = ExtResource("1_fxysy") diff --git a/scenes/peernode.gd b/scenes/peernode.gd new file mode 100644 index 0000000..5c5405e --- /dev/null +++ b/scenes/peernode.gd @@ -0,0 +1,13 @@ +extends Node +class_name PeerNode +## Node containing all possible RPCs callable by a non-identified peer. + + +## Identifies the peer as the player with the given name. +@rpc("authority", "reliable") # Won't ever get called by server +func rpc_identify(player_name: String): + if multiplayer.is_server(): + identified.emit(player_name) + +## Emitted on the server when the peer with authority over this node calls [method rpc_identify]. +signal identified(player_name: String) diff --git a/scenes/peernode.tscn b/scenes/peernode.tscn new file mode 100644 index 0000000..2026c01 --- /dev/null +++ b/scenes/peernode.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://b3xvsnotg0ee2"] + +[ext_resource type="Script" path="res://scenes/peernode.gd" id="1_svlk8"] + +[node name="PeerNode" type="Node"] +script = ExtResource("1_svlk8") diff --git a/scenes/peernode_directory.gd b/scenes/peernode_directory.gd new file mode 100644 index 0000000..5fffb47 --- /dev/null +++ b/scenes/peernode_directory.gd @@ -0,0 +1,51 @@ +extends Node +class_name PeerNodeDirectory + + +## The scene to instantiate on creation of a new [PeerNode]. +@export var peernode_scene: PackedScene = preload("res://scenes/peernode.tscn") + + +## Cache dictionary mapping peer_ids to their respective [PeerNode]. +## +## This script is responsible for keeping it updated. +var peernodes_by_id: Dictionary = {} + + +## Find the subordinate [PeerNode] with the given peer_id, and return it if found, otherwise return null. +func get_peernode(peer_id: int) -> PeerNode: + return peernodes_by_id.get(peer_id) as PeerNode + + +## Create a new [PeerNode] for the given peer_id, or do nothing if it already exists. +@rpc("authority", "call_local", "reliable") +func rpc_create_peernode(peer_id: int): + # Make sure the peernode does not exist + var peernode: PeerNode = get_peernode(peer_id) + if peernode != null: + return + # Create a new peernode + peernode = peernode_scene.instantiate() + peernodes_by_id[peer_id] = peernode + peernode.set_multiplayer_authority(peer_id) + peernode.identified.connect(_on_peernode_identified.bind(peernode)) + add_child(peernode) + + +## Destroy the [PeerNode] for the given peer_id, or do nothing if it does not exist. +@rpc("authority", "call_local", "reliable") +func rpc_destroy_peernode(peer_id: int): + # Make sure the peernode exists + var peernode: PeerNode = get_peernode(peer_id) + if peernode == null: + return + # Destroy the peernode + peernode.queue_free() + + +## Called on the server when a [PeerNode] calls [method rpc_identify] for itself. +func _on_peernode_identified(peernode: PeerNode, player_name: String): + peernode_identified.emit(peernode, player_name) + +## Emitted on the server when a [PeerNode] calls [method rpc_identify] for itself. +signal peernode_identified(peernode: PeerNode, player_name: String) diff --git a/scenes/peernode_directory.tscn b/scenes/peernode_directory.tscn new file mode 100644 index 0000000..37d8376 --- /dev/null +++ b/scenes/peernode_directory.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://7ux0cl08c2ho"] + +[ext_resource type="Script" path="res://scenes/peernode_directory.gd" id="1_mc47a"] + +[node name="PeerNodeDirectory" type="Node"] +script = ExtResource("1_mc47a") diff --git a/scenes/playernode.gd b/scenes/playernode.gd new file mode 100644 index 0000000..24e050d --- /dev/null +++ b/scenes/playernode.gd @@ -0,0 +1,5 @@ +extends Node +class_name PlayerNode + + +# TODO \ No newline at end of file diff --git a/scenes/playernode.tscn b/scenes/playernode.tscn new file mode 100644 index 0000000..3827e6f --- /dev/null +++ b/scenes/playernode.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://dfhunwafh4hc7"] + +[ext_resource type="Script" path="res://scenes/playernode.gd" id="1_rxnrx"] + +[node name="PlayerNode" type="Node"] +script = ExtResource("1_rxnrx") diff --git a/scenes/playernode_directory.gd b/scenes/playernode_directory.gd new file mode 100644 index 0000000..6b830ad --- /dev/null +++ b/scenes/playernode_directory.gd @@ -0,0 +1,44 @@ +extends Node +class_name PlayerNodeDirectory + + +## The scene to instantiate on creation of a new [PlayerNode]. +@export var playernode_scene: PackedScene = preload("res://scenes/playernode.tscn") + + +## Cache dictionary mapping player names to their respective [PlayerNode]. +## +## This script is responsible for keeping it updated. +var playernodes_by_name: Dictionary = {} + + +## Find the subordinate [PlayerNode] with the given player_name, and return it if found, otherwise return null. +func get_playernode(player_name: String) -> PlayerNode: + return playernodes_by_name.get(player_name) + +## Called everywhere when a [PlayerNode] is renamed. +func _on_playernode_renamed(old_name: String, new_name: String) -> void: + var playernode = playernodes_by_name.get(old_name) + playernodes_by_name.erase(old_name) + playernodes_by_name[new_name] = playernode + + +## Create a new [PlayerNode] for the given [param player_name], giving control of it to [param peer_id]. +## +## If a node with the given name already exists, only its multiplayer authority is changed, leaving the rest intact. +## +## If both node and multiplayer authority match the requested values, nothing is done at all. +@rpc("authority", "call_local", "reliable") +func rpc_possess_playernode(player_name: String, peer_id: int): + var playernode: PlayerNode = get_playernode(player_name) + # If the playernode does not exist, create it + if playernode == null: + playernode = playernode_scene.instantiate() + add_child(playernode) + # If the multiplayer authority does not match the requested one, make it match + if playernode.get_multiplayer_authority() != peer_id: + playernode.set_multiplayer_authority(peer_id) + child_repossessed.emit(playernode) + +## Emitted everywhere when one of the children [PlayerNode]s has changed multiplayer authority. +signal child_repossessed(playernode: PlayerNode) diff --git a/scenes/playernode_directory.tscn b/scenes/playernode_directory.tscn new file mode 100644 index 0000000..11b21b7 --- /dev/null +++ b/scenes/playernode_directory.tscn @@ -0,0 +1,6 @@ +[gd_scene load_steps=2 format=3 uid="uid://d3jo4swi2c7ae"] + +[ext_resource type="Script" path="res://scenes/playernode_directory.gd" id="1_rv34m"] + +[node name="PlayerNodeDirectory" type="Node"] +script = ExtResource("1_rv34m") diff --git a/scenes/single_peer_tracker.gd b/scenes/single_peer_tracker.gd deleted file mode 100644 index 523e8cd..0000000 --- a/scenes/single_peer_tracker.gd +++ /dev/null @@ -1,12 +0,0 @@ -extends Node -class_name SinglePeerTracker - -## Node representative of a single connected peer. -## -## That specific peer must have authority over this node. -## -## Then, that authority is used to connect to a specific player. - -@rpc("authority", "call_local", "reliable") -func takeover(player: SinglePlayerTracker): - pass diff --git a/scenes/single_peer_tracker.tscn b/scenes/single_peer_tracker.tscn deleted file mode 100644 index a8807c4..0000000 --- a/scenes/single_peer_tracker.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://gabtrafmbrmn"] - -[ext_resource type="Script" path="res://scenes/single_peer_tracker.gd" id="1_pofmw"] - -[node name="SinglePeerTracker" type="Node"] -script = ExtResource("1_pofmw") diff --git a/scenes/single_player_tracker.gd b/scenes/single_player_tracker.gd deleted file mode 100644 index 376bd61..0000000 --- a/scenes/single_player_tracker.gd +++ /dev/null @@ -1,37 +0,0 @@ -extends Node -class_name SinglePlayerTracker - -## Node representative of a player connected to the room. -## -## The peer of the player this node represents has authority over it. - -## The player's name. -var player_name: String = "Player" - -## The player's color. -var player_color: Color = Color.WHITE - -## Whether this player is currently connected or not. -var player_connected: bool = false - -## Change the name of this player. -@rpc("authority", "call_local", "reliable") -func set_player_name(value: String): - player_name = value - -## Change the color of this player. -@rpc("authority", "call_local", "reliable") -func set_player_color(value: Color): - player_color = value - -## Ask the authority for this player to repeat the player's name. -@rpc("any_peer", "call_local", "reliable") -func query_player_name(): - if is_multiplayer_authority(): - set_player_name.rpc(player_name) - -## Ask the authority for this player to repeat the player's color. -@rpc("any_peer", "call_local", "reliable") -func query_player_color(): - if is_multiplayer_authority(): - set_player_color.rpc(player_color) diff --git a/scenes/single_player_tracker.tscn b/scenes/single_player_tracker.tscn deleted file mode 100644 index ec5116e..0000000 --- a/scenes/single_player_tracker.tscn +++ /dev/null @@ -1,6 +0,0 @@ -[gd_scene load_steps=2 format=3 uid="uid://drccgvtcng3ju"] - -[ext_resource type="Script" path="res://scenes/single_player_tracker.gd" id="1_jwlkv"] - -[node name="SinglePlayerTracker" type="Node"] -script = ExtResource("1_jwlkv")