Skip to Content
DocsGame ServerRoom Collection

Managing Room Collection Data

This guide explains how to manage collection data scoped to a room in Agent8. Collections provide a structured way to store and retrieve persistent room-specific data—such as leaderboards, game records, or other room-related information. The main difference compared to global collections is that the API functions here are prefixed with $room instead of $global.

Room collections operate almost identically to global collections but their data is scoped to an individual room.

Server API

  • $room.getCollectionItems(collectionId: string, options?: CollectionOptions): Promise<Item[]>
    Retrieves multiple items from a room collection based on filtering, sorting, and pagination options.

  • $room.getCollectionItem(collectionId: string, itemId: string): Promise<Item>
    Retrieves a single item from the room collection using its unique ID.

  • $room.addCollectionItem(collectionId: string, item: any): Promise<Item>
    Adds a new item to the specified room collection and returns the added item with its unique identifier.

  • $room.updateCollectionItem(collectionId: string, item: any): Promise<Item>
    Updates an existing item in the room collection and returns the updated item.

  • $room.deleteCollectionItem(collectionId: string, itemId: string): Promise<{ __id: string }>
    Deletes an item from the room collection and returns a confirmation containing the deleted item’s ID.

server.js
class Server { async addRoomCollectionItem(collectionId, item) { return await $room.addCollectionItem(collectionId, item); } async updateRoomCollectionItem(collectionId, item) { return await $room.updateCollectionItem(collectionId, item); } async deleteRoomCollectionItem(collectionId, itemId) { return await $room.deleteCollectionItem(collectionId, itemId); } async getRoomCollectionItems(collectionId, options = {}) { return await $room.getCollectionItems(collectionId, options); } async getRoomCollectionItem(collectionId, itemId) { return await $room.getCollectionItem(collectionId, itemId); } }

Client API

subscriptions

  • server.subscribeRoomCollection(roomId, collectionId: string, ({ items, changes }: { items: any[], changes: { op: 'add'|'update'|'delete'|'deleteAll', items: any[]} }) => {}): UnsubscribeFunction

hooks

  • const { items } = useRoomCollection(collectionId)

Subscribe to Room Collection Updates

import { useGameServer } from "@agent8/gameserver"; import { useEffect } from "react"; function RoomCollectionComponent() { const { connected, server } = useGameServer(); const roomId = "my-room"; const collectionId = "room-scores"; useEffect(() => { if (!connected) return; const unsubscribe = server.subscribeRoomCollection( roomId, collectionId, ({ items, changes }) => { console.log("all items", items); console.log("Updated items:", changes.items); // Handle different operations if (changes.op === "add") { // Handle added items } else if (changes.op === "update") { // Handle updated items } else if (changes.op === "delete") { // Handle deleted items } } ); // Cleanup subscription when component unmounts return () => unsubscribe(); }, [connected, server, collectionId]); return <div>Room Collection Component</div>; }

Sync Room Collection with React Hooks

To synchronize room collections in real-time using hooks:

import { useRoomCollection } from "@agent8/gameserver"; function RoomCollectionDisplay() { const roomId = "my-room"; const collectionId = "room-scores"; const { items } = useRoomCollection(collectionId); return ( <div> <h2>Room Collection Items</h2> <ul> {items.map((item) => ( <li key={item.__id}>{JSON.stringify(item)}</li> ))} </ul> </div> ); }

The useRoomCollection hook automatically handles subscriptions and unsubscriptions, making it the recommended approach for React applications.

Example: Room Scoreboard

This example demonstrates a simple room-specific scoreboard that tracks player scores.

server.js
class Server { async addScore(points) { const myState = await $room.getMyState(); const scoreItem = { playerName: myState.name || "Anonymous", playerAccount: $sender.account, score: points, timestamp: Date.now(), }; return await $room.addCollectionItem("scores", scoreItem); } async getTopScores(limit = 10) { return await $room.getCollectionItems("scores", { limit, orderBy: [{ field: "score", direction: "desc" }], }); } }
src/Scoreboard.tsx
import { useGameServer, useRoomCollection } from "@agent8/gameserver"; import { useState } from "react"; export default function Scoreboard() { const { connected, server } = useGameServer(); const { items: scores } = useRoomCollection("scores"); const [newScore, setNewScore] = useState(0); if (!connected) return <p>Loading...</p>; const handleAddScore = async () => { if (newScore > 0) { await server.remoteFunction("addScore", [newScore]); setNewScore(0); } }; // Sort scores by highest first const sortedScores = [...scores].sort((a, b) => b.score - a.score); return ( <div> <h2>Room Scoreboard</h2> <div> <input type="number" value={newScore} onChange={(e) => setNewScore(parseInt(e.target.value) || 0)} min="0" /> <button onClick={handleAddScore}>Add Score</button> </div> <table style={{ width: "100%", marginTop: "20px" }}> <thead> <tr> <th>Rank</th> <th>Player</th> <th>Score</th> <th>Date</th> </tr> </thead> <tbody> {sortedScores.map((score, index) => ( <tr key={score.__id}> <td>{index + 1}</td> <td>{score.playerName}</td> <td>{score.score}</td> <td>{new Date(score.timestamp).toLocaleString()}</td> </tr> ))} </tbody> </table> </div> ); }

For additional collection features like filtering, sorting, and pagination, please refer to the Global Collection documentation.

Last updated on