From 8f95413782b5614dfa18a2cc6d43447d6eeddcfe Mon Sep 17 00:00:00 2001 From: Resistencia Dev Date: Sat, 6 Dec 2025 00:32:09 +0100 Subject: [PATCH] Checkpoint: Fix role shuffling bug and improve mission reveal flow --- client/src/components/GameBoard.tsx | 27 +++++++++++++ client/src/components/MissionReveal.tsx | 51 ++++++++++++++++--------- server/src/index.ts | 16 ++++---- 3 files changed, 70 insertions(+), 24 deletions(-) diff --git a/client/src/components/GameBoard.tsx b/client/src/components/GameBoard.tsx index d07f264..4e1f0fb 100644 --- a/client/src/components/GameBoard.tsx +++ b/client/src/components/GameBoard.tsx @@ -63,6 +63,26 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB actions.voteMission(vote); }; + // Componente de Debug para mostrar facción + const DebugInfo = () => ( +
+
+ 🐛 DEBUG INFO +
+
+
Fase: {gameState.phase}
+
ID: {currentPlayerId}
+
Facción: + {currentPlayer?.faction || 'UNDEFINED'} +
+
Rol: {currentPlayer?.role || 'UNDEFINED'}
+ {gameState.currentLeaderId && ( +
Líder: {gameState.currentLeaderId === currentPlayerId ? 'TÚ' : gameState.currentLeaderId}
+ )} +
+
+ ); + // Coordenadas porcentuales de los hexágonos de misión en el mapa const missionCoords = [ @@ -208,6 +228,9 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB if (gameState.phase === 'roll_call' as any) { return (
+ {/* Debug Info */} + +
Resistance HQ
@@ -260,6 +283,9 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB return (
+ {/* Debug Info */} + +
Game Background
@@ -599,6 +625,7 @@ export default function GameBoard({ gameState, currentPlayerId, actions }: GameB {gameState.phase === 'mission_reveal' as any && ( actions.finishMissionReveal()} /> )} diff --git a/client/src/components/MissionReveal.tsx b/client/src/components/MissionReveal.tsx index 257f50b..ef0bb48 100644 --- a/client/src/components/MissionReveal.tsx +++ b/client/src/components/MissionReveal.tsx @@ -3,42 +3,59 @@ import { useEffect } from 'react'; interface MissionRevealProps { votes: boolean[]; + onFinished?: () => void; } -export default function MissionReveal({ votes }: MissionRevealProps) { - // Auto-avanzar después de mostrar todas las cartas +export default function MissionReveal({ votes, onFinished }: MissionRevealProps) { + // Timer de seguridad: 10 segundos y avanza useEffect(() => { const timer = setTimeout(() => { - // El servidor avanzará automáticamente - // Este timer es solo para dar tiempo a ver las cartas - }, 3000 + votes.length * 300); // 3s base + 300ms por carta - + if (onFinished) onFinished(); + }, 10000); + return () => clearTimeout(timer); - }, [votes.length]); + }, [onFinished]); return ( -

Resultados de la Misión

-
+

+ Resultado de Misión +

+ +
{votes.map((vote, idx) => ( {vote ? '✓' : '✗'} ))}
-

Procesando resultado...

+ + + Analizando resultado estratégico... + ); } diff --git a/server/src/index.ts b/server/src/index.ts index 4bde9ca..5d364d6 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -149,18 +149,18 @@ io.on('connection', (socket) => { } }); - // 2.3 FINALIZAR ROLL CALL -> PRIMER TURNO DE JUEGO (TEAM_BUILDING) + // 2.3 FINALIZAR ROLL CALL -> PRIMER TURNO DE JUEGO socket.on('finish_roll_call', ({ roomId }) => { const game = games[roomId]; if (game && game.hostId === socket.id && game.state.phase === 'roll_call') { - // Ir a VOTE_LEADER (ya que startGame lo inicializa a VOTE_LEADER en el modelo, y nextLeader tambien) - // Solo debemos asegurarnos que el GameState se sincronice. - if (game.startGame()) { - io.to(roomId).emit('game_state', game.state); - } + // ERROR CORREGIDO: No llamar a startGame() de nuevo porque re-baraja los roles. + // Simplemente avanzamos a la fase de votación de líder que ya estaba configurada. + game.state.phase = 'vote_leader' as any; + io.to(roomId).emit('game_state', game.state); } }); + // 2.4 VOTAR LÍDER socket.on('vote_leader', ({ roomId, approve }) => { const game = games[roomId]; @@ -200,12 +200,14 @@ io.on('connection', (socket) => { // 5.1 FINALIZAR REVELACIÓN DE CARTAS socket.on('finish_reveal', ({ roomId }) => { const game = games[roomId]; - if (game && game.hostId === socket.id && game.state.phase === 'mission_reveal') { + // Permitir a cualquiera avanzar para evitar bloqueos + if (game && game.state.phase === 'mission_reveal') { game.finishReveal(); io.to(roomId).emit('game_state', game.state); } }); + // 5.2 FINALIZAR PANTALLA DE RESULTADO socket.on('finish_mission_result', ({ roomId }) => { const game = games[roomId];