docs: add contributor and Colyseus guides

feat(client): parametrize WS/API via VITE_WS_URL and VITE_API_URL; add .env.example and README env section
This commit is contained in:
2025-08-07 17:10:08 -06:00
parent 5a273766a6
commit 1912b3a76f
5 changed files with 200 additions and 10 deletions

117
COLYSEUS-GUIA.md Normal file
View File

@@ -0,0 +1,117 @@
# Colyseus: Guía de Integración para Snatchgame
Esta guía resume las APIs de Colyseus necesarias para: un lobby unificado, salas de juego (máx. 2 jugadores) y un dashboard para inspección/acciones por sala y globales.
## Conceptos Clave
- Rooms: unidades de ejecución con ciclo de vida (`onCreate`, `onJoin`, `onLeave`, `onDispose`).
- Schema: sincroniza estado autoritativo del servidor a clientes con `@type`.
- Mensajería: `room.onMessage(type, handler)`, `client.send(type, payload)`, `room.broadcast(type, payload)`.
- Matchmaker: descubrimiento/control de salas (`matchMaker.query`, `remoteRoomCall`, `stats`).
- Monitor: panel listo para usar en Express (`@colyseus/monitor`).
## Lobby Unificado
- Definir una sala pública única `lobby` que gestione nombres, matchmaking y listado.
- API útil: `gameServer.define("lobby", LobbyRoom)`, `setPrivate(false)`, `enableRealtimeListing()` en salas de juego para listar.
- Mensajes recomendados: `setName`, `quickPlay`, `joinRoom`.
Ejemplo (server/src/rooms/LobbyRoom.ts):
```ts
export class LobbyRoom extends Room<LobbyState> {
onCreate() {
this.setState(new LobbyState());
this.onMessage("setName", (client, name) => {/* validar + asignar */});
this.onMessage("quickPlay", async (client) => {
// Crear o elegir una sala "game" con cupo
const rooms = await matchMaker.query({ name: "game", locked: false });
const target = rooms.find(r => r.clients < r.maxClients) ||
await matchMaker.createRoom("game", { maxClients: 2 });
client.send("gameJoined", { roomId: target.roomId || target.roomId });
});
}
}
```
## Game Rooms (2 jugadores)
- Definición: `gameServer.define("game", GameRoom).filterBy(["maxClients"]).enableRealtimeListing()`.
- Capacidad: `maxClients = 2;` en la clase de la sala.
- Re-conexión: `await this.allowReconnection(client, 30);` para tolerancia a fallos.
- Ticks: usar `this.setSimulationInterval((deltaTime) => { /* actualizar timer */ }, 1000);`.
Ejemplo (server/src/rooms/GameRoom.ts):
```ts
export class GameRoom extends Room<GameState> {
maxClients = 2;
onCreate() {
this.setState(new GameState());
this.onMessage("click", (client) => {/* sumar clicks si PLAYING */});
}
onJoin(client, { playerName }) {
this.state.addPlayer(client.sessionId, playerName);
if (this.state.players.size === 2) this.state.startGame();
}
onLeave(client) {
this.state.players.get(client.sessionId)!.connected = false;
this.allowReconnection(client, 30);
}
}
```
## Estado Autoritativo (Schema)
- Definir modelos con `@type` y colecciones `MapSchema`/`ArraySchema`.
- Patrón: solo el servidor muta estado; clientes envían mensajes de intención.
Ejemplo:
```ts
export class GameState extends Schema {
@type({ map: Player }) players = new MapSchema<Player>();
@type("string") gameStatus: GameStatus = GameStatus.WAITING;
@type("number") timeRemaining = 600;
}
```
## Dashboard y Control Administrativo
- Monitor integrado: `app.use("/colyseus", monitor());` para ver salas/CCU.
- REST/Admin personalizado vía `matchMaker`:
- Listar: `await matchMaker.query({ name: "game" });`
- Llamar métodos remotos: `await matchMaker.remoteRoomCall(roomId, "getState");`
- Acciones por sala: `await matchMaker.remoteRoomCall(roomId, "broadcast", ["admin:pause"]);`
Ejemplos (server/src/adminApi.ts):
```ts
router.get("/rooms", async (_, res) => {
const rooms = await matchMaker.query({});
res.json(rooms);
});
router.post("/rooms/:roomId/restart", async (req, res) => {
await matchMaker.remoteRoomCall(req.params.roomId, "broadcast", ["admin:restart"]);
res.json({ success: true });
});
```
Acciones globales (todas las salas "game"):
```ts
const rooms = await matchMaker.query({ name: "game" });
await Promise.all(rooms.map(r => matchMaker.remoteRoomCall(r.roomId, "broadcast", ["admin:pause"])));
```
## Buenas Prácticas
- Validar inputs en `onMessage` y nunca confiar en el cliente.
- Usar `metadata`/`filterBy` para matchmaking por atributos.
- Mantener `maxClients` y reglas de inicio/pausa dentro del servidor.
- Exponer solo métodos necesarios para `remoteRoomCall` (p. ej., `getState`).
Referencias: documentación oficial Colyseus (Rooms, Schema, Matchmaker, Monitor).
## Configuración de WebSocket (Cliente)
- Variable de entorno en Vite: `VITE_WS_URL`.
- Si no se define, el cliente usa `ws(s)://<hostname>:3000` según el protocolo actual.
- Ejemplos:
- Desarrollo local: `VITE_WS_URL=ws://localhost:3000`
- Producción (TLS): `VITE_WS_URL=wss://api.midominio.com`
## Configuración de REST API (Cliente)
- Variable de entorno en Vite: `VITE_API_URL` con la base completa del API (incluye `/api`).
- Si no se define, el cliente usa `http(s)://<hostname>:3000/api` según el protocolo actual.
- Ejemplos:
- Desarrollo local: `VITE_API_URL=http://localhost:3000/api`
- Producción (TLS): `VITE_API_URL=https://api.midominio.com/api`