/** * SAVE SYSTEM EXPANSION * Advanced save/load with cloud sync, multiple slots, and auto-save */ class SaveSystemExpansion { constructor(scene) { this.scene = scene; this.enabled = true; // Save slots this.maxSlots = 5; this.currentSlot = 1; this.saveSlots = new Map(); // Cloud sync this.cloudSyncEnabled = false; this.lastCloudSync = 0; this.syncInterval = 300000; // 5 minutes // Auto-save this.autoSaveEnabled = true; this.autoSaveInterval = 300000; // 5 minutes this.lastAutoSave = 0; this.preventSaveDuringCombat = true; // Backup this.backupEnabled = true; this.maxBackups = 3; this.loadSaveSlots(); this.init(); console.log('✅ Save System Expansion initialized'); } init() { this.setupAutoSave(); console.log('💾 Save system ready'); } // ========== SAVE SLOTS ========== createSaveSlot(slotNumber, saveName) { if (slotNumber < 1 || slotNumber > this.maxSlots) { console.log('❌ Invalid slot number'); return false; } const saveData = this.gatherSaveData(); const slot = { slotNumber, name: saveName || `Save ${slotNumber}`, timestamp: Date.now(), playTime: this.calculatePlayTime(), thumbnail: this.generateThumbnail(), data: saveData }; this.saveSlots.set(slotNumber, slot); this.saveToDisk(slotNumber); console.log(`💾 Save created: Slot ${slotNumber} - ${slot.name}`); return true; } loadSaveSlot(slotNumber) { const slot = this.saveSlots.get(slotNumber); if (!slot) { console.log('❌ Save slot not found'); return false; } this.applySaveData(slot.data); this.currentSlot = slotNumber; console.log(`📂 Save loaded: Slot ${slotNumber} - ${slot.name}`); return true; } deleteSaveSlot(slotNumber) { if (!this.saveSlots.has(slotNumber)) { console.log('❌ Save slot not found'); return false; } this.saveSlots.delete(slotNumber); localStorage.removeItem(`novafarma_save_${slotNumber}`); console.log(`🗑️ Save deleted: Slot ${slotNumber}`); return true; } renameSaveSlot(slotNumber, newName) { const slot = this.saveSlots.get(slotNumber); if (!slot) return false; slot.name = newName; this.saveToDisk(slotNumber); console.log(`✏️ Save renamed: Slot ${slotNumber} → ${newName}`); return true; } // ========== SAVE DATA ========== gatherSaveData() { const data = { version: '3.0.0', timestamp: Date.now(), // Player data player: this.getPlayerData(), // World data world: this.getWorldData(), // Systems data systems: this.getSystemsData(), // Progress progress: this.getProgressData() }; return data; } getPlayerData() { if (!this.scene.player) return null; return { position: this.scene.player.getPosition(), health: this.scene.statsSystem?.health || 100, hunger: this.scene.statsSystem?.hunger || 100, level: this.scene.skillTree?.level || 1, xp: this.scene.skillTree?.xp || 0 }; } getWorldData() { return { time: this.scene.weatherSystem?.currentTime || 0, day: this.scene.weatherSystem?.currentDay || 1, weather: this.scene.weatherSystem?.currentWeather || 'clear', season: this.scene.weatherSystem?.currentSeason || 'spring' }; } getSystemsData() { return { inventory: this.scene.inventorySystem?.items || {}, skills: this.scene.skillTree?.skills || {}, quests: { active: Array.from(this.scene.storyQuest?.activeQuests || []), completed: Array.from(this.scene.storyQuest?.completedQuests || []) }, automation: { workers: this.scene.farmAutomation?.zombieWorkers.length || 0, buildings: this.scene.farmAutomation?.automationBuildings.size || 0 } }; } getProgressData() { return { achievements: this.scene.uiGraphics?.unlockedAchievements || [], bossesDefeated: Array.from(this.scene.bossBattles?.defeatedBosses || []), recipesDiscovered: Array.from(this.scene.cooking?.knownRecipes || []) }; } applySaveData(data) { // Restore player if (data.player && this.scene.player) { this.scene.player.setPosition(data.player.position.x, data.player.position.y); if (this.scene.statsSystem) { this.scene.statsSystem.health = data.player.health; this.scene.statsSystem.hunger = data.player.hunger; } } // Restore world if (data.world && this.scene.weatherSystem) { this.scene.weatherSystem.currentTime = data.world.time; this.scene.weatherSystem.currentDay = data.world.day; this.scene.weatherSystem.setWeather(data.world.weather); } // Restore systems if (data.systems) { if (this.scene.inventorySystem && data.systems.inventory) { this.scene.inventorySystem.items = data.systems.inventory; } } console.log('✅ Save data applied'); } // ========== AUTO-SAVE ========== setupAutoSave() { if (!this.autoSaveEnabled) return; setInterval(() => { this.performAutoSave(); }, this.autoSaveInterval); console.log(`⏰ Auto-save enabled (every ${this.autoSaveInterval / 1000}s)`); } performAutoSave() { if (!this.canAutoSave()) return; this.quickSave(); this.lastAutoSave = Date.now(); console.log('💾 Auto-save performed'); } canAutoSave() { // Don't save during combat if (this.preventSaveDuringCombat && this.isInCombat()) { return false; } return true; } isInCombat() { // Check if player is in combat return false; // Placeholder } // ========== QUICK SAVE/LOAD ========== quickSave() { return this.createSaveSlot(this.currentSlot, `Quick Save`); } quickLoad() { return this.loadSaveSlot(this.currentSlot); } // ========== CLOUD SYNC ========== enableCloudSync() { this.cloudSyncEnabled = true; console.log('☁️ Cloud sync enabled'); } disableCloudSync() { this.cloudSyncEnabled = false; console.log('☁️ Cloud sync disabled'); } syncToCloud(slotNumber) { if (!this.cloudSyncEnabled) { console.log('❌ Cloud sync is disabled'); return false; } const slot = this.saveSlots.get(slotNumber); if (!slot) return false; // Upload to Steam Cloud console.log(`☁️ Uploading save to cloud: Slot ${slotNumber}`); // Simulate cloud upload this.lastCloudSync = Date.now(); return true; } syncFromCloud(slotNumber) { if (!this.cloudSyncEnabled) { console.log('❌ Cloud sync is disabled'); return false; } console.log(`☁️ Downloading save from cloud: Slot ${slotNumber}`); // Simulate cloud download return true; } resolveConflict(localSlot, cloudSlot) { // Show UI to let player choose which save to keep console.log('⚠️ Save conflict detected'); if (localSlot.timestamp > cloudSlot.timestamp) { console.log('📤 Local save is newer - uploading'); return 'upload'; } else { console.log('📥 Cloud save is newer - downloading'); return 'download'; } } // ========== BACKUP SYSTEM ========== createBackup(slotNumber) { if (!this.backupEnabled) return false; const slot = this.saveSlots.get(slotNumber); if (!slot) return false; const backupKey = `novafarma_backup_${slotNumber}_${Date.now()}`; localStorage.setItem(backupKey, JSON.stringify(slot)); // Clean old backups this.cleanOldBackups(slotNumber); console.log(`💾 Backup created: ${backupKey}`); return true; } cleanOldBackups(slotNumber) { const backups = this.getBackups(slotNumber); if (backups.length > this.maxBackups) { // Remove oldest backups const toRemove = backups.slice(0, backups.length - this.maxBackups); toRemove.forEach(backup => { localStorage.removeItem(backup.key); }); } } getBackups(slotNumber) { const backups = []; const prefix = `novafarma_backup_${slotNumber}_`; for (let i = 0; i < localStorage.length; i++) { const key = localStorage.key(i); if (key && key.startsWith(prefix)) { const timestamp = parseInt(key.split('_').pop()); backups.push({ key, timestamp }); } } return backups.sort((a, b) => a.timestamp - b.timestamp); } restoreBackup(backupKey) { const backup = localStorage.getItem(backupKey); if (!backup) { console.log('❌ Backup not found'); return false; } const slot = JSON.parse(backup); this.saveSlots.set(slot.slotNumber, slot); console.log(`📂 Backup restored: ${backupKey}`); return true; } // ========== THUMBNAILS ========== generateThumbnail() { // Generate screenshot thumbnail return { width: 160, height: 90, data: null // Base64 image data }; } // ========== PLAY TIME ========== calculatePlayTime() { // Calculate total play time in seconds return 0; // Placeholder } formatPlayTime(seconds) { const hours = Math.floor(seconds / 3600); const minutes = Math.floor((seconds % 3600) / 60); return `${hours}h ${minutes}m`; } // ========== PERSISTENCE ========== saveToDisk(slotNumber) { const slot = this.saveSlots.get(slotNumber); if (!slot) return; localStorage.setItem(`novafarma_save_${slotNumber}`, JSON.stringify(slot)); // Create backup if (this.backupEnabled) { this.createBackup(slotNumber); } } loadSaveSlots() { for (let i = 1; i <= this.maxSlots; i++) { const saved = localStorage.getItem(`novafarma_save_${i}`); if (saved) { try { const slot = JSON.parse(saved); this.saveSlots.set(i, slot); } catch (error) { console.error(`Failed to load save slot ${i}:`, error); } } } console.log(`✅ Loaded ${this.saveSlots.size} save slots`); } // ========== UPDATE ========== update(delta) { // Auto cloud sync if (this.cloudSyncEnabled) { const now = Date.now(); if (now - this.lastCloudSync > this.syncInterval) { this.syncToCloud(this.currentSlot); } } } destroy() { console.log('💾 Save System Expansion destroyed'); } }