From 05e5acd503ad3486bb81ec332facffb1477487bb Mon Sep 17 00:00:00 2001 From: denizk0461 Date: Sun, 6 Jul 2025 19:49:08 +0200 Subject: [PATCH] server: added SSL context for running on remote server --- components/client_interface.gd | 5 +- components/web_client_tcp.gd | 67 ++++------ export_presets.cfg | 2 +- game.tscn | 100 +++++++++------ game_client.gd | 8 +- server_tcp.py | 224 +++++++++++++++++++++++++++++++++ 6 files changed, 318 insertions(+), 88 deletions(-) create mode 100644 server_tcp.py diff --git a/components/client_interface.gd b/components/client_interface.gd index 67fa5ed..c29c5f2 100644 --- a/components/client_interface.gd +++ b/components/client_interface.gd @@ -2,7 +2,6 @@ class_name ClientInterface extends Control @export var client: WebClientTCP -@export var game_client: GameClient @export var connect_button: Button @export var create_lobby_button: Button @@ -22,14 +21,12 @@ func _write_line(text: String) -> void: func _on_create_lobby_button_pressed() -> void: client.create_lobby(name_input.text.strip_edges()) - game_client.is_host = true func _on_connect_button_pressed() -> void: - client.connect_to_server() + client.connect_to_server($MarginContainer/VBoxContainer/URLInput.text) func _on_join_lobby_button_pressed() -> void: client.join_lobby(lobby_code_input.text.strip_edges(), name_input.text.strip_edges()) - game_client.is_host = false func _on_disconnect_lobby_button_pressed() -> void: leave_lobby_button.disabled = true diff --git a/components/web_client_tcp.gd b/components/web_client_tcp.gd index f5efbe3..586baeb 100644 --- a/components/web_client_tcp.gd +++ b/components/web_client_tcp.gd @@ -17,6 +17,8 @@ var cached_response: String var _thread: Thread var _stop_thread: bool = false +var _players_in_lobby: int = 0 + signal connected_to_server() signal connection_error_occurred() signal disconnected_from_server() @@ -47,8 +49,8 @@ func _process(_delta: float) -> void: WebSocketPeer.STATE_OPEN: print("open") _stop_thread = false - _thread = Thread.new() - _thread.start(_listen_for_data) + #_thread = Thread.new() + #_thread.start(_listen_for_data) connected_to_server.emit() connection_status_changed.emit(ConnectionStatus.LOBBYLESS) WebSocketPeer.STATE_CONNECTING: @@ -59,40 +61,13 @@ func _process(_delta: float) -> void: pass WebSocketPeer.STATE_CLOSED: print("closed") - _clean_up_thread() + #_clean_up_thread() connection_status_changed.emit(ConnectionStatus.DISCONNECTED) _processed_status = _new_status - #_new_status = _tcp.get_status() - ## Ensure status change is only processed once - #if not _processed_status == _new_status: - #match _new_status: - #StreamPeerTCP.Status.STATUS_NONE: - #_clean_up_thread() - #connection_status_changed.emit(ConnectionStatus.DISCONNECTED) - #StreamPeerTCP.Status.STATUS_CONNECTING: - #connection_status_changed.emit(ConnectionStatus.ATTEMPTING_CONNECTION) - #StreamPeerTCP.Status.STATUS_CONNECTED: - #_stop_thread = false - #_thread = Thread.new() - #_thread.start(_listen_for_data) - #connected_to_server.emit() - #connection_status_changed.emit(ConnectionStatus.LOBBYLESS) - #StreamPeerTCP.Status.STATUS_ERROR: - #connection_error_occurred.emit() - #connection_status_changed.emit(ConnectionStatus.DISCONNECTED) - # - #_processed_status = _new_status - -func _listen_for_data() -> void: - while true: - #received_data = _tcp.get_data(1) - - # Error (e.g. abrupt disconnect), stop listening - #if not received_data[0] == OK: - #disconnected_from_server.emit.call_deferred() - #return - if _socket.get_available_packet_count(): + + if _processed_status == WebSocketPeer.STATE_OPEN: + while _socket.get_available_packet_count(): cached_response = _socket.get_packet().get_string_from_utf8() print(cached_response) #cached_response += (received_data[1] as PackedByteArray).get_string_from_utf8() @@ -101,6 +76,15 @@ func _listen_for_data() -> void: _handle_response(cached_response) cached_response = "" +func _listen_for_data() -> void: + while true: + if _socket.get_available_packet_count(): + cached_response = _socket.get_packet().get_string_from_utf8() + print(cached_response) + if cached_response.ends_with("}"): + _handle_response(cached_response) + cached_response = "" + func _handle_response(response: String) -> void: var data = JSON.parse_string(response) match data["response"]: @@ -113,6 +97,7 @@ func _handle_response(response: String) -> void: "join_lobby": if data["status"] == "ok": _client_id = data["client_id"] + _players_in_lobby = data["connected_player_count"] connected_to_lobby.emit.call_deferred(_lobby_id) connection_status_changed.emit.call_deferred(ConnectionStatus.JOINED) "client_joined_lobby": @@ -121,6 +106,7 @@ func _handle_response(response: String) -> void: leave_lobby() "leave_lobby": if data["status"] == "ok": + _players_in_lobby = data["connected_player_count"] client_left_lobby.emit.call_deferred(data["client_name"]) "client_left_lobby": client_left_lobby.emit.call_deferred(data["client_name"]) @@ -130,26 +116,16 @@ func _handle_response(response: String) -> void: func _exit_tree() -> void: disconnect_from_server() -func connect_to_server() -> void: - #_tcp.connect_to_host("168.119.97.227", 9974) - #_tcp.set_no_delay(true) - var err = _socket.connect_to_url("127.0.0.1:9974") +func connect_to_server(text: String) -> void: + var err = _socket.connect_to_url(text) if err != OK: print("didn't work!") func disconnect_from_server() -> void: - #_tcp.disconnect_from_host() _socket.close() - _clean_up_thread() disconnected_from_server.emit() connection_status_changed.emit(ConnectionStatus.DISCONNECTED) -func _clean_up_thread() -> void: - _stop_thread = true - if _thread: - _thread.wait_to_finish() - _thread = null - func create_lobby(client_name: String) -> void: _client_name = client_name @@ -175,5 +151,4 @@ func send_chat_message(message: String) -> void: _send_message(TCPMessages.send_chat_message(_lobby_id, _client_id, message)) func _send_message(message: String) -> void: - #_tcp.put_data(message.to_utf8_buffer()) _socket.send_text(message) diff --git a/export_presets.cfg b/export_presets.cfg index bf96a06..50f20e1 100644 --- a/export_presets.cfg +++ b/export_presets.cfg @@ -51,7 +51,7 @@ custom_features="" export_filter="all_resources" include_filter="" exclude_filter="" -export_path="../00 Exports/magician/20250704/magician_server.html" +export_path="../00 Exports/magician/20250705/index.html" patches=PackedStringArray() encryption_include_filters="" encryption_exclude_filters="" diff --git a/game.tscn b/game.tscn index efcea2a..0cf3fe4 100644 --- a/game.tscn +++ b/game.tscn @@ -13,15 +13,19 @@ font_weight = 500 [node name="WebClientTCP" type="Node" parent="."] script = ExtResource("1_feb5d") -[node name="ClientInterface" type="ColorRect" parent="." node_paths=PackedStringArray("client", "game_client", "connect_button", "create_lobby_button", "join_lobby_button", "leave_lobby_button", "chat_message_input", "send_chat_message_button", "name_input", "lobby_code_input", "output")] -anchors_preset = 9 +[node name="HBoxContainer" type="HBoxContainer" parent="."] +anchors_preset = 15 +anchor_right = 1.0 anchor_bottom = 1.0 -offset_right = 362.0 +grow_horizontal = 2 grow_vertical = 2 + +[node name="ClientInterface" type="ColorRect" parent="HBoxContainer" node_paths=PackedStringArray("client", "connect_button", "create_lobby_button", "join_lobby_button", "leave_lobby_button", "chat_message_input", "send_chat_message_button", "name_input", "lobby_code_input", "output")] +custom_minimum_size = Vector2(316, 0) +layout_mode = 2 color = Color(0.26, 0.2236, 0.230273, 1) script = ExtResource("2_e2o6t") -client = NodePath("../WebClientTCP") -game_client = NodePath("../GameClient") +client = NodePath("../../WebClientTCP") connect_button = NodePath("MarginContainer/VBoxContainer/VBoxContainer/ConnectButton") create_lobby_button = NodePath("MarginContainer/VBoxContainer/VBoxContainer/CreateLobbyButton") join_lobby_button = NodePath("MarginContainer/VBoxContainer/VBoxContainer/JoinLobbyButton") @@ -32,7 +36,7 @@ name_input = NodePath("MarginContainer/VBoxContainer/VBoxContainer/NameInput") lobby_code_input = NodePath("MarginContainer/VBoxContainer/VBoxContainer/LobbyCodeInput") output = NodePath("MarginContainer/VBoxContainer/ScrollContainer/Output") -[node name="MarginContainer" type="MarginContainer" parent="ClientInterface"] +[node name="MarginContainer" type="MarginContainer" parent="HBoxContainer/ClientInterface"] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 @@ -44,10 +48,10 @@ theme_override_constants/margin_top = 8 theme_override_constants/margin_right = 8 theme_override_constants/margin_bottom = 8 -[node name="VBoxContainer" type="VBoxContainer" parent="ClientInterface/MarginContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/ClientInterface/MarginContainer"] layout_mode = 2 -[node name="Label" type="RichTextLabel" parent="ClientInterface/MarginContainer/VBoxContainer"] +[node name="Label" type="RichTextLabel" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer"] layout_mode = 2 theme_override_font_sizes/italics_font_size = 24 theme_override_font_sizes/normal_font_size = 24 @@ -55,46 +59,50 @@ bbcode_enabled = true text = "[i]Magician Online![/i]" fit_content = true -[node name="VBoxContainer" type="VBoxContainer" parent="ClientInterface/MarginContainer/VBoxContainer"] +[node name="URLInput" type="LineEdit" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer"] +layout_mode = 2 +placeholder_text = "URL" + +[node name="VBoxContainer" type="VBoxContainer" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer"] custom_minimum_size = Vector2(300, 0) layout_mode = 2 -[node name="ConnectButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] +[node name="ConnectButton" type="Button" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 text = "Connect to Server" -[node name="NameInput" type="LineEdit" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] +[node name="NameInput" type="LineEdit" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 placeholder_text = "Your Name" editable = false -[node name="CreateLobbyButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] +[node name="CreateLobbyButton" type="Button" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 disabled = true text = "Create Lobby" -[node name="LobbyCodeInput" type="LineEdit" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] +[node name="LobbyCodeInput" type="LineEdit" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 placeholder_text = "Lobby Code" editable = false -[node name="JoinLobbyButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] +[node name="JoinLobbyButton" type="Button" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 disabled = true text = "Join Lobby" -[node name="LeaveLobbyButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] +[node name="LeaveLobbyButton" type="Button" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 disabled = true text = "Disconnect" -[node name="ScrollContainer" type="ScrollContainer" parent="ClientInterface/MarginContainer/VBoxContainer"] +[node name="ScrollContainer" type="ScrollContainer" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer"] layout_mode = 2 size_flags_vertical = 3 horizontal_scroll_mode = 0 vertical_scroll_mode = 4 -[node name="Output" type="Label" parent="ClientInterface/MarginContainer/VBoxContainer/ScrollContainer"] +[node name="Output" type="Label" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ScrollContainer"] custom_minimum_size = Vector2(64, 1) layout_mode = 2 size_flags_horizontal = 3 @@ -103,32 +111,52 @@ theme_override_fonts/font = SubResource("SystemFont_80nbo") autowrap_mode = 2 metadata/_edit_lock_ = true -[node name="ChatContainer" type="HBoxContainer" parent="ClientInterface/MarginContainer/VBoxContainer"] +[node name="ChatContainer" type="HBoxContainer" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer"] layout_mode = 2 -[node name="MessageInput" type="LineEdit" parent="ClientInterface/MarginContainer/VBoxContainer/ChatContainer"] +[node name="MessageInput" type="LineEdit" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ChatContainer"] layout_mode = 2 size_flags_horizontal = 3 -[node name="SendMessageButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/ChatContainer"] +[node name="SendMessageButton" type="Button" parent="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ChatContainer"] layout_mode = 2 text = "Send" -[node name="GameClient" type="Node" parent="." node_paths=PackedStringArray("web_client")] +[node name="GameUI" type="Control" parent="HBoxContainer" node_paths=PackedStringArray("web_client")] +layout_mode = 2 +size_flags_horizontal = 3 script = ExtResource("3_feb5d") -web_client = NodePath("../WebClientTCP") +web_client = NodePath("../../WebClientTCP") -[connection signal="client_joined_lobby" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_client_joined_lobby"] -[connection signal="client_left_lobby" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_client_left_lobby"] -[connection signal="connected_to_lobby" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_connected_to_lobby"] -[connection signal="connected_to_server" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_connected_to_server"] -[connection signal="connection_error_occurred" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_connection_error_occurred"] -[connection signal="connection_status_changed" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_connection_status_changed"] -[connection signal="disconnected_from_lobby" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_disconnected_from_lobby"] -[connection signal="disconnected_from_server" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_disconnected_from_server"] -[connection signal="received_chat_message" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_received_chat_message"] -[connection signal="pressed" from="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/ConnectButton" to="ClientInterface" method="_on_connect_button_pressed"] -[connection signal="pressed" from="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/CreateLobbyButton" to="ClientInterface" method="_on_create_lobby_button_pressed"] -[connection signal="pressed" from="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/JoinLobbyButton" to="ClientInterface" method="_on_join_lobby_button_pressed"] -[connection signal="pressed" from="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/LeaveLobbyButton" to="ClientInterface" method="_on_disconnect_lobby_button_pressed"] -[connection signal="pressed" from="ClientInterface/MarginContainer/VBoxContainer/ChatContainer/SendMessageButton" to="ClientInterface" method="_on_send_message_button_pressed"] +[node name="StartGameButton" type="Button" parent="HBoxContainer/GameUI"] +layout_mode = 1 +anchors_preset = 8 +anchor_left = 0.5 +anchor_top = 0.5 +anchor_right = 0.5 +anchor_bottom = 0.5 +offset_left = -50.0 +offset_top = -15.5 +offset_right = 50.0 +offset_bottom = 15.5 +grow_horizontal = 2 +grow_vertical = 2 +text = "Start Game!" + +[connection signal="client_joined_lobby" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_client_joined_lobby"] +[connection signal="client_left_lobby" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_client_left_lobby"] +[connection signal="connected_to_lobby" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_connected_to_lobby"] +[connection signal="connected_to_server" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_connected_to_server"] +[connection signal="connection_error_occurred" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_connection_error_occurred"] +[connection signal="connection_status_changed" from="WebClientTCP" to="HBoxContainer/ClientInterface" method="_on_web_client_tcp_connection_status_changed"] +[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="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/ConnectButton" to="HBoxContainer/ClientInterface" method="_on_connect_button_pressed"] +[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/CreateLobbyButton" to="HBoxContainer/ClientInterface" method="_on_create_lobby_button_pressed"] +[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/CreateLobbyButton" to="HBoxContainer/GameUI" method="_on_create_lobby_button_pressed"] +[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/JoinLobbyButton" to="HBoxContainer/ClientInterface" method="_on_join_lobby_button_pressed"] +[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/JoinLobbyButton" to="HBoxContainer/GameUI" method="_on_join_lobby_button_pressed"] +[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/VBoxContainer/LeaveLobbyButton" to="HBoxContainer/ClientInterface" method="_on_disconnect_lobby_button_pressed"] +[connection signal="pressed" from="HBoxContainer/ClientInterface/MarginContainer/VBoxContainer/ChatContainer/SendMessageButton" to="HBoxContainer/ClientInterface" method="_on_send_message_button_pressed"] +[connection signal="pressed" from="HBoxContainer/GameUI/StartGameButton" to="HBoxContainer/GameUI" method="_on_start_game_button_pressed"] diff --git a/game_client.gd b/game_client.gd index 82475af..ac0a375 100644 --- a/game_client.gd +++ b/game_client.gd @@ -5,5 +5,11 @@ extends Node var is_host: bool = false -func start_game() -> void: +func _on_start_game_button_pressed() -> void: web_client.start_game() + +func _on_create_lobby_button_pressed() -> void: + is_host = true + +func _on_join_lobby_button_pressed() -> void: + is_host = false diff --git a/server_tcp.py b/server_tcp.py new file mode 100644 index 0000000..3c2d647 --- /dev/null +++ b/server_tcp.py @@ -0,0 +1,224 @@ +import json +import random +import sys + +import ssl +import asyncio +from websockets.asyncio.server import serve + +def generate_code() -> str: + result = "" + for i in range(6): + result += chr(random.randint(0, 25) + 65) + return result + + +class Lobby: + + def __init__(self, lobby_id, host_client_id): + self.lobby_id = lobby_id + self.host_client_id = host_client_id + self.connected_clients = {} + +class Client: + + def __init__(self, client_id, client_name, websocket): + self.client_id = client_id + self.client_name = client_name + self.websocket = websocket + +class LobbyManager: + + def __init__(self): + self.active_lobbies = {} + + def get_lobby(self, lobby_id) -> Lobby: + return self.active_lobbies[lobby_id] + + def lobby_id_exists(self, lobby_id) -> bool: + return lobby_id in self.active_lobbies + + def client_id_exists_in_lobby(self, lobby_id, client_id) -> bool: + if not self.lobby_id_exists(lobby_id): + return False + return client_id in self.active_lobbies[lobby_id].connected_clients + + def get_unique_lobby_id(self) -> str: + id = generate_code() + if self.lobby_id_exists(id): + return self.get_unique_lobby_id() + return id + + def get_unique_client_id(self, lobby_id) -> str: + id = generate_code() + if self.client_id_exists_in_lobby(lobby_id, id): + return self.get_unique_client_id(lobby_id) + return id + + def create_lobby(self, lobby_id, host_client_id) -> None: + self.active_lobbies[lobby_id] = Lobby(lobby_id, host_client_id) + print(f"Created lobby {lobby_id}") + + def delete_lobby(self, lobby_id) -> None: + try: + del self.active_lobbies[lobby_id] + print(f"Deleted lobby {lobby_id}") + except KeyError: + print(f"Lobby with ID {lobby_id} not found, could not be deleted") + + async def join_lobby(self, lobby_id, client_id, client_name, websocket) -> None: + self.active_lobbies[lobby_id].connected_clients[client_id] = Client( + client_id, + client_name, + websocket, + ) + print(f"Client {client_id} joined lobby {lobby_id}") + + await self.broadcast_message( + lobby_id, + json.dumps({ + "response": "client_joined_lobby", + "new_client_id": client_id, + "new_client_name": client_name, + }) + ) + + async def leave_lobby(self, lobby_id, client_id) -> None: + try: + # get client name BEFORE deleting the client... + client_name = self.get_client_name(lobby_id, client_id) + del self.active_lobbies[lobby_id].connected_clients[client_id] + await self.broadcast_message( + lobby_id, + json.dumps({ + "response": "client_left_lobby", + "status": "ok", + "client_name": client_name, + }), + ) + print(f"Deleted client {client_id} from lobby {lobby_id}") + except KeyError: + print(f"Client with ID {client_id} in lobby {lobby_id} not found, could not be deleted") + + def get_lobby_player_count(self, lobby_id) -> int: + return len(self.active_lobbies[lobby_id].connected_clients) + + def get_client_name(self, lobby_id, client_id) -> str: + return self.active_lobbies[lobby_id].connected_clients[client_id].client_name + + def get_lobby_host_client_id(self, lobby_id) -> str: + return self.active_lobbies[lobby_id].host_client_id + + async def send_message(self, lobby_id, client_id, message) -> None: + await self.active_lobbies[lobby_id].connected_clients[client_id].websocket.send(message) + + async def broadcast_message(self, lobby_id, message) -> None: + connected_clients = self.active_lobbies[lobby_id].connected_clients + for client_id in connected_clients: + await connected_clients[client_id].websocket.send(message) + +lobby_manager = LobbyManager() + +async def listen_websocket(run_local: bool) -> None: + ssl_context = None + if not run_local: + ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + ssl_context.load_cert_chain("/etc/letsencrypt/live/denizk0461.dev/fullchain.pem", "/etc/letsencrypt/live/denizk0461.dev/privkey.pem") + async with serve(start_listen_client_websocket, "127.0.0.1", 9974, ssl=ssl_context) as server: + await server.serve_forever() + +async def start_listen_client_websocket(websocket) -> None: + async for message in websocket: + # await + await process_input(message, websocket) + +async def process_input(message: str, websocket) -> None: + data_object = json.loads(message) + + if data_object["response"] == "create_lobby": + new_lobby_id = lobby_manager.get_unique_lobby_id() + new_client_id = lobby_manager.get_unique_client_id(new_lobby_id) + print(new_client_id + " is creating lobby " + new_lobby_id) + + lobby_manager.create_lobby( + new_lobby_id, + new_client_id, + ) + await lobby_manager.join_lobby( + new_lobby_id, + new_client_id, + data_object["client_name"], + websocket, + ) + await lobby_manager.send_message( + new_lobby_id, + new_client_id, + json.dumps({ + "response": "create_lobby", + "status": "ok", + "lobby_id": new_lobby_id, + "client_id": new_client_id, + }), + ) + + elif data_object["response"] == "join_lobby": + print("joining lobby") + lobby_id = data_object["lobby_id"] + new_client_id = lobby_manager.get_unique_client_id(lobby_id) + + await lobby_manager.join_lobby( + lobby_id, + new_client_id, + data_object["client_name"], + websocket, + ) + await lobby_manager.send_message( + lobby_id, + new_client_id, + json.dumps({ + "response": "join_lobby", + "status": "ok", + "client_id": new_client_id, + }), + ) + + # send message to all connected clients + + elif data_object["response"] == "leave_lobby": + print("leaving lobby") + lobby_id = data_object["lobby_id"] + host_client_id = lobby_manager.get_lobby_host_client_id(lobby_id) + + if host_client_id == data_object["client_id"]: + # client is host; close lobby + await lobby_manager.leave_lobby(lobby_id, data_object["client_id"]) + await lobby_manager.broadcast_message( + lobby_id, + json.dumps({ + "response": "leave_lobby_request", + }) + ) + if lobby_manager.get_lobby_player_count(lobby_id) == 0: + lobby_manager.delete_lobby(lobby_id) + else: + # client is not host; client leaves only + await lobby_manager.leave_lobby(lobby_id, data_object["client_id"]) + + elif data_object["response"] == "send_chat_message": + print("relaying chat message") + await lobby_manager.broadcast_message( + data_object["lobby_id"], + json.dumps({ + "response": "receive_chat_message", + "message": data_object["message"], + "client_name": lobby_manager.get_client_name(data_object["lobby_id"], data_object["client_id"]), + }) + ) + +if __name__ == '__main__': + run_local = False + if len(sys.argv) > 1 and sys.argv[1] == "local": + run_local = True + + print('Listening on *:9974') + asyncio.run(listen_websocket(run_local)) \ No newline at end of file