import { useEffect, useRef, useState, useCallback } from 'react' import { createGameConnection, STATE_PLACING_SHIPS, STATE_OPPONENT_READY, STATE_WAIT_OPPONENT_READY, STATE_YOUR_TURN, STATE_WAIT_OPPONENT_TURN, } from '../game' import ShipPlacementScreen from './ShipPlacementScreen' export default function GameScreen({ session, onLeave }) { const [status, setStatus] = useState('connecting') // 'connecting' | 'placing' | 'game' | 'error' const [gameState, setGameState] = useState(STATE_PLACING_SHIPS) const [isSubmitting, setIsSubmitting] = useState(false) const [opponentReady, setOpponentReady] = useState(false) const [error, setError] = useState(null) const connectionRef = useRef(null) const attemptRef = useRef(0) useEffect(() => { const attempt = ++attemptRef.current let cancelled = false const connInstance = createGameConnection(session) connInstance.promise .then((conn) => { if (cancelled || attempt !== attemptRef.current) return connectionRef.current = conn conn.onState = (newState) => { if (cancelled || attempt !== attemptRef.current) return if (newState === STATE_OPPONENT_READY) { setOpponentReady(true) } else if ( newState === STATE_WAIT_OPPONENT_READY || newState === STATE_YOUR_TURN || newState === STATE_WAIT_OPPONENT_TURN ) { setIsSubmitting(false) setGameState(newState) setStatus('game') } } conn.onEnd = (_code, reason) => { if (cancelled || attempt !== attemptRef.current) return setIsSubmitting(false) setError(reason || 'Партия завершена') setStatus('error') } conn.onClose = () => { if (cancelled || attempt !== attemptRef.current) return setIsSubmitting(false) setStatus((prev) => { if (prev !== 'error') { setError('Соединение с сервером прервано') return 'error' } return prev }) } setStatus('placing') }) .catch((err) => { if (cancelled || attempt !== attemptRef.current) return setError(err.message || 'Не удалось подключиться к игре') setStatus('error') }) return () => { cancelled = true connInstance.cancel() } }, [session]) const handleReady = useCallback((ships) => { if (!connectionRef.current) return setIsSubmitting(true) connectionRef.current.placeShips(ships) }, []) // Текст заглушки в зависимости от состояния игры const getGameStubText = () => { switch (gameState) { case STATE_WAIT_OPPONENT_READY: return 'Соперник расставляет корабли...' case STATE_YOUR_TURN: return 'Ваш ход' case STATE_WAIT_OPPONENT_TURN: return 'Соперник ходит' default: return '' } } return (