# @lobstar/preact

<p align="left">
    <img src="../../images/mascot.png" alt="Lobstar logo" width="128" />
</p>

> [!WARNING]
> This is an early prototype and the API is subject to change and bugs are expected.

A collection of Preact hooks that make it easy to integrate with the [Lobstar library](https://github.com/jamsinclair/lobstar) for network and lobby management of multiplayer web games.

[![npm version](https://img.shields.io/npm/v/@lobstar/preact.svg)](https://www.npmjs.com/package/@lobstar/preact)
[![license](https://img.shields.io/npm/l/@lobstar/preact.svg)](https://github.com/jamsinclair/@lobstar/preact/blob/main/LICENSE.md)
[![bundlephobia minzipped size](https://badgen.net/bundlephobia/minzip/@lobstar/preact)](https://bundlephobia.com/package/@lobstar/preact)

## Installation

```bash
npm install @lobstar/preact
```

## Features

- Simple WebRTC game session management
- Lobby creation and joining
- Player status tracking
- Ready state management
- Host controls (kick players, start/end game)
- Game messaging system
- Preact-optimized state updates

## Usage

### Basic Example

```jsx
import { useGameLobby } from '@lobstar/preact';

function GameLobby() {
  const {
    // Session methods
    host,
    join,
    leave,
    setReady,
    startGame,
    endGame,
    kickPlayer,
    sendMessage,
    sendMessageToHost,
    broadcastMessage,

    // Session state
    state,
    isConnected,
    isPlaying,
    isInLobby,
    isGameOver,

    // Players info
    areAllPlayersReady,
    playersList,
    self,
    hostPlayer,
    isHost,
    maxPlayers,

    // Raw lobstar game session access (for advanced use cases)
    session,
  } = useGameLobby();
  
  // Your component logic here
}
```

### Creating or Joining a Game

```jsx
// Host a new game
const handleHost = async () => {
  const lobbyId = await host("Player1");
  console.log(`Created lobby: ${lobbyId}`);
};

// Join an existing game
const handleJoin = async () => {
  await join("LOBBY-ID", "Player2");
};
```

### Player Management

```jsx
// Get all players
const playersList = Object.values(players);

// Check if current player is host
if (isHost) {
  // Host-only functionality
}

// Set ready status
const toggleReady = () => {
  setReady(!self.isReady);
};

// Kick a player (host only)
const removePlayer = (playerId) => {
  kickPlayer(playerId);
};
```

### Game State Management

```jsx
// Check current state
if (isInLobby) {
  // Show lobby UI
} else if (isPlaying) {
  // Show game UI
}

// Start the game (host only)
const beginGame = () => {
  startGame();
};

// End the game (host only)
const finishGame = () => {
  endGame();
};
```

### Game Communication

```jsx
// Send a message to specific player
const sendMessage = (playerId, data) => {
  sendMessage(playerId, data);
};

// Broadcast to all players
const broadcastToAll = (data) => {
  broadcastMessage(data);
};
```

### Event Handling

```jsx
// Handle incoming messages
useGameLobby({
    onMessage: (data, peerId) => {
        console.log(`Message from ${peerId}:`, data);
        // Handle game logic here
    }
});

// Handle kick events
useGameLobby({
    onKicked: (peerId) => {
        console.log(`Player ${peerId} was kicked`);
    }
});

// Handle errors
useGameLobby({
    onError: (error) => {
        console.error(`Error:`, error);
    }
});
```

## Configuration

```jsx
useGameLobby({
  options: {
    maxPlayers: 8,                 // Maximum players allowed
    playerJoinTimeoutMs: 10000,    // Time in ms before a player is kicked for joining late
    requireReadyBeforeStart: true, // Require all players to be ready
    debug: true,                   // Enable debug logging
    peerOptions: {}                // PeerJS connection options
  },
});
```

## License

MIT