@usions/game-server
v1.0.1
Published
Server SDK for Usion direct-mode multiplayer games
Downloads
105
Maintainers
Readme
@usions/game-server
Server SDK for building multiplayer games on the Usion platform.
Handles token validation, room management, WebSocket protocol, and result submission — so you can focus on game logic.
Install
npm install @usions/game-serverQuick Start
import { UsionGameServer } from '@usions/game-server';
const server = new UsionGameServer({
serviceId: process.env.SERVICE_ID,
sharedSecret: process.env.USION_SHARED_SECRET,
port: 3005,
});
server.onPlayerJoin((player, room) => {
console.log(`${player.name} joined room ${room.id}`);
room.broadcast('player_joined', { player_id: player.id, name: player.name });
});
server.onAction('move', (data, player, room) => {
// Your game logic here
room.setState({ lastMove: data });
room.broadcast('state_update', room.getState());
});
server.onRealtime('position', (data, player, room) => {
// High-frequency updates (fire-and-forget)
room.broadcastExcept(player.id, 'position', {
player_id: player.id,
...data,
});
});
server.listen(() => console.log('Game server ready'));What It Does For You
| Without SDK | With SDK |
|------------|----------|
| Implement RS256 JWKS token validation | Automatic on every connection |
| Build WebSocket server + room management | new UsionGameServer() |
| Construct HMAC-SHA256 canonical strings | server.submitResult() |
| Handle reconnection + heartbeats | Built-in |
| Parse/format wire protocol messages | Built-in |
API Reference
new UsionGameServer(options)
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| serviceId | string | required | Your game's service ID on Usion |
| sharedSecret | string | required | HMAC secret from service registration |
| keyId | string | 'default' | Signing key ID |
| apiUrl | string | 'https://mobile.mongolai.mn' | Usion API base URL |
| port | number | 3005 | Server port |
| maxPlayersPerRoom | number | 2 | Max players per room |
| heartbeatIntervalMs | number | 25000 | Heartbeat check interval |
| staleTimeoutMs | number | 90000 | Stale connection timeout |
| wsPath | string | '/ws' | WebSocket upgrade path |
| jwksUrl | string | auto | JWKS endpoint (derived from apiUrl) |
Event Handlers
server.onPlayerJoin(handler)
Called when a new player connects and is authenticated.
server.onPlayerJoin((player, room) => {
// player: { id, name, sessionId, ws, connectedAt }
// room: Room instance (see below)
});server.onPlayerLeave(handler)
Called when a player disconnects.
server.onPlayerReconnect(handler)
Called when a player reconnects to a room they were already in.
server.onAction(actionType, handler)
Handle validated, stateful actions. Maps to client SDK's Usion.game.action().
server.onAction('move', (data, player, room) => {
// data: the action payload from client
// Validate and apply game logic here
});
// Catch-all handler for any action type
server.onAction('*', (data, player, room) => {
console.log('Action:', data.action_type);
});server.onRealtime(actionType, handler)
Handle fire-and-forget, high-frequency updates. Maps to client SDK's Usion.game.realtime().
server.onRealtime('position', (data, player, room) => {
room.broadcastExcept(player.id, 'player_position', {
player_id: player.id,
x: data.x,
y: data.y,
});
});server.onRematch(handler) / server.onForfeit(handler)
Handle rematch requests and forfeits.
Result Submission
await server.submitResult(roomId, {
winnerIds: ['user-a'], // Winners
participants: ['user-a', 'user-b'], // All players (auto-filled from room if omitted)
reason: 'completed', // 'completed' | 'forfeit' | 'timeout' | 'opponent_left'
finalStats: { // Per-player stats (optional)
'user-a': { score: 150 },
'user-b': { score: 80 },
},
});HMAC-SHA256 signing is handled automatically.
Room Class
Rooms are created automatically when players join. Access them via server.getRoom(roomId).
room.id // Room ID
room.status // 'waiting' | 'playing' | 'finished'
room.playerCount // Number of connected players
room.playerIds // Array of user IDs
room.playerList // Array of { id, name, sessionId }
room.isFull // Whether room is at capacity
room.maxPlayers // Max allowed players
room.getState() // Get game state object
room.setState({ key: value }) // Merge into game state
room.replaceState(newState) // Replace entire game state
room.broadcast(type, payload) // Send to ALL players
room.broadcastExcept(userId, type, payload) // Send to all except one
room.send(userId, type, payload) // Send to one player
room.getPlayer(userId) // Get player by user ID
room.getPlayerBySession(sid) // Get player by session IDServer Lifecycle
server.listen(callback) // Start HTTP + WebSocket server
server.close() // Graceful shutdown
server.roomCount // Number of active rooms
server.getRoom(roomId) // Get a specific roomHealth Check
The server exposes GET /health:
{ "status": "ok", "service": "my-game", "rooms": 3, "uptime": 1234 }Environment Variables
SERVICE_ID=your-service-id
USION_SHARED_SECRET=your-hmac-secret
USION_KEY_ID=default
API_URL=https://mobile.mongolai.mn
PORT=3005How Direct Mode Works
Usion App ──GET /games/rooms/{id}/access──> Usion Backend
│ │
│ <── RS256 JWT access token + ws_url ──────┘
│
└── WebSocket ?token=xxx ──> Your Game Server (@usions/game-server)
│
├── Validates JWT via JWKS
├── Creates/joins Room
├── Routes messages to your handlers
└── Submits results via HMAC-signed POSTTypeScript
Full TypeScript declarations included. Import types:
import type { Player, Room, UsionGameServerOptions, SubmitResultPayload } from '@usions/game-server';License
MIT
