class_name WebClient extends Node ## Sender tag for system messages displayed in the chat. const SENDER_SYSTEM: String = "SYSTEM" ## Server address to connect to. ## Local: 127.0.0.1:9974 ## Remote: wss://denizk0461.dev/magsrv const SERVER_ADDRESS: String = "127.0.0.1:9974" var _socket := WebSocketPeer.new() var _new_status: int = WebSocketPeer.STATE_CLOSED var _processed_status: int = -1 var _lobby_id: String var _own_client_data: ClientData = ClientData.new() var _playing_order: Array[ClientData] #var _client_id: String #var _client_name: String var _is_host: bool var received_data: Array var cached_response: String var _is_first_play: bool = false @export var chat_panel: ChatPanel signal connected_to_lobby(lobby_id: String, client_id: String) signal connected_clients_changed(connected_clients: Array[ClientData]) signal received_chat_message(client_name: String, message: String) signal connection_status_changed(new_status: ConnectionStatus) # This signal is messy as fuck signal client_order_received(playing_order: Array[ClientData]) signal client_played_card(client_id: String, card_id: int) signal received_expected_bet(client_id: String, expected_bet: int) signal new_round_started() signal cards_received(cards: Dictionary) signal trump_received(trump_id: int) signal received_bet_request(disallowed_bet: int, current_round: int) signal received_win() signal received_winning_client(client_id: String) signal notify_play_card_request() signal reset_first_card() signal received_first_card(card_id: int) signal received_played_card(client_id: String, card_id: int) signal received_play_winner_request() signal received_end_game_request() signal request_next_play() signal request_next_round() ## Notifies to signal a player's turn. signal notify_player_turn(client_id: String, is_self: bool) enum ConnectionStatus { DISCONNECTED, ATTEMPTING_CONNECTION, LOBBYLESS, # == connected ATTEMPTING_JOIN, JOINED, } func _ready() -> void: connect_to_server(SERVER_ADDRESS) func _process(_delta: float) -> void: _socket.poll() _new_status = _socket.get_ready_state() if not _processed_status == _new_status: match _new_status: WebSocketPeer.STATE_OPEN: chat_panel.put_chat_message(SENDER_SYSTEM, "You successfully connected to the server.") connection_status_changed.emit(ConnectionStatus.LOBBYLESS) WebSocketPeer.STATE_CONNECTING: connection_status_changed.emit(ConnectionStatus.ATTEMPTING_CONNECTION) WebSocketPeer.STATE_CLOSING: pass WebSocketPeer.STATE_CLOSED: chat_panel.put_chat_message(SENDER_SYSTEM, "You lost connection to the server.") connection_status_changed.emit(ConnectionStatus.DISCONNECTED) _processed_status = _new_status if _processed_status == WebSocketPeer.STATE_OPEN: while _socket.get_available_packet_count(): cached_response = _socket.get_packet().get_string_from_utf8() if cached_response.ends_with("}"): _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"]: "created_lobby": _lobby_id = data["lobby_id"] _own_client_data.client_id = data["client_id"] chat_panel.put_chat_message(SENDER_SYSTEM, "You created and connected to lobby {lobby_id} with client ID {client_id}.".format({ "lobby_id": _lobby_id, "client_id": _own_client_data.client_id, })) connection_status_changed.emit.call_deferred(ConnectionStatus.JOINED) connected_to_lobby.emit.call_deferred(_lobby_id, _own_client_data.client_id) "join_lobby_response": _handle_join(data) "joined_lobby": _playing_order = _get_client_data(data) connected_clients_changed.emit.call_deferred(_playing_order) chat_panel.put_chat_message(SENDER_SYSTEM, "{client_name} joined the lobby.".format({ "client_name": data["client_name"], })) "leave_lobby_request": leave_lobby() "left_lobby": _playing_order = _get_client_data(data) connected_clients_changed.emit.call_deferred(_playing_order) chat_panel.put_chat_message(SENDER_SYSTEM, "{client_name} left the lobby.".format({ "client_name": data["client_name"], })) ## A chat message has been received "receive_chat_message": # Relay message to be displayed in the chat panel chat_panel.put_chat_message(data["client_name"], data["message"]) "round_started": if data["current_round"] == 1: var playing_order: Array[String] = [] playing_order.assign(data["playing_order"]) client_order_received.emit.call_deferred(_playing_order) var received_cards = data["cards"] new_round_started.emit.call_deferred() cards_received.emit.call_deferred(received_cards) trump_received.emit.call_deferred(data["trump"]) "client_submitted_bet": received_expected_bet.emit.call_deferred( data["client_id"], data["bet"], ) "request_bet": if data["client_id"] == _own_client_data.client_id: received_bet_request.emit.call_deferred(data["disallowed_bet"], data["round"]) notify_player_turn.emit.call_deferred(data["client_id"], data["client_id"] == _own_client_data.client_id) "begin_playing_cards": # all players know it's time to play print(data) _is_first_play = true reset_first_card.emit.call_deferred() "request_card": if data["client_id"] == _own_client_data.client_id: notify_play_card_request.emit.call_deferred() notify_player_turn.emit.call_deferred(data["client_id"], data["client_id"] == _own_client_data.client_id) "begin_next_play": print("beginning next play!") _is_first_play = true reset_first_card.emit.call_deferred() "play_card": print(data) #client_played_card.emit.call_deferred(data["client_id"], data["played_card"]) "determine_play_winner_request": # single card go-around received_play_winner_request.emit.call_deferred() "end_game_request": received_end_game_request.emit.call_deferred() "client_played_card": print("RECEIVED FOLLOWING CARD ID: " + str(data["played_card"])) if _is_first_play: print("set first card") received_first_card.emit.call_deferred(data["played_card"]) if not CardManager.get_card_color(data["played_card"]) == Card.CardColor.WHITE: _is_first_play = false received_played_card.emit.call_deferred(data["client_id"], data["played_card"]) "client_won_play": if data["client_id"] == _own_client_data.client_id: received_win.emit.call_deferred() received_winning_client.emit.call_deferred(data["client_id"]) func _get_client_data(data) -> Array[ClientData]: var connected_client_ids = [] connected_client_ids.assign(data["connected_client_ids"]) var connected_client_names = [] connected_client_names.assign(data["connected_client_names"]) var order: Array[ClientData] = [] for index in connected_client_ids.size(): order.append(ClientData.new(connected_client_ids[index], connected_client_names[index])) return order func _handle_join(data) -> void: match data["status"]: "lobby_not_found": chat_panel.put_chat_message(SENDER_SYSTEM, "Could not join; lobby does not exist.") connection_status_changed.emit.call_deferred(ConnectionStatus.LOBBYLESS) "lobby_full": chat_panel.put_chat_message(SENDER_SYSTEM, "Could not join; lobby is full.") connection_status_changed.emit.call_deferred(ConnectionStatus.LOBBYLESS) "ok": _own_client_data.client_id = data["client_id"] chat_panel.put_chat_message(SENDER_SYSTEM, "You connected to lobby {lobby_id} with client ID {client_id}.".format({ "lobby_id": _lobby_id, "client_id": _own_client_data.client_id, })) connection_status_changed.emit.call_deferred(ConnectionStatus.JOINED) connected_to_lobby.emit.call_deferred(_lobby_id, _own_client_data.client_id) func _exit_tree() -> void: disconnect_from_server() 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: _socket.close() chat_panel.put_chat_message(SENDER_SYSTEM, "You were disconnected from the server.") connection_status_changed.emit(ConnectionStatus.DISCONNECTED) func send_chat_message(message: String) -> void: #_send_message(TCPMessages.send_chat_message(_lobby_id, _client_id, message)) pass func start_game() -> void: _send_message(JSON.stringify({ "response": "start_game", "lobby_id": _lobby_id, "cards": CardManager.get_shuffled_cards(_playing_order, 1), })) func start_next_play() -> void: _send_message(JSON.stringify({ "response": "start_next_play", "lobby_id": _lobby_id, })) func start_next_round(round_count: int) -> void: _send_message(JSON.stringify({ "response": "start_next_round", "lobby_id": _lobby_id, "round": round_count, "cards": CardManager.get_shuffled_cards(_playing_order, round_count), })) func end_game() -> void: _send_message(JSON.stringify({ "response": "end_game", "lobby_id": _lobby_id, })) func play_card(card_id: int) -> void: _send_message(JSON.stringify({ "response": "play_card", "lobby_id": _lobby_id, "client_id": _own_client_data.client_id, "played_card": card_id, })) func submit_bet(bet: int, current_round: int) -> void: _send_message(JSON.stringify({ "response": "submit_bet", "lobby_id": _lobby_id, "client_id": _own_client_data.client_id, "round": current_round, "bet": bet, })) func submit_play_winner(winning_client_id: String) -> void: _send_message(JSON.stringify({ "response": "submit_play_winner", "lobby_id": _lobby_id, "client_id": winning_client_id, })) request_next_play.emit.call_deferred() #request_next_round.emit.call_deferred() func _send_message(message: String) -> void: _socket.send_text(message) func create_lobby(client_name: String) -> void: _own_client_data.client_name = client_name _send_message(PeerMessages.create_lobby(client_name)) func join_lobby(lobby_id: String, client_name: String) -> void: _lobby_id = lobby_id _own_client_data.client_name = client_name _send_message(PeerMessages.join_lobby(_lobby_id, client_name)) connection_status_changed.emit.call_deferred(ConnectionStatus.ATTEMPTING_JOIN) func leave_lobby() -> void: _send_message(PeerMessages.leave_lobby(_lobby_id, _own_client_data.client_id)) connection_status_changed.emit.call_deferred(ConnectionStatus.LOBBYLESS) # Notify user about disconnect chat_panel.put_chat_message(SENDER_SYSTEM, "You were disconnected from the lobby {lobby_id}.".format({ "lobby_id": _lobby_id, })) # Reset saved data about lobby and client _lobby_id = "" _own_client_data = ClientData.new() func _on_chat_panel_message_sent(message: String) -> void: _send_message(PeerMessages.send_chat_message(_lobby_id, _own_client_data.client_id, message))