const axios = require("axios"); const { getGame, createGame } = require("../state/game"); const { getUser } = require("../state/connection"); const API_URL = "http://localhost:8000/api/v1"; module.exports = (io, socket) => { // --- EVENTO: ENTRAR NO JOGO (Validado pela tabela GAMES) --- socket.on("join-game", async ({ gameId }) => { const user = getUser(socket.id); if (!user) { socket.emit("error", { message: "Não autenticado." }); return; } console.log(`[Socket] User ${user.id} a tentar entrar no Game ${gameId}`); // 1. Verificar se o jogo já está na memória do Node let game = getGame(gameId); // 2. Se NÃO existe na memória, vamos buscá-lo ao Laravel if (!game) { try { // Token para autenticação no Laravel const token = socket.handshake.auth.token; // CHAMADA À API GAMES const response = await axios.get(`${API_URL}/games/${gameId}`, { headers: { Authorization: token }, }); const gameData = response.data.data; // Validação: O user pertence a este jogo? if ( gameData.player1_user_id != user.id && gameData.player2_user_id != user.id ) { socket.emit("error", { message: "Não pertences a este jogo!" }); return; } // Validação: O jogo já acabou? if (gameData.status === "Ended") { socket.emit("error", { message: "Este jogo já terminou." }); return; } console.log(`[Laravel] Game ${gameId} validado. A iniciar lógica...`); // Preparar jogadores // Nota: O endpoint 'games/{id}' deve retornar info básica dos users ou pelo menos os IDs. // Se não vier o nome, usamos um placeholder ou o nome do user atual se coincidir. const p1Name = gameData.player1 && gameData.player1.name ? gameData.player1.name : "Player 1"; const p2Name = gameData.player2 && gameData.player2.name ? gameData.player2.name : "Player 2"; const p1 = { id: gameData.player1_user_id, name: p1Name }; const p2 = { id: gameData.player2_user_id, name: p2Name }; // Tipo de jogo ('3' ou '9') const type = gameData.type == "9" ? 9 : 3; // CRIAR O JOGO NA MEMÓRIA game = createGame(gameId, type, p1, p2); } catch (error) { console.error( `[Erro Laravel] Falha ao buscar Game ${gameId}:`, error.message ); // Dica: Se der 404, o jogo não existe na BD socket.emit("error", { message: "Erro ao buscar dados do jogo." }); return; } } // 3. Juntar o socket à sala do jogo socket.join(`game_${gameId}`); // 4. Enviar o estado do jogo ao jogador if (game.players[user.id]) { // Envia apenas o que este jogador pode ver (esconde mão do adversário) const gameState = game.getStateForPlayer(user.id); socket.emit("game-state", gameState); } }); // --- EVENTO: JOGAR CARTA --- socket.on("play-card", ({ gameId, cardId }) => { const user = getUser(socket.id); const game = getGame(gameId); if (!game || !user) return; // 1. Processar jogada const result = game.playCard(user.id, cardId); if (result.error) { socket.emit("game-error", { message: result.error }); return; } const roomName = `game_${gameId}`; // 2. Atualizar estado visual (Solução rápida: Forçar refresh nos clientes) // O ideal é iterar os sockets da sala e enviar 'game-state' personalizado a cada um const socketsInRoom = io.sockets.adapter.rooms.get(roomName); if (socketsInRoom) { for (const socketId of socketsInRoom) { const s = io.sockets.sockets.get(socketId); // Precisamos saber qual User ID pertence a este socket para enviar o estado certo // Assumindo que o teu getUser(socketId) funciona: const u = getUser(socketId); if (u && game.players[u.id]) { s.emit("game-state", game.getStateForPlayer(u.id)); } } } // 3. Eventos de Animação (Vaza / Fim de Jogo) if (result.action === "trick_resolved") { io.to(roomName).emit("trick-end", result.trickResult); } if (result.action === "game_ended") { io.to(roomName).emit("game-over", { winnerId: result.winnerId }); // AQUI: Salvar o resultado na BD 'GAMES' // axios.put(`${API_URL}/games/${gameId}`, { // status: 'Ended', // winner_user_id: result.winnerId, // ...pontos... // }); } }); };