diff --git a/components/client_interface.gd b/components/client_interface.gd index 24e8753..548e5cc 100644 --- a/components/client_interface.gd +++ b/components/client_interface.gd @@ -123,3 +123,7 @@ func _on_web_client_tcp_connection_status_changed(new_status: WebClientTCP.Conne lobby_code_input.editable = false chat_message_input.editable = true send_chat_message_button.disabled = false + + +func _on_web_client_tcp_received_connection_message(message: String) -> void: + _write_line(message) diff --git a/components/web_client_tcp.gd b/components/web_client_tcp.gd index 384dff0..b1357e6 100644 --- a/components/web_client_tcp.gd +++ b/components/web_client_tcp.gd @@ -29,6 +29,7 @@ signal disconnected_from_lobby() signal client_joined_lobby(client_name: String, currently_connected_client_names: Array[String]) signal client_left_lobby(client_name: String, currently_connected_client_names: Array[String]) +signal received_connection_message(message: String) signal received_chat_message(client_name: String, message: String) signal connection_status_changed(new_status: ConnectionStatus) @@ -94,11 +95,8 @@ func _handle_response(response: String) -> void: _client_id = data["client_id"] connected_to_lobby.emit.call_deferred(_lobby_id) connection_status_changed.emit.call_deferred(ConnectionStatus.JOINED) - "join_lobby": - if data["status"] == "ok": - _client_id = data["client_id"] - connected_to_lobby.emit.call_deferred(_lobby_id) - connection_status_changed.emit.call_deferred(ConnectionStatus.JOINED) + "join_lobby_response": + _handle_join(data) "client_joined_lobby": _currently_connected_client_names.assign(data["connected_client_names"]) client_joined_lobby.emit.call_deferred(data["new_client_name"], _currently_connected_client_names) @@ -115,6 +113,19 @@ func _handle_response(response: String) -> void: "receive_chat_message": received_chat_message.emit.call_deferred(data["client_name"], data["message"]) +func _handle_join(data) -> void: + match data["status"]: + "lobby_not_found": + received_connection_message.emit.call_deferred("Could not join; lobby does not exist") + connection_status_changed.emit.call_deferred(ConnectionStatus.LOBBYLESS) + "lobby_full": + received_connection_message.emit.call_deferred("Could not join; lobby is full") + connection_status_changed.emit.call_deferred(ConnectionStatus.LOBBYLESS) + "ok": + _client_id = data["client_id"] + connected_to_lobby.emit.call_deferred(_lobby_id) + connection_status_changed.emit.call_deferred(ConnectionStatus.JOINED) + func _exit_tree() -> void: disconnect_from_server() @@ -138,6 +149,7 @@ func join_lobby(lobby_id: String, client_name: String) -> void: _client_name = client_name _send_message(TCPMessages.join_lobby(_lobby_id, client_name)) + connection_status_changed.emit.call_deferred(ConnectionStatus.ATTEMPTING_JOIN) func leave_lobby() -> void: _send_message(TCPMessages.leave_lobby(_lobby_id, _client_id)) diff --git a/game.tscn b/game.tscn index 706888b..ccb4c23 100644 --- a/game.tscn +++ b/game.tscn @@ -153,6 +153,7 @@ text = "Start Game!" [connection signal="disconnected_from_lobby" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_disconnected_from_lobby"] [connection signal="disconnected_from_server" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_disconnected_from_server"] [connection signal="received_chat_message" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_received_chat_message"] +[connection signal="received_connection_message" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_received_connection_message"] [connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/ConnectButton" to="HBoxContainer/ClientInterface" method="_on_connect_button_pressed"] [connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/CreateLobbyButton" to="HBoxContainer/ClientInterface" method="_on_create_lobby_button_pressed"] [connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ServerInputs/CreateLobbyButton" to="HBoxContainer/GameUI" method="_on_create_lobby_button_pressed"] diff --git a/server_tcp.py b/server_tcp.py index 1a06593..1867787 100644 --- a/server_tcp.py +++ b/server_tcp.py @@ -6,6 +6,8 @@ import ssl import asyncio from websockets.asyncio.server import serve +MAX_LOBBY_CLIENT_COUNT = 6 + # Generates a 6-character code from the letters A-Z def generate_code() -> str: result = "" @@ -42,7 +44,15 @@ class LobbyManager: print(f"Created lobby {lobby_id}") # Joins a client to an existing lobby - async def join_lobby(self, lobby_id, client_id, client_name, websocket) -> None: + async def join_lobby(self, lobby_id, client_id, client_name, websocket) -> str: + if not self.lobby_id_exists(lobby_id): + # Cannot join; lobby does not exist + return "lobby_not_found" + + if self.get_lobby_player_count(lobby_id) >= MAX_LOBBY_CLIENT_COUNT: + # Lobby full! Cannot join + return "lobby_full" + # Add client to lobby self.active_lobbies[lobby_id].connected_clients[client_id] = Client( client_id, @@ -61,6 +71,8 @@ class LobbyManager: "connected_client_names": self.get_lobby_client_names(lobby_id), }) ) + + return "ok" # Removes a client from a lobby async def leave_lobby(self, lobby_id, client_id) -> None: @@ -201,7 +213,9 @@ async def process_input(message: str, websocket) -> None: new_client_id, ) - # Join requesting client to new lobby + # Join requesting client to new lobby. + # No error handling here, since lobby was just created, so it + # must exist and be empty await lobby_manager.join_lobby( new_lobby_id, new_client_id, @@ -226,28 +240,51 @@ async def process_input(message: str, websocket) -> None: # Join client to existing lobby elif data_object["response"] == "join_lobby": lobby_id = data_object["lobby_id"] - new_client_id = lobby_manager.get_unique_client_id(lobby_id) + client_id = lobby_manager.get_unique_client_id(lobby_id) + client_name = data_object["client_name"] # Join client to lobby - await lobby_manager.join_lobby( + response = await lobby_manager.join_lobby( lobby_id, - new_client_id, - data_object["client_name"], + client_id, + client_name, websocket, ) - # Send success confirmation - await lobby_manager.send_message( - lobby_id, - new_client_id, - json.dumps({ - "response": "join_lobby", - "status": "ok", - "client_id": new_client_id, - }), - ) + match response: + case "lobby_not_found": + await websocket.send( + json.dumps({ + "response": "join_lobby_response", + "status": "lobby_not_found", + }) + ) + + print(f"Client {client_name} could not connect; lobby {lobby_id} does not exist") + + case "lobby_full": + await websocket.send( + json.dumps({ + "response": "join_lobby_response", + "status": "lobby_full", + }) + ) - print(f"Client {new_client_id} joined lobby {lobby_id}") + print(f"Client {client_name} could not connect; lobby {lobby_id} is full") + + case "ok": + # Send success confirmation + await lobby_manager.send_message( + lobby_id, + client_id, + json.dumps({ + "response": "join_lobby_response", + "status": "ok", + "client_id": client_id, + }), + ) + + print(f"Client {client_id} joined lobby {lobby_id}") # Disconnect client from lobby elif data_object["response"] == "leave_lobby":