/** * Galaxy Strike Online - Game Engine * Core game loop and state management */ class GameEngine extends EventTarget { constructor() { super(); // Call EventTarget constructor first console.log('🛑 DEBUG STOP 1: GameEngine constructor starting'); const debugLogger = window.debugLogger; if (debugLogger) debugLogger.log('GameEngine constructor called', { autoSaveInterval: 5, timestamp: new Date().toISOString() }); this.isRunning = false; this.lastUpdate = 0; this.gameTime = 0; // Auto-save settings this.autoSaveInterval = 1; // Default 1 minute this.autoSaveTimer = null; this.lastAutoSave = 0; // Save slot information this.saveSlotInfo = { slot: 1, // Default save slot useFileSystem: !!window.electronAPI // Use file system if Electron API is available }; console.log('🛑 DEBUG STOP 2: Save slot info initialized:', this.saveSlotInfo); // GUI update settings this.guiUpdateInterval = 1000; // Update GUI once per second (1000ms) this.lastGUIUpdate = 0; // Game logic settings (independent of frame rate) this.gameLogicInterval = 1000; // Update game logic every 1 second this.gameLogicTimer = null; // Game state this.state = { paused: false, currentTab: 'dashboard', notifications: [], loading: true }; console.log('🛑 DEBUG STOP 3: Game state initialized:', this.state); // Systems this.systems = {}; // Event listeners this.eventListeners = new Map(); console.log('🛑 DEBUG STOP 4: About to call this.init()'); this.init(); console.log('🛑 DEBUG STOP 5: GameEngine constructor completed'); } setMultiplayerMode(isMultiplayer, socket = null, serverData = null, currentUser = null) { const debugLogger = window.debugLogger; console.log('[GAME ENGINE] Setting multiplayer mode:', isMultiplayer); if (debugLogger) debugLogger.logStep('setMultiplayerMode', { isMultiplayer }); this.isMultiplayer = isMultiplayer; this.socket = socket; this.serverData = serverData; this.currentUser = currentUser; // Store multiplayer settings for systems that need them this.multiplayerConfig = { isMultiplayer, socket, serverData, currentUser }; console.log('[GAME ENGINE] Multiplayer mode configured:', { isMultiplayer, hasSocket: !!socket, hasServerData: !!serverData, hasCurrentUser: !!currentUser }); } // Get random integer between min and max (inclusive) getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } // Get random float between min and max getRandomFloat(min, max) { return Math.random() * (max - min) + min; } async init() { console.log('[GAME ENGINE] Initializing game engine'); const logger = window.logger; const debugLogger = window.debugLogger; if (logger) await logger.info('Initializing game engine'); if (debugLogger) await debugLogger.startStep('gameEngineInit'); try { // Initialize core systems but don't setup new game data await this.initializeSystemsForLoad(); if (debugLogger) await debugLogger.logStep('Systems initialized, setting up event listeners'); // Set up event listeners await this.setupEventListeners(); if (debugLogger) await debugLogger.logStep('Event listeners setup complete'); if (logger) await logger.info('Game engine initialization completed'); if (debugLogger) await debugLogger.endStep('gameEngineInit', { systemsInitialized: Object.keys(this.systems).length, eventListeners: this.eventListeners.size }); } catch (error) { console.error('Failed to initialize game:', error); if (logger) await logger.errorEvent(error, 'Game Engine Initialization'); if (debugLogger) await debugLogger.errorEvent(error, 'Game Engine Initialization'); } } async startGame(continueGame = false) { const logger = window.logger; const debugLogger = window.debugLogger; console.log('[GAME ENGINE] startGame called with continueGame =', continueGame); if (logger) await logger.info('Starting game', { continueGame }); if (debugLogger) await debugLogger.startStep('startGame', { continueGame }); try { if (continueGame) { console.log('[GAME ENGINE] Loading existing save data...'); if (debugLogger) await debugLogger.logStep('Loading existing save data'); await this.loadGame(); console.log('[GAME ENGINE] Save data loaded'); } else { console.log('[GAME ENGINE] Creating new game...'); if (debugLogger) await debugLogger.logStep('Creating new game'); await this.newGame(); console.log('[GAME ENGINE] New game created'); } // Start game loop // CRITICAL: Ensure UIManager is initialized before starting game if (this.systems.ui) { console.log('[GAME ENGINE] Final UIManager initialization check...'); try { await this.systems.ui.initialize(); console.log('[GAME ENGINE] UIManager initialized successfully'); } catch (error) { console.error('[GAME ENGINE] UIManager initialization failed:', error); } } this.start(); console.log('[GAME ENGINE] Game loop started'); if (debugLogger) await debugLogger.logStep('Game loop started'); const loadingStatus = document.getElementById('loadingStatus'); if (loadingStatus) { console.log('[GAME ENGINE] Hiding loading status text'); if (debugLogger) await debugLogger.logStep('Hiding loading status text'); loadingStatus.classList.add('hidden'); } const gameInterface = document.getElementById('gameInterface'); if (gameInterface) { console.log('[GAME ENGINE] Showing game interface'); if (debugLogger) await debugLogger.logStep('Showing game interface'); gameInterface.classList.remove('hidden'); // CRITICAL: Initialize UIManager after showing interface console.log('[GAME ENGINE] Initializing UIManager after showing interface...'); if (this.systems.ui) { try { await this.systems.ui.initialize(); console.log('[GAME ENGINE] UIManager initialized successfully (post-interface)'); } catch (error) { console.error('[GAME ENGINE] UIManager initialization failed:', error); } } else { console.log('[GAME ENGINE] UIManager not found when trying to initialize after interface'); } } else { console.warn('[GAME ENGINE] gameInterface element not found'); if (debugLogger) await debugLogger.warn('gameInterface element not found'); } if (logger) await logger.info('Game started successfully'); if (debugLogger) await debugLogger.endStep('startGame', { continueGame, isRunning: this.isRunning, gameTime: this.gameTime }); } catch (error) { console.error('[GAME ENGINE] Failed to start game:', error); if (logger) await logger.errorEvent(error, 'Game Start'); if (debugLogger) await debugLogger.errorEvent(error, 'Game Start'); } } async initializeSystemsForLoad() { const logger = window.logger; const debugLogger = window.debugLogger; if (debugLogger) await debugLogger.startStep('initializeSystemsForLoad'); if (logger) { await logger.timeAsync('Game Systems Initialization for Load', async () => { await logger.info('Initializing game systems for loading'); if (debugLogger) await debugLogger.logStep('Initializing TextureManager'); // Initialize texture manager first this.systems.textureManager = new TextureManager(this); if (logger) await logger.systemEvent('TextureManager', 'Initialized'); if (debugLogger) await debugLogger.logStep('TextureManager initialized'); if (debugLogger) await debugLogger.logStep('Creating Player system (without initialization)'); // Create systems but don't initialize with default data this.systems.player = new Player(this); if (logger) await logger.systemEvent('Player', 'Created'); if (debugLogger) await debugLogger.logStep('Player system created'); if (debugLogger) await debugLogger.logStep('Creating Inventory system (without initialization)'); this.systems.inventory = new Inventory(this); if (logger) await logger.systemEvent('Inventory', 'Created'); if (debugLogger) await debugLogger.logStep('Inventory system created'); if (debugLogger) await debugLogger.logStep('Creating Economy system (without initialization)'); this.systems.economy = new Economy(this); if (logger) await logger.systemEvent('Economy', 'Created'); if (debugLogger) await debugLogger.logStep('Economy system created'); if (debugLogger) await debugLogger.logStep('Creating IdleSystem'); this.systems.idleSystem = new IdleSystem(this); if (logger) await logger.systemEvent('IdleSystem', 'Created'); if (debugLogger) await debugLogger.logStep('IdleSystem created'); if (debugLogger) await debugLogger.logStep('Creating DungeonSystem'); this.systems.dungeonSystem = new DungeonSystem(this); if (logger) await logger.systemEvent('DungeonSystem', 'Created'); if (debugLogger) await debugLogger.logStep('DungeonSystem created'); if (debugLogger) await debugLogger.logStep('Creating SkillSystem'); this.systems.skillSystem = new SkillSystem(this); if (logger) await logger.systemEvent('SkillSystem', 'Created'); if (debugLogger) await debugLogger.logStep('SkillSystem created'); if (debugLogger) await debugLogger.logStep('Creating BaseSystem'); this.systems.baseSystem = new BaseSystem(this); if (logger) await logger.systemEvent('BaseSystem', 'Created'); if (debugLogger) await debugLogger.logStep('BaseSystem created'); if (debugLogger) await debugLogger.logStep('Creating QuestSystem'); this.systems.questSystem = new QuestSystem(this); if (logger) await logger.systemEvent('QuestSystem', 'Created'); if (debugLogger) await debugLogger.logStep('QuestSystem created'); if (debugLogger) await debugLogger.logStep('Creating ShipSystem'); this.systems.shipSystem = new ShipSystem(this); if (logger) await logger.systemEvent('ShipSystem', 'Created'); if (debugLogger) await debugLogger.logStep('ShipSystem created'); if (debugLogger) await debugLogger.logStep('Creating UIManager'); if (typeof UIManager !== 'undefined') { console.log('[GAME ENGINE] UIManager class found, creating real UIManager'); this.systems.ui = new UIManager(this); // Expose UIManager globally for button onclick handlers window.uiManager = this.systems.ui; window.game.systems.ui = this.systems.ui; if (logger) await logger.systemEvent('UIManager', 'Created'); if (debugLogger) await debugLogger.logStep('UIManager created and exposed'); } else { console.error('[GAME ENGINE] UIManager class not found - this should not happen!'); if (debugLogger) await debugLogger.error('UIManager class not found - this should not happen!'); // Create minimal UI system to prevent crashes (should never be needed based on logs) this.systems.ui = { showNotification: (message, type, duration) => { console.log(`[UI MINIMAL] ${type}: ${message}`); }, updateUI: () => { console.log('[UI MINIMAL] updateUI called'); }, switchTab: (tabName) => { console.log('[UI MINIMAL] switchTab called'); } }; } if (debugLogger) await debugLogger.logStep('Creating CraftingSystem'); this.systems.crafting = new CraftingSystem(this); if (logger) await logger.systemEvent('CraftingSystem', 'Created'); if (debugLogger) await debugLogger.logStep('CraftingSystem created'); if (debugLogger) await debugLogger.endStep('initializeSystemsForLoad', { systemsCreated: Object.keys(this.systems).length }); }); } } async initializeSystems() { const logger = window.logger; const debugLogger = window.debugLogger; if (debugLogger) await debugLogger.startStep('initializeSystems'); if (logger) { await logger.timeAsync('Game Systems Initialization', async () => { await logger.info('Initializing game systems'); if (debugLogger) await debugLogger.logStep('Initializing TextureManager'); // Initialize texture manager first this.systems.textureManager = new TextureManager(this); if (logger) await logger.systemEvent('TextureManager', 'Initialized'); if (debugLogger) await debugLogger.logStep('TextureManager initialized'); if (debugLogger) await debugLogger.logStep('Initializing Player system'); // Initialize in dependency order this.systems.player = new Player(this); if (logger) await logger.systemEvent('Player', 'Initialized'); if (debugLogger) await debugLogger.logStep('Player system initialized', { playerLevel: this.systems.player.stats.level, playerExperience: this.systems.player.stats.experience }); if (debugLogger) await debugLogger.logStep('Initializing Inventory system'); this.systems.inventory = new Inventory(this); if (logger) await logger.systemEvent('Inventory', 'Initialized'); if (debugLogger) await debugLogger.logStep('Inventory system initialized', { inventorySize: this.systems.inventory.items.length }); if (debugLogger) await debugLogger.logStep('Initializing Economy system'); this.systems.economy = new Economy(this); if (logger) await logger.systemEvent('Economy', 'Initialized'); if (debugLogger) await debugLogger.logStep('Economy system initialized', { credits: this.systems.economy.credits, gems: this.systems.economy.gems }); if (debugLogger) await debugLogger.logStep('Initializing IdleSystem'); this.systems.idleSystem = new IdleSystem(this); if (logger) await logger.systemEvent('IdleSystem', 'Initialized'); if (debugLogger) await debugLogger.logStep('IdleSystem initialized'); if (debugLogger) await debugLogger.logStep('Initializing DungeonSystem'); this.systems.dungeonSystem = new DungeonSystem(this); if (logger) await logger.systemEvent('DungeonSystem', 'Initialized'); if (debugLogger) await debugLogger.logStep('DungeonSystem initialized'); if (debugLogger) await debugLogger.logStep('Initializing SkillSystem'); this.systems.skillSystem = new SkillSystem(this); if (logger) await logger.systemEvent('SkillSystem', 'Initialized'); if (debugLogger) await debugLogger.logStep('SkillSystem initialized'); if (debugLogger) await debugLogger.logStep('Initializing BaseSystem'); this.systems.baseSystem = new BaseSystem(this); if (logger) await logger.systemEvent('BaseSystem', 'Initialized'); if (debugLogger) await debugLogger.logStep('BaseSystem initialized'); if (debugLogger) await debugLogger.logStep('Initializing QuestSystem'); this.systems.questSystem = new QuestSystem(this); await this.systems.questSystem.initialize(); if (logger) await logger.systemEvent('QuestSystem', 'Initialized'); if (debugLogger) await debugLogger.logStep('QuestSystem initialized'); if (debugLogger) await debugLogger.logStep('Initializing ShipSystem'); this.systems.ship = new ShipSystem(this); if (logger) await logger.systemEvent('ShipSystem', 'Initialized'); if (debugLogger) await debugLogger.logStep('ShipSystem initialized'); if (debugLogger) await debugLogger.logStep('UIManager already initialized in initializeSystemsForLoad'); if (debugLogger) await debugLogger.logStep('Initializing CraftingSystem'); this.systems.crafting = new CraftingSystem(this); if (logger) await logger.systemEvent('CraftingSystem', 'Initialized'); if (debugLogger) await debugLogger.logStep('CraftingSystem initialized'); if (logger) await logger.info('All game systems initialized'); if (debugLogger) await debugLogger.logStep('All systems created, running individual initializations'); if (debugLogger) await debugLogger.logStep('Running individual system initializations'); for (const [name, system] of Object.entries(this.systems)) { if (system.initialize) { if (debugLogger) await debugLogger.logStep(`Initializing ${name} system`); await system.initialize(); if (debugLogger) await debugLogger.logStep(`${name} system initialization complete`); } else { if (debugLogger) await debugLogger.logStep(`${name} system has no initialize method`); } } if (debugLogger) await debugLogger.endStep('initializeSystems', { totalSystems: Object.keys(this.systems).length, systemsList: Object.keys(this.systems) }); }); } else { // Fallback without timing if (debugLogger) await debugLogger.logStep('Logger not available, using fallback initialization'); // Initialize texture manager first this.systems.textureManager = new TextureManager(this); // Initialize in dependency order this.systems.player = new Player(this); this.systems.inventory = new Inventory(this); this.systems.economy = new Economy(this); this.systems.idleSystem = new IdleSystem(this); this.systems.dungeonSystem = new DungeonSystem(this); this.systems.skillSystem = new SkillSystem(this); this.systems.baseSystem = new BaseSystem(this); this.systems.questSystem = new QuestSystem(this); // UIManager already initialized in initializeSystemsForLoad this.systems.crafting = new CraftingSystem(this); for (const [name, system] of Object.entries(this.systems)) { if (system.initialize) { await system.initialize(); } } if (debugLogger) await debugLogger.endStep('initializeSystems', { fallbackMode: true, totalSystems: Object.keys(this.systems).length }); } } async setupEventListeners() { const debugLogger = window.debugLogger; if (debugLogger) await debugLogger.startStep('setupEventListeners'); // Window events if (debugLogger) await debugLogger.logStep('Setting up window event listeners'); window.addEventListener('beforeunload', () => { if (debugLogger) debugLogger.logStep('beforeunload event triggered - saving game'); this.save(); }); window.addEventListener('visibilitychange', () => { // if (debugLogger) debugLogger.logStep('visibilitychange event triggered', { // hidden: document.hidden, // visibilityState: document.visibilityState // }); if (document.hidden) { // if (debugLogger) debugLogger.logStep('Document hidden - saving game'); this.save(); } }); // Keyboard shortcuts if (debugLogger) await debugLogger.logStep('Setting up keyboard shortcuts'); document.addEventListener('keydown', (event) => { if (debugLogger) debugLogger.logStep('Key pressed', { key: event.key, code: event.code, ctrlKey: event.ctrlKey, altKey: event.altKey, shiftKey: event.shiftKey }); // Ctrl+S for manual save if (event.ctrlKey && event.key === 's') { event.preventDefault(); if (debugLogger) debugLogger.logStep('Manual save shortcut triggered (Ctrl+S)'); this.save(); } }); // Game loop events if (debugLogger) await debugLogger.logStep('Setting up game loop events'); this.addEventListener('gameStarted', () => { if (debugLogger) debugLogger.logStep('Game started event received'); }); this.addEventListener('gameStopped', () => { if (debugLogger) debugLogger.logStep('Game stopped event received'); }); this.addEventListener('gameSaved', () => { // if (debugLogger) debugLogger.logStep('Game saved event received'); }); this.addEventListener('gameLoaded', () => { if (debugLogger) debugLogger.logStep('Game loaded event received'); }); // Setup UI event listeners if (debugLogger) await debugLogger.logStep('Setting up UI event listeners'); if (this.systems.ui && typeof this.systems.ui.setupEventListeners === 'function' && !this.uiEventListenersSetup) { this.systems.ui.setupEventListeners(); this.uiEventListenersSetup = true; // Prevent duplicate setup if (debugLogger) await debugLogger.logStep('UI event listeners setup complete'); } else if (this.uiEventListenersSetup) { if (debugLogger) await debugLogger.logStep('UI event listeners already setup, skipping'); } if (debugLogger) await debugLogger.endStep('setupEventListeners', { windowEvents: 2, keyboardShortcuts: 2, gameLoopEvents: 4 }); } start() { const debugLogger = window.debugLogger; if (this.isRunning) { if (debugLogger) debugLogger.log('GameEngine.start() called but game is already running', { isRunning: this.isRunning, gameTime: this.gameTime }); return; } if (debugLogger) debugLogger.logStep('Starting game engine', { gameLogicInterval: this.gameLogicInterval }); this.isRunning = true; this.lastUpdate = performance.now(); if (debugLogger) debugLogger.logStep('Game engine started, beginning game loop'); this.gameLoop(); // Loading screen is now handled by startGame() method // Don't duplicate the hiding logic here if (debugLogger) debugLogger.logStep('Game loop initiated'); } async stop() { const debugLogger = window.debugLogger; if (debugLogger) await debugLogger.startStep('stopGame'); console.log('[GAME ENGINE] Stopping game and saving...'); if (debugLogger) await debugLogger.logStep('Stopping game engine'); if (!this.isRunning) { if (debugLogger) debugLogger.logStep('Game already stopped, ignoring stop request'); return; } this.isRunning = false; // Clear game logic timer if (this.gameLogicTimer) { clearInterval(this.gameLogicTimer); this.gameLogicTimer = null; } // Clear auto-save timer if (this.autoSaveTimer) { clearInterval(this.autoSaveTimer); this.autoSaveTimer = null; } console.log('[GAME ENGINE] Game stopped and saved successfully'); if (debugLogger) await debugLogger.endStep('stopGame', { gameTime: this.gameTime, isRunning: this.isRunning }); } startAutoSave() { const debugLogger = window.debugLogger; // Load saved interval or use default const savedInterval = localStorage.getItem('autoSaveInterval'); this.autoSaveInterval = savedInterval ? parseInt(savedInterval) : 5; console.log(`[GAME ENGINE] Starting auto-save with ${this.autoSaveInterval} minute interval`); if (debugLogger) debugLogger.logStep('Starting auto-save system', { interval: this.autoSaveInterval, intervalMs: this.autoSaveInterval * 60 * 1000, savedInterval: savedInterval, isRunning: this.isRunning }); // Clear any existing timer this.stopAutoSave(); // Set up new timer this.autoSaveTimer = setInterval(async () => { if (debugLogger) debugLogger.logStep('Auto-save timer triggered', { isRunning: this.isRunning, paused: this.state.paused, gameTime: this.gameTime, lastAutoSave: this.lastAutoSave }); console.log('[GAME ENGINE] Auto-save timer triggered - isRunning:', this.isRunning, 'paused:', this.state.paused); if (this.isRunning && !this.state.paused) { console.log('[GAME ENGINE] Auto-saving game...'); if (debugLogger) debugLogger.logStep('Auto-saving game'); try { await this.save(); this.showNotification('Game auto-saved', 'info', 2000); console.log('[GAME ENGINE] Auto-save completed successfully'); this.lastAutoSave = Date.now(); if (debugLogger) debugLogger.logStep('Auto-save completed successfully', { lastAutoSave: this.lastAutoSave }); } catch (error) { console.error('[GAME ENGINE] Auto-save failed:', error); if (debugLogger) await debugLogger.errorEvent(error, 'Auto-save'); } } else { console.log('[GAME ENGINE] Auto-save skipped - game not running or paused'); if (debugLogger) debugLogger.logStep('Auto-save skipped', { reason: this.isRunning ? 'paused' : 'not running', isRunning: this.isRunning, paused: this.state.paused }); } }, this.autoSaveInterval * 60 * 1000); // Convert minutes to milliseconds this.lastAutoSave = Date.now(); if (debugLogger) debugLogger.logStep('Auto-save timer started', { timerId: this.autoSaveTimer, lastAutoSave: this.lastAutoSave }); } stopAutoSave() { const debugLogger = window.debugLogger; if (this.autoSaveTimer) { console.log('[GAME ENGINE] Stopping auto-save timer'); if (debugLogger) debugLogger.logStep('Stopping auto-save timer', { timerId: this.autoSaveTimer, wasRunning: true }); clearInterval(this.autoSaveTimer); this.autoSaveTimer = null; if (debugLogger) debugLogger.logStep('Auto-save timer stopped'); } else { if (debugLogger) debugLogger.logStep('stopAutoSave called but no timer was active', { timerId: this.autoSaveTimer, wasRunning: false }); } } updateAutoSaveInterval(newInterval) { const debugLogger = window.debugLogger; console.log(`[GAME ENGINE] Updating auto-save interval to ${newInterval} minutes`); if (debugLogger) debugLogger.logStep('Updating auto-save interval', { oldInterval: this.autoSaveInterval, newInterval: newInterval, isRunning: this.isRunning }); this.autoSaveInterval = newInterval; // Save to localStorage localStorage.setItem('autoSaveInterval', newInterval.toString()); // Restart auto-save with new interval if game is running if (this.isRunning) { if (debugLogger) debugLogger.logStep('Restarting auto-save with new interval'); this.startAutoSave(); } if (debugLogger) debugLogger.logStep('Auto-save interval updated successfully', { currentInterval: this.autoSaveInterval, savedToStorage: true }); } start() { const debugLogger = window.debugLogger; if (this.isRunning) { if (debugLogger) debugLogger.log('GameEngine.start() called but game is already running', { isRunning: this.isRunning, gameTime: this.gameTime }); return; } if (debugLogger) debugLogger.logStep('Starting game engine', { gameLogicInterval: this.gameLogicInterval }); this.isRunning = true; this.lastUpdate = Date.now(); // Start game logic timer (completely independent of frame rate) console.log('[GAME ENGINE] Starting game logic timer with interval:', this.gameLogicInterval); this.gameLogicTimer = setInterval(() => { this.updateGameLogic(); }, this.gameLogicInterval); // Start auto-save this.startAutoSave(); console.log('[GAME ENGINE] Game engine started'); if (debugLogger) debugLogger.logStep('Game engine started successfully', { gameLogicInterval: this.gameLogicInterval, autoSaveInterval: this.autoSaveInterval }); } updateGameLogic() { const debugLogger = window.debugLogger; // Use fixed 1-second interval for all updates const fixedDelta = 1000; // 1 second in milliseconds console.log('[GAME ENGINE] Game logic update called - adding', fixedDelta, 'ms to playtime'); if (this.state.paused) { if (debugLogger) debugLogger.logStep('Game logic update called but game is paused', { gameTime: this.gameTime, fixedDelta: fixedDelta }); return; } this.gameTime += fixedDelta; console.log('[GAME ENGINE] Total game time now:', this.gameTime, 'ms'); // Emit UI update event instead of direct call this.emitUIUpdateEvent('full'); // Log update performance every 300 frames (approximately 5 seconds) if (debugLogger && this.gameTime % 15000 === 0) { // Every 15 seconds of game time debugLogger.logStep('Game logic update cycle', { gameTime: this.gameTime, fixedDelta: fixedDelta, isRunning: this.isRunning, paused: this.state.paused, currentTab: this.state.currentTab }); } // Update player play time with fixed delta if (this.systems.player && this.systems.player.updatePlayTime) { console.log('[GAME ENGINE] Before update - player playTime:', this.systems.player.stats.playTime); this.systems.player.updatePlayTime(fixedDelta); console.log('[GAME ENGINE] After update - player playTime:', this.systems.player.stats.playTime); } // Update all systems with fixed delta for (const [name, system] of Object.entries(this.systems)) { if (system && typeof system.update === 'function') { try { system.update(fixedDelta); } catch (error) { console.error(`[GAME ENGINE] Error updating ${name} system:`, error); if (debugLogger) debugLogger.errorEvent(error, `Update ${name} system`); } } } // Update UI displays (money, gems, energy) after system updates if (this.systems && this.systems.ui) { console.log('[GAME ENGINE] Updating UI displays'); try { this.systems.ui.updateUI(); console.log('[GAME ENGINE] UI update completed'); } catch (error) { console.error('[GAME ENGINE] Error updating UI:', error); } } } update(deltaTime) { // Legacy method - game logic now handled by updateGameLogic() // This method kept for compatibility but doesn't process game systems } shouldUpdateGUI() { const currentTime = Date.now(); if (currentTime - this.lastGUIUpdate >= this.guiUpdateInterval) { this.lastGUIUpdate = currentTime; return true; } return false; } updateGUI() { const debugLogger = window.debugLogger; console.log('[GAME ENGINE] Updating GUI'); // Update UI displays (money, gems, energy) after system updates if (this.systems && this.systems.ui) { console.log('[GAME ENGINE] Updating UI displays'); try { this.systems.ui.updateUI(); console.log('[GAME ENGINE] UI update completed'); } catch (error) { console.error('[GAME ENGINE] Error updating UI:', error); } } } // Event system on(event, callback) { if (!this.eventListeners.has(event)) { this.eventListeners.set(event, []); } this.eventListeners.get(event).push(callback); } emit(event, data) { if (this.eventListeners.has(event)) { this.eventListeners.get(event).forEach(callback => { try { callback(data); } catch (error) { console.error(`[GAME ENGINE] Error in event listener for ${event}:`, error); } }); } // Also dispatch as DOM event for UIManager this.dispatchEvent(new CustomEvent(event, { detail: data })); } emitUIUpdateEvent(type, data = {}) { const eventData = { type: type, timestamp: Date.now(), ...data }; console.log('[GAME ENGINE] Emitting UI update event:', eventData); this.emit('uiUpdate', eventData); } // Notification system async showNotification(message, type = 'info', duration = 3000) { const logger = window.logger; if (logger) await logger.playerAction('Notification', { message, type, duration }); const notification = { id: Date.now(), message, type, duration, timestamp: Date.now() }; this.state.notifications.push(notification); // Auto-remove notification after duration setTimeout(() => { this.removeNotification(notification.id); }, duration); // Update UI if (this.systems.ui) { // UI updates handled by individual systems } } removeNotification(id) { this.state.notifications = this.state.notifications.filter(notification => notification.id !== id); } processNotifications() { const now = Date.now(); this.state.notifications = this.state.notifications.filter( notification => now - notification.timestamp < notification.duration ); } // Save/Load system async save() { const logger = window.logger; const debugLogger = window.debugLogger; console.log('[GAME ENGINE] Save method called'); if (logger) await logger.info('Saving game'); // if (debugLogger) await debugLogger.startStep('saveGame'); try { // if (debugLogger) await debugLogger.logStep('Collecting save data from systems'); console.log('[GAME ENGINE] Collecting save data from systems...'); const saveData = { player: this.systems.player.save(), inventory: this.systems.inventory.save(), economy: this.systems.economy.save(), idleSystem: this.systems.idleSystem.save(), dungeonSystem: this.systems.dungeonSystem.save(), skillSystem: this.systems.skillSystem.save(), baseSystem: this.systems.baseSystem.save(), questSystem: this.systems.questSystem.save(), gameTime: this.gameTime, lastSave: Date.now() }; // if (debugLogger) await debugLogger.logStep('Save data collected', { // playerLevel: saveData.player?.stats?.level, // gameTime: this.gameTime, // saveDataSize: JSON.stringify(saveData).length, // }); // console.log('[GAME ENGINE] Save data collected, player level:', saveData.player?.stats?.level); // console.log('[GAME ENGINE] Save slot info:', this.saveSlotInfo); // Check if we're in local mode and should use localStorage const isLocalMode = window.liveMainMenu && window.liveMainMenu.isLocalMode; if (isLocalMode) { console.log('[GAME ENGINE] Using localStorage for local mode save'); if (debugLogger) await debugLogger.logStep('Saving via localStorage for local mode'); try { const saveKey = `gso_save_slot_${this.saveSlotInfo.slot}`; const saveString = JSON.stringify(saveData); // Save to localStorage localStorage.setItem(saveKey, saveString); console.log('[GAME ENGINE] Game saved successfully to localStorage'); console.log('[GAME ENGINE] Save key:', saveKey); console.log('[GAME ENGINE] Save data size:', saveString.length, 'characters'); console.log('[GAME ENGINE] Current localStorage keys:', Object.keys(localStorage)); // Verify save exists const verifySave = localStorage.getItem(saveKey); console.log('[GAME ENGINE] Save verification:', !!verifySave ? 'SUCCESS' : 'FAILED'); if (debugLogger) await debugLogger.logStep('Game saved successfully to localStorage', { saveKey, saveDataSize: saveString.length }); // Emit save event this.emit('gameSaved', { slot: this.saveSlotInfo.slot, saveData }); // if (debugLogger) debugLogger.logStep('Game saved event emitted'); } catch (error) { console.error('[GAME ENGINE] Failed to save to localStorage:', error); if (debugLogger) await debugLogger.errorEvent(error, 'LocalStorage Save'); throw error; } } else { // Use file system if available, otherwise localStorage (original logic) if (this.saveSlotInfo && this.saveSlotInfo.useFileSystem) { if (window.electronAPI) { // console.log('[GAME ENGINE] Using Electron API to save game'); // if (debugLogger) await debugLogger.logStep('Saving via Electron API', { // slot: this.saveSlotInfo.slot, // useFileSystem: true // }); try { // Save through Electron API const result = await window.electronAPI.saveGame(this.saveSlotInfo.slot, saveData); if (result.success) { // console.log('[GAME ENGINE] Game saved successfully via Electron API'); if (debugLogger) await debugLogger.logStep('Game saved successfully via Electron API', { slot: this.saveSlotInfo.slot, result: result }); // Emit save event this.emit('gameSaved', { slot: this.saveSlotInfo.slot, saveData }); // if (debugLogger) debugLogger.logStep('Game saved event emitted'); } else { console.error('[GAME ENGINE] Failed to save via Electron API:', result.error); if (debugLogger) await debugLogger.errorEvent(new Error(result.error), 'Electron API Save'); // Fallback to localStorage if (debugLogger) await debugLogger.logStep('Falling back to localStorage'); const saveKey = `gso_save_slot_${this.saveSlotInfo.slot}`; localStorage.setItem(saveKey, JSON.stringify(saveData)); console.log('[GAME ENGINE] Fallback: Game saved to localStorage with key:', saveKey); if (debugLogger) await debugLogger.logStep('Game saved to localStorage fallback', { saveKey, dataSize: JSON.stringify(saveData).length }); } } catch (error) { console.error('[GAME ENGINE] Electron API save error:', error); if (debugLogger) await debugLogger.errorEvent(error, 'Electron API Save'); // Fallback to localStorage if (debugLogger) await debugLogger.logStep('Falling back to localStorage due to error'); const saveKey = `gso_save_slot_${this.saveSlotInfo.slot}`; localStorage.setItem(saveKey, JSON.stringify(saveData)); console.log('[GAME ENGINE] Error fallback: Game saved to localStorage with key:', saveKey); } } else { console.warn('[GAME ENGINE] Electron API not available, using localStorage'); if (debugLogger) await debugLogger.warn('Electron API not available, using localStorage'); const saveKey = `gso_save_slot_${this.saveSlotInfo.slot}`; localStorage.setItem(saveKey, JSON.stringify(saveData)); console.log('[GAME ENGINE] Game saved to localStorage with key:', saveKey); if (debugLogger) await debugLogger.logStep('Game saved to localStorage', { saveKey, dataSize: JSON.stringify(saveData).length }); } } else { // LocalStorage fallback if (debugLogger) await debugLogger.logStep('Using localStorage save'); const saveKey = `gso_save_slot_${this.saveSlotInfo.slot}`; localStorage.setItem(saveKey, JSON.stringify(saveData)); console.log('[GAME ENGINE] Game saved to localStorage with key:', saveKey); if (debugLogger) await debugLogger.logStep('Game saved to localStorage', { saveKey, dataSize: JSON.stringify(saveData).length }); } } if (logger) await logger.info('Game saved successfully'); // if (debugLogger) await debugLogger.endStep('saveGame', { // gameTime: this.gameTime, // saveSlot: this.saveSlotInfo?.slot, // success: true // }); } catch (error) { console.error('[GAME ENGINE] Save failed:', error); if (logger) await logger.errorEvent(error, 'Game Save'); if (debugLogger) await debugLogger.errorEvent(error, 'Game Save'); throw error; } } async loadGame() { const logger = window.logger; const debugLogger = window.debugLogger; console.log('[GAME ENGINE] Load method called'); if (logger) await logger.info('Loading game'); if (debugLogger) await debugLogger.startStep('loadGame'); try { if (debugLogger) await debugLogger.logStep('Loading save data', { saveSlot: this.saveSlotInfo?.slot, useFileSystem: this.saveSlotInfo?.useFileSystem }); let saveData; // Use file system if available, otherwise localStorage if (this.saveSlotInfo && this.saveSlotInfo.useFileSystem && window.electronAPI) { console.log('[GAME ENGINE] Loading via Electron API'); if (debugLogger) await debugLogger.logStep('Loading via Electron API'); const result = await window.electronAPI.loadGame(this.saveSlotInfo.slot); if (result.success) { saveData = result.data; console.log('[GAME ENGINE] Game loaded successfully via Electron API'); if (debugLogger) await debugLogger.logStep('Game loaded via Electron API', { slot: this.saveSlotInfo.slot, dataSize: JSON.stringify(saveData).length }); } else { console.error('[GAME ENGINE] Failed to load via Electron API:', result.error); if (debugLogger) await debugLogger.errorEvent(new Error(result.error), 'Electron API Load'); throw new Error(result.error); } } else { // LocalStorage fallback console.log('[GAME ENGINE] Loading from localStorage'); if (debugLogger) await debugLogger.logStep('Loading from localStorage'); const saveKey = `gso_save_slot_${this.saveSlotInfo.slot}`; const saveString = localStorage.getItem(saveKey); if (saveString) { try { saveData = JSON.parse(saveString); console.log('[GAME ENGINE] Game loaded from localStorage'); if (debugLogger) await debugLogger.logStep('Game loaded from localStorage', { saveKey, dataSize: saveString.length }); } catch (parseError) { console.error('[GAME ENGINE] Failed to parse save data:', parseError); if (debugLogger) await debugLogger.errorEvent(parseError, 'Parse Save Data'); throw new Error('Corrupted save data'); } } else { console.warn('[GAME ENGINE] No save data found in localStorage'); if (debugLogger) await debugLogger.warn('No save data found in localStorage', { saveKey }); throw new Error('No save data found'); } } if (debugLogger) await debugLogger.logStep('Applying save data to systems'); // Apply save data to systems if (saveData.player && this.systems.player) { console.log('[GAME ENGINE] Loading player data...'); this.systems.player.load(saveData.player); if (debugLogger) await debugLogger.logStep('Player data loaded', { level: saveData.player?.stats?.level, experience: saveData.player?.stats?.experience }); } if (saveData.inventory && this.systems.inventory) { console.log('[GAME ENGINE] Loading inventory data...'); this.systems.inventory.load(saveData.inventory); if (debugLogger) await debugLogger.logStep('Inventory data loaded', { itemCount: saveData.inventory.items?.length || 0 }); } if (saveData.economy && this.systems.economy) { console.log('[GAME ENGINE] Loading economy data...'); this.systems.economy.load(saveData.economy); if (debugLogger) await debugLogger.logStep('Economy data loaded', { credits: saveData.economy.credits, gems: saveData.economy.gems }); } if (saveData.questSystem && this.systems.questSystem) { console.log('[GAME ENGINE] Loading quest data...'); try { this.systems.questSystem.load(saveData.questSystem); if (debugLogger) await debugLogger.logStep('Quest data loaded', { mainQuestsCount: saveData.questSystem.mainQuests?.length || 0, dailyQuestsCount: saveData.questSystem.dailyQuests?.length || 0 }); console.log('[GAME ENGINE] Quest data loaded successfully'); } catch (questError) { console.error('[GAME ENGINE] Failed to load quest data:', questError); if (debugLogger) await debugLogger.errorEvent(questError, 'Quest data load failed'); // Continue with other systems instead of throwing } } if (saveData.baseSystem && this.systems.baseSystem) { console.log('[GAME ENGINE] Loading base data...'); try { this.systems.baseSystem.load(saveData.baseSystem); if (debugLogger) await debugLogger.logStep('Base data loaded', { baseLevel: saveData.baseSystem.base?.level || 1, roomsCount: saveData.baseSystem.base?.rooms?.length || 0 }); console.log('[GAME ENGINE] Base data loaded successfully'); } catch (baseError) { console.error('[GAME ENGINE] Failed to load base data:', baseError); if (debugLogger) await debugLogger.errorEvent(baseError, 'Base data load failed'); } } if (saveData.skillSystem && this.systems.skillSystem) { console.log('[GAME ENGINE] Loading skill data...'); try { this.systems.skillSystem.load(saveData.skillSystem); if (debugLogger) await debugLogger.logStep('Skill data loaded'); console.log('[GAME ENGINE] Skill data loaded successfully'); } catch (skillError) { console.error('[GAME ENGINE] Failed to load skill data:', skillError); if (debugLogger) await debugLogger.errorEvent(skillError, 'Skill data load failed'); } } // CRITICAL: Initialize UIManager after loading save data console.log('[GAME ENGINE] About to initialize UIManager - checking systems...'); console.log('[GAME ENGINE] Available systems:', Object.keys(this.systems)); console.log('[GAME ENGINE] UIManager exists:', !!this.systems.ui); if (this.systems.ui) { console.log('[GAME ENGINE] Initializing UIManager after save load...'); if (debugLogger) await debugLogger.logStep('Initializing UIManager after save load'); try { await this.systems.ui.initialize(); console.log('[GAME ENGINE] UIManager initialized successfully'); if (debugLogger) await debugLogger.logStep('UIManager initialized successfully'); } catch (uiError) { console.error('[GAME ENGINE] UIManager initialization failed:', uiError); if (debugLogger) await debugLogger.errorEvent(uiError, 'UIManager initialization failed'); } } else { console.log('[GAME ENGINE] UIManager not found in systems!'); } console.log('[GAME ENGINE] UIManager initialization section completed'); // Initialize DungeonSystem after UIManager is ready if (this.systems.dungeonSystem) { console.log('[GAME ENGINE] Initializing DungeonSystem...'); if (debugLogger) await debugLogger.logStep('Initializing DungeonSystem after save load'); try { await this.systems.dungeonSystem.initialize(); console.log('[GAME ENGINE] DungeonSystem initialized successfully'); if (debugLogger) await debugLogger.logStep('DungeonSystem initialized successfully'); } catch (dungeonError) { console.error('[GAME ENGINE] DungeonSystem initialization failed:', dungeonError); if (debugLogger) await debugLogger.errorEvent(dungeonError, 'DungeonSystem initialization failed'); } } else { console.log('[GAME ENGINE] DungeonSystem not found in systems!'); } // Restore game time if (saveData.gameTime !== undefined) { this.gameTime = saveData.gameTime; console.log('[GAME ENGINE] Game time restored:', this.gameTime); } console.log('[GAME ENGINE] loadGame method completed successfully'); } catch (error) { console.error('[GAME ENGINE] Failed to load game:', error); if (logger) await logger.errorEvent(error, 'Game Load'); if (debugLogger) await debugLogger.errorEvent(error, 'loadGame'); if (debugLogger) await debugLogger.endStep('loadGame', { success: false, error: error.message }); throw error; } } async load() { const logger = window.logger; const debugLogger = window.debugLogger; console.log('[GAME ENGINE] Load method called'); if (logger) await logger.info('Loading game'); if (debugLogger) await debugLogger.startStep('loadGame'); try { if (debugLogger) await debugLogger.logStep('Loading save data', { saveSlot: this.saveSlotInfo?.slot, useFileSystem: this.saveSlotInfo?.useFileSystem }); let saveData; // Use file system if available, otherwise localStorage if (this.saveSlotInfo && this.saveSlotInfo.useFileSystem && window.electronAPI) { console.log('[GAME ENGINE] Loading via Electron API'); if (debugLogger) await debugLogger.logStep('Loading via Electron API'); const result = await window.electronAPI.loadGame(this.saveSlotInfo.slot); if (result.success) { saveData = result.data; console.log('[GAME ENGINE] Game loaded successfully via Electron API'); if (debugLogger) await debugLogger.logStep('Game loaded via Electron API', { slot: this.saveSlotInfo.slot, dataSize: JSON.stringify(saveData).length }); } else { console.error('[GAME ENGINE] Failed to load via Electron API:', result.error); if (debugLogger) await debugLogger.errorEvent(new Error(result.error), 'Electron API Load'); throw new Error(result.error); } } else { // LocalStorage fallback console.log('[GAME ENGINE] Loading from localStorage'); if (debugLogger) await debugLogger.logStep('Loading from localStorage'); const saveKey = `gso_save_slot_${this.saveSlotInfo.slot}`; const saveString = localStorage.getItem(saveKey); if (saveString) { try { saveData = JSON.parse(saveString); console.log('[GAME ENGINE] Game loaded from localStorage'); if (debugLogger) await debugLogger.logStep('Game loaded from localStorage', { saveKey, dataSize: saveString.length }); } catch (parseError) { console.error('[GAME ENGINE] Failed to parse save data:', parseError); if (debugLogger) await debugLogger.errorEvent(parseError, 'Parse Save Data'); throw new Error('Corrupted save data'); } } else { console.warn('[GAME ENGINE] No save data found in localStorage'); if (debugLogger) await debugLogger.warn('No save data found in localStorage', { saveKey }); throw new Error('No save data found'); } } // if (debugLogger) await debugLogger.logStep('Applying save data to systems'); // Apply save data to systems if (saveData.player && this.systems.player) { console.log('[GAME ENGINE] Loading player data...'); this.systems.player.load(saveData.player); if (debugLogger) await debugLogger.logStep('Player data loaded', { level: saveData.player?.stats?.level, experience: saveData.player?.stats?.experience }); } if (saveData.inventory && this.systems.inventory) { console.log('[GAME ENGINE] Loading inventory data...'); this.systems.inventory.load(saveData.inventory); if (debugLogger) await debugLogger.logStep('Inventory data loaded', { itemCount: saveData.inventory.items?.length || 0 }); } if (saveData.economy && this.systems.economy) { console.log('[GAME ENGINE] Loading economy data...'); this.systems.economy.load(saveData.economy); if (debugLogger) await debugLogger.logStep('Economy data loaded', { credits: saveData.economy.credits, gems: saveData.economy.gems }); } if (saveData.gameTime) { this.gameTime = saveData.gameTime; if (debugLogger) await debugLogger.logStep('Game time restored', { gameTime: this.gameTime }); } // Emit load event this.emit('gameLoaded', { saveData }); if (debugLogger) debugLogger.logStep('Game loaded event emitted'); if (logger) await logger.info('Game loaded successfully'); if (debugLogger) await debugLogger.endStep('loadGame', { gameTime: this.gameTime, saveSlot: this.saveSlotInfo?.slot, success: true }); } catch (error) { console.error('[GAME ENGINE] Load failed:', error); if (logger) await logger.errorEvent(error, 'Game Load'); if (debugLogger) await debugLogger.errorEvent(error, 'Game Load'); throw error; } } async newGame() { const logger = window.logger; const debugLogger = window.debugLogger; console.log('[GAME ENGINE] Starting new game initialization'); if (logger) await logger.info('Starting new game'); if (debugLogger) await debugLogger.startStep('newGame'); try { // For new games, we need to properly initialize systems with default data if (debugLogger) await debugLogger.logStep('Initializing systems for new game'); // Initialize inventory with starting items if (this.systems.inventory) { console.log('[GAME ENGINE] Initializing inventory with starting items'); if (debugLogger) await debugLogger.logStep('Initializing inventory with starting items'); await this.systems.inventory.initialize(); } // Initialize DungeonSystem for new game if (this.systems.dungeonSystem) { console.log('[GAME ENGINE] Initializing DungeonSystem for new game...'); if (debugLogger) await debugLogger.logStep('Initializing DungeonSystem for new game'); try { await this.systems.dungeonSystem.initialize(); console.log('[GAME ENGINE] DungeonSystem initialized successfully for new game'); if (debugLogger) await debugLogger.logStep('DungeonSystem initialized successfully for new game'); } catch (dungeonError) { console.error('[GAME ENGINE] DungeonSystem initialization failed for new game:', dungeonError); if (debugLogger) await debugLogger.errorEvent(dungeonError, 'DungeonSystem initialization failed for new game'); } } else { console.log('[GAME ENGINE] DungeonSystem not found in systems!'); } if (this.systems.player) { console.log('[GAME ENGINE] Resetting player to initial state'); if (debugLogger) await debugLogger.logStep('Resetting player to initial state'); this.systems.player.resetToLevel1(); console.log('[GAME ENGINE] Player reset completed'); if (debugLogger) await debugLogger.logStep('Player reset completed', { level: this.systems.player.stats.level, experience: this.systems.player.stats.experience, playTime: this.systems.player.stats.playTime }); console.log('[GAME ENGINE] Setting up new player'); if (debugLogger) await debugLogger.logStep('Setting up new player'); this.systems.player.setupNewPlayer(); console.log('[GAME ENGINE] Player setup completed'); if (debugLogger) await debugLogger.logStep('Player setup completed', { level: this.systems.player.stats.level, experience: this.systems.player.stats.experience }); } else { console.error('[GAME ENGINE] Player system not available'); if (debugLogger) await debugLogger.error('Player system not available'); } if (debugLogger) await debugLogger.logStep('Resetting economy system'); console.log('[GAME ENGINE] Step 2: Resetting economy system'); if (this.systems.economy) { console.log('[GAME ENGINE] Calling economy.reset()'); if (debugLogger) await debugLogger.logStep('Calling economy.reset()'); this.systems.economy.reset(); console.log('[GAME ENGINE] Economy reset completed'); if (debugLogger) await debugLogger.logStep('Economy reset completed', { credits: this.systems.economy.credits, gems: this.systems.economy.gems }); } else { console.error('[GAME ENGINE] Economy system not available'); if (debugLogger) await debugLogger.error('Economy system not available'); } // Skip inventory reset - initialize() already handles proper setup if (debugLogger) await debugLogger.logStep('Skipping inventory reset - already initialized'); console.log('[GAME ENGINE] Skipping inventory reset - already initialized with starting items'); if (this.systems.inventory) { if (debugLogger) await debugLogger.logStep('Inventory already initialized', { itemCount: this.systems.inventory.items.length }); } else { console.error('[GAME ENGINE] Inventory system not available'); if (debugLogger) await debugLogger.error('Inventory system not available'); } if (debugLogger) await debugLogger.logStep('Resetting quest system'); console.log('[GAME ENGINE] Step 4: Resetting quest system'); if (this.systems.questSystem) { console.log('[GAME ENGINE] Calling questSystem.reset()'); if (debugLogger) await debugLogger.logStep('Calling questSystem.reset()'); this.systems.questSystem.reset(); console.log('[GAME ENGINE] Quest system reset completed'); if (debugLogger) await debugLogger.logStep('Quest system reset completed'); // Activate the tutorial quest for new games console.log('[GAME ENGINE] Activating tutorial quest for new game'); if (debugLogger) await debugLogger.logStep('Activating tutorial quest'); this.systems.questSystem.startQuest('tutorial_complete'); console.log('[GAME ENGINE] Tutorial quest activated'); if (debugLogger) await debugLogger.logStep('Tutorial quest activated'); } else { console.error('[GAME ENGINE] Quest system not available'); if (debugLogger) await debugLogger.error('Quest system not available'); } if (debugLogger) await debugLogger.logStep('Resetting game time'); console.log('[GAME ENGINE] Step 5: Resetting game time'); this.gameTime = 0; console.log('[GAME ENGINE] Game time reset to 0'); if (debugLogger) await debugLogger.logStep('Game time reset', { gameTime: this.gameTime }); if (logger) await logger.info('New game initialized successfully'); if (debugLogger) await debugLogger.endStep('newGame', { gameTime: this.gameTime, playerLevel: this.systems.player?.stats.level, success: true }); } catch (error) { console.error('[GAME ENGINE] Failed to initialize new game:', error); if (logger) await logger.errorEvent(error, 'New Game Initialization'); if (debugLogger) await debugLogger.errorEvent(error, 'New Game Initialization'); throw error; } } // Utility methods formatNumber(num) { if (num >= 1e9) return (num / 1e9).toFixed(2) + 'B'; if (num >= 1e6) return (num / 1e6).toFixed(2) + 'M'; if (num >= 1e3) return (num / 1e3).toFixed(2) + 'K'; return num.toString(); } formatTime(seconds) { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); const secs = Math.floor(seconds % 60); if (hours > 0) { return `${hours}h ${minutes}m ${secs}s`; } else if (minutes > 0) { return `${minutes}m ${secs}s`; } else { return `${secs}s`; } } toggleDebugConsole() { const debugLogger = window.debugLogger; // if (debugLogger) debugLogger.logStep('Toggle debug console requested'); // Implementation would go here // console.log('[GAME ENGINE] Debug console toggle requested'); } getPerformanceStats() { const debugLogger = window.debugLogger; const stats = { gameTime: this.gameTime, isRunning: this.isRunning, lastUpdate: this.lastUpdate, memory: null }; // Add memory info if available if (window.performance && window.performance.memory) { stats.memory = { used: window.performance.memory.usedJSHeapSize, total: window.performance.memory.totalJSHeapSize, limit: window.performance.memory.jsHeapSizeLimit }; } // if (debugLogger) debugLogger.logStep('Performance stats requested', stats); return stats; } } // Global game instance let game = null; // Export GameEngine to global scope if (typeof window !== 'undefined') { window.GameEngine = GameEngine; }