Skip to main content

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.

This page traces the exact sequence of protocol messages from the moment a client opens the WebSocket connection through login, world entry, gameplay, and logout or reconnect. Every step maps to one or more messages defined in protocol-v1.json. No state mutation happens on the client until the server has confirmed the outcome.

Full session flow

1

Open WebSocket

The client opens a persistent WebSocket connection to WS /session. No message is sent at this point — the connection is held open for the login step.
2

Login

The client sends login_request with account_name, password, protocol_version: "v1", and optionally runtime_delta_protocol: 1 to opt into delta mode.The server responds with login_response:
{
  "type": "login_response",
  "payload": {
    "login_status": "ok",
    "session_id": "a1b2c3d4-...",
    "account_id": "e5f6g7h8-..."
  }
}
login_status values:
  • "ok" — authentication passed; session_id and account_id are populated
  • "invalid_credentials" — account name or password did not match; connection closes
  • "account_inactive" — account exists but is disabled; connection closes
  • "unsupported_version"protocol_version did not match the server’s expected value; connection closes
On any failure, the server closes the WebSocket. The session is never created.
3

Character load

On successful login, the server immediately follows with character_load_response. This binds the authenticated session to the account’s owned character before world entry begins.
{
  "type": "character_load_response",
  "payload": {
    "session_id": "a1b2c3d4-...",
    "character_id": "c9d0e1f2-..."
  }
}
character_id is null if the account has no character. In that case, world entry does not proceed.
4

Enter world

The server sends enter_world_response with the character’s authoritative starting position and presence source.
{
  "type": "enter_world_response",
  "payload": {
    "session_id": "a1b2c3d4-...",
    "character_id": "c9d0e1f2-...",
    "map_id": "x1000y992",
    "tile_x": 12,
    "tile_y": 7,
    "facing": "south",
    "presence_source": "character_save"
  }
}
presence_source is "character_save" when position was restored from the database, or "default" for a fresh spawn.
5

World snapshot

The server sends world_snapshot immediately after enter_world_response. This message carries the complete authoritative state the client needs to render the world: the local player’s full status, skills, inventory, and equipment; all visible NPCs; all visible ground items; owner-only private ground items (delta clients); and all remote players on the map with their equipment.Both delta and legacy clients receive one world_snapshot on enter-world. The snapshot includes character_revision and map_revision so delta clients can begin tracking revision continuity.
6

Gameplay loop

Once the world snapshot is applied, the client enters the gameplay loop. The main message flows are:Movement — the client sends movement_intent with a target tile. The server resolves the path using cardinal A* and responds with movement_applied, which carries the authoritative final position, movement status, and updated map_revision.Inventory and equipment — the client sends request messages (inventory_item_use_request, inventory_item_drop_request, ground_item_pickup_request, equipment_item_unequip_request). The server decides the outcome and responds with the matching response message. The client applies only the confirmed result.Server-pushed updates — the server broadcasts npc_state_update and player_state_update as NPCs and remote players move. These carry map_revision so delta clients can detect gaps.State delivery mode — delta clients (those that sent runtime_delta_protocol: 1 on login) receive character_state_updated messages after inventory, equipment, status, and skill mutations. Legacy clients receive a full world_snapshot instead.
7

Disconnect (unexpected)

If the WebSocket closes without an explicit logout_request, the server records disconnected_at on the session row. Live map presence is preserved for the duration of the reconnect grace window (default: 10 seconds).During the grace window, the character’s position remains on the map and the session is reconnect-eligible. No duplicate presence record is created on reconnect.
8

Reconnect

Within the grace window, the client sends reconnect_request with the prior session_id and character_id.The server validates the session and responds with reconnect_response:
{
  "type": "reconnect_response",
  "payload": {
    "reconnect_status": "restored",
    "session_id": "a1b2c3d4-...",
    "character_id": "c9d0e1f2-...",
    "map_id": "x1000y992",
    "tile_x": 12,
    "tile_y": 7,
    "facing": "south"
  }
}
On success, the server immediately sends a fresh world_snapshot so the client can re-synchronize all state from the restored position.
9

Logout

The client sends logout_request with session_id and character_id. The server revokes the session immediately, removes live map presence, and closes the WebSocket normally.There is no logout_response message. After the connection closes, any attempt to send a reconnect_request for that session returns "session_invalid" because the session’s revoked_at column is set.

Reconnect grace window

Reconnect is accepted only when both conditions hold:
  1. The session’s revoked_at column is null — explicit logout has not been called.
  2. The session’s disconnected_at is within the configured reconnect grace window (10 seconds).
Once the grace window expires, the session is considered expired and reconnect is rejected. The client must go through the full login flow to re-enter the world. Supported reconnect_status values:
  • "restored" — session restored; position fields are populated
  • "session_invalid" — session record not found, already revoked, or presence could not be loaded
  • "reauthentication_required" — session has expired or the reconnect grace window has elapsed

Resync

Delta clients track character_revision and map_revision across all messages that carry them. If the client receives a revision that is not exactly last_seen + 1, a message was lost in transit. When a gap is detected, the client sends world_resync_request:
{
  "type": "world_resync_request",
  "payload": {
    "streams": ["inventory", "equipment"],
    "character_revision": 14,
    "map_revision": 22,
    "reason": "character_revision_gap"
  }
}
The server responds with a fresh world_snapshot that resets both revision counters to their current authoritative values.

Build docs developers (and LLMs) love