// /public/js/gameSetup.js // ПРИМЕРНЫЕ РЕАЛИЗАЦИИ ВСПОМОГАТЕЛЬНЫХ ФУНКЦИЙ (лучше передавать из main.js) /* function parseJwtPayloadForValidation(token) { try { if (typeof token !== 'string') return null; const base64Url = token.split('.')[1]; if (!base64Url) return null; const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/'); const jsonPayload = decodeURIComponent(atob(base64).split('').map(function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); return JSON.parse(jsonPayload); } catch (e) { return null; } } function isTokenValid(token) { if (!token) { return false; } const decodedToken = parseJwtPayloadForValidation(token); if (!decodedToken || !decodedToken.exp) { localStorage.removeItem('jwtToken'); return false; } const currentTimeInSeconds = Math.floor(Date.now() / 1000); if (decodedToken.exp < currentTimeInSeconds) { localStorage.removeItem('jwtToken'); return false; } return true; } */ // Конец примерных реализаций export function initGameSetup(dependencies) { const { socket, clientState, ui, utils } = dependencies; // Предполагаем, что utils.isTokenValid передается const { createAIGameButton, createPvPGameButton, joinPvPGameButton, findRandomPvPGameButton, gameIdInput, availableGamesDiv, pvpCharacterRadios } = ui.elements; // Получаем функцию isTokenValid либо из utils, либо используем локальную, если она определена выше const checkTokenValidity = utils?.isTokenValid || window.isTokenValidFunction; // window.isTokenValidFunction - если вы определили ее глобально/локально if (typeof checkTokenValidity !== 'function') { console.error("[GameSetup.js] CRITICAL: isTokenValid function is not available. Auth checks will fail."); // Можно добавить фоллбэк или аварийное поведение } // --- Вспомогательные функции --- function getSelectedCharacterKey() { let selectedKey = 'elena'; // Значение по умолчанию if (pvpCharacterRadios) { pvpCharacterRadios.forEach(radio => { if (radio.checked) { selectedKey = radio.value; } }); } return selectedKey; } function updateAvailableGamesList(games) { if (!availableGamesDiv) return; availableGamesDiv.innerHTML = '

Доступные PvP игры:

'; if (games && games.length > 0) { const ul = document.createElement('ul'); games.forEach(game => { if (game && game.id) { const li = document.createElement('li'); li.textContent = `ID: ${game.id.substring(0, 8)}... - ${game.status || 'Ожидает игрока'}`; const joinBtn = document.createElement('button'); joinBtn.textContent = 'Присоединиться'; joinBtn.dataset.gameId = game.id; if (clientState.isLoggedIn && clientState.myUserId && game.ownerIdentifier === clientState.myUserId) { joinBtn.disabled = true; joinBtn.title = "Вы не можете присоединиться к своей же ожидающей игре."; } else { joinBtn.disabled = false; } joinBtn.addEventListener('click', (e) => { // --- ПРОВЕРКА ТОКЕНА ПЕРЕД ДЕЙСТВИЕМ --- if (typeof checkTokenValidity === 'function' && (!clientState.isLoggedIn || !checkTokenValidity(localStorage.getItem('jwtToken')))) { if (typeof ui.redirectToLogin === 'function') { ui.redirectToLogin('Для присоединения к игре необходимо войти или обновить сессию.'); } else { alert('Для присоединения к игре необходимо войти или обновить сессию.'); window.location.href = '/'; // Фоллбэк } return; } // --- КОНЕЦ ПРОВЕРКИ ТОКЕНА --- if (e.target.disabled) return; ui.disableSetupButtons(); socket.emit('joinGame', { gameId: e.target.dataset.gameId }); ui.setGameStatusMessage(`Присоединение к игре ${e.target.dataset.gameId.substring(0, 8)}...`); }); li.appendChild(joinBtn); ul.appendChild(li); } }); availableGamesDiv.appendChild(ul); } else { availableGamesDiv.innerHTML += '

Нет доступных игр. Создайте свою!

'; } ui.enableSetupButtons(); } // --- Обработчики событий DOM --- if (createAIGameButton) { createAIGameButton.addEventListener('click', () => { // --- ПРОВЕРКА ТОКЕНА ПЕРЕД ДЕЙСТВИЕМ --- if (typeof checkTokenValidity === 'function' && (!clientState.isLoggedIn || !checkTokenValidity(localStorage.getItem('jwtToken')))) { if (typeof ui.redirectToLogin === 'function') { ui.redirectToLogin('Для создания игры необходимо войти или обновить сессию.'); } else { alert('Для создания игры необходимо войти или обновить сессию.'); window.location.href = '/'; // Фоллбэк } return; } // --- КОНЕЦ ПРОВЕРКИ ТОКЕНА --- ui.disableSetupButtons(); socket.emit('createGame', { mode: 'ai', characterKey: 'elena' }); // Персонаж для AI может быть фиксированным ui.setGameStatusMessage("Создание игры против AI..."); }); } if (createPvPGameButton) { createPvPGameButton.addEventListener('click', () => { // --- ПРОВЕРКА ТОКЕНА ПЕРЕД ДЕЙСТВИЕМ --- if (typeof checkTokenValidity === 'function' && (!clientState.isLoggedIn || !checkTokenValidity(localStorage.getItem('jwtToken')))) { if (typeof ui.redirectToLogin === 'function') { ui.redirectToLogin('Для создания PvP игры необходимо войти или обновить сессию.'); } else { alert('Для создания PvP игры необходимо войти или обновить сессию.'); window.location.href = '/'; // Фоллбэк } return; } // --- КОНЕЦ ПРОВЕРКИ ТОКЕНА --- ui.disableSetupButtons(); const characterKey = getSelectedCharacterKey(); socket.emit('createGame', { mode: 'pvp', characterKey: characterKey }); ui.setGameStatusMessage("Создание PvP игры..."); }); } if (joinPvPGameButton) { joinPvPGameButton.addEventListener('click', () => { // --- ПРОВЕРКА ТОКЕНА ПЕРЕД ДЕЙСТВИЕМ --- if (typeof checkTokenValidity === 'function' && (!clientState.isLoggedIn || !checkTokenValidity(localStorage.getItem('jwtToken')))) { if (typeof ui.redirectToLogin === 'function') { ui.redirectToLogin('Для присоединения к игре необходимо войти или обновить сессию.'); } else { alert('Для присоединения к игре необходимо войти или обновить сессию.'); window.location.href = '/'; // Фоллбэк } return; } // --- КОНЕЦ ПРОВЕРКИ ТОКЕНА --- const gameId = gameIdInput ? gameIdInput.value.trim() : ''; if (gameId) { ui.disableSetupButtons(); socket.emit('joinGame', { gameId: gameId }); ui.setGameStatusMessage(`Присоединение к игре ${gameId}...`); } else { ui.setGameStatusMessage("Введите ID игры, чтобы присоединиться.", true); } }); } if (findRandomPvPGameButton) { findRandomPvPGameButton.addEventListener('click', () => { // --- ПРОВЕРКА ТОКЕНА ПЕРЕД ДЕЙСТВИЕМ --- if (typeof checkTokenValidity === 'function' && (!clientState.isLoggedIn || !checkTokenValidity(localStorage.getItem('jwtToken')))) { if (typeof ui.redirectToLogin === 'function') { ui.redirectToLogin('Для поиска игры необходимо войти или обновить сессию.'); } else { alert('Для поиска игры необходимо войти или обновить сессию.'); window.location.href = '/'; // Фоллбэк } return; } // --- КОНЕЦ ПРОВЕРКИ ТОКЕНА --- ui.disableSetupButtons(); const characterKey = getSelectedCharacterKey(); socket.emit('findRandomGame', { characterKey: characterKey }); ui.setGameStatusMessage("Поиск случайной PvP игры..."); }); } // --- Обработчики событий Socket.IO --- socket.on('gameCreated', (data) => { if (!clientState.isLoggedIn) return; console.log('[GameSetup] Game created by this client:', data); clientState.currentGameId = data.gameId; clientState.myPlayerId = data.yourPlayerId; ui.updateGlobalWindowVariablesForUI(); }); socket.on('availablePvPGamesList', (games) => { // Проверяем, залогинен ли пользователь, ПЕРЕД обновлением списка. // Если пользователь разлогинился, а список пришел, его не нужно показывать на экране логина. if (!clientState.isLoggedIn) { if (availableGamesDiv) availableGamesDiv.innerHTML = ''; // Очищаем, если пользователь не залогинен return; } updateAvailableGamesList(games); }); socket.on('noPendingGamesFound', (data) => { if (!clientState.isLoggedIn) return; ui.setGameStatusMessage(data.message || "Свободных игр не найдено. Создана новая для вас. Ожидание оппонента..."); updateAvailableGamesList([]); if (data.gameId) clientState.currentGameId = data.gameId; if (data.yourPlayerId) clientState.myPlayerId = data.yourPlayerId; ui.updateGlobalWindowVariablesForUI(); clientState.isInGame = false; ui.disableSetupButtons(); if (window.gameUI?.updateTurnTimerDisplay) { window.gameUI.updateTurnTimerDisplay(null, false, 'pvp'); } }); socket.on('waitingForOpponent', () => { if (!clientState.isLoggedIn) return; ui.setGameStatusMessage("Ожидание присоединения оппонента..."); ui.disableSetupButtons(); if (window.gameUI?.updateTurnTimerDisplay) { window.gameUI.updateTurnTimerDisplay(null, false, 'pvp'); } }); }