fix
This commit is contained in:
parent
06e95fb432
commit
5390d5d675
4 changed files with 41 additions and 22 deletions
|
|
@ -105,6 +105,11 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect, On
|
|||
console.log(`🔌 Client ${client.id} joining WebSocket room ${payload.roomCode}, userId: ${payload.userId}`);
|
||||
client.join(payload.roomCode);
|
||||
|
||||
// Логируем всех клиентов в комнате
|
||||
const roomClients = this.server.sockets.adapter.rooms.get(payload.roomCode);
|
||||
console.log(`👥 Clients in room ${payload.roomCode}: ${roomClients?.size || 0}`,
|
||||
Array.from(roomClients || []));
|
||||
|
||||
// Получаем полное состояние для отправки присоединившемуся клиенту
|
||||
const room = (await this.prisma.room.findUnique({
|
||||
where: { code: payload.roomCode },
|
||||
|
|
@ -574,7 +579,9 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect, On
|
|||
})
|
||||
};
|
||||
|
||||
const roomClients = this.server.sockets.adapter.rooms.get(roomCode);
|
||||
console.log(`📡 Broadcasting gameStateUpdated to room ${roomCode} with ${room.participants.length} participants`);
|
||||
console.log(`📡 Target clients: ${roomClients?.size || 0}`, Array.from(roomClients || []));
|
||||
this.server.to(roomCode).emit('gameStateUpdated', fullState);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -153,10 +153,6 @@ export class RoomsService {
|
|||
|
||||
// Отправляем событие roomUpdate всем клиентам в комнате
|
||||
if (updatedRoom) {
|
||||
// Небольшая задержка, чтобы дать время новому игроку присоединиться к WebSocket комнате
|
||||
// WebSocket joinRoom может выполняться параллельно с REST API joinRoom
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
|
||||
console.log(`📤 Broadcasting room update for ${updatedRoom.code} with ${updatedRoom.participants.length} participants`);
|
||||
this.roomEventsService.emitRoomUpdate(updatedRoom.code, updatedRoom);
|
||||
// Также отправляем gameStateUpdated через broadcastFullState
|
||||
|
|
@ -248,9 +244,6 @@ export class RoomsService {
|
|||
|
||||
// Отправляем событие roomUpdate всем клиентам в комнате
|
||||
if (updatedRoom) {
|
||||
// Небольшая задержка, чтобы дать время новому игроку присоединиться к WebSocket комнате
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
|
||||
this.roomEventsService.emitRoomUpdate(updatedRoom.code, updatedRoom);
|
||||
// Также отправляем gameStateUpdated через broadcastFullState
|
||||
await this.gameGateway.broadcastFullState(updatedRoom.code);
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ export const useRoom = (roomCode, onGameStarted = null, password = null) => {
|
|||
const [participants, setParticipants] = useState([]);
|
||||
const [requiresPassword, setRequiresPassword] = useState(false);
|
||||
|
||||
// Используем ref для onGameStarted, чтобы не пересоздавать обработчики при его изменении
|
||||
const onGameStartedRef = useRef(onGameStarted);
|
||||
useEffect(() => {
|
||||
onGameStartedRef.current = onGameStarted;
|
||||
}, [onGameStarted]);
|
||||
|
||||
// Обработчики событий вынесены наружу useEffect, чтобы они регистрировались только один раз
|
||||
// и не зависели от изменений зависимостей
|
||||
const handleRoomUpdate = useCallback((updatedRoom) => {
|
||||
|
|
@ -22,11 +28,11 @@ export const useRoom = (roomCode, onGameStarted = null, password = null) => {
|
|||
const handleGameStarted = useCallback((updatedRoom) => {
|
||||
console.log('🎮 gameStarted received');
|
||||
setRoom(updatedRoom);
|
||||
// Вызываем callback для навигации на страницу игры
|
||||
if (onGameStarted) {
|
||||
onGameStarted(updatedRoom);
|
||||
// Вызываем callback через ref
|
||||
if (onGameStartedRef.current) {
|
||||
onGameStartedRef.current(updatedRoom);
|
||||
}
|
||||
}, [onGameStarted]);
|
||||
}, []); // Теперь НЕТ зависимости от onGameStarted!
|
||||
|
||||
const handleGameStateUpdated = useCallback((state) => {
|
||||
console.log('🔄 gameStateUpdated received:', state.participants?.length, 'participants');
|
||||
|
|
@ -57,11 +63,11 @@ export const useRoom = (roomCode, onGameStarted = null, password = null) => {
|
|||
return updatedRoom;
|
||||
});
|
||||
|
||||
// Если игра началась, вызываем callback
|
||||
if (state.status === 'PLAYING' && onGameStarted) {
|
||||
onGameStarted(state);
|
||||
// Если игра началась, вызываем callback через ref
|
||||
if (state.status === 'PLAYING' && onGameStartedRef.current) {
|
||||
onGameStartedRef.current(state);
|
||||
}
|
||||
}, [onGameStarted]);
|
||||
}, []); // Теперь НЕТ зависимости от onGameStarted!
|
||||
|
||||
const handleRoomPackUpdated = useCallback((updatedRoom) => {
|
||||
setRoom(updatedRoom);
|
||||
|
|
@ -140,7 +146,7 @@ export const useRoom = (roomCode, onGameStarted = null, password = null) => {
|
|||
socketService.off('gameStateUpdated', handleGameStateUpdated);
|
||||
socketService.off('roomPackUpdated', handleRoomPackUpdated);
|
||||
};
|
||||
}, [roomCode, password, user?.id, authLoading, handleRoomUpdate, handleGameStarted, handleGameStateUpdated, handleRoomPackUpdated]);
|
||||
}, [roomCode, password, user?.id, authLoading]); // Убрали обработчики из зависимостей!
|
||||
|
||||
const createRoom = useCallback(async (hostId, questionPackId, settings = {}, hostName) => {
|
||||
try {
|
||||
|
|
@ -155,16 +161,24 @@ export const useRoom = (roomCode, onGameStarted = null, password = null) => {
|
|||
|
||||
const joinRoom = useCallback(async (roomId, userId, name, role = 'PLAYER') => {
|
||||
try {
|
||||
// ВАЖНО: Сначала подключаемся к WebSocket комнате
|
||||
// Это гарантирует, что мы получим broadcast от backend после создания участника
|
||||
if (roomCode) {
|
||||
socketService.connect();
|
||||
socketService.joinRoom(roomCode, userId);
|
||||
// Даем время на установку WebSocket соединения
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
// Теперь вызываем REST API для создания участника
|
||||
const response = await roomsApi.join(roomId, userId, name, role);
|
||||
|
||||
// После успешного присоединения запрашиваем полное состояние через WebSocket
|
||||
// Это гарантирует получение актуального состояния от сервера (список игроков, тема, voiceMode)
|
||||
// НЕ обновляем состояние локально - полагаемся только на серверные обновления для консистентности
|
||||
// (дополнительная гарантия получения актуального состояния)
|
||||
if (roomCode) {
|
||||
// Небольшая задержка, чтобы убедиться, что WebSocket подключен
|
||||
setTimeout(() => {
|
||||
socketService.emit('requestFullState', { roomCode });
|
||||
}, 100);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
return response.data;
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ import GameManagementModal from '../components/GameManagementModal';
|
|||
const RoomPage = () => {
|
||||
const { roomCode } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const { user } = useAuth();
|
||||
const { user, loading: authLoading } = useAuth();
|
||||
const { changeTheme } = useTheme();
|
||||
|
||||
// Храним предыдущий themeId комнаты для отслеживания изменений
|
||||
|
|
@ -107,6 +107,11 @@ const RoomPage = () => {
|
|||
// Единая логика присоединения к комнате
|
||||
useEffect(() => {
|
||||
const handleJoin = async () => {
|
||||
// Ждем загрузки пользователя из куки
|
||||
if (authLoading) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Перенаправляем на главный экран, если нет пользователя
|
||||
if (!user) {
|
||||
alert('Пожалуйста, задайте имя на главном экране');
|
||||
|
|
@ -156,7 +161,7 @@ const RoomPage = () => {
|
|||
};
|
||||
|
||||
handleJoin();
|
||||
}, [room, user, joined, participants, joinRoom, navigate, isRoleSelectionModalOpen]);
|
||||
}, [room, user, joined, participants, joinRoom, navigate, isRoleSelectionModalOpen, authLoading]);
|
||||
|
||||
// Обработка выбора роли
|
||||
// Присоединение разрешено независимо от статуса игры (WAITING, PLAYING, FINISHED)
|
||||
|
|
|
|||
Loading…
Reference in a new issue