API Reference
Complete API documentation for @ctrllr/core.
CtrllrManager
Main manager class for handling controller connections.
Constructor
const ctrllr = new CtrllrManager(options: CtrllrManagerOptions);
Options
| Property | Type | Description |
| --------------- | -------- | ------------------------------------- |
| signalingUrl | string | WebSocket URL of the signaling server |
| socketOptions | object | Optional socket.io client options |
Properties
| Property | Type | Description |
| ------------- | ------------------------- | ------------------------------------- |
| controllers | Map<number, Controller> | All currently connected controllers |
| socketId | string \| null | Socket ID used for QR code generation |
Methods
connect()
Connect to the signaling server.
await ctrllr.connect(): Promise<void>
disconnect()
Disconnect from the signaling server and clean up all connections.
ctrllr.disconnect(): void
getController(index)
Get a specific controller by its index.
ctrllr.getController(index: number): Controller | undefined
getQRCodeDataURL(options?)
Generate a QR code as a data URL (base64 image).
await ctrllr.getQRCodeDataURL(options?: QRCodeOptions): Promise<string>
getQRCodeSVG(options?)
Generate a QR code as an SVG string.
await ctrllr.getQRCodeSVG(options?: QRCodeOptions): Promise<string>
setAdapter(adapter)
Set a custom signaling adapter.
ctrllr.setAdapter(adapter: SignalingAdapter): void
Events
Subscribe to events using ctrllr.on(event, handler) and unsubscribe with ctrllr.off(event, handler).
| Event | Payload | Description |
| ------------------------ | -------------------------------------------------------------------- | ------------------------------------- |
| controllerconnected | { controller: Controller } | A new controller has connected |
| controllerdisconnected | { controller: Controller } | A controller has disconnected |
| statechange | { controller: Controller, state: ControllerState } | Any controller's state changed |
| buttondown | { controller: Controller, input: InputName, x: number, y: number } | Any button pressed on any controller |
| buttonup | { controller: Controller, input: InputName, x: number, y: number } | Any button released on any controller |
Controller
Represents a single connected controller.
Properties
| Property | Type | Description |
| ----------- | ----------------- | ------------------------------- |
| index | number | Controller index (0, 1, 2, ...) |
| userId | string \| null | User ID from the mobile app |
| username | string \| null | Username from the mobile app |
| state | ControllerState | Current input state |
| connected | boolean | Connection status |
Methods
getInput(name)
Get the state of a specific input.
controller.getInput(name: InputName): InputState
isAnyButtonPressed()
Check if any button is currently pressed.
controller.isAnyButtonPressed(): boolean
Events
Subscribe to events using controller.on(event, handler) and unsubscribe with controller.off(event, handler).
| Event | Payload | Description |
| ------------- | -------------------------------------------- | ---------------------------------------- |
| statechange | { state: ControllerState } | Input state changed |
| buttondown | { input: InputName, x: number, y: number } | Button pressed (edge: false → true) |
| buttonup | { input: InputName, x: number, y: number } | Button released (edge: true → false) |
Types
ControllerState
The complete state of a controller's inputs.
interface ControllerState {
joystick: InputState; // Left analog stick
a: InputState; // Aimable button A
x: InputState; // Aimable button X
y: InputState; // Aimable button Y
z: InputState; // Aimable button Z
}
InputState
The state of a single input (joystick or button).
interface InputState {
pressed: boolean; // Is the input active
x: number; // Horizontal axis (-1 to 1)
y: number; // Vertical axis (-1 to 1)
}
InputName
Valid input names.
type InputName = 'joystick' | 'a' | 'x' | 'y' | 'z';
QRCodeOptions
Options for QR code generation.
interface QRCodeOptions {
width?: number; // Size in pixels (default: 256)
margin?: number; // Margin in modules (default: 2)
darkColor?: string; // Foreground color (default: '#000000')
lightColor?: string; // Background color (default: '#ffffff')
}
CtrllrManagerOptions
Options for the CtrllrManager constructor.
interface CtrllrManagerOptions {
signalingUrl: string; // WebSocket URL of signaling server
socketOptions?: object; // Optional socket.io options
}
SignalingAdapter
Interface for implementing custom signaling adapters.
interface SignalingAdapter {
readonly socketId: string | null;
connect(): Promise<void>;
disconnect(): void;
onPeerConnected(
cb: (peerId: string, peer: SimplePeer.Instance) => void
): void;
onPeerDisconnected(cb: (peerId: string) => void): void;
}
Example Custom Adapter
import { SignalingAdapter, CtrllrManager } from '@ctrllr/core';
import SimplePeer from 'simple-peer';
class MyAdapter implements SignalingAdapter {
get socketId(): string | null {
// Return your socket/session ID
}
async connect(): Promise<void> {
// Connect to your signaling server
}
disconnect(): void {
// Disconnect and clean up
}
onPeerConnected(
cb: (peerId: string, peer: SimplePeer.Instance) => void
): void {
// Call cb when a new peer connects
}
onPeerDisconnected(cb: (peerId: string) => void): void {
// Call cb when a peer disconnects
}
}
// Usage
const ctrllr = new CtrllrManager({ signalingUrl: '' });
ctrllr.setAdapter(new MyAdapter());
await ctrllr.connect();
Architecture
┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐
│ Game App │ │ Signaling Server │ │ Mobile App │
│ (@ctrllr/core) │ │ (socket.io) │ │ (Controller) │
└────────┬────────┘ └────────┬─────────┘ └────────┬────────┘
│ │ │
│◄──── 1. Connect ─────►│◄──── 2. Connect ──────►│
│ │ │
│ 3. Get socket ID │ │
│ 4. Show QR code ──────┼───────► 5. Scan QR │
│ │ │
│◄─────────────── 6. WebRTC Signaling ──────────►│
│ │ │
│◄═══════════════ 7. WebRTC DataChannel ════════►│
│ │ │
│◄─────────── 8. Controller Input ──────────────│
The SDK uses WebRTC DataChannels for low-latency peer-to-peer communication between the game and mobile controllers. The signaling server is only used for initial connection setup.