/** * Live Main Menu System * Handles server authentication, server browser, and multiplayer game initialization */ console.log('[LIVE MAIN MENU] LiveMainMenu.js script loaded'); class LiveMainMenu { constructor() { console.log('[LIVE MAIN MENU] Constructor called'); // Check if DOM is ready if (document.readyState === 'loading') { console.warn('[LIVE MAIN MENU] DOM not ready yet, elements may not be found'); } else { console.log('[LIVE MAIN MENU] DOM is ready'); } this.mainMenu = document.getElementById('mainMenu'); console.log('[LIVE MAIN MENU] Main menu element found:', !!this.mainMenu); this.selectedServer = null; this.authToken = null; this.currentUser = null; this.servers = []; // Renamed from serverList to avoid conflict with DOM element this.apiBaseUrl = 'https://api.korvarix.com/api'; // API Server URL this.gameServerUrl = 'https://api.korvarix.com'; // Game Server URL for Socket.IO this.isLocalMode = false; // Track if we're in local mode console.log('[LIVE MAIN MENU] Initializing elements'); this.initializeElements(); console.log('[LIVE MAIN MENU] Initializing event listeners'); this.bindEvents(); // Check for existing auth token this.checkExistingAuth(); // Check for local server and update URLs if needed this.checkForLocalServer(); console.log('[LIVE MAIN MENU] Constructor completed'); } initializeElements() { // Menu sections this.loginSection = document.getElementById('loginSection'); this.serverSection = document.getElementById('serverSection'); this.serverConfirmSection = document.getElementById('serverConfirmSection'); this.optionsSection = document.getElementById('optionsSection'); // Login form elements this.emailInput = document.getElementById('emailInput'); this.passwordInput = document.getElementById('passwordInput'); this.loginBtn = document.getElementById('loginBtn'); this.registerBtn = document.getElementById('registerBtn'); this.loginNotice = document.getElementById('loginNotice'); // Server browser elements this.createServerBtn = document.getElementById('createServerBtn'); this.refreshServersBtn = document.getElementById('refreshServersBtn'); this.regionFilter = document.getElementById('regionFilter'); this.typeFilter = document.getElementById('typeFilter'); this.serverList = document.getElementById('serverList'); this.serverLoading = document.getElementById('serverLoading'); this.serverEmpty = document.getElementById('serverEmpty'); // Server confirmation elements this.joinServerBtn = document.getElementById('joinServerBtn'); this.serverInfoBtn = document.getElementById('serverInfoBtn'); this.leaveServerBtn = document.getElementById('leaveServerBtn'); // Server detail elements this.selectedServerName = document.getElementById('selectedServerName'); this.selectedServerType = document.getElementById('selectedServerType'); this.selectedServerRegion = document.getElementById('selectedServerRegion'); this.selectedServerPlayers = document.getElementById('selectedServerPlayers'); this.selectedServerOwner = document.getElementById('selectedServerOwner'); // Navigation buttons this.backToLoginBtn = document.getElementById('backToLoginBtn'); this.backToServersBtn = document.getElementById('backToServersBtn'); console.log('[LIVE MAIN MENU] All elements initialized'); } bindEvents() { console.log('[LIVE MAIN MENU] Binding events...'); // Login events if (this.loginBtn) { this.loginBtn.addEventListener('click', () => this.handleLogin()); console.log('[LIVE MAIN MENU] Login button event bound'); } else { console.warn('[LIVE MAIN MENU] Login button not found'); } if (this.registerBtn) { this.registerBtn.addEventListener('click', () => this.handleRegister()); console.log('[LIVE MAIN MENU] Register button event bound'); } else { console.warn('[LIVE MAIN MENU] Register button not found'); } // Enter key login if (this.passwordInput) { this.passwordInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') this.handleLogin(); }); console.log('[LIVE MAIN MENU] Password input event bound'); } else { console.warn('[LIVE MAIN MENU] Password input not found'); } // Server browser events if (this.createServerBtn) { this.createServerBtn.addEventListener('click', () => this.startLocalServer()); console.log('[LIVE MAIN MENU] Create server button event bound (now starts local server)'); } else { console.warn('[LIVE MAIN MENU] Create server button not found'); } if (this.refreshServersBtn) { this.refreshServersBtn.addEventListener('click', () => this.refreshServerListWithoutAnimation()); console.log('[LIVE MAIN MENU] Refresh servers button event bound'); } else { console.warn('[LIVE MAIN MENU] Refresh servers button not found'); } if (this.regionFilter) { this.regionFilter.addEventListener('change', () => this.filterServers()); console.log('[LIVE MAIN MENU] Region filter event bound'); } else { console.warn('[LIVE MAIN MENU] Region filter not found'); } if (this.typeFilter) { this.typeFilter.addEventListener('change', () => this.filterServers()); console.log('[LIVE MAIN MENU] Type filter event bound'); } else { console.warn('[LIVE MAIN MENU] Type filter not found'); } // Server confirmation events if (this.joinServerBtn) { this.joinServerBtn.addEventListener('click', () => this.joinServer()); console.log('[LIVE MAIN MENU] Join server button event bound'); } else { console.warn('[LIVE MAIN MENU] Join server not found'); } // Navigation events if (this.backToLoginBtn) { this.backToLoginBtn.addEventListener('click', () => this.showLoginSection()); console.log('[LIVE MAIN MENU] Back to login button event bound'); } else { console.warn('[LIVE MAIN MENU] Back to login button not found'); } if (this.backToServersBtn) { this.backToServersBtn.addEventListener('click', () => this.showServerSection()); console.log('[LIVE MAIN MENU] Back to servers button event bound'); } else { console.warn('[LIVE MAIN MENU] Back to servers button not found'); } console.log('[LIVE MAIN MENU] All events bound (with warnings for missing elements)'); } checkExistingAuth() { const token = localStorage.getItem('authToken'); const user = localStorage.getItem('currentUser'); if (token && user) { this.authToken = token; this.currentUser = JSON.parse(user); console.log('[LIVE MAIN MENU] Found existing auth token, validating...'); this.validateToken(); } else { console.log('[LIVE MAIN MENU] No existing auth found'); this.showLoginSection(); } } async validateToken() { try { const response = await fetch(`${this.apiBaseUrl}/auth/verify`, { method: 'GET', headers: { 'Authorization': `Bearer ${this.authToken}`, 'Content-Type': 'application/json' } }); if (response.ok) { const data = await response.json(); this.currentUser = data.user; localStorage.setItem('currentUser', JSON.stringify(this.currentUser)); console.log('[LIVE MAIN MENU] Token validated successfully'); this.showServerSection(); } else { console.log('[LIVE MAIN MENU] Token invalid, clearing auth'); this.clearAuth(); this.showLoginSection(); } } catch (error) { console.error('[LIVE MAIN MENU] Token validation failed:', error); this.clearAuth(); this.showLoginSection(); } } clearAuth() { this.authToken = null; this.currentUser = null; localStorage.removeItem('authToken'); localStorage.removeItem('currentUser'); } showSection(sectionName, animate = true) { // Don't re-animate if we're showing the same section if (this.currentSection === sectionName) { animate = false; } // Hide all sections this.loginSection?.classList.add('hidden'); this.serverSection?.classList.add('hidden'); this.serverConfirmSection?.classList.add('hidden'); this.optionsSection?.classList.add('hidden'); // Show selected section const section = document.getElementById(`${sectionName}Section`); if (section) { section.classList.remove('hidden'); // Control animation if (animate) { section.style.animation = 'fadeInUp 0.5s ease-out'; } else { section.style.animation = 'none'; } this.currentSection = sectionName; } } showLoginSection() { this.showSection('login'); this.clearLoginForm(); } showServerSection(refreshServers = true, animate = true) { this.showSection('server', animate); if (refreshServers) { this.refreshServerList(); } } showServerConfirmSection() { this.showSection('serverConfirm'); this.updateServerConfirmSection(); } clearLoginForm() { if (this.emailInput) this.emailInput.value = ''; if (this.passwordInput) this.passwordInput.value = ''; this.clearLoginNotice(); } clearLoginNotice() { if (this.loginNotice) { this.loginNotice.innerHTML = `

Connect to the live server to play

Note: You need an internet connection to play Galaxy Strike Online.

`; } } showLoginNotice(message, type = 'info') { if (this.loginNotice) { const iconClass = type === 'error' ? 'fa-exclamation-triangle' : type === 'success' ? 'fa-check-circle' : 'fa-info-circle'; this.loginNotice.innerHTML = `

${message}

`; this.loginNotice.className = `login-notice ${type}`; this.loginNotice.style.display = 'block'; } } hideLoginNotice() { if (this.loginNotice) { this.loginNotice.style.display = 'none'; } } async handleLogin() { const email = this.emailInput?.value?.trim(); const password = this.passwordInput?.value?.trim(); if (!email || !password) { this.showLoginNotice('Please enter email and password', 'error'); return; } // Disable login button if (this.loginBtn) { this.loginBtn.disabled = true; this.loginBtn.innerHTML = ' Logging in...'; } try { const response = await fetch(`${this.apiBaseUrl}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password }) }); // Check if response is HTML (error page) instead of JSON const contentType = response.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) { throw new Error('API server is not available. Please check your connection.'); } const data = await response.json(); if (response.ok) { this.authToken = data.token; this.currentUser = data.user; // Save to localStorage localStorage.setItem('authToken', this.authToken); localStorage.setItem('currentUser', JSON.stringify(this.currentUser)); this.showLoginNotice('Login successful!', 'success'); console.log('[LIVE MAIN MENU] Login successful'); // Show server browser after a short delay setTimeout(() => this.showServerSection(), 1000); } else { this.showLoginNotice(data.error || 'Login failed', 'error'); } } catch (error) { console.error('[LIVE MAIN MENU] Login error:', error); this.showLoginNotice('Connection error. Please try again.', 'error'); } finally { // Re-enable login button if (this.loginBtn) { this.loginBtn.disabled = false; this.loginBtn.innerHTML = ' Login'; } } } async handleRegister() { const email = this.emailInput?.value?.trim(); const password = this.passwordInput?.value?.trim(); if (!email || !password) { this.showLoginNotice('Please enter email and password', 'error'); return; } if (password.length < 6) { this.showLoginNotice('Password must be at least 6 characters', 'error'); return; } // Disable register button if (this.registerBtn) { this.registerBtn.disabled = true; this.registerBtn.innerHTML = ' Registering...'; } try { // Generate a username from email const username = email.split('@')[0]; const response = await fetch(`${this.apiBaseUrl}/auth/register`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, email, password }) }); // Check if response is HTML (error page) instead of JSON const contentType = response.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) { throw new Error('API server is not available. Please check your connection.'); } const data = await response.json(); if (response.ok) { this.authToken = data.token; this.currentUser = data.user; // Save to localStorage localStorage.setItem('authToken', this.authToken); localStorage.setItem('currentUser', JSON.stringify(this.currentUser)); this.showLoginNotice('Registration successful!', 'success'); console.log('[LIVE MAIN MENU] Registration successful'); // Show server browser after a short delay setTimeout(() => this.showServerSection(), 1000); } else { this.showLoginNotice(data.error || 'Registration failed', 'error'); } } catch (error) { console.error('[LIVE MAIN MENU] Registration error:', error); this.showLoginNotice('Connection error. Please try again.', 'error'); } finally { // Re-enable register button if (this.registerBtn) { this.registerBtn.disabled = false; this.registerBtn.innerHTML = ' Register'; } } } async refreshServerListWithoutAnimation() { // Ensure we're in server section without animation if (this.currentSection !== 'server') { this.showServerSection(true, false); // Refresh but don't animate } else { // Already in server section, just refresh await this.refreshServerList(); } } async refreshServerList() { if (!this.authToken) { console.error('[LIVE MAIN MENU] No auth token for server list'); return; } // Show loading state if (this.serverLoading) this.serverLoading.classList.remove('hidden'); if (this.serverEmpty) this.serverEmpty.classList.add('hidden'); try { let response; // Use SimpleLocalServer mock API if in local mode if (this.isLocalMode && window.localServerManager && window.localServerManager.localServer && window.localServerManager.localServer.mockRequest) { console.log('[LIVE MAIN MENU] Using SimpleLocalServer mock API for server list'); response = await window.localServerManager.localServer.mockRequest('GET', '/api/servers'); } else { console.log('[LIVE MAIN MENU] Fetching server list from:', `${this.apiBaseUrl}/servers`); response = await fetch(`${this.apiBaseUrl}/servers`, { method: 'GET', headers: { 'Authorization': `Bearer ${this.authToken}`, 'Content-Type': 'application/json' } }); } console.log('[LIVE MAIN MENU] Server list response status:', response.status); // Check if response is HTML (error page) instead of JSON const contentType = response.headers ? response.headers.get('content-type') : 'application/json'; if (!contentType || !contentType.includes('application/json')) { throw new Error('API server is not available. Please check your connection.'); } if (response.ok) { const data = await response.json(); this.servers = data.servers || []; console.log('[LIVE MAIN MENU] Server list loaded:', this.servers); this.renderServerList(); } else { const errorText = await response.text(); console.error('[LIVE MAIN MENU] Failed to load server list - Status:', response.status, 'Error:', errorText); this.servers = []; this.renderServerList(); // Show error message to user this.showLoginNotice(`Failed to connect to server: ${response.status}`, 'error'); } } catch (error) { console.error('[LIVE MAIN MENU] Server list error:', error); this.servers = []; this.renderServerList(); // Show error message to user this.showLoginNotice(`Network error: ${error.message}`, 'error'); } finally { // Hide loading state if (this.serverLoading) this.serverLoading.classList.add('hidden'); } } renderServerList() { if (!this.servers) return; const filteredServers = this.getFilteredServers(); // Handle empty state if (filteredServers.length === 0) { if (this.serverEmpty) this.serverEmpty.classList.remove('hidden'); // Remove existing server items smoothly this.removeServerItemsSmoothly(); return; } else { if (this.serverEmpty) this.serverEmpty.classList.add('hidden'); } // Get current server items const currentItems = this.serverList?.querySelectorAll('.server-item') || []; // Create new server items HTML const serverListHtml = filteredServers.map(server => this.createServerItem(server)).join(''); // Create a temporary container to hold new items const tempDiv = document.createElement('div'); tempDiv.innerHTML = serverListHtml; const newItems = Array.from(tempDiv.querySelectorAll('.server-item')); // Smooth update: fade out current items, then replace with new ones this.updateServerItemsSmoothly(currentItems, newItems); } removeServerItemsSmoothly() { const existingItems = this.serverList?.querySelectorAll('.server-item') || []; if (existingItems.length === 0) return; // Add fade-out transition existingItems.forEach(item => { item.style.transition = 'opacity 0.2s ease-out'; item.style.opacity = '0'; }); // Remove items after fade out setTimeout(() => { existingItems.forEach(item => item.remove()); }, 200); } updateServerItemsSmoothly(currentItems, newItems) { // Fade out current items if (currentItems.length > 0) { currentItems.forEach(item => { item.style.transition = 'opacity 0.2s ease-out'; item.style.opacity = '0'; }); // Replace with new items after fade out setTimeout(() => { currentItems.forEach(item => item.remove()); this.addNewServerItems(newItems); }, 200); } else { // No current items, add new ones immediately this.addNewServerItems(newItems); } } addNewServerItems(newItems) { if (!this.serverList) return; // Add fade-in transition to new items newItems.forEach(item => { item.style.transition = 'opacity 0.3s ease-in'; item.style.opacity = '0'; }); // Add new items to DOM newItems.forEach(item => { this.serverList.appendChild(item); }); // Add click handlers newItems.forEach(item => { item.addEventListener('click', () => { const serverId = item.dataset.serverId; this.selectServer(serverId); }); }); // Fade in new items setTimeout(() => { newItems.forEach(item => { item.style.opacity = '1'; }); }, 50); } createServerItem(server) { const playerCount = `${server.currentPlayers}/${server.maxPlayers}`; const createdDate = new Date(server.createdAt).toLocaleDateString(); return `
${server.name}
${server.region || 'Unknown'} ${createdDate}
${server.type} ${playerCount}
`; } getFilteredServers() { let filtered = [...this.servers]; const regionFilter = this.regionFilter?.value; const typeFilter = this.typeFilter?.value; if (regionFilter) { filtered = filtered.filter(server => server.region === regionFilter); } if (typeFilter) { filtered = filtered.filter(server => server.type === typeFilter); } return filtered; } filterServers() { this.renderServerList(); } selectServer(serverId) { this.selectedServer = this.servers.find(server => server.id === serverId); if (this.selectedServer) { console.log('[LIVE MAIN MENU] Server selected:', this.selectedServer); this.showServerConfirmSection(); } } updateServerConfirmSection() { if (!this.selectedServer) return; // Update server details if (this.selectedServerName) this.selectedServerName.textContent = this.selectedServer.name; if (this.selectedServerType) this.selectedServerType.textContent = this.selectedServer.type; if (this.selectedServerRegion) this.selectedServerRegion.textContent = this.selectedServer.region || 'Unknown'; if (this.selectedServerPlayers) this.selectedServerPlayers.textContent = `${this.selectedServer.currentPlayers}/${this.selectedServer.maxPlayers}`; if (this.selectedServerOwner) this.selectedServerOwner.textContent = this.selectedServer.ownerName || 'Unknown'; } async joinServer() { if (!this.selectedServer || !this.authToken) { console.error('[LIVE MAIN MENU] No server selected or not authenticated'); return; } // Disable join button if (this.joinServerBtn) { this.joinServerBtn.disabled = true; this.joinServerBtn.innerHTML = ' Joining...'; } try { let response; // Use SimpleLocalServer mock API if in local mode if (this.isLocalMode && window.localServerManager && window.localServerManager.localServer && window.localServerManager.localServer.mockRequest) { console.log('[LIVE MAIN MENU] Using SimpleLocalServer mock API for join server'); response = await window.localServerManager.localServer.mockRequest('POST', `/servers/${this.selectedServer.id}/join`, { userId: this.currentUser.id, token: this.authToken }); } else { console.log('[LIVE MAIN MENU] Using real fetch for join server'); response = await fetch(`${this.apiBaseUrl}/servers/${this.selectedServer.id}/join`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.authToken}`, 'Content-Type': 'application/json' } }); } // Check if response is HTML (error page) instead of JSON const contentType = response.headers ? response.headers.get('content-type') : 'application/json'; if (!contentType || !contentType.includes('application/json')) { throw new Error('API server is not available. Please check your connection.'); } const data = await response.json(); if (response.ok) { console.log('[LIVE MAIN MENU] Joined server successfully'); // Apply existing save data if in local mode if (this.isLocalMode && window.localServerManager && window.localServerManager.localServer) { console.log('[LIVE MAIN MENU] Applying existing save data for local mode...'); // Store save data for later application (after GameEngine is created) this.pendingSaveData = window.localServerManager.localServer.existingSaveData; if (this.pendingSaveData) { console.log('[LIVE MAIN MENU] Save data stored for later application'); } else { console.log('[LIVE MAIN MENU] No save data to store'); } } this.launchMultiplayerGame(this.selectedServer, data.server); } else { console.error('[LIVE MAIN MENU] Failed to join server:', data.error); alert(data.error || 'Failed to join server'); } } catch (error) { console.error('[LIVE MAIN MENU] Join server error:', error); alert('Connection error. Please try again.'); } finally { // Re-enable join button if (this.joinServerBtn) { this.joinServerBtn.disabled = false; this.joinServerBtn.innerHTML = ' Join Server'; } } } showServerInfo() { if (!this.selectedServer) return; const info = ` Server Information: Name: ${this.selectedServer.name} Type: ${this.selectedServer.type} Region: ${this.selectedServer.region} Players: ${this.selectedServer.currentPlayers}/${this.selectedServer.maxPlayers} Owner: ${this.selectedServer.ownerName} Created: ${new Date(this.selectedServer.createdAt).toLocaleString()} Status: ${this.selectedServer.status} `.trim(); alert(info); } leaveServer() { this.selectedServer = null; this.showServerSection(); } showCreateServerDialog() { return new Promise((resolve) => { // Create modal dialog const modal = document.createElement('div'); modal.className = 'modal-overlay'; modal.innerHTML = ` `; // Add styles for modal const style = document.createElement('style'); style.textContent = ` .modal-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0, 0, 0, 0.8); display: flex; justify-content: center; align-items: center; z-index: 10000; } .modal-dialog { background: var(--bg-primary); border: 1px solid var(--border-color); border-radius: 8px; padding: 20px; min-width: 400px; max-width: 500px; } .modal-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px; } .modal-header h3 { margin: 0; color: var(--text-primary); } .modal-close { background: none; border: none; color: var(--text-secondary); font-size: 24px; cursor: pointer; } .form-group { margin-bottom: 15px; } .form-group label { display: block; margin-bottom: 5px; color: var(--text-primary); } .form-group input, .form-group select { width: 100%; padding: 8px; background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 4px; color: var(--text-primary); } .modal-footer { display: flex; justify-content: flex-end; gap: 10px; margin-top: 20px; } .btn { padding: 8px 16px; border: none; border-radius: 4px; cursor: pointer; } .btn-primary { background: var(--primary-color); color: white; } .btn-secondary { background: var(--bg-secondary); color: var(--text-primary); border: 1px solid var(--border-color); } `; document.head.appendChild(style); // Add modal to page document.body.appendChild(modal); // Get elements const closeBtn = modal.querySelector('.modal-close'); const cancelBtn = modal.querySelector('#cancelBtn'); const createBtn = modal.querySelector('#createBtn'); const nameInput = modal.querySelector('#serverName'); // Event handlers const closeModal = () => { document.body.removeChild(modal); document.head.removeChild(style); resolve(null); }; const handleCreate = () => { const name = nameInput.value.trim(); const type = modal.querySelector('#serverType').value; const region = modal.querySelector('#serverRegion').value; const maxPlayers = parseInt(modal.querySelector('#maxPlayers').value); if (!name) { nameInput.focus(); return; } if (maxPlayers < 1 || maxPlayers > 20) { modal.querySelector('#maxPlayers').focus(); return; } document.body.removeChild(modal); document.head.removeChild(style); resolve({ name, type, region, maxPlayers }); }; closeBtn.addEventListener('click', closeModal); cancelBtn.addEventListener('click', closeModal); createBtn.addEventListener('click', handleCreate); // Handle Enter key in name input nameInput.addEventListener('keypress', (e) => { if (e.key === 'Enter') { handleCreate(); } }); // Focus on name input nameInput.focus(); }); } async handleCreateServer() { try { // Get server details from user using custom dialog const serverDetails = await this.showCreateServerDialog(); if (!serverDetails) { return; // User cancelled } const { name, type, maxPlayers, region } = serverDetails; // Show loading state if (this.serverLoading) this.serverLoading.classList.remove('hidden'); const response = await fetch(`${this.apiBaseUrl}/servers/create`, { method: 'POST', headers: { 'Authorization': `Bearer ${this.authToken}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ name, type, maxPlayers, region, username: this.currentUser.username }) }); // Check if response is HTML (error page) instead of JSON const contentType = response.headers.get('content-type'); if (!contentType || !contentType.includes('application/json')) { throw new Error('API server is not available. Please check your connection.'); } if (response.ok) { const data = await response.json(); console.log('[LIVE MAIN MENU] Server created:', data.server); // Refresh server list await this.refreshServerList(); // Show success message this.showLoginNotice('Server created successfully!', 'success'); // Auto-join the created server this.joinServer(data.server.id); } else { const errorData = await response.json(); console.error('[LIVE MAIN MENU] Failed to create server:', errorData); this.showLoginNotice(`Failed to create server: ${errorData.error}`, 'error'); } } catch (error) { console.error('[LIVE MAIN MENU] Create server error:', error); this.showLoginNotice('Failed to create server', 'error'); } finally { // Hide loading state if (this.serverLoading) this.serverLoading.classList.add('hidden'); } } launchMultiplayerGame(server, serverData) { console.log('[LIVE MAIN MENU] Launching multiplayer game on server:', server.name); // Hide main menu and start game in multiplayer mode this.hideLoadingScreenAndShowGame(); this.initializeMultiplayerGame(server, serverData); } hideLoadingScreenAndShowGame() { console.log('[LIVE MAIN MENU] Hiding main menu and showing game interface'); // Hide main menu if (this.mainMenu) { this.mainMenu.classList.add('hidden'); } // Show game interface const gameInterface = document.getElementById('gameInterface'); if (gameInterface) { gameInterface.classList.remove('hidden'); } // Note: gameContainer element doesn't exist in HTML, so we skip it } initializeMultiplayerGame(server, serverData) { console.log('[LIVE MAIN MENU] Initializing multiplayer game'); // Check if GameEngine is available, if not create a basic fallback if (typeof GameEngine === 'undefined') { console.warn('[LIVE MAIN MENU] GameEngine class not available, creating fallback'); // Create a basic fallback GameEngine class window.GameEngine = class GameEngine extends EventTarget { constructor() { super(); this.systems = {}; this.gameTime = 0; this.isRunning = false; this.isFallback = true; // Mark as fallback for UIManager console.log('[LIVE MAIN MENU] Fallback GameEngine created'); } async init() { console.log('[LIVE MAIN MENU] Fallback GameEngine init() called'); return true; } setMultiplayerMode(isMultiplayer, socket, serverData, currentUser) { console.log('[LIVE MAIN MENU] Fallback GameEngine setMultiplayerMode called'); this.isMultiplayer = isMultiplayer; this.socket = socket; this.serverData = serverData; this.currentUser = currentUser; } startGame(continueGame) { console.log('[LIVE MAIN MENU] Fallback GameEngine startGame called, continueGame:', continueGame); this.isRunning = true; // Add simple return to menu functionality window.returnToMainMenu = () => { console.log('[LIVE MAIN MENU] Return to main menu requested'); if (window.liveMainMenu) { window.liveMainMenu.showLoginSection(); } }; } getPerformanceStats() { console.log('[LIVE MAIN MENU] Fallback GameEngine getPerformanceStats called'); return { gameTime: this.gameTime, isRunning: this.isRunning, fps: 60, memory: 'N/A (fallback mode)' }; } showNotification(message, type = 'info', duration = 3000) { console.log(`[LIVE MAIN MENU] Fallback notification: ${message} (${type})`); // Simple console notification for fallback mode if (typeof console !== 'undefined') { console.log(`📢 ${type.toUpperCase()}: ${message}`); } } save() { console.log('[LIVE MAIN MENU] Fallback GameEngine save called'); // Save will be handled by the main save logic when it detects local mode return Promise.resolve({ success: true }); } }; } // Create GameEngine if it doesn't exist if (!window.game) { console.log('[LIVE MAIN MENU] Creating new GameEngine instance for multiplayer'); try { window.game = new GameEngine(); // Initialize the game engine window.game.init().then(() => { console.log('[LIVE MAIN MENU] GameEngine initialized successfully for multiplayer'); // Apply pending save data if available (after GameEngine is ready) if (window.liveMainMenu && window.liveMainMenu.pendingSaveData) { console.log('[LIVE MAIN MENU] Applying pending save data after GameEngine init...'); try { const saveData = window.liveMainMenu.pendingSaveData; console.log('[LIVE MAIN MENU] Save data structure:', { hasPlayer: !!saveData.player, hasInventory: !!saveData.inventory, hasEconomy: !!saveData.economy, hasIdleSystem: !!saveData.idleSystem, hasDungeonSystem: !!saveData.dungeonSystem, hasSkillSystem: !!saveData.skillSystem, hasBaseSystem: !!saveData.baseSystem, hasQuestSystem: !!saveData.questSystem, gameTime: saveData.gameTime, playerLevel: saveData.player?.stats?.level }); console.log('[LIVE MAIN MENU] Game systems available:', { hasGame: !!window.game, hasSystems: !!window.game?.systems, hasPlayer: !!window.game?.systems?.player, hasInventory: !!window.game?.systems?.inventory, hasEconomy: !!window.game?.systems?.economy, hasIdleSystem: !!window.game?.systems?.idleSystem, hasDungeonSystem: !!window.game?.systems?.dungeonSystem, hasSkillSystem: !!window.game?.systems?.skillSystem, hasBaseSystem: !!window.game?.systems?.baseSystem, hasQuestSystem: !!window.game?.systems?.questSystem }); let appliedCount = 0; // Apply save data to game systems if (saveData.player && window.game.systems.player) { window.game.systems.player.load(saveData.player); console.log('[LIVE MAIN MENU] ✅ Player data loaded from pending save'); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Player data NOT loaded - saveData.player:', !!saveData.player, 'window.game.systems.player:', !!window.game?.systems?.player); } if (saveData.inventory && window.game.systems.inventory) { window.game.systems.inventory.load(saveData.inventory); console.log('[LIVE MAIN MENU] ✅ Inventory data loaded from pending save'); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Inventory data NOT loaded - saveData.inventory:', !!saveData.inventory, 'window.game.systems.inventory:', !!window.game?.systems?.inventory); } if (saveData.economy && window.game.systems.economy) { window.game.systems.economy.load(saveData.economy); console.log('[LIVE MAIN MENU] ✅ Economy data loaded from pending save'); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Economy data NOT loaded - saveData.economy:', !!saveData.economy, 'window.game.systems.economy:', !!window.game?.systems?.economy); } if (saveData.idleSystem && window.game.systems.idleSystem) { window.game.systems.idleSystem.load(saveData.idleSystem); console.log('[LIVE MAIN MENU] ✅ Idle system data loaded from pending save'); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Idle system data NOT loaded - saveData.idleSystem:', !!saveData.idleSystem, 'window.game.systems.idleSystem:', !!window.game?.systems?.idleSystem); } if (saveData.dungeonSystem && window.game.systems.dungeonSystem) { window.game.systems.dungeonSystem.load(saveData.dungeonSystem); console.log('[LIVE MAIN MENU] ✅ Dungeon system data loaded from pending save'); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Dungeon system data NOT loaded - saveData.dungeonSystem:', !!saveData.dungeonSystem, 'window.game.systems.dungeonSystem:', !!window.game?.systems?.dungeonSystem); } if (saveData.skillSystem && window.game.systems.skillSystem) { window.game.systems.skillSystem.load(saveData.skillSystem); console.log('[LIVE MAIN MENU] ✅ Skill system data loaded from pending save'); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Skill system data NOT loaded - saveData.skillSystem:', !!saveData.skillSystem, 'window.game.systems.skillSystem:', !!window.game?.systems?.skillSystem); } if (saveData.baseSystem && window.game.systems.baseSystem) { window.game.systems.baseSystem.load(saveData.baseSystem); console.log('[LIVE MAIN MENU] ✅ Base system data loaded from pending save'); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Base system data NOT loaded - saveData.baseSystem:', !!saveData.baseSystem, 'window.game.systems.baseSystem:', !!window.game?.systems?.baseSystem); } if (saveData.questSystem && window.game.systems.questSystem) { window.game.systems.questSystem.load(saveData.questSystem); console.log('[LIVE MAIN MENU] ✅ Quest system data loaded from pending save'); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Quest system data NOT loaded - saveData.questSystem:', !!saveData.questSystem, 'window.game.systems.questSystem:', !!window.game?.systems?.questSystem); } if (saveData.gameTime && window.game) { window.game.gameTime = saveData.gameTime; console.log('[LIVE MAIN MENU] ✅ Game time loaded from pending save:', saveData.gameTime); appliedCount++; } else { console.log('[LIVE MAIN MENU] ❌ Game time NOT loaded - saveData.gameTime:', !!saveData.gameTime, 'window.game:', !!window.game); } console.log(`[LIVE MAIN MENU] Save data application complete: ${appliedCount}/9 systems loaded`); if (appliedCount === 0) { console.warn('[LIVE MAIN MENU] ⚠️ NO save data was applied! This is why the UI shows fresh game state.'); console.warn('[LIVE MAIN MENU] ⚠️ The fallback GameEngine does not have the required game systems.'); } console.log('[LIVE MAIN MENU] Pending save data applied successfully'); // Clear pending save data window.liveMainMenu.pendingSaveData = null; } catch (error) { console.error('[LIVE MAIN MENU] Error applying pending save data:', error); } } else { console.log('[LIVE MAIN MENU] No pending save data to apply'); } // Now initialize multiplayer mode through GameInitializer if (window.gameInitializer) { window.gameInitializer.initializeMultiplayer(server, serverData, this.authToken, this.currentUser); } }).catch(error => { console.error('[LIVE MAIN MENU] Failed to initialize GameEngine for multiplayer:', error); this.showLoginNotice('Failed to initialize game: ' + error.message, 'error'); }); } catch (error) { console.error('[LIVE MAIN MENU] Error creating GameEngine:', error); this.showLoginNotice('Failed to create game engine: ' + error.message, 'error'); } } else { console.log('[LIVE MAIN MENU] GameEngine already exists, initializing multiplayer mode'); // Initialize multiplayer mode through GameInitializer if (window.gameInitializer) { window.gameInitializer.initializeMultiplayer(server, serverData, this.authToken, this.currentUser); } } } async startLocalServer() { console.log('[LIVE MAIN MENU] Starting local server...'); try { if (!window.localServerManager) { console.error('[LIVE MAIN MENU] LocalServerManager not available'); this.showLoginNotice('Local server manager not available', 'error'); return; } // Update button to show loading state if (this.createServerBtn) { this.createServerBtn.innerHTML = ' Starting...'; this.createServerBtn.disabled = true; } // Show loading message this.showLoginNotice('Starting local server...', 'info'); const result = await window.localServerManager.startServer(); if (result.success) { console.log('[LIVE MAIN MENU] Local server started successfully:', result); // Update to local mode this.isLocalMode = true; this.apiBaseUrl = `http://localhost:${result.port}/api`; this.gameServerUrl = `http://localhost:${result.port}`; console.log(`[LIVE MAIN MENU] Updated to local mode - API: ${this.apiBaseUrl}`); // Update button to show running state if (this.createServerBtn) { this.createServerBtn.innerHTML = ' Local Server Running'; this.createServerBtn.classList.remove('btn-primary'); this.createServerBtn.classList.add('btn-success'); } // Auto-login for local mode await this.autoLoginLocalMode(); // Show success message this.showLoginNotice('Local server started successfully!', 'success'); } else { console.error('[LIVE MAIN MENU] Failed to start local server:', result.error); this.showLoginNotice(`Failed to start local server: ${result.error}`, 'error'); // Reset button to original state if (this.createServerBtn) { this.createServerBtn.innerHTML = ' Start Local Server'; this.createServerBtn.disabled = false; } } } catch (error) { console.error('[LIVE MAIN MENU] Error starting local server:', error); this.showLoginNotice('Error starting local server', 'error'); // Reset button to original state if (this.createServerBtn) { this.createServerBtn.innerHTML = ' Start Local Server'; this.createServerBtn.disabled = false; } } } checkForLocalServer() { console.log('[LIVE MAIN MENU] Checking for local server...'); // Check if local server manager is available and running if (window.localServerManager) { const serverStatus = window.localServerManager.getStatus(); if (serverStatus.isRunning) { console.log('[LIVE MAIN MENU] Local server detected, switching to local mode'); this.isLocalMode = true; this.apiBaseUrl = `http://localhost:${serverStatus.port}/api`; this.gameServerUrl = `http://localhost:${serverStatus.port}`; console.log(`[LIVE MAIN MENU] Updated API URL to: ${this.apiBaseUrl}`); console.log(`[LIVE MAIN MENU] Updated Game Server URL to: ${this.gameServerUrl}`); // Update login notice to show local mode this.showLoginNotice('Local server active - Singleplayer mode available', 'info'); // Auto-login for local mode this.autoLoginLocalMode(); } else { console.log('[LIVE MAIN MENU] Local server not running, using remote servers'); } } else { console.log('[LIVE MAIN MENU] LocalServerManager not available'); } } async autoLoginLocalMode() { console.log('[LIVE MAIN MENU] Auto-logging in to local mode...'); try { let response; // Use SimpleLocalServer mock API if available if (window.localServerManager && window.localServerManager.localServer && window.localServerManager.localServer.mockRequest) { console.log('[LIVE MAIN MENU] Using SimpleLocalServer mock API'); response = await window.localServerManager.localServer.mockRequest('POST', '/api/auth/login', { email: 'local@player.com', password: 'local' }); } else { // Fallback to real fetch console.log('[LIVE MAIN MENU] Using real fetch for local login'); response = await fetch(`${this.apiBaseUrl}/auth/login`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email: 'local@player.com', password: 'local' }) }); } const data = await response.json(); if (data.success) { console.log('[LIVE MAIN MENU] Local mode login successful'); this.authToken = data.token; this.currentUser = data.user; // Update UI this.hideLoginNotice(); this.showServerSection(false, false); // Show section without refreshing or animating // Load servers (will show local server) this.refreshServerList(); } else { console.error('[LIVE MAIN MENU] Local mode login failed:', data); } } catch (error) { console.error('[LIVE MAIN MENU] Error in local mode auto-login:', error); } } } // Initialize the live main menu when DOM is ready function initializeLiveMainMenu() { console.log('[LIVE MAIN MENU] Initializing LiveMainMenu...'); // Wait a bit for DOM to be fully ready setTimeout(() => { if (!window.liveMainMenu) { console.log('[LIVE MAIN MENU] Creating new LiveMainMenu instance'); window.liveMainMenu = new LiveMainMenu(); } else { console.log('[LIVE MAIN MENU] LiveMainMenu already exists'); } }, 100); } // Try multiple initialization methods if (document.readyState === 'loading') { // DOM is still loading, wait for DOMContentLoaded document.addEventListener('DOMContentLoaded', initializeLiveMainMenu); } else { // DOM is already ready, initialize immediately initializeLiveMainMenu(); } // Also try initialization as a fallback setTimeout(() => { if (!window.liveMainMenu) { console.warn('[LIVE MAIN MENU] Fallback initialization triggered'); window.liveMainMenu = new LiveMainMenu(); } }, 1000); // Export for use in other scripts if (typeof module !== 'undefined' && module.exports) { module.exports = LiveMainMenu; }