diff --git a/components/client_interface.gd b/components/client_interface.gd index cf83ac4..c186abd 100644 --- a/components/client_interface.gd +++ b/components/client_interface.gd @@ -8,6 +8,9 @@ extends Control @export var join_lobby_button: Button @export var leave_lobby_button: Button +@export var chat_message_input: LineEdit +@export var send_chat_message_button: Button + @export var name_input: LineEdit @export var lobby_code_input: LineEdit @@ -41,6 +44,12 @@ func _on_disconnect_lobby_button_pressed() -> void: leave_lobby_button.disabled = true client.leave_lobby() +func _on_send_message_button_pressed() -> void: + var msg: String = chat_message_input.text.strip_edges() + if not msg.is_empty(): + client.send_chat_message(msg) + chat_message_input.text = "" + func _on_web_client_tcp_connected_to_server() -> void: create_lobby_button.disabled = false join_lobby_button.disabled = false @@ -73,6 +82,12 @@ func _on_web_client_tcp_client_joined_lobby(client_name: String) -> void: "you": " (that's you!)" if client_name == name_input.text.strip_edges() else "" })) +func _on_web_client_tcp_received_chat_message(client_name: String, message: String) -> void: + _write_line("<{client_name}> {message}".format({ + "client_name": client_name, + "message": message, + })) + func _on_web_client_tcp_connection_status_changed(new_status: WebClientTCP.ConnectionStatus) -> void: match new_status: @@ -84,6 +99,8 @@ func _on_web_client_tcp_connection_status_changed(new_status: WebClientTCP.Conne name_input.editable = true lobby_code_input.editable = false lobby_code_input.text = "" + chat_message_input.editable = false + send_chat_message_button.disabled = true WebClientTCP.ConnectionStatus.ATTEMPTING_CONNECTION: connect_button.disabled = true @@ -93,6 +110,8 @@ func _on_web_client_tcp_connection_status_changed(new_status: WebClientTCP.Conne name_input.editable = true lobby_code_input.editable = false lobby_code_input.text = "" + chat_message_input.editable = false + send_chat_message_button.disabled = true WebClientTCP.ConnectionStatus.LOBBYLESS: connect_button.disabled = true @@ -102,6 +121,8 @@ func _on_web_client_tcp_connection_status_changed(new_status: WebClientTCP.Conne name_input.editable = true lobby_code_input.editable = true lobby_code_input.text = "" + chat_message_input.editable = false + send_chat_message_button.disabled = true WebClientTCP.ConnectionStatus.ATTEMPTING_JOIN: connect_button.disabled = true @@ -110,6 +131,8 @@ func _on_web_client_tcp_connection_status_changed(new_status: WebClientTCP.Conne leave_lobby_button.disabled = true name_input.editable = false lobby_code_input.editable = false + chat_message_input.editable = false + send_chat_message_button.disabled = true WebClientTCP.ConnectionStatus.JOINED: connect_button.disabled = true @@ -118,3 +141,5 @@ func _on_web_client_tcp_connection_status_changed(new_status: WebClientTCP.Conne leave_lobby_button.disabled = false name_input.editable = false lobby_code_input.editable = false + chat_message_input.editable = true + send_chat_message_button.disabled = false diff --git a/components/web_client_tcp.gd b/components/web_client_tcp.gd index 5b7c25d..1b468b8 100644 --- a/components/web_client_tcp.gd +++ b/components/web_client_tcp.gd @@ -24,6 +24,8 @@ signal disconnected_from_lobby() signal client_joined_lobby(client_name: String) +signal received_chat_message(client_name: String, message: String) + signal connection_status_changed(new_status: ConnectionStatus) enum ConnectionStatus { @@ -86,8 +88,8 @@ func _handle_response(response: String) -> void: "leave_lobby": if data["status"] == "ok": print(data["client_id"] + " left") - #if data["client_id"] == _client_id: - #connection_status_changed.emit.call_deferred(ConnectionStatus.LOBBYLESS) + "receive_chat_message": + received_chat_message.emit.call_deferred(data["client_name"], data["message"]) func _exit_tree() -> void: disconnect_from_server() @@ -123,8 +125,11 @@ func leave_lobby() -> void: _client_id = "" _client_name = "" - disconnected_from_lobby.emit() - connection_status_changed.emit(ConnectionStatus.LOBBYLESS) + disconnected_from_lobby.emit.call_deferred() + connection_status_changed.emit.call_deferred(ConnectionStatus.LOBBYLESS) + +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()) diff --git a/game.tscn b/game.tscn index 1b4acbc..ed94257 100644 --- a/game.tscn +++ b/game.tscn @@ -12,7 +12,7 @@ font_weight = 500 [node name="WebClientTCP" type="Node" parent="."] script = ExtResource("1_feb5d") -[node name="ClientInterface" type="ColorRect" parent="." node_paths=PackedStringArray("client", "connect_button", "create_lobby_button", "join_lobby_button", "leave_lobby_button", "name_input", "lobby_code_input", "output")] +[node name="ClientInterface" type="ColorRect" parent="." 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")] anchors_preset = 9 anchor_bottom = 1.0 offset_right = 362.0 @@ -20,62 +20,97 @@ grow_vertical = 2 color = Color(0.26, 0.2236, 0.230273, 1) script = ExtResource("2_e2o6t") client = NodePath("../WebClientTCP") -connect_button = NodePath("VBoxContainer/VBoxContainer/ConnectButton") -create_lobby_button = NodePath("VBoxContainer/VBoxContainer/CreateLobbyButton") -join_lobby_button = NodePath("VBoxContainer/VBoxContainer/JoinLobbyButton") -leave_lobby_button = NodePath("VBoxContainer/VBoxContainer/LeaveLobbyButton") -name_input = NodePath("VBoxContainer/VBoxContainer/NameInput") -lobby_code_input = NodePath("VBoxContainer/VBoxContainer/LobbyCodeInput") -output = NodePath("VBoxContainer/Output") +connect_button = NodePath("MarginContainer/VBoxContainer/VBoxContainer/ConnectButton") +create_lobby_button = NodePath("MarginContainer/VBoxContainer/VBoxContainer/CreateLobbyButton") +join_lobby_button = NodePath("MarginContainer/VBoxContainer/VBoxContainer/JoinLobbyButton") +leave_lobby_button = NodePath("MarginContainer/VBoxContainer/VBoxContainer/LeaveLobbyButton") +chat_message_input = NodePath("MarginContainer/VBoxContainer/ChatContainer/MessageInput") +send_chat_message_button = NodePath("MarginContainer/VBoxContainer/ChatContainer/SendMessageButton") +name_input = NodePath("MarginContainer/VBoxContainer/VBoxContainer/NameInput") +lobby_code_input = NodePath("MarginContainer/VBoxContainer/VBoxContainer/LobbyCodeInput") +output = NodePath("MarginContainer/VBoxContainer/ScrollContainer/Output") -[node name="VBoxContainer" type="VBoxContainer" parent="ClientInterface"] +[node name="MarginContainer" type="MarginContainer" parent="ClientInterface"] layout_mode = 1 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 +theme_override_constants/margin_left = 8 +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/VBoxContainer"] +[node name="VBoxContainer" type="VBoxContainer" parent="ClientInterface/MarginContainer"] +layout_mode = 2 + +[node name="Label" type="RichTextLabel" parent="ClientInterface/MarginContainer/VBoxContainer"] +layout_mode = 2 +theme_override_font_sizes/italics_font_size = 24 +theme_override_font_sizes/normal_font_size = 24 +bbcode_enabled = true +text = "[i]Magician Online![/i]" +fit_content = true + +[node name="VBoxContainer" type="VBoxContainer" parent="ClientInterface/MarginContainer/VBoxContainer"] custom_minimum_size = Vector2(300, 0) layout_mode = 2 -[node name="ConnectButton" type="Button" parent="ClientInterface/VBoxContainer/VBoxContainer"] +[node name="ConnectButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 text = "Connect to Server" -[node name="NameInput" type="LineEdit" parent="ClientInterface/VBoxContainer/VBoxContainer"] +[node name="NameInput" type="LineEdit" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 placeholder_text = "Your Name" editable = false -[node name="CreateLobbyButton" type="Button" parent="ClientInterface/VBoxContainer/VBoxContainer"] +[node name="CreateLobbyButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 disabled = true text = "Create Lobby" -[node name="LobbyCodeInput" type="LineEdit" parent="ClientInterface/VBoxContainer/VBoxContainer"] +[node name="LobbyCodeInput" type="LineEdit" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 placeholder_text = "Lobby Code" editable = false -[node name="JoinLobbyButton" type="Button" parent="ClientInterface/VBoxContainer/VBoxContainer"] +[node name="JoinLobbyButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 disabled = true text = "Join Lobby" -[node name="LeaveLobbyButton" type="Button" parent="ClientInterface/VBoxContainer/VBoxContainer"] +[node name="LeaveLobbyButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/VBoxContainer"] layout_mode = 2 disabled = true text = "Disconnect" -[node name="Output" type="Label" parent="ClientInterface/VBoxContainer"] +[node name="ScrollContainer" type="ScrollContainer" parent="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"] custom_minimum_size = Vector2(64, 1) layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 1 theme_override_fonts/font = SubResource("SystemFont_80nbo") autowrap_mode = 2 +metadata/_edit_lock_ = true + +[node name="ChatContainer" type="HBoxContainer" parent="ClientInterface/MarginContainer/VBoxContainer"] +layout_mode = 2 + +[node name="MessageInput" type="LineEdit" parent="ClientInterface/MarginContainer/VBoxContainer/ChatContainer"] +layout_mode = 2 +size_flags_horizontal = 3 + +[node name="SendMessageButton" type="Button" parent="ClientInterface/MarginContainer/VBoxContainer/ChatContainer"] +layout_mode = 2 +text = "Send" [connection signal="client_joined_lobby" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_client_joined_lobby"] [connection signal="connected_to_lobby" from="WebClientTCP" to="ClientInterface" method="_on_web_client_tcp_connected_to_lobby"] @@ -84,7 +119,9 @@ autowrap_mode = 2 [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="pressed" from="ClientInterface/VBoxContainer/VBoxContainer/ConnectButton" to="ClientInterface" method="_on_connect_button_pressed"] -[connection signal="pressed" from="ClientInterface/VBoxContainer/VBoxContainer/CreateLobbyButton" to="ClientInterface" method="_on_create_lobby_button_pressed"] -[connection signal="pressed" from="ClientInterface/VBoxContainer/VBoxContainer/JoinLobbyButton" to="ClientInterface" method="_on_join_lobby_button_pressed"] -[connection signal="pressed" from="ClientInterface/VBoxContainer/VBoxContainer/LeaveLobbyButton" to="ClientInterface" method="_on_disconnect_lobby_button_pressed"] +[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"] diff --git a/globals/tcp_messages.gd b/globals/tcp_messages.gd index b370fcc..db5a7c2 100644 --- a/globals/tcp_messages.gd +++ b/globals/tcp_messages.gd @@ -27,3 +27,15 @@ func leave_lobby( "lobby_id": lobby_id, "client_id": client_id, }) + +func send_chat_message( + lobby_id: String, + client_id: String, + message: String, +) -> String: + return JSON.stringify({ + "response": "send_chat_message", + "lobby_id": lobby_id, + "client_id": client_id, + "message": message, + }) diff --git a/server_tcp.py b/server_tcp.py index 50a62e6..f4f6f49 100644 --- a/server_tcp.py +++ b/server_tcp.py @@ -227,6 +227,7 @@ class ClientConnection: # client is host; close lobby lobby_clients = self.lobby_manager.get_lobby(lobby_id).connected_clients.copy() # for client_id in lobby_clients: + self.lobby_manager.leave_lobby(lobby_id, data_object["client_id"]) self.lobby_manager.broadcast_message( lobby_id, json.dumps({ @@ -238,6 +239,17 @@ class ClientConnection: else: # client is not host; client leaves only self.lobby_manager.leave_lobby(lobby_id, data_object["client_id"]) + + elif data_object["response"] == "send_chat_message": + print("relaying chat message") + self.lobby_manager.broadcast_message( + data_object["lobby_id"], + json.dumps({ + "response": "receive_chat_message", + "message": data_object["message"], + "client_name": self.lobby_manager.active_lobbies[data_object["lobby_id"]].connected_clients[data_object["client_id"]].client_name, + }) + ) if __name__ == '__main__': if len(sys.argv) < 2: