Documentation Index
Fetch the complete documentation index at: https://mintlify.com/TaylorZaneKirk/MMO-Project/llms.txt
Use this file to discover all available pages before exploring further.
session_client.gd is the thin WebSocket transport layer in the Godot client. It owns opening and closing the connection, serializing outbound messages to JSON, reading inbound frames, and emitting them as typed GDScript signals. It does not interpret message content, make session decisions, or own any game state. The transport boundary is intentionally kept thin so the shared protocol can evolve without requiring changes to the client modules that call it.
Location
SessionClient extends Node and is instantiated as a child of the SessionState autoload during _enter_tree(). Both LoginScreen and GameScreen reach it through SessionState.session_client.
Signals
| Signal | When emitted |
|---|---|
connection_opened | WebSocket state transitions from CONNECTING to OPEN |
connection_closed(was_clean: bool) | WebSocket state reaches CLOSED after a previously open connection |
connection_failed(reason: String) | Connection attempt fails, or a non-JSON frame is received |
message_received(message_name: String, payload: Dictionary) | A valid JSON frame arrives; name is extracted as message_name and payload as the inner dictionary |
Connecting and disconnecting
connect_to_session creates a fresh WebSocketPeer, clears the previous state, and calls connect_to_url. If the peer cannot connect, connection_failed is emitted immediately.
Polling
SessionClient does not use _process. Callers are responsible for driving the poll loop each frame:
LoginScreen and GameScreen call poll_client() in their own _process implementations. poll_client() checks WebSocketPeer state transitions, fires connection_opened or connection_closed / connection_failed as appropriate, and drains all available packets in a single frame.
Sending messages
All outbound messages are JSON objects with a top-levelname field and a payload dictionary. SessionClient exposes a dedicated method for each protocol message:
| Method | name field in wire message |
|---|---|
send_login_request(account_name, password, protocol_version?) | "login_request" |
send_movement_intent(session_id, character_id, target_tile_x, target_tile_y) | "movement_intent" |
send_inventory_item_use_request(session_id, character_id, slot_index, use_action) | "inventory_item_use_request" |
send_inventory_item_drop_request(session_id, character_id, slot_index) | "inventory_item_drop_request" |
send_ground_item_pickup_request(session_id, character_id, ground_item_id) | "ground_item_pickup_request" |
send_equipment_item_unequip_request(session_id, character_id, equipment_slot_id) | "equipment_item_unequip_request" |
send_world_resync_request(streams, character_revision, map_revision, reason) | "world_resync_request" |
_send_message(message) helper, which polls the socket once, checks that the state is STATE_OPEN, serializes the dictionary with JSON.stringify, and calls _socket.send_text. If the socket is not open, ERR_UNAVAILABLE is returned and the caller is responsible for handling the failure.
Receiving messages
Incoming frames are parsed as JSON inpoll_client(). The name field becomes message_name and the payload field becomes the payload dictionary. Both are emitted via message_received. If a frame cannot be parsed as a JSON dictionary, connection_failed is emitted with a descriptive reason string.
session_client.gd does not interpret message content. It passes raw
message_name and payload pairs up to GameSessionPresenter, which
classifies them and forwards authoritative state messages into
GameStateStore. Controllers should never subscribe to
session_client.message_received directly for game-state messages.