UNPKG

@lobstar/core

Version:

A simple network and lobby manager for multiplayer web games

220 lines (170 loc) 6.6 kB
<p align="center"> <img src="../../images/mascot.png" alt="Lobstar logo" width="256" /> </p> > [!WARNING] > This is an early prototype and the API is subject to change and bugs are expected. A lightweight peer-to-peer multiplayer game session and lobby manager for web games. [![npm version](https://img.shields.io/npm/v/@lobstar/core.svg)](https://www.npmjs.com/package/@lobstar/core) [![license](https://img.shields.io/npm/l/@lobstar/core.svg)](https://github.com/jamsinclair/@lobstar/core/blob/main/LICENSE.md) [![bundlephobia minzipped size](https://badgen.net/bundlephobia/minzip/@lobstar/core)](https://bundlephobia.com/package/@lobstar/core) ## Features - Simple peer-to-peer networking with WebRTC (via [PeerJS](https://peerjs.com/)) - Host/client architecture with configurable lobby settings - Player management (joining, leaving, kicking, ready states) - Game state lifecycle (lobby, playing, game over) - Event-based messaging system - Robust error handling and state management ## Installation ```bash npm install @lobstar/core ``` ## Basic Usage ### Creating a Game Session ```typescript import { GameSessionManager } from '@lobstar/core'; // Create a session manager with default options const gameSession = new GameSessionManager({ maxPlayers: 4, // Maximum number of players allowed (default: 8) requireReadyBeforeStart: true, // Require all players to be ready before starting (default: true) debug: true // Enable debug logging (default: false) }); // Listen for state changes gameSession.on('stateChange', ({ state, previousState }) => { console.log(`Game state changed from ${previousState} to ${state}`); }); // Host a new game async function hostGame() { try { const lobbyId = await gameSession.host('HostPlayer'); console.log(`Game hosted with lobby ID: ${lobbyId}`); // Share this lobby ID with other players so they can join } catch (error) { console.error('Failed to host game:', error); } } // Join an existing game async function joinGame(lobbyId) { try { await gameSession.join(lobbyId, 'GuestPlayer'); console.log('Successfully joined the game!'); } catch (error) { console.error('Failed to join game:', error); } } ``` ### Managing Players and Game State ```typescript // Set player ready state gameSession.setReady(true); // Start the game (host only) if (gameSession.isHost()) { gameSession.startGame(); } // Get current players const players = gameSession.getPlayers(); console.log('Current players:', players); // Kick a player (host only) if (gameSession.isHost()) { gameSession.kickPlayer('player-id-to-kick'); } // End the game (host only) if (gameSession.isHost()) { gameSession.endGame(); } // Leave the game gameSession.leave(); ``` ### Custom Communication The session manager provides a custom message system that allows you to send and receive messages between players. This allows you to - Extend the lobby experience with chat, character selection, etc. - Send and receive game-specific messages between players on game start > [!NOTE] > The host will operate like a server, they can send messages to all players and receive messages from all players. > > The clients can only send messages and receive messages from the host. ```typescript // Send a custom message to the host gameSession.sendMessageToHost({ type: 'move', x: 100, y: 200 }); // Broadcast a message to all players gameSession.broadcastMessage({ type: 'itemCollected', playerId: 'player-id-123', itemId: 'power-up-22' }); // Send a custom message to a specific player from the host gameSession.sendMessage('player-id-123', { type: 'secretObjective', objective: 'Find the hidden gold necklace' }); // Listen for custom messages gameSession.on('customMessage', ({ data, peerId }) => { console.log(`Received message from ${peerId}:`, data); }); ``` ## API Reference ### Constructor ```typescript new GameSessionManager(options?: GameSessionOptions) ``` **Options:** - `maxPlayers`: Maximum number of players allowed (default: 8) - `requireReadyBeforeStart`: Require all players to be ready before starting (default: true) - `debug`: Enable debug logging (default: false) - `peerOptions`: Options to pass to the underlying PeerJS instance - `playerJoinTimeoutMs`: Timeout for player join (default: 10000) ### Methods #### Session Management - `host(playerName: string, lobbyId?: string): Promise<string>` - Host a new game session - `join(lobbyId: string, playerName: string): Promise<void>` - Join an existing game session - `leave(): void` - Leave the current session #### Game Flow - `setReady(isReady: boolean): void` - Set player ready state - `startGame(): void` - Start the game (host only) - `endGame(): void` - End the game (host only) #### Player Management - `kickPlayer(playerId: string): void` - Kick a player (host only) - `getPlayers(): PlayerMap` - Get all players - `getPlayer(id: string): Player | null` - Get a specific player - `getSelf(): Player | null` - Get the current player - `getHost(): Player | null` - Get the host player #### Communication - `sendMessage(peerId: string, data: unknown): void` - Send a message to a specific player. Only the host can send messages to other players. Clients can only send messages to the host's `peerId`. - `sendMessageToHost(data: unknown): void` - Send a message to the host. - `broadcastMessage(data: unknown, excludeSelf: boolean = true): void` - Broadcast a message to all players. Only the host can broadcast messages. #### Status - `isHost(): boolean` - Check if the current player is the host - `getState(): SessionState` - Get the current session state - `getMaxPlayers(): number` - Get the maximum allowed players ### Events Listen to events using the `on` method: ```typescript gameSession.on('eventName', (eventData) => { // Handle the event }); ``` Available events: - `stateChange`: Fired when the session state changes - `playersUpdate`: Fired when the players list is updated - `customMessage`: Fired when a custom message is received - `error`: Fired when an error occurs - `kicked`: Fired when the player is kicked from the session ## Error Handling The session manager provides detailed error information through the `error` event: ```typescript gameSession.on('error', ({ code, message, context, originalError }) => { console.error(`Error [${code}]: ${message} (${context})`); if (originalError) { console.error('Original error:', originalError); } }); ``` Error codes are available in the `ERROR_CODES` constant. ## License MIT