2024-12-03 21:44:07 +01:00
extends Node
2024-12-05 19:39:07 +01:00
signal playerlist_changed ( )
2024-12-04 21:01:24 +01:00
## Connection Code
# Connect the signals.
func _ready ( ) - > void :
if multiplayer . connected_to_server . connect ( _on_connected_ok ) != OK :
Log . error ( " FAILED to connect the connected_to_server signal to _on_connected_ok! " , " Internal Error: Failed to connect signal. " )
if multiplayer . connection_failed . connect ( close_network ) != OK :
Log . error ( " FAILED to connect the connection_failed signal to _on_connected_fail! " , " Internal Error: Failed to connect signal. " )
if multiplayer . server_disconnected . connect ( close_network ) != OK :
Log . error ( " FAILED to connect the server_disconnected signal to _on_server_disconnected! " , " Internal Error: Failed to connect signal. " )
2024-12-05 10:34:01 +01:00
if multiplayer . peer_disconnected . connect ( _on_peer_disconnected ) != OK :
Log . error ( " FAILED to connect the peer_disconnected signal to _on_peer_disconnected! " , " Internal Error: Failed to connect signal. " )
2024-12-05 19:39:07 +01:00
if playerlist_changed . connect ( _on_playerlist_changed ) != OK :
Log . error ( " FAILED to connect the playerlist_changed signal to _on_playerlist_changed! " , " Internal Error: Failed to connect signal. " )
func _on_playerlist_changed ( ) - > void :
pass
2024-12-03 21:44:07 +01:00
# Start the network listener.
2024-12-04 21:01:24 +01:00
func start_server ( ) - > Error :
2024-12-03 21:44:07 +01:00
var peer : ENetMultiplayerPeer = ENetMultiplayerPeer . new ( )
2024-12-04 21:01:24 +01:00
if peer . create_server ( Game . port , Game . max_clients ) != OK :
Log . warning ( " Couldn ' t create the server at port %d ! " % Game . port )
return FAILED
2024-12-03 21:44:07 +01:00
multiplayer . multiplayer_peer = peer
2024-12-04 21:01:24 +01:00
Log . info ( " Created the server at port %d . " % Game . port )
return OK
2024-12-03 21:44:07 +01:00
# Connect to a server.
2024-12-04 21:01:24 +01:00
func join_server ( ) - > Error :
2024-12-03 21:44:07 +01:00
var peer : ENetMultiplayerPeer = ENetMultiplayerPeer . new ( )
2024-12-04 21:01:24 +01:00
if peer . create_client ( Game . ip , Game . port ) != OK :
Log . warning ( " Couldn ' t connect to the server at %s : %d ! " % [ Game . ip , Game . port ] )
return FAILED
2024-12-03 21:44:07 +01:00
multiplayer . multiplayer_peer = peer
2024-12-04 21:01:24 +01:00
Log . info ( " Connected to the server at %s : %d . " % [ Game . ip , Game . port ] )
return OK
2024-12-03 21:44:07 +01:00
# Close all network connections.
func close_network ( ) - > void :
multiplayer . multiplayer_peer = null
Log . info ( " Closed all network connections. " )
2024-12-04 21:01:24 +01:00
## Matchmaking Code
var mutex : Mutex = Mutex . new ( )
var rooms : Dictionary = { }
2024-12-05 19:39:07 +01:00
# peers has two different uses: On the server it is an index of all rooms with their peers, while on the client it is just a lookup table for peers and their usernames.
2024-12-04 21:01:24 +01:00
var peers : Dictionary = { }
2024-12-05 19:39:07 +01:00
var isManager : bool = false
var managerID : int
2024-12-04 21:01:24 +01:00
func join_room ( ) - > void :
if join_server ( ) != OK :
Log . warning ( " Failed to connect to sever. " )
func _on_connected_ok ( ) - > void :
2024-12-05 19:39:07 +01:00
if rpc_id ( 1 , " send_roomname " , Game . roomname ) != OK :
2024-12-04 21:01:24 +01:00
Log . warning ( " Failed to send roomname! " )
2024-12-05 10:34:01 +01:00
func _on_peer_disconnected ( id : int ) - > void :
mutex . lock ( )
if multiplayer . get_unique_id ( ) == 1 :
if rooms . has ( id ) :
var roomname : String = rooms [ id ]
if ! rooms . erase ( roomname ) :
Log . warning ( " The room %s associated with %d doesn ' t exist in rooms, even though it should! " % [ roomname , id ] )
if ! rooms . erase ( id ) :
Log . warning ( " The peer %d doesn ' t exist in rooms, even though it should! " % id )
for peer : int in peers [ roomname ] :
if peer == id :
continue
if rpc_id ( peer , " host_disconnected_message " ) :
Log . warning ( " Peer %d couldn ' t be disconnected! " % peer )
if ! peers . erase ( roomname ) :
Log . warning ( " Room %s couldn ' t be found, even though it should exist! " % roomname )
Log . info ( " Room %s terminated. " % roomname )
else :
for room : String in peers :
for peer : int in peers [ room ] :
if peer == id :
var peer_array : Array = peers [ room ]
peer_array . erase ( id )
peers [ room ] = peer_array
for found_peer : int in peers [ room ] :
if rpc_id ( found_peer , " peer_disconnected_message " ) != OK :
Log . warning ( " Failed to send disconnect message to %d ! " % found_peer )
mutex . unlock ( )
# The following function sends the roomname selected by the client.
2024-12-04 21:01:24 +01:00
@ rpc ( " any_peer " , " call_remote " , " reliable " )
func send_roomname ( roomname : String ) - > void :
mutex . lock ( )
if multiplayer . get_unique_id ( ) == 1 :
if ! rooms . has ( roomname ) and ! rooms . has ( multiplayer . get_remote_sender_id ( ) ) :
rooms [ roomname ] = multiplayer . get_remote_sender_id ( )
rooms [ multiplayer . get_remote_sender_id ( ) ] = roomname
peers [ roomname ] = [ multiplayer . get_remote_sender_id ( ) ]
Log . info ( " Room %s registered. " % roomname )
2024-12-05 19:39:07 +01:00
if rpc_id ( multiplayer . get_remote_sender_id ( ) , " server_response " , 0 , rooms [ roomname ] ) != OK :
2024-12-05 10:34:01 +01:00
Log . warning ( " Failed to send elevation reply to %d ! " )
2024-12-04 21:01:24 +01:00
elif peers [ roomname ] is Array :
# For some odd reason, Godot doesn't allow casting peers[roomname] to an Array, but this works?
var peer_array : Array = peers [ roomname ]
peer_array . append ( multiplayer . get_remote_sender_id ( ) )
peers [ roomname ] = peer_array
2024-12-05 19:39:07 +01:00
if rpc_id ( multiplayer . get_remote_sender_id ( ) , " server_response " , 1 , rooms [ roomname ] ) != OK :
2024-12-05 10:34:01 +01:00
Log . warning ( " Failed to send join reply to %d ! " )
2024-12-04 21:01:24 +01:00
Log . debug ( " Room %s joined by peer %d . " % [ roomname , multiplayer . get_remote_sender_id ( ) ] )
else :
Log . warning ( " Peer %d tried to send this client a request meant for the authority! " % multiplayer . get_remote_sender_id ( ) )
2024-12-05 19:39:07 +01:00
if rpc_id ( multiplayer . get_remote_sender_id ( ) , " server_response " , 2 , 0 ) != OK :
2024-12-05 10:34:01 +01:00
Log . warning ( " Failed to send fail reply to %d ! " )
2024-12-04 21:01:24 +01:00
mutex . unlock ( )
2024-12-05 10:34:01 +01:00
# This is the message sent out if the host of the room has left.
@ rpc ( " authority " , " call_remote " , " reliable " )
func host_disconnected_message ( ) - > void :
pass # TODO: Implement this
# This is the message sent out if a peer in the room has left.
@ rpc ( " authority " , " call_remote " , " reliable " )
func peer_disconnected_message ( ) - > void :
pass # TODO: Implement this
# This is the initial server response, which tells the client what its role is.
@ rpc ( " authority " , " call_remote " , " reliable " )
2024-12-05 19:39:07 +01:00
func server_response ( status : int , manager : int ) - > void :
2024-12-05 10:34:01 +01:00
match status :
0 :
2024-12-05 19:39:07 +01:00
# create new room host
isManager = true
if get_tree ( ) . change_scene_to_file ( " res://scenes/ui/lobby.tscn " ) != OK :
Log . error ( " Couldn ' t change to the lobby scene! Closing application. " , " Couldn ' t change to the lobby scene! " )
peers [ Game . username ] = manager
managerID = manager
2024-12-05 10:34:01 +01:00
1 :
2024-12-05 19:39:07 +01:00
# create new room member
managerID = manager
if rpc_id ( managerID , " request_playerlist " , Game . username ) != OK :
Log . warning ( " Failed to send username to room host %d . " % multiplayer . get_remote_sender_id ( ) )
2024-12-05 10:34:01 +01:00
2 :
2024-12-05 19:39:07 +01:00
Log . warning ( " Sent a join request to a regular peer, not the server! " )
# This informs the server of the recently joined player.
@ rpc ( " any_peer " , " call_remote " , " reliable " )
func inform_server ( roomname : String ) - > void :
mutex . lock ( )
if multiplayer . get_unique_id ( ) == 1 :
if multiplayer . get_remote_sender_id ( ) == rooms [ roomname ] :
var peer_array : Array = peers [ roomname ]
peer_array . append ( multiplayer . get_remote_sender_id ( ) )
peers [ roomname ] = peer_array
else :
Log . warning ( " Peer %d attempted to trick the server into adding it to the room! " % multiplayer . get_remote_sender_id ( ) )
else :
Log . warning ( " Peer %d tried to send this client a request meant for the authority! " % multiplayer . get_remote_sender_id ( ) )
mutex . unlock ( )
# Get the playerlist from the room host.
@ rpc ( " any_peer " , " call_remote " , " reliable " )
func request_playerlist ( peername : String ) - > void :
if isManager :
if ! peers . has ( peername ) :
peers [ peername ] = multiplayer . get_remote_sender_id ( )
if rpc_id ( multiplayer . get_remote_sender_id ( ) , " send_playerlist " , 0 , peers ) != OK :
Log . warning ( " Failed to send join status to %d . " % multiplayer . get_remote_sender_id ( ) )
if rpc_id ( 1 , " inform_server " , Game . roomname ) != OK :
Log . warning ( " Failed to send playerinfo to server. " )
for peer : String in peers :
var remote_id : int = peers [ peer ]
if remote_id != multiplayer . get_unique_id ( ) :
if rpc_id ( remote_id , " send_playerlist " , 1 , peers ) != OK :
Log . warning ( " Failed to send playerlist to %d . " % multiplayer . get_remote_sender_id ( ) )
if emit_signal ( " playerlist_changed " ) != OK :
Log . warning ( " Couldn ' t emit playerlist_changed signal. " )
else :
if rpc_id ( multiplayer . get_remote_sender_id ( ) , " send_playerlist " , 2 , { } ) != OK :
Log . warning ( " Couldn ' t send failure response to peer %d ! " % multiplayer . get_remote_sender_id ( ) )
Log . warning ( " Peer %d tried to register with name %s , which already exists! " % [ multiplayer . get_remote_sender_id ( ) , peername ] )
else :
if rpc_id ( multiplayer . get_remote_sender_id ( ) , " send_playerlist " , 3 , { } ) != OK :
Log . warning ( " Couldn ' t send failure response to peer %d ! " % multiplayer . get_remote_sender_id ( ) )
Log . warning ( " Peer %d tried to send this client a request meant for the room host! " % multiplayer . get_remote_sender_id ( ) )
# Recive the playerlist on the client.
@ rpc ( " any_peer " , " call_remote " , " reliable " )
func send_playerlist ( status : int , newPeers : Dictionary ) - > void :
if multiplayer . get_remote_sender_id ( ) == managerID :
match status :
0 :
peers = newPeers
Log . info ( " Room %s successfully joined. " % Game . roomname )
if get_tree ( ) . change_scene_to_file ( " res://scenes/ui/lobby.tscn " ) != OK :
Log . error ( " Couldn ' t change to the lobby scene! Closing application. " , " Couldn ' t change to the lobby scene! " )
1 :
peers = newPeers
Log . debug ( " Playerlist recived. " )
if emit_signal ( " playerlist_changed " ) != OK :
Log . warning ( " Couldn ' t emit playerlist_changed signal. " )
2 :
Log . warning ( " Name %s is already taken in the room! " % Game . username )
3 :
Log . warning ( " Sent a playerlist request to a regular peer, not the host! " )