Skip to main content

Documentation Index

Fetch the complete documentation index at: https://v5.rpgjs.dev/llms.txt

Use this file to discover all available pages before exploring further.

Server Engine Hooks

Server engine hooks allow you to listen to server-level events and customize server behavior. These hooks are defined in the engine property of your server module.

Usage

import { RpgServerEngine, RpgServerEngineHooks, defineModule } from '@rpgjs/server'

const engine: RpgServerEngineHooks = {
    onStart(server: RpgServerEngine) {
        console.log('Server is starting...')
    },
    onStep(server: RpgServerEngine) {
        // Called at each server frame (60 FPS)
    },
    auth(server: RpgServerEngine, socket: any) {
        // Custom authentication logic
        const token = socket.handshake.query.token
        if (!token) {
            throw 'Authentication failed: No token provided'
        }
        return 'user-id-123'
    }
}

export default defineModule({
    engine
})

Available Hooks

onStart

Description: Called when the server starts Parameters:
  • server: RpgServerEngine - The server engine instance
Example:
const engine: RpgServerEngineHooks = {
    onStart(server: RpgServerEngine) {
        console.log('Server started successfully')
        // Initialize global server data
        server.globalData = {
            startTime: Date.now(),
            playerCount: 0
        }
    }
}

onStep

Description: Called at each server frame, typically representing 60 FPS Parameters:
  • server: RpgServerEngine - The server engine instance
Example:
const engine: RpgServerEngineHooks = {
    onStep(server: RpgServerEngine) {
        // Update global timers, check conditions, etc.
        const currentTime = Date.now()
        if (currentTime % 10000 === 0) { // Every 10 seconds
            console.log(`Server running for ${currentTime - server.globalData.startTime}ms`)
        }
    }
}

auth

Description: Flexible authentication function for player connections. This function is called during each RPGJS room connection and should handle credential verification before the player is allowed to join the room. Parameters:
  • server: RpgServerEngine - The server engine instance
  • socket: any - The socket instance for the connecting player
Returns:
  • Promise<string> | string | undefined - Player’s stable public identifier if authentication succeeds, or undefined to generate an ID automatically
Throws:
  • string - Error message if authentication fails
The returned identifier becomes the player publicId used by RPGJS and Signe room user collections. In MMORPG mode, the hook is called when the client connects to the lobby and again when it reconnects to map rooms. Send the same token on each connection and return the same id for the same account. For browser MMORPG clients, pass the token through provideMmorpg({ query }); see Authentication. Example:
const engine: RpgServerEngineHooks = {
    async auth(server: RpgServerEngine, socket: any) {
        const token = socket.handshake.query.token
        
        if (!token) {
            throw 'Authentication failed: No token provided'
        }
        
        try {
            // Verify token with your authentication service
            const user = await verifyJWTToken(token)
            return user.id
        } catch (error) {
            throw 'Authentication failed: Invalid token'
        }
    }
}

Engine Runtime API

The server argument is an RpgServerEngine instance. It exposes stable helpers for reading the current RPGJS room without depending on low-level Signe internals.
const engine: RpgServerEngineHooks = {
    onStart(server: RpgServerEngine) {
        const room = server.getCurrentRoom()
        const roomInfo = server.getCurrentRoomInfo()
        const globalConfig = server.globalConfig

        console.log(roomInfo?.id, roomInfo?.kind, globalConfig)
    }
}

getCurrentRoom

Returns the current RPGJS room instance, such as LobbyRoom or RpgMap.
const room = server.getCurrentRoom()
This is different from server.room, which is the low-level Signe/Party room wrapper.

getCurrentRoomInfo

Returns stable metadata for the current room:
const info = server.getCurrentRoomInfo()

if (info?.kind === 'map') {
    console.log(`Current map room: ${info.name}`)
}
The returned object contains:
  • id: full room id, such as lobby-1 or map-town
  • kind: lobby, map, or unknown
  • name: room id without the RPGJS prefix
  • className: runtime room class name
  • playersCount: number of players in the room when available
  • autoSync: whether automatic sync is enabled
  • hasDatabase: whether the room exposes a database signal
You can also use getCurrentRoomId() and getCurrentRoomKind() when you only need one value.

globalConfig

server.globalConfig is provided for compatibility with older server-engine usage:
const globalConfig = server.globalConfig
In map rooms, it returns the current map’s globalConfig. In lobby rooms or before room initialization, it returns the last assigned value or {}.

app and io

server.app and server.io are optional compatibility handles. RPGJS v5 does not create Express or socket.io automatically, but custom Node entries can assign these properties when migrating older code:
server.app = app
server.io = wsServer

Complete Example

import { RpgServerEngine, RpgServerEngineHooks, defineModule } from '@rpgjs/server'
import { verifyJWTToken } from './auth-service'

const engine: RpgServerEngineHooks = {
    onStart(server: RpgServerEngine) {
        console.log('🚀 RPG Server started')
        server.globalData = {
            startTime: Date.now(),
            events: []
        }
    },
    
    onStep(server: RpgServerEngine) {
        // Process global events every frame
        if (server.globalData.events.length > 0) {
            const event = server.globalData.events.shift()
            console.log('Processing global event:', event)
        }
    },
    
    async auth(server: RpgServerEngine, socket: any) {
        const { token, guestMode } = socket.handshake.query
        
        if (guestMode === 'true') {
            // Allow guest connections
            return `guest_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`
        }
        
        if (!token) {
            throw 'Authentication required'
        }
        
        try {
            const user = await verifyJWTToken(token)
            console.log(`User ${user.username} authenticated`)
            return user.id
        } catch (error) {
            throw 'Invalid authentication token'
        }
    }
}

export default defineModule({
    engine
})