diff --git a/scripts/utils/game.gd b/scripts/utils/game.gd index 52b9e5c..c20b085 100644 --- a/scripts/utils/game.gd +++ b/scripts/utils/game.gd @@ -1,5 +1,11 @@ extends Node +# This tells the game what the logmode is. +# 0 -> None +# 1 -> Errors +# 2 -> Errors/Warnings +# 3 -> Errors/Warnings/Infos +# 4 -> All var logmode: int = 4 var ip: String = "127.0.0.1" diff --git a/scripts/utils/log.gd b/scripts/utils/log.gd index 03d4f93..ef0a21c 100644 --- a/scripts/utils/log.gd +++ b/scripts/utils/log.gd @@ -1,14 +1,10 @@ extends Node -# This tells the game what the logmode is. -# 0 -> None -# 1 -> Errors -# 2 -> Errors/Warnings -# 3 -> Errors/Warnings/Infos -# 4 -> All +var mutex: Mutex = Mutex.new() # Used for errors. func error(message: String, alert_message: String) -> void: + mutex.lock() if message == "": message = "Empty message string passed to an error message!" if Game.logmode >= 1: @@ -19,26 +15,35 @@ func error(message: String, alert_message: String) -> void: else: OS.alert("An error has occured. The program will now exit.", "Error!") get_tree().quit() + mutex.unlock() # Used for warnings. func warning(message: String) -> void: + mutex.lock() if message == "": message = "Empty message string passed to a warning message!" if Game.logmode >= 2: printerr("[WARNING] " + message) + mutex.unlock() # Used for simple info. func info(message: String) -> void: + mutex.lock() if message == "": warning("Empty message string passed to an info message!") + mutex.unlock() return if Game.logmode >= 3: print("[INFO] " + message) + mutex.unlock() # Used for debugging. func debug(message: String) -> void: + mutex.lock() if message == "": warning("Empty message string passed to a debug message!") + mutex.unlock() return if Game.logmode >= 4: print("[DEBUG] " + message) + mutex.unlock() diff --git a/scripts/utils/networking.gd b/scripts/utils/networking.gd index d0265ea..2eaceda 100644 --- a/scripts/utils/networking.gd +++ b/scripts/utils/networking.gd @@ -16,6 +16,7 @@ func _ready() -> void: Log.error("FAILED to connect the peer_disconnected signal to _on_peer_disconnected!", "Internal Error: Failed to connect signal.") 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 @@ -49,7 +50,7 @@ func close_network() -> void: var mutex: Mutex = Mutex.new() var rooms: Dictionary = {} -# 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. +var server_peers: Dictionary = {} var peers: Dictionary = {} var isManager: bool = false var managerID: int @@ -69,26 +70,36 @@ func _on_peer_disconnected(id: int) -> void: 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]) + mutex.unlock() + return 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]: + mutex.unlock() + return + for peer: int in server_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): + mutex.unlock() + return + if !server_peers.erase(roomname): Log.warning("Room %s couldn't be found, even though it should exist!" % roomname) + mutex.unlock() + return Log.info("Room %s terminated." % roomname) else: - for room: String in peers: - for peer: int in peers[room]: + for room: String in server_peers: + for peer: int in server_peers[room]: if peer == id: - var peer_array: Array = peers[room] + var peer_array: Array = server_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: + server_peers[room] = peer_array + for found_peer: int in server_peers[room]: + if rpc_id(found_peer, "peer_disconnected_message", id) != OK: Log.warning("Failed to send disconnect message to %d!" % found_peer) + mutex.unlock() + return mutex.unlock() # The following function sends the roomname selected by the client. @@ -99,17 +110,19 @@ func send_roomname(roomname: String) -> void: 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()] + server_peers[roomname] = [multiplayer.get_remote_sender_id()] Log.info("Room %s registered." % roomname) if rpc_id(multiplayer.get_remote_sender_id(), "server_response", 0, rooms[roomname]) != OK: Log.warning("Failed to send elevation reply to %d!") - 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] + elif server_peers[roomname] is Array: + # For some odd reason, Godot doesn't allow casting server_peers[roomname] to an Array, but this works? + var peer_array: Array = server_peers[roomname] peer_array.append(multiplayer.get_remote_sender_id()) - peers[roomname] = peer_array + server_peers[roomname] = peer_array if rpc_id(multiplayer.get_remote_sender_id(), "server_response", 1, rooms[roomname]) != OK: Log.warning("Failed to send join reply to %d!") + mutex.unlock() + return 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()) @@ -120,13 +133,26 @@ func send_roomname(roomname: String) -> void: # 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 + Log.info("Host disconnected from the session.") + managerID = 1 + close_network() + if get_tree().change_scene_to_file("res://start.tscn"): + Log.warning("Failed to change back to the main scene!") # 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 - +func peer_disconnected_message(id: int) -> void: + for peer: String in peers: + if peers[peer] == id: + if !peers.erase(peer): + Log.warning("Peer %d never existed, but was tasked to remove it!" % id) + return + if emit_signal("playerlist_changed") != OK: + Log.warning("Couldn't emit playerlist_changed signal.") + return + Log.info("Peer %d successfully removed." % id) + + # This is the initial server response, which tells the client what its role is. @rpc("authority", "call_remote", "reliable") func server_response(status: int, manager: int) -> void: @@ -152,9 +178,9 @@ 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] + var peer_array: Array = server_peers[roomname] peer_array.append(multiplayer.get_remote_sender_id()) - peers[roomname] = peer_array + server_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: @@ -165,12 +191,16 @@ func inform_server(roomname: String) -> void: @rpc("any_peer", "call_remote", "reliable") func request_playerlist(peername: String) -> void: if isManager: - if !peers.has(peername): + if !peers.has(peername) and !peers.has(multiplayer.get_remote_sender_id()): 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 !peers.erase(peername): + Log.warning("Couldn't reverse adding %d to the playerlist." % peername) + return if rpc_id(1, "inform_server", Game.roomname) != OK: Log.warning("Failed to send playerinfo to server.") + return for peer: String in peers: var remote_id: int = peers[peer] if remote_id != multiplayer.get_unique_id():