1
Fork 0
mirror of https://github.com/Steffo99/nanogolf.git synced 2024-11-25 01:24:18 +00:00

Actually make some progress

This commit is contained in:
Steffo 2024-03-09 05:48:31 +01:00
parent b466eb09eb
commit 2c51d84bbc
Signed by: steffo
GPG key ID: 5ADA3868646C3FC0
15 changed files with 139 additions and 213 deletions

View file

@ -2,80 +2,5 @@ extends Node
class_name Game class_name Game
signal trackers_changed(trackers: Dictionary) func _on_peernode_identified(peernode: PeerNode, player_name: String) -> void:
pass # Replace with function body.
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.")

View file

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

View file

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

13
scenes/peernode.gd Normal file
View file

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

6
scenes/peernode.tscn Normal file
View file

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

View file

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

View file

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

5
scenes/playernode.gd Normal file
View file

@ -0,0 +1,5 @@
extends Node
class_name PlayerNode
# TODO

6
scenes/playernode.tscn Normal file
View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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