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:
parent
b466eb09eb
commit
2c51d84bbc
15 changed files with 139 additions and 213 deletions
|
@ -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.")
|
|
||||||
|
|
|
@ -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)
|
|
|
@ -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
13
scenes/peernode.gd
Normal 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
6
scenes/peernode.tscn
Normal 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")
|
51
scenes/peernode_directory.gd
Normal file
51
scenes/peernode_directory.gd
Normal 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)
|
6
scenes/peernode_directory.tscn
Normal file
6
scenes/peernode_directory.tscn
Normal 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
5
scenes/playernode.gd
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
extends Node
|
||||||
|
class_name PlayerNode
|
||||||
|
|
||||||
|
|
||||||
|
# TODO
|
6
scenes/playernode.tscn
Normal file
6
scenes/playernode.tscn
Normal 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")
|
44
scenes/playernode_directory.gd
Normal file
44
scenes/playernode_directory.gd
Normal 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)
|
6
scenes/playernode_directory.tscn
Normal file
6
scenes/playernode_directory.tscn
Normal 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")
|
|
@ -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
|
|
|
@ -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")
|
|
|
@ -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)
|
|
|
@ -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")
|
|
Loading…
Reference in a new issue