/** * GAME MANAGER - AUTO-SAVE SYSTEM * "The Silent Protector" - Never lose progress! */ class GameManager { constructor(scene) { this.scene = scene; this.saveKey = 'mrtva_dolina_save'; // Slot_0 // Auto-save state this.lastAutoSave = Date.now(); this.autoSaveInterval = 5 * 60 * 1000; // 5 minutes this.isSaving = false; // Save indicator this.saveIndicator = null; // Initialize this.init(); } init() { console.log('💾 GameManager initialized - Auto-save active'); // Start periodic auto-save timer this.startPeriodicAutoSave(); // Listen for scene transitions this.scene.events.on('shutdown', () => this.onSceneTransition()); // Listen for progression events this.listenForProgressionEvents(); } /** * TRIGGER 1: SCENE TRANSITION SAVE */ onSceneTransition() { console.log('🚪 Scene transition detected - Auto-saving...'); this.autoSaveGame('Scene Transition'); } /** * TRIGGER 2: PROGRESSION MILESTONE SAVE */ listenForProgressionEvents() { // Listen for aging events this.scene.events.on('kai-aged', (data) => { console.log(`⏰ Kai aged to ${data.newAge} - Auto-saving...`); this.autoSaveGame('Aging Milestone'); }); // Listen for memory found this.scene.events.on('memory-found', (data) => { console.log(`📸 Memory found (${data.id}) - Auto-saving...`); this.autoSaveGame('Memory Found'); }); // Listen for Gronk level up if (window.gronkStats) { window.addEventListener('gronk-levelup', (e) => { console.log(`💨 Gronk level ${e.detail.level} - Auto-saving...`); this.autoSaveGame('Gronk Level Up'); }); } // Listen for companion unlocks window.addEventListener('companion-unlocked', (e) => { console.log(`🐕 Companion unlocked (${e.detail.name}) - Auto-saving...`); this.autoSaveGame('Companion Unlock'); }); } /** * TRIGGER 3: PERIODIC AUTO-SAVE (5 Minutes) */ startPeriodicAutoSave() { this.periodicTimer = this.scene.time.addEvent({ delay: this.autoSaveInterval, callback: () => { const timeSinceLastSave = Date.now() - this.lastAutoSave; if (timeSinceLastSave >= this.autoSaveInterval) { console.log('⏱️ 5 minutes elapsed - Auto-saving...'); this.autoSaveGame('Periodic (5min)'); } }, loop: true }); } /** * AUTO-SAVE GAME (Silent, no interruption) */ autoSaveGame(reason = 'Manual') { if (this.isSaving) { console.log('⚠️ Save already in progress, skipping...'); return; } this.isSaving = true; console.log(`💾 AUTO-SAVING (${reason})...`); // Show save indicator this.showSaveIndicator(); try { // Gather save data const saveData = this.gatherSaveData(); // Save to LocalStorage (Slot_0) localStorage.setItem(this.saveKey, JSON.stringify(saveData)); // Update timestamp this.lastAutoSave = Date.now(); console.log('✅ Auto-save complete!'); console.log(` Reason: ${reason}`); console.log(` Size: ${JSON.stringify(saveData).length} bytes`); } catch (error) { console.error('❌ Auto-save failed:', error); } finally { this.isSaving = false; } } /** * GATHER ALL SAVE DATA */ gatherSaveData() { const data = { version: '1.0.0', lastSaved: new Date().toISOString(), playtime: this.getPlaytime(), // Player data player: this.getPlayerData(), // Progress progress: this.getProgressData(), // Companions companions: this.getCompanionData(), // Farm state farm: this.getFarmData(), // Economy economy: this.getEconomyData(), // Current scene currentScene: this.scene.scene.key }; return data; } /** * GET PLAYER DATA */ getPlayerData() { // Get PlayerStats if exists let playerStats = null; if (this.scene.playerStats) { playerStats = this.scene.playerStats.getAgeInfo(); } else { // Load from LocalStorage const stored = localStorage.getItem('player_stats'); if (stored) { playerStats = JSON.parse(stored); } } return { position: this.getPlayerPosition(), age_level: playerStats?.level || 1, current_age: playerStats?.age || 14, age_sprite: playerStats?.sprite || 'kai_age14', inventory: this.getInventory(), health: 100, stamina: 100, equipped_tools: {} }; } /** * GET PROGRESS DATA */ getProgressData() { return { memories_found: this.getMemoriesFound(), total_memories: 100, quests_completed: [], npcs_met: [], biomes_unlocked: ['grassland'] }; } /** * GET COMPANION DATA */ getCompanionData() { const companions = { gronk: { unlocked: false, level: 1, xp: 0 }, susi: { unlocked: false, position: { x: 0, y: 0 }, loyalty: 0 } }; // Check Gronk stats if (window.gronkStats) { const gronkData = gronkStats.getStats(); companions.gronk = { unlocked: true, level: gronkData.level, xp: gronkData.xp }; } // Check Susi unlock const susiUnlocked = localStorage.getItem('susi_unlocked'); if (susiUnlocked === 'true') { companions.susi.unlocked = true; } return companions; } /** * GET FARM DATA */ getFarmData() { return { crops: [], buildings: [], animals: [], resources: {} }; } /** * GET ECONOMY DATA */ getEconomyData() { return { money: 0, cannabis_seeds: 5, // Starting capital! cannabis_harvested: 0 }; } /** * HELPER: Get player position */ getPlayerPosition() { if (this.scene.player) { return { x: this.scene.player.x, y: this.scene.player.y }; } return { x: 640, y: 360 }; // Default center } /** * HELPER: Get inventory */ getInventory() { // TODO: Get from inventory system return []; } /** * HELPER: Get memories found */ getMemoriesFound() { const stored = localStorage.getItem('player_stats'); if (stored) { const data = JSON.parse(stored); return data.memoriesFound || 0; } return 0; } /** * HELPER: Get playtime */ getPlaytime() { const stored = localStorage.getItem('playtime'); if (stored) { return parseInt(stored) + Math.floor(this.scene.time.now / 1000); } return Math.floor(this.scene.time.now / 1000); } /** * SHOW SAVE INDICATOR (Spinning Longboard) */ showSaveIndicator() { if (this.saveIndicator) { return; // Already showing } const width = this.scene.cameras.main.width; const height = this.scene.cameras.main.height; // Create longboard emoji as indicator this.saveIndicator = this.scene.add.text( width - 80, height - 80, '🛹', { fontSize: '32px' } ); this.saveIndicator.setScrollFactor(0); this.saveIndicator.setDepth(9999); this.saveIndicator.setAlpha(0); // Add "Saving..." text const savingText = this.scene.add.text( width - 140, height - 50, 'Saving...', { fontSize: '14px', fontFamily: 'Georgia, serif', color: '#f4e4c1', stroke: '#000000', strokeThickness: 3 } ); savingText.setScrollFactor(0); savingText.setDepth(9999); savingText.setAlpha(0); // Fade in this.scene.tweens.add({ targets: [this.saveIndicator, savingText], alpha: 0.8, duration: 300 }); // Spin animation this.scene.tweens.add({ targets: this.saveIndicator, angle: 360, duration: 1000, repeat: 1 }); // Fade out after 2 seconds this.scene.time.delayedCall(2000, () => { this.scene.tweens.add({ targets: [this.saveIndicator, savingText], alpha: 0, duration: 500, onComplete: () => { if (this.saveIndicator) { this.saveIndicator.destroy(); this.saveIndicator = null; } if (savingText) { savingText.destroy(); } } }); }); } /** * MANUAL SAVE (for explicit save points) */ manualSave() { console.log('💾 Manual save requested...'); this.autoSaveGame('Manual Save'); } /** * CLEANUP */ destroy() { if (this.periodicTimer) { this.periodicTimer.remove(); } console.log('💾 GameManager destroyed'); } } export default GameManager;