feat(client): parametrize WS/API via VITE_WS_URL and VITE_API_URL; add .env.example and README env section
4.8 KiB
4.8 KiB
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
lobbyque 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):
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):
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
@typey coleccionesMapSchema/ArraySchema. - Patrón: solo el servidor muta estado; clientes envían mensajes de intención.
Ejemplo:
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"]);
- Listar:
Ejemplos (server/src/adminApi.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"):
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
onMessagey nunca confiar en el cliente. - Usar
metadata/filterBypara matchmaking por atributos. - Mantener
maxClientsy 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>:3000según el protocolo actual. - Ejemplos:
- Desarrollo local:
VITE_WS_URL=ws://localhost:3000 - Producción (TLS):
VITE_WS_URL=wss://api.midominio.com
- Desarrollo local:
Configuración de REST API (Cliente)
- Variable de entorno en Vite:
VITE_API_URLcon la base completa del API (incluye/api). - Si no se define, el cliente usa
http(s)://<hostname>:3000/apisegú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
- Desarrollo local: