Web Engine Docs
Preparing documentation
Use the search bar to quickly find any topic
Preparing documentation
Use the search bar to quickly find any topic
Configure and run the Web Engine multiplayer server with Colyseus for real-time networked gameplay.
The Web Engine multiplayer system uses Colyseus as its networking backend, providing robust room management, state synchronization, and scalability features.
Authoritative game server runs game logic and validates all client inputs to prevent cheating.
Real-time bidirectional communication using WebSockets with automatic reconnection support.
The multiplayer server is included in the monorepo under apps/server. Start it with:
# Start the multiplayer serverpnpm server# Server will start on ws://localhost:2567
Development Mode
In development, the server automatically reloads when you make changes to server-side code. The server runs independently from the editor/client.
Configure the server via environment variables or the configuration file:
# Server configurationPORT=2567NODE_ENV=development# Colyseus configurationCOLYSEUS_MONITOR_PASSWORD=admin123COLYSEUS_PRESENCE_TYPE=local# Room configurationMAX_ROOM_CAPACITY=10CONNECTION_TIMEOUT=30000HEARTBEAT_INTERVAL=5000
Rooms are the core concept in Colyseus. Each room manages a game session with its own state.
import { Room, Client } from 'colyseus';import { GameRoomState } from './schema/GameRoomState';export class GameRoom extends Room<GameRoomState> {maxClients = 10;onCreate(options: any) {this.setState(new GameRoomState());// Set up room logicthis.setSimulationInterval((deltaTime) => {this.state.update(deltaTime);});// Set up message handlersthis.onMessage('input', (client, message) => {this.handlePlayerInput(client, message);});console.log('GameRoom created!', options);}onJoin(client: Client, options: any) {console.log(client.sessionId, 'joined!');// Create player entitythis.state.createPlayer(client.sessionId, options);}onLeave(client: Client, consented: boolean) {console.log(client.sessionId, 'left!');// Remove player entitythis.state.removePlayer(client.sessionId);}onDispose() {console.log('GameRoom disposed!');}private handlePlayerInput(client: Client, message: any) {// Validate and process player inputconst player = this.state.players.get(client.sessionId);if (player) {player.processInput(message);}}}
Use Colyseus schemas to define synchronized state. Schemas enable automatic state tracking and delta compression.
import { Schema, MapSchema, type } from '@colyseus/schema';export class Player extends Schema {@type('number') x = 0;@type('number') y = 0;@type('number') z = 0;@type('number') rotX = 0;@type('number') rotY = 0;@type('number') rotZ = 0;@type('number') rotW = 1;@type('string') name = '';@type('string') avatarId = '';}export class GameRoomState extends Schema {@type({ map: Player }) players = new MapSchema<Player>();@type('number') gameTime = 0;createPlayer(sessionId: string, options: any) {const player = new Player();player.name = options.name || 'Player';player.avatarId = options.avatarId || 'default';this.players.set(sessionId, player);}removePlayer(sessionId: string) {this.players.delete(sessionId);}update(deltaTime: number) {this.gameTime += deltaTime;// Update game logicthis.players.forEach((player) => {// Physics, movement, etc.});}}
Schema Benefits
Colyseus automatically tracks changes to schema properties and sends only deltas to clients, significantly reducing bandwidth usage. The schema is also type-safe on both client and server.
The server includes robust connection management with heartbeat monitoring, timeout handling, and automatic reconnection support:
import { getConnectionManager } from './ConnectionManager';// Initialize connection managerconst connectionManager = getConnectionManager({heartbeatInterval: 5000, // 5 secondsconnectionTimeout: 30000, // 30 secondsmaxReconnectionAttempts: 5,autoReconnect: true,});// Register connectionconnectionManager.registerConnection(clientId);// Track connection qualityconnectionManager.updateQuality(clientId, rtt, packetLoss, jitter);// Handle heartbeatconnectionManager.updateHeartbeat(clientId);
The connection manager automatically monitors connection quality and categorizes it:
Configure different environments for development, staging, and production:
export const environment = {development: {port: 2567,wsUrl: 'ws://localhost:2567',corsOrigins: ['http://localhost:3000', 'http://localhost:5173'],logLevel: 'debug',},production: {port: process.env.PORT || 8080,wsUrl: process.env.WS_URL || 'wss://game.example.com',corsOrigins: ['https://game.example.com'],logLevel: 'info',},};export const config = environment[process.env.NODE_ENV || 'development'];
Connect to the server from your game client:
import { NetworkManager } from '@web-engine-dev/core/network';const network = NetworkManager.getInstance();// Connect to serverawait network.connectToColyseus('ws://localhost:2567','game_room',{name: 'Player1',avatarId: 'avatar-001'});// Create private roomawait network.createPrivateRoom('game_room', {name: 'Player1',avatarId: 'avatar-001'});// Join by invite codeawait network.joinPrivateRoom('ABC123', {name: 'Player2',avatarId: 'avatar-002'});
Colyseus includes a built-in monitoring dashboard accessible at:
http://localhost:2567/colyseusLogin credentials (configure in .env):Username: adminPassword: admin123
Production Security
Always change the default monitoring password in production environments. Consider disabling the monitor entirely or restricting access via firewall rules.