/** * Game Initializer * Handles initialization of multiplayer game modes */ console.log('[GAME INITIALIZER] GameInitializer.js script loaded'); class GameInitializer { constructor() { console.log('[GAME INITIALIZER] Constructor called'); this.gameMode = 'multiplayer'; this.serverData = null; this.authToken = null; this.currentUser = null; this.socket = null; this.apiBaseUrl = 'https://api.korvarix.com/api'; // API Server this.gameServerUrl = 'https://dev.gameserver.galaxystrike.online'; // Game Server for Socket.IO console.log('[GAME INITIALIZER] Constructor - gameServerUrl set to:', this.gameServerUrl); } updateServerUrls(apiUrl, gameUrl) { console.log('[GAME INITIALIZER] Updating server URLs:', { apiUrl: apiUrl, gameUrl: gameUrl }); console.log('[GAME INITIALIZER] Previous gameServerUrl:', this.gameServerUrl); this.apiBaseUrl = apiUrl; this.gameServerUrl = gameUrl; console.log('[GAME INITIALIZER] New gameServerUrl:', this.gameServerUrl); } initializeMultiplayer(server, serverData, authToken, currentUser) { console.log('[GAME INITIALIZER] Initializing multiplayer game mode'); this.gameMode = 'multiplayer'; this.serverData = { ...server, ...serverData }; this.authToken = authToken; this.currentUser = currentUser; // Initialize Socket.IO connection this.initializeSocketConnection(); // Set SmartSaveManager to multiplayer mode if (window.smartSaveManager) { window.smartSaveManager.setMultiplayerMode(true, this); } // Update UI for multiplayer mode this.updateUIForMultiplayerMode(); console.log('[GAME INITIALIZER] Multiplayer game initialized'); } initializeSocketConnection() { if (!this.serverData) { console.error('[GAME INITIALIZER] No server data for socket connection'); return; } console.log('[GAME INITIALIZER] Initializing Socket.IO connection'); console.log('[GAME INITIALIZER] Using gameServerUrl:', this.gameServerUrl); // Check if we're in local mode and should use mock socket if (this.gameServerUrl.includes('localhost') && window.localServerManager && window.localServerManager.localServer) { console.log('[GAME INITIALIZER] Using mock socket for local mode'); this.socket = window.localServerManager.localServer.createMockSocket(); // Trigger connected event immediately since mock socket auto-connects setTimeout(() => { this.onSocketConnected(); }, 200); return; } // Resolve server URL: use serverData.url if set, otherwise gameServerUrl, then dev default const FORCED_URL = (this.serverData && this.serverData.url) ? this.serverData.url : (this.gameServerUrl || 'https://dev.gameserver.galaxystrike.online'); console.log('[GAME INITIALIZER] Connecting to:', FORCED_URL); // Connect to the game server this.socket = io(FORCED_URL, { auth: { token: this.authToken, serverId: this.serverData.id } }); console.log('[GAME INITIALIZER] Socket.IO connection initiated to:', FORCED_URL); // Socket event handlers this.socket.on('connect', () => { console.log('[GAME INITIALIZER] Connected to server'); this.onSocketConnected(); }); this.socket.on('disconnect', () => { console.log('[GAME INITIALIZER] Disconnected from server'); this.onSocketDisconnected(); }); this.socket.on('error', (error) => { console.error('[GAME INITIALIZER] Socket error:', error); }); this.socket.on('force_disconnect', (data) => { console.warn('[GAME INITIALIZER] Force disconnected:', data); this.onForceDisconnect(data); }); // Game-specific events this.socket.on('playerJoined', (data) => { console.log('[GAME INITIALIZER] Player joined:', data); this.onPlayerJoined(data); }); this.socket.on('playerLeft', (data) => { console.log('[GAME INITIALIZER] Player left:', data); this.onPlayerLeft(data); }); this.socket.on('gameUpdate', (data) => { console.log('[GAME INITIALIZER] Game update:', data); this.onGameUpdate(data); }); this.socket.on('chatMessage', (data) => { console.log('[GAME INITIALIZER] Chat message:', data); this.onChatMessage(data); }); // Server data events this.socket.on('authenticated', (data) => { console.log('[GAME INITIALIZER] Authentication response:', data); this.onAuthenticated(data); }); this.socket.on('gameDataLoaded', (data) => { console.log('[GAME INITIALIZER] Game data loaded:', data); this.onGameDataLoaded(data); }); this.socket.on('updatePlayerStats', (data) => { console.log('[GAME INITIALIZER] Player stats updated on server:', data); this.onGameDataSaved(data); }); this.socket.on('gameDataSaved', (data) => { console.log('[GAME INITIALIZER] Game data saved:', data); this.onGameDataSaved(data); }); // Idle rewards events this.socket.on('offlineRewardsClaimed', (data) => { console.log('[GAME INITIALIZER] Offline rewards claimed:', data); this.onOfflineRewardsClaimed(data); }); this.socket.on('onlineIdleRewards', (data) => { if (data.credits > 0 || data.experience > 0) { console.log('[GAME INITIALIZER] Online idle rewards received:', data); } this.onOnlineIdleRewards(data); }); // Quest completion events this.socket.on('quest_completed', (data) => { console.log('[GAME INITIALIZER] Quest completed:', data); this.onQuestCompleted(data); }); // Player stat update events this.socket.on('player_stat_update', (data) => { // Check for level-up const oldLevel = this.serverPlayerData?.stats?.level || 0; const newLevel = data.stats?.level || data.level || 0; if (newLevel > oldLevel && oldLevel > 0) { this.showNotification(`๐ŸŽ‰ Level Up! Commander Level ${newLevel}`, 'success'); if (window.GSO_Dashboard) GSO_Dashboard.refresh(this.serverPlayerData); } console.log('[GAME INITIALIZER] Player stat update:', data); this.onPlayerStatUpdate(data); }); // Quest data events this.socket.on('quests_data', (data) => { console.log('[GAME INITIALIZER] Quest data received:', data); this.onQuestsData(data); }); // PlayTime events this.socket.on('playTimeUpdated', (data) => { // Only log playtime updates every minute (600,000 ms) to reduce spam if (!this.lastPlayTimeLog || Date.now() - this.lastPlayTimeLog > 60000) { console.log('[GAME INITIALIZER] PlayTime updated:', `${Math.floor(data.playTime / 3600000)}h ${Math.floor((data.playTime % 3600000) / 60000)}m`); this.lastPlayTimeLog = Date.now(); } this.onPlayTimeUpdated(data); }); // Shop purchase events this.socket.on('purchaseCompleted', (data) => { console.log('[GAME INITIALIZER] Purchase completed:', data); this.onPurchaseCompleted(data); }); // Item system events this.socket.on('shopItemsReceived', (data) => { console.log('[GAME INITIALIZER] Shop items received:', data); this.onShopItemsReceived(data); }); this.socket.on('season_data', (data) => { if (!data?.active) return; const s = data.season; const banner = document.getElementById('season-banner'); if (banner) { banner.style.display = 'flex'; const set = (id,v) => { const el=document.getElementById(id); if(el) el.textContent=v; }; set('season-icon', s.icon||'๐ŸŒ‘'); set('season-name', `Season ${s.id}: ${s.name}`); set('season-desc', s.description||''); set('season-eta', `${s.daysLeft} days remaining (${s.progress}%)`); set('season-score', data.myScore ? `Your score: ${data.myScore.toLocaleString()}` : ''); } }); this.socket.on('galaxy_event_data', (data) => { if (!data?.active) return; const ev = data.event; const banner = document.getElementById('galaxy-event-banner'); if (banner) { banner.style.display = 'flex'; const set = (id,v) => { const el=document.getElementById(id); if(el) el.textContent=v; }; set('gev-icon', ev.icon||'๐Ÿ‘พ'); set('gev-name', ev.name||'Galaxy Event'); set('gev-desc', ev.desc||''); set('gev-eta', ev.etaLabel||''); set('gev-participants', `${ev.participantCount||0} commanders participating`); } }); this.socket.on('resource_update', (data) => { // Keep serverPlayerData.resources in sync if (this.serverPlayerData && data.resources) { this.serverPlayerData.resources = data.resources; } if (window.GSO_Resources) GSO_Resources.update(data); }); this.socket.on('itemDetailsReceived', (data) => { console.log('[GAME INITIALIZER] Item details received:', data); this.onItemDetailsReceived(data); }); // โ”€โ”€ Crafting (GDD ยง11) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ this.socket.on('recipes_data', (data) => { console.log('[CRAFTING] Recipes received:', Array.isArray(data) ? data.length : '(map)'); if (typeof GSO_Crafting !== 'undefined') GSO_Crafting.onRecipesData(data); }); this.socket.on('craft_result', (data) => { if (typeof GSO_Crafting !== 'undefined') GSO_Crafting.onCraftResult(data); else if (data.success) { if (typeof showNotification === 'function') showNotification('Item crafted!', 'success'); } else { if (typeof showNotification === 'function') showNotification(data.error || 'Craft failed', 'error'); } }); // Craft queue events (v3.3) this.socket.on('craft_queue_update', (data) => { if (typeof GSO_Crafting !== 'undefined') GSO_Crafting.onQueueUpdate(data); }); this.socket.on('collect_craft_result', (data) => { if (typeof GSO_Crafting !== 'undefined') GSO_Crafting.onCollectResult(data); }); // Gem speed-up result this.socket.on('speedup_craft_result', (data) => { if (data.success) { if (typeof showNotification === 'function') showNotification('โšก Craft instant-finished!', 'success'); this.socket.emit('get_craft_queue'); if (this.serverPlayerData) this.serverPlayerData.stats.gems = data.gems; this._updateEconomyDisplay({ gems: data.gems }); } else { if (typeof showNotification === 'function') showNotification(data.error || 'Speed-up failed', 'error'); } }); // Gem store purchase result (v3.3) this.socket.on('gem_purchase_result', (data) => { if (typeof GSO_GemStore !== 'undefined') GSO_GemStore.onPurchaseResult(data); if (data.success) { if (this.serverPlayerData) { this.serverPlayerData.stats.gems = data.gems; // If purchase added an inventory item, sync it if (data.newItem) { this.serverPlayerData.inventory = this.serverPlayerData.inventory || { items: [] }; this.serverPlayerData.inventory.items = this.serverPlayerData.inventory.items || []; this.serverPlayerData.inventory.items.push(data.newItem); } } this._updateEconomyDisplay({ gems: data.gems }); } }); this.socket.on('inventory_update', (data) => { if (this.serverPlayerData) { this.serverPlayerData.inventory = data; } if (typeof GSO_Inventory !== 'undefined' && GSO_Inventory.render) { GSO_Inventory.render(this.serverPlayerData); } }); // โ”€โ”€ Ship Modules (GDD ยง7.3) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ this.socket.on('ship_modules_data', (data) => { if (typeof GSO_Modules !== 'undefined') GSO_Modules.onModulesData(data); }); this.socket.on('equip_result', (data) => { if (typeof GSO_Modules !== 'undefined') GSO_Modules.onEquipResult(data); else if (data.success) { if (typeof showNotification === 'function') showNotification('Module equipped!', 'success'); } else { if (typeof showNotification === 'function') showNotification(data.error || 'Equip failed', 'error'); } }); // โ”€โ”€ PvP Challenges (GDD ยง9.4) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ this.socket.on('pvp_challenge_received', (data) => { if (typeof GSO_PvP !== 'undefined') GSO_PvP.onChallengeReceived(data); else { const accept = confirm(`${data.challengerName} challenges you to PvP! Accept?`); if (accept) this.socket.emit('pvp_accept', { challengeId: data.challengeId }); else this.socket.emit('pvp_decline', { challengeId: data.challengeId }); } }); this.socket.on('pvp_challenge_sent', (data) => { if (typeof showNotification === 'function') showNotification(data.message || 'Challenge sent!', 'info'); }); this.socket.on('pvp_result', (data) => { if (typeof GSO_PvP !== 'undefined') GSO_PvP.onPvpResult(data); else if (data.youWon) { if (typeof showNotification === 'function') showNotification(`PvP Victory! +${data.creditsWon} credits`, 'success'); } else if (!data.declined) { if (typeof showNotification === 'function') showNotification('PvP Defeat!', 'error'); } }); this.socket.on('pvp_challenge_expired', (data) => { if (typeof showNotification === 'function') showNotification('PvP challenge expired.', 'warning'); }); this.socket.on('pvp_declined', (data) => { if (typeof showNotification === 'function') showNotification(`${data.targetName} declined your challenge.`, 'warning'); }); // โ”€โ”€ Season Leaderboard (GDD ยง20.3) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ this.socket.on('season_leaderboard_data', (data) => { if (typeof GSO_Leaderboard !== 'undefined' && GSO_Leaderboard.onSeasonData) { GSO_Leaderboard.onSeasonData(data); } }); // โ”€โ”€ Phase 3: Raids, PvP Rankings, Alliance Wars, Push Notifications, Gem Purchase โ”€โ”€ if (typeof GSO_Raids !== 'undefined') GSO_Raids.init(this.socket); if (typeof GSO_PvpRankings !== 'undefined') GSO_PvpRankings.init(this.socket); if (typeof GSO_AllianceWars !== 'undefined') GSO_AllianceWars.init(this.socket); if (typeof GSO_PushNotifications !== 'undefined') GSO_PushNotifications.init(this.socket); if (typeof GSO_GemPurchase !== 'undefined') GSO_GemPurchase.init(this.socket); } onSocketConnected() { // Expose socket globally for systems that need it if (window.game) { window.game.socket = this.socket; } // Join the server room this.socket.emit('joinServer', { serverId: this.serverData.id, userId: this.currentUser.userId, username: this.currentUser.username }); // Authenticate with server to get player data this.authenticateWithServer(); // Show connected status this.showConnectionStatus('Connected', 'success'); } onSocketDisconnected() { console.log('[GAME INITIALIZER] Socket disconnected - switching to singleplayer mode'); // Show disconnected status this.showConnectionStatus('Disconnected', 'error'); // Switch SmartSaveManager back to singleplayer mode if (window.smartSaveManager) { window.smartSaveManager.setMultiplayerMode(false); console.log('[GAME INITIALIZER] SmartSaveManager set to singleplayer mode'); } // Clear socket reference this.socket = null; console.log('[GAME INITIALIZER] Socket reference cleared'); } // Force disconnect from multiplayer server forceDisconnect() { console.log('[GAME INITIALIZER] Force disconnect called'); if (this.socket) { console.log('[GAME INITIALIZER] Disconnecting socket...'); this.socket.disconnect(); this.socket = null; } // Switch to singleplayer mode if (window.smartSaveManager) { window.smartSaveManager.setMultiplayerMode(false); console.log('[GAME INITIALIZER] Force switched to singleplayer mode'); } this.showConnectionStatus('Disconnected', 'error'); console.log('[GAME INITIALIZER] Force disconnect completed'); } onPlayerJoined(data) { // Handle player joining this.updatePlayerList(); this.showNotification(`${data.username} joined the server`, 'info'); } onPlayerLeft(data) { // Handle player leaving this.updatePlayerList(); this.showNotification(`${data.username} left the server`, 'info'); } onGameUpdate(data) { // Handle game state updates if (window.game && window.game.handleServerUpdate) { window.game.handleServerUpdate(data); } } onChatMessage(data) { // Handle chat messages if (window.game && window.game.handleChatMessage) { window.game.handleChatMessage(data); } } onAuthenticated(data) { console.log('[GAME INITIALIZER] Authentication successful:', data); if (data.success && data.playerData) { // Store server player data from authentication (this is our primary source) this.serverPlayerData = data.playerData; this.currentUser = data.user; // CRITICAL: Force multiplayer mode and prevent fallback if (window.smartSaveManager) { console.log('[GAME INITIALIZER] FORCING multiplayer mode after authentication'); window.smartSaveManager.setMultiplayerMode(true, this); } // ItemSystem is now initialized by GameEngine - no need to initialize here console.log('[GAME INITIALIZER] ItemSystem initialization handled by GameEngine'); console.log('[GAME INITIALIZER] Using authentication data as primary source:', this.serverPlayerData); // NOW create GameEngine AFTER authentication is successful if (!window.game) { console.log('[GAME INITIALIZER] Creating GameEngine after successful authentication'); this.createGameEngineForMultiplayer(); } // Set SmartSaveManager to multiplayer mode if (window.smartSaveManager) { window.smartSaveManager.setMultiplayerMode(true, this); console.log('[GAME INITIALIZER] SmartSaveManager set to multiplayer mode'); // Apply authentication data immediately (this will be stored for later) window.smartSaveManager.applyServerDataToGame(data.playerData); } // NOTE: Don't apply to GameEngine here - it doesn't exist yet! // The data will be applied in createGameEngineForMultiplayer() after the game is created. this.showNotification(`Welcome back! Level ${data.playerData.stats?.level || 1}`, 'success'); } else { this.showNotification(data.error || 'Authentication failed', 'error'); } } createGameEngineForMultiplayer() { console.log('[GAME INITIALIZER] Creating GameEngine for multiplayer mode'); console.log('[GAME INITIALIZER] Server player data available:', !!this.serverPlayerData); try { // Create GameEngine instance window.game = new GameEngine(); // CRITICAL: Set multiplayer mode BEFORE initializing systems console.log('[GAME INITIALIZER] Setting multiplayer mode BEFORE initialization'); window.game.setMultiplayerMode(true, this.socket, this.serverData, this.currentUser); // NOTE: Don't apply server data immediately - wait for full initialization console.log('[GAME INITIALIZER] Server data ready, will apply after GameEngine initialization'); console.log('[GAME INITIALIZER] - this.serverPlayerData:', !!this.serverPlayerData); console.log('[GAME INITIALIZER] - window.game:', !!window.game); console.log('[GAME INITIALIZER] - window.game.loadServerPlayerData:', !!window.game?.loadServerPlayerData); // Initialize the game engine console.log('[GAME INITIALIZER] About to call window.game.init()'); const initPromise = window.game.init(); console.log('[GAME INITIALIZER] GameEngine.init() returned:', typeof initPromise, initPromise); // Apply server data and refresh UI after initialization is complete initPromise.then(() => { console.log('[GAME INITIALIZER] GameEngine initialized successfully for multiplayer'); // Apply server data immediately after initialization if (this.serverPlayerData && window.game.loadServerPlayerData) { console.log('[GAME INITIALIZER] Applying server player data to GameEngine:', this.serverPlayerData); window.game.loadServerPlayerData(this.serverPlayerData); console.log('[GAME INITIALIZER] Server player data applied to GameEngine'); // CRITICAL: Force immediate economy sync if (window.game.systems && window.game.systems.economy && window.game.systems.economy.syncWithServerData) { console.log('[GAME INITIALIZER] Forcing immediate economy sync with server data'); window.game.systems.economy.syncWithServerData(this.serverPlayerData); } // Force UI refresh if (window.game.systems && window.game.systems.ui && window.game.systems.ui.forceRefreshAllUI) { console.log('[GAME INITIALIZER] Forcing UI refresh after data application'); window.game.systems.ui.forceRefreshAllUI(); } else { console.warn('[GAME INITIALIZER] UI refresh not available - systems:', !!window.game.systems, 'ui:', !!window.game.systems?.ui, 'forceRefreshAllUI:', !!window.game.systems?.ui?.forceRefreshAllUI); } } else { console.warn('[GAME INITIALIZER] No server player data or loadServerPlayerData method available'); console.log('[GAME INITIALIZER] - this.serverPlayerData:', !!this.serverPlayerData); console.log('[GAME INITIALIZER] - window.game.loadServerPlayerData:', !!window.game?.loadServerPlayerData); } // Start the game if (window.game.start) { window.game.start(); } }).catch((error) => { console.error('[GAME INITIALIZER] GameEngine init failed:', error); console.error('[GAME INITIALIZER] Error details:', error.stack); this.showNotification('Failed to initialize game engine', 'error'); }); } catch (error) { console.error('[GAME INITIALIZER] Error creating GameEngine:', error); this.showNotification('Error creating game engine', 'error'); } } onGameDataLoaded(data) { console.log('[GAME INITIALIZER] Server game data loaded:', data); console.log('[GAME INITIALIZER] Data success:', data.success); console.log('[GAME INITIALIZER] Data content:', data.data); console.log('[GAME INITIALIZER] Data keys:', data.data ? Object.keys(data.data) : 'No data object'); // Only process if we don't already have good data from authentication if (data.success && data.data && Object.keys(data.data).length > 0 && !this.serverPlayerData) { console.log('[GAME INITIALIZER] Using gameDataLoaded as primary source (no auth data available)'); this.serverPlayerData = data.data; // Apply server data to game if game is running if (window.game && window.game.loadServerPlayerData) { window.game.loadServerPlayerData(data.data); // Force UI refresh when server data is applied if (window.game.systems && window.game.systems.ui && window.game.systems.ui.forceRefreshAllUI) { window.game.systems.ui.forceRefreshAllUI(); } } } else { console.log('[GAME INITIALIZER] Ignoring gameDataLoaded - already have data from authentication or data is empty'); } } onGameDataSaved(data) { console.log('[GAME INITIALIZER] Server game data saved:', data); if (data.success) { this.showNotification('Game saved to server!', 'success'); } else { this.showNotification(data.error || 'Failed to save to server', 'error'); } } onForceDisconnect(data) { // Handle forced disconnection from server console.warn('[GAME INITIALIZER] Force disconnected by server:', data); // Show notification to user if (window.game && window.game.showNotification) { window.game.showNotification( `Disconnected: ${data.reason}`, 'warning', 10000 ); } // Disconnect the socket if (this.socket) { this.socket.disconnect(); } // Clean up multiplayer mode if (window.game) { window.game.setMultiplayerMode(false); } // Return to main menu after a delay setTimeout(() => { if (window.liveMainMenu) { window.liveMainMenu.showLoginSection(); } }, 2000); } initializeGameSystems() { console.log('[GAME INITIALIZER] Initializing game systems'); // Wait for the main game script to be ready if (typeof window.game !== 'undefined') { console.log('[GAME INITIALIZER] window.game is available, calling setupGameSystems'); this.setupGameSystems(); } else { console.log('[GAME INITIALIZER] window.game not available, waiting 100ms'); // Wait for the game to be initialized setTimeout(() => this.initializeGameSystems(), 100); } } setupGameSystems() { if (!window.game) { console.error('[GAME INITIALIZER] Game not available'); return; } console.log('[GAME INITIALIZER] Setting up game systems for multiplayer mode'); // Configure game for multiplayer mode console.log('[GAME INITIALIZER] Configuring for multiplayer mode'); // Note: setMultiplayerMode already called in createGameEngineForMultiplayer() before initialization window.game.gameInitializer = this; // Store reference for server polling // DISABLE game logic in multiplayer - server is authoritative if (window.game) { console.log('[GAME INITIALIZER] Disabling client game logic - server is authoritative'); // Override game logic methods to do nothing in multiplayer const originalUpdateGameLogic = window.game.updateGameLogic; window.game.updateGameLogic = function() { // In multiplayer mode, client does NO game logic // Server is authoritative for ALL game data including credits // Client is display-only }; const originalStart = window.game.start; window.game.start = function() { console.log('[GAME ENGINE] Multiplayer mode - client does not run game logic, server is authoritative'); console.log('[GAME ENGINE] GameInitializer reference:', !!this.gameInitializer); console.log('[GAME ENGINE] Socket reference:', !!(this.gameInitializer && this.gameInitializer.socket)); console.log('[GAME ENGINE] Game mode:', this.gameInitializer ? this.gameInitializer.gameMode : 'no gameInitializer'); this.isRunning = true; // NO game logic timer - client is display-only // Server handles all game logic including credit generation // Start server data polling for UI updates if (this.gameInitializer && this.gameInitializer.socket) { console.log('[GAME ENGINE] Starting server data polling for UI updates'); this.serverPollTimer = setInterval(() => { console.log('[GAME ENGINE] Polling server for data...'); this.gameInitializer.loadGameDataFromServer(); }, 5000); // Request updates every 5 seconds } else { console.warn('[GAME ENGINE] Cannot start server polling - no gameInitializer or socket'); } // Only start UI updates that use server data (every second) if (this.systems.ui) { console.log('[GAME ENGINE] Starting multiplayer UI updates'); this.uiUpdateTimer = setInterval(() => { if (this.systems && this.systems.ui && this.systems.ui.updateUI) { console.log('[GAME ENGINE] Updating multiplayer UI with server data'); this.systems.ui.updateUI(); } }, 1000); } }; } // Game is already set up with save data, just start the game loop if (window.game.start) { // console.log('[GAME INITIALIZER] Calling start() to begin game loop'); window.game.start(); } else if (window.game.startGame) { // console.log('[GAME INITIALIZER] Calling startGame(false) - save data already applied'); window.game.startGame(false); // false = don't load again (save data already applied) } else { console.error('[GAME INITIALIZER] No start method available on window.game'); } console.log('[GAME INITIALIZER] Game systems configured'); } updateUIForMultiplayerMode() { // Update UI elements to show multiplayer mode const playerName = document.getElementById('playerName'); const playerTitle = document.getElementById('playerTitle'); const playerUsername = document.getElementById('playerUsername'); if (this.currentUser) { // Set the player name (rank/title) if (playerName) { playerName.textContent = 'Commander'; } // Set the player title if (playerTitle) { playerTitle.textContent = '- Rookie Pilot'; } // Set the username next to the level if (playerUsername) { playerUsername.textContent = this.currentUser.username + ' '; } } // Show multiplayer-specific UI elements this.showMultiplayerUI(); // Show server info this.showServerInfo(); } hideMultiplayerUI() { // Hide elements that are only relevant in multiplayer const chatContainer = document.getElementById('chatContainer'); if (chatContainer) { chatContainer.classList.add('hidden'); } const playerList = document.getElementById('playerList'); if (playerList) { playerList.classList.add('hidden'); } } showMultiplayerUI() { // Show multiplayer-specific elements const chatContainer = document.getElementById('chatContainer'); if (chatContainer) { chatContainer.classList.remove('hidden'); } const playerList = document.getElementById('playerList'); if (playerList) { playerList.classList.remove('hidden'); } } showServerInfo() { // Add server information to the UI const header = document.querySelector('.game-header'); if (header && !header.querySelector('.server-info')) { const serverInfo = document.createElement('div'); serverInfo.className = 'server-info'; serverInfo.innerHTML = ` ${this.serverData.name} (${this.serverData.currentPlayers}/${this.serverData.maxPlayers}) `; serverInfo.style.cssText = ` background: rgba(0, 212, 255, 0.2); color: #00d4ff; padding: 4px 8px; border-radius: 4px; font-size: 0.8rem; margin-left: 10px; `; header.appendChild(serverInfo); } } showConnectionStatus(status, type) { // Show connection status in the UI const statusElement = document.getElementById('connectionStatus'); if (statusElement) { statusElement.textContent = status; statusElement.className = `connection-status ${type}`; } } updatePlayerList() { // Update the player list UI if (this.socket && this.serverData) { // Request updated player list from server this.socket.emit('getPlayerList', { serverId: this.serverData.id }); } } showNotification(message, type = 'info') { // Show a notification to the user if (window.game && window.game.showNotification) { window.game.showNotification(message, type, 3000); } else { // Fallback to alert console.log(`[GAME INITIALIZER] Notification: ${message}`); } } // Method to send actions to the server sendGameAction(actionType, actionData) { if (this.socket && this.gameMode === 'multiplayer') { this.socket.emit('gameAction', { type: actionType, data: actionData, userId: this.currentUser.userId, serverId: this.serverData.id }); } } // Method to send chat messages sendChatMessage(message) { if (this.socket && this.gameMode === 'multiplayer') { this.socket.emit('chatMessage', { message: message, userId: this.currentUser.userId, username: this.currentUser.username, serverId: this.serverData.id }); } } // Method to save game data to server (SECURE: only send specific updates) saveGameDataToServer(gameData) { if (this.socket && this.gameMode === 'multiplayer') { console.log('[GAME INITIALIZER] Sending secure game updates to server'); // Only send specific, validated updates - not entire game state const secureUpdates = { playerStats: { credits: gameData.player?.credits || 0, level: gameData.player?.level || 1, experience: gameData.player?.experience || 0, playTime: gameData.player?.playTime || 0 }, timestamp: Date.now() }; // Send only the specific updates for server validation this.socket.emit('updatePlayerStats', secureUpdates); } } // Method to load game data from server loadGameDataFromServer() { if (this.socket && this.gameMode === 'multiplayer') { console.log('[GAME INITIALIZER] Loading game data from server'); console.log('[GAME INITIALIZER] Socket available:', !!this.socket); console.log('[GAME INITIALIZER] Game mode:', this.gameMode); console.log('[GAME INITIALIZER] Current user:', this.currentUser); console.log('[GAME INITIALIZER] Emitting loadGameData event with username'); // Get username from current user or fallback to stored user let username = 'anonymous'; // default fallback if (this.currentUser?.username) { username = this.currentUser.username; } else { // Try to get from localStorage as fallback const storedUser = localStorage.getItem('currentUser'); if (storedUser) { try { const user = JSON.parse(storedUser); username = user.username || 'anonymous'; } catch (e) { console.warn('[GAME INITIALIZER] Failed to parse stored user, using default'); } } } console.log('[GAME INITIALIZER] Using username for data load:', username); // Send the username to load the correct player data this.socket.emit('loadGameData', { username: username }); } else { console.log('[GAME INITIALIZER] Cannot load game data - socket or multiplayer mode not available'); console.log('[GAME INITIALIZER] Socket available:', !!this.socket); console.log('[GAME INITIALIZER] Game mode:', this.gameMode); } } // Method to authenticate with server authenticateWithServer() { console.log('[GAME INITIALIZER] authenticateWithServer called'); console.log('[GAME INITIALIZER] Socket available:', !!this.socket); console.log('[GAME INITIALIZER] Game mode:', this.gameMode); console.log('[GAME INITIALIZER] Current user:', this.currentUser); if (this.socket && this.currentUser) { console.log('[GAME INITIALIZER] Sending authentication to server'); this.socket.emit('authenticate', { userId: this.currentUser.userId, username: this.currentUser.username }); } else { // Try to get from localStorage as fallback const storedUser = localStorage.getItem('currentUser'); if (storedUser) { try { const user = JSON.parse(storedUser); const username = user.username || 'anonymous'; } catch (e) { console.warn('[GAME INITIALIZER] Failed to parse stored user, using default'); } } else { window.game.showNotification('No offline rewards available', 'info', 3000); } } } onOnlineIdleRewards(data) { if (window.game && window.game.systems) { // Only log if there are actual rewards to process if (data.credits > 0 || data.experience > 0 || data.energy > 0) { console.log('[GAME INITIALIZER] Processing online idle rewards:', data); } // Update player balance with online idle rewards if (data.credits > 0) { // Update the Economy system's local credits if (window.game.systems.economy) { window.game.systems.economy.credits += data.credits; // Update UI immediately if (window.game.ui) { window.game.ui.updatePlayerStats(); console.log('[GAME INITIALIZER] UI updated with new credits'); } } else { console.warn('[GAME INITIALIZER] Economy system not available for credit update'); } // Show notification window.game.showNotification(`+${data.credits} credits (online idle)`, 'success', 2000); } // Update experience if provided if (data.experience > 0 && window.game.systems.player) { window.game.systems.player.addExperience(data.experience); console.log('[GAME INITIALIZER] Added idle experience:', data.experience); } } else { console.warn('[GAME INITIALIZER] Game systems not available for idle rewards'); } } onPlayTimeUpdated(data) { // PlayTime updates are handled in the socket listener with throttled logging if (window.game && window.game.systems && window.game.systems.player) { const player = window.game.systems.player; // Update playTime from server player.stats.playTime = data.playTime; // Update UI player.updateUI(); } } onPurchaseCompleted(data) { if (data.success) { // Update local player data with server response if (window.game && window.game.systems && window.game.systems.economy) { const economy = window.game.systems.economy; // Update currency balance if (data.currency === 'credits') { economy.credits = data.newBalance; } else if (data.currency === 'gems') { economy.gems = data.newBalance; } // Add item to inventory if it's a consumable or material if (data.item && (data.item.type === 'consumable' || data.item.type === 'material')) { if (window.game.systems.inventory) { console.log('[GAME INITIALIZER] Adding item to inventory:', data.item); window.game.systems.inventory.addItem(data.item, data.quantity || 1); window.game.showNotification(`${data.item.name} added to inventory!`, 'success', 3000); } } // Update owned ships if it's a ship if (data.item && data.item.type === 'ship') { if (!economy.ownedShips) economy.ownedShips = []; if (!economy.ownedShips.includes(data.item.id)) { economy.ownedShips.push(data.item.id); console.log('[GAME INITIALIZER] Ship added to owned ships:', data.item.id); // Add ship to BaseSystem ship gallery if (window.game.systems.baseSystem) { console.log('[GAME INITIALIZER] BaseSystem available, adding ship to gallery'); const shipData = { id: data.item.id, name: data.item.name, class: data.item.name.replace(/\s+/g, '_').toLowerCase(), // Generate class from name level: 1, stats: data.item.stats || {}, texture: data.item.texturePath || `assets/textures/ships/${data.item.id}.png`, isCurrent: false, rarity: data.item.rarity || 'common' }; console.log('[GAME INITIALIZER] Ship data prepared:', shipData); // Initialize ship gallery if needed if (!window.game.systems.baseSystem.purchasedShips) { console.log('[GAME INITIALIZER] Initializing ship gallery'); window.game.systems.baseSystem.initializeShipGallery(); } // Check if ship already exists const existingShip = window.game.systems.baseSystem.purchasedShips.find(s => s.id === shipData.id); if (!existingShip) { // Add ship to gallery window.game.systems.baseSystem.purchasedShips.push(shipData); console.log('[GAME INITIALIZER] Ship added to gallery. Total ships:', window.game.systems.baseSystem.purchasedShips.length); // Update the ship gallery UI window.game.systems.baseSystem.updateShipGallery(); console.log('[GAME INITIALIZER] Ship gallery UI updated'); } else { console.log('[GAME INITIALIZER] Ship already exists in gallery:', shipData.id); } } else { console.error('[GAME INITIALIZER] BaseSystem not available for ship gallery'); } } } // Update owned cosmetics if it's a cosmetic if (data.item && data.item.type === 'cosmetic') { if (!economy.ownedCosmetics) economy.ownedCosmetics = []; if (!economy.ownedCosmetics.includes(data.item.id)) { economy.ownedCosmetics.push(data.item.id); console.log('[GAME INITIALIZER] Cosmetic added to owned cosmetics:', data.item.id); } } // Request fresh economy data from server to ensure sync if (economy.requestEconomyData) { setTimeout(() => { economy.requestEconomyData(); }, 500); } // Also request economy data immediately to prevent reset if (economy.requestEconomyData) { economy.requestEconomyData(); } // Update UI economy.updateUI(); // Update inventory UI if item was added if (data.item && (data.item.type === 'consumable' || data.item.type === 'material')) { if (window.game.systems.inventory) { window.game.systems.inventory.updateUI(); } } // Show success message window.game.showNotification(`Purchased ${data.item.name}!`, 'success', 3000); } } else { // Show error message window.game.showNotification(`Purchase failed: ${data.error}`, 'error', 5000); } } onShopItemsReceived(data) { if (data.success && window.game && window.game.systems && window.game.systems.itemSystem) { console.log('[GAME INITIALIZER] Processing shop items data structure:', Object.keys(data)); // Handle both old (data.items) and new (data.shopItems) structures let itemsToProcess = null; if (data.shopItems && typeof data.shopItems === 'object') { // New structure: categorized items console.log('[GAME INITIALIZER] Using new shop structure'); itemsToProcess = Object.values(data.shopItems).flat(); console.log('[GAME INITIALIZER] Flattened', itemsToProcess.length, 'items from categories'); } else if (data.items && Array.isArray(data.items)) { // Old structure: flat array console.log('[GAME INITIALIZER] Using old shop structure'); itemsToProcess = data.items; console.log('[GAME INITIALIZER] Processing', itemsToProcess.length, 'items from flat array'); } else { console.warn('[GAME INITIALIZER] Invalid shop items structure:', data); return; } // Update ItemSystem with server data window.game.systems.itemSystem.processServerItems(itemsToProcess); console.log('[GAME INITIALIZER] ItemSystem updated with server shop items'); // Update Economy shop UI if (window.game.systems.economy) { window.game.systems.economy.updateShopUI(); console.log('[GAME INITIALIZER] Economy shop UI updated'); } } else { console.warn('[GAME INITIALIZER] Failed to receive shop items:', data); } } onItemDetailsReceived(data) { // This is handled by the ItemSystem directly // Just log for debugging if (data.success) { console.log('[GAME INITIALIZER] Item details received for:', data.item.name); } else { console.warn('[GAME INITIALIZER] Failed to receive item details:', data); } } // Cleanup method cleanup() { console.log('[GAME INITIALIZER] Cleaning up'); // Reset SmartSaveManager to singleplayer mode if (window.smartSaveManager) { window.smartSaveManager.setMultiplayerMode(false); } if (this.socket) { this.socket.disconnect(); this.socket = null; } this.gameMode = null; this.serverData = null; this.authToken = null; this.currentUser = null; this.serverPlayerData = null; } onQuestCompleted(data) { console.log('[GAME INITIALIZER] Processing quest completion:', data); // Show quest completion notification if (window.game && window.game.showNotification) { const questName = data.questId.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase()); window.game.showNotification(`Quest Completed: ${questName}! ๐ŸŽฏ`, 'success', 5000); } // Award quest rewards if (data.rewards) { if (data.rewards.experience > 0 && window.game.systems.player) { window.game.systems.player.addExperience(data.rewards.experience); console.log('[GAME INITIALIZER] Awarded quest experience:', data.rewards.experience); } if (data.rewards.credits > 0 && window.game.systems.economy) { window.game.systems.economy.credits += data.rewards.credits; console.log('[GAME INITIALIZER] Awarded quest credits:', data.rewards.credits); } } // Update quest UI if quest system exists if (window.game && window.game.systems && window.game.systems.questSystem) { window.game.systems.questSystem.completeQuest(data.questId, data.rewards); // Force fetch fresh quest data from server (Fix #1 - Corrected) console.log('[GAME INITIALIZER] Requesting fresh quest data from server after completion'); // Request fresh quest data from server if (window.gameInitializer && window.gameInitializer.socket) { window.gameInitializer.socket.emit('get_quests'); } } // Force quest UI refresh for server-driven quests if (typeof updateQuestDisplay === 'function') { updateQuestDisplay(); } // Update UI if (window.game && window.game.ui) { window.game.ui.updatePlayerStats(); } } onPlayerStatUpdate(data) { console.log('[GAME INITIALIZER] Processing player stat update:', data); if (window.game && window.game.systems && window.game.systems.player && window.game.systems.player.stats) { // Update the player stat window.game.systems.player.stats[data.stat] = data.value; console.log('[GAME INITIALIZER] Updated player stat:', data.stat, '=', data.value); // Update UI to reflect the change if (window.game.ui) { window.game.ui.updatePlayerStats(); } // Update quest system to check for quest progress if (window.game.systems.questSystem) { window.game.systems.questSystem.checkQuestAvailability(); } } } onQuestsData(data) { console.log('[GAME INITIALIZER] Processing quest data from server:', data); console.log('[GAME INITIALIZER] Quest data keys:', Object.keys(data || {})); console.log('[GAME INITIALIZER] Main quests count:', (data?.mainQuests || []).length); console.log('[GAME INITIALIZER] Daily quests count:', (data?.dailyQuests || []).length); console.log('[GAME INITIALIZER] Weekly quests count:', (data?.weeklyQuests || []).length); if (window.game && window.game.systems && window.game.systems.questSystem) { // Load quest data into the quest system if (window.game.systems.questSystem.loadServerQuests) { console.log('[GAME INITIALIZER] Calling loadServerQuests with data'); window.game.systems.questSystem.loadServerQuests(data); console.log('[GAME INITIALIZER] Loaded quest data into quest system'); } else { console.log('[GAME INITIALIZER] loadServerQuests method not found'); } // Update quest UI if (typeof updateQuestDisplay === 'function') { console.log('[GAME INITIALIZER] Calling updateQuestDisplay'); updateQuestDisplay(); } else { console.log('[GAME INITIALIZER] updateQuestDisplay function not found'); } } else { console.log('[GAME INITIALIZER] Quest system not available'); } } } // Create global instance window.gameInitializer = new GameInitializer(); // Make force disconnect available globally for testing window.forceDisconnectMultiplayer = function() { if (window.gameInitializer && window.gameInitializer.forceDisconnect) { window.gameInitializer.forceDisconnect(); } else { console.log('[GAME INITIALIZER] GameInitializer not available for force disconnect'); } }; // Debug: Log the global instance immediately console.log('[GAME INITIALIZER] Global instance created:', window.gameInitializer); console.log('[GAME INITIALIZER] Global instance gameServerUrl:', window.gameInitializer.gameServerUrl); // Export for use in other scripts if (typeof module !== 'undefined' && module.exports) { module.exports = GameInitializer; }