256 lines
12 KiB
JavaScript
256 lines
12 KiB
JavaScript
// /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 = '<h3>Доступные PvP игры:</h3>';
|
||
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 += '<p>Нет доступных игр. Создайте свою!</p>';
|
||
}
|
||
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');
|
||
}
|
||
});
|
||
} |