Documentation Index
Fetch the complete documentation index at: https://mintlify.com/smogon/pokemon-showdown-client/llms.txt
Use this file to discover all available pages before exploring further.
PSConnection is the single object responsible for keeping the Pokémon Showdown client talking to the game server. It tries to open the socket inside a dedicated Web Worker (so that the main thread is never blocked by socket I/O), falls back to a direct SockJS connection if workers aren’t available, and transparently queues outbound messages while the socket is down. The class is instantiated exactly once during boot and stored at PS.connection. You will almost never construct it directly — instead you interact with it through PS.send() or by subscribing to PS for connection state changes.
PSConnection is created automatically by PSConnection.connect() at the bottom of client-connection.ts. That call happens once, immediately after the module loads. Do not call new PSConnection() yourself unless you are writing tests or a custom embedding.PSConnection
Constructor
PSStorage.init(). If storage initialisation is asynchronous (cross-origin iframe handshake required), the actual socket connection is deferred until the returned Promise resolves. Otherwise, initConnection() is called synchronously.
(no parameters)
PSConnection takes no constructor arguments. Server configuration is read from PS.server, which is populated by PSStorage before initConnection() runs.Properties
The active SockJS / WebSocket instance when using a direct connection.
null when a Web Worker is handling the socket, or when the client is disconnected.true when the underlying transport (worker or direct socket) has successfully completed its handshake with the server. Flips to false on disconnect; the client re-renders via PS.update() whenever this changes.The parsed integer value of
PS.lastMessageTime captured at the moment of the most recent successful connection. Used by rooms to determine which messages are “new” after a reconnect.Messages that were passed to
send() while connected was false. Flushed in order as soon as the connection succeeds. Messages are stored as raw protocol strings (roomid|message).Current delay in milliseconds before the next reconnect attempt. Starts at
1000 (1 second), doubles after each failed attempt up to a cap of 15000 (15 seconds). Resets to 1000 on a successful direct connection.Handle for the pending reconnect
setTimeout. null when no reconnect is scheduled. Checked by the internal retryConnection() method to prevent duplicate timers from being queued simultaneously.Methods
Called once during construction (after storage is ready). Tries
tryConnectInWorker() first; if that returns false it falls back to directConnect(). This is the only entry point for the initial connection.Attempts to establish the server connection inside a dedicated Web Worker (
/js/client-connection-worker.js). Returns true if a worker was successfully spawned (or one is already running), false if workers are unavailable or if a direct socket already exists.Opens a SockJS (or plain WebSocket) connection on the main thread. Used as the fallback when workers are unavailable or encounter a fatal error. Attaches
onopen, onmessage, onclose, and onerror handlers that mirror the worker message protocol.Returns
false (and prompts the user to refresh) if the client has been running for more than 24 hours (Date.now() - PS.startTime > 86_400_000). Otherwise returns the value of the internal shouldReconnect flag, which is set to false by disconnect().Sends a raw protocol string to the server.
- If
connectedisfalse, the message is pushed toqueueand sent once the connection succeeds. - If a worker is active, the message is forwarded via
worker.postMessage({ type: 'send', data: msg }). - If a direct socket is active, the message is sent via
socket.send(msg).
Permanently closes the connection and prevents automatic reconnection. Terminates the worker (if any), closes the socket (if any), and sets the internal
shouldReconnect flag to false.Manually attempts to re-open the connection. No-op if already connected. Prefers the worker path; falls back to
directConnect() if no worker exists.Static Methods
The module-level bootstrap function. Called automatically when
client-connection.ts loads.- If
PS.connectiondoes not exist, creates a newPSConnection. - If
PS.connectionexists but is not connected, callsreconnect(). - Also calls
PS.prefs.doAutojoin()to rejoin rooms from preferences.
PSLoginServer
PSLoginServer is an anonymous singleton (accessed as PSLoginServer) that wraps the PS authentication HTTP endpoint (/~~<serverid>/action.php).
Methods
Posts a form-encoded request to the login server. Returns the raw response text, or
null on any error.Convenience wrapper around
rawQuery that strips the leading ] from PS login-server responses and JSON-parses the result.Net — HTTP Fetch Utility
Net is a thin XMLHttpRequest wrapper that provides a promise-based API for GET and POST requests throughout the client.
Net(url) to get a NetRequest instance, then chain .get() or .post().
Makes a GET request (or any method specified in
opts.method). Resolves with the response body text, rejects with an HttpError if the status is not 200.Convenience wrapper for POST requests. Merges
body into the options and calls get() with method: 'POST'.URL-encodes a
PostData object (or passes a string through unchanged). Converts true → 'on', false / null / undefined → ''.Reads all
input[name], select[name], and textarea[name] elements inside a <form> and returns their values as a plain object. Checkbox values follow HTML conventions.PSStorage — Cross-Origin Storage Abstraction
PSStorage ensures that localStorage data (preferences, teams, server config) can be shared between the client and embedded third-party deployments, even when they run on different origins. It uses a hidden <iframe> pointing at play.pokemonshowdown.com and window.postMessage to proxy storage reads and writes.
Called in the
PSConnection constructor. Returns a Promise if cross-origin initialisation is required (iframe handshake), or void if the client is already on the correct origin (or in test mode).Sends a proxied HTTP request through the cross-origin iframe. Returns
void when not in cross-origin mode (direct requests are used instead).Posts a raw message string to the cross-origin iframe. Message format is a single-character type prefix followed by JSON-encoded content (e.g.
'P{"theme":"dark"}' for a prefs update).Code Examples
Reconnection Logic
Exponential back-off schedule
Exponential back-off schedule
After a disconnect,
The delay resets to 1 000 ms on any successful direct-socket connection (
PSConnection schedules a reconnect via setTimeout using reconnectDelay. Each failed attempt doubles the delay, capped at 15 seconds:| Attempt | Delay |
|---|---|
| 1st | 1 000 ms |
| 2nd | 2 000 ms |
| 3rd | 4 000 ms |
| 4th | 8 000 ms |
| 5th+ | 15 000 ms |
socket.onopen). Worker connections do not reset the delay (since the worker may have been running for a while already).24-hour session limit
24-hour session limit
canReconnect() compares Date.now() against PS.startTime (set when the PS object is constructed). If the difference exceeds 24 hours, the method returns false and shows a modal asking the user to refresh. This prevents very long-lived tabs from accumulating WebSocket state indefinitely.Room reconnect state
Room reconnect state
When a disconnect occurs, every room whose
connected flag is true has it set to 'autoreconnect'. This sentinel value tells room panels to display a “Reconnecting…” banner rather than a hard error. Once the connection is restored, rooms re-send their /join commands automatically via PS.prefs.doAutojoin().