/** * 存档系统 - 保存、加载、重置游戏数据 * Phase 7 核心实现 */ import { resetSkillSystem } from './skillSystem.js' // 存档版本(用于版本控制和迁移) const SAVE_VERSION = 1 const SAVE_KEY = 'wwa3_save_data' /** * 保存游戏数据 * @param {Object} gameStore - 游戏Store * @param {Object} playerStore - 玩家Store * @returns {boolean} 是否保存成功 */ export function saveGame(gameStore, playerStore) { try { // 构建存档数据 const saveData = { version: SAVE_VERSION, timestamp: Date.now(), player: serializePlayerData(playerStore), game: serializeGameData(gameStore) } // 使用uni.setStorageSync同步保存 uni.setStorageSync(SAVE_KEY, JSON.stringify(saveData)) console.log('Game saved successfully') return true } catch (error) { console.error('Failed to save game:', error) return false } } /** * 加载游戏数据 * @param {Object} gameStore - 游戏Store * @param {Object} playerStore - 玩家Store * @returns {Object} { success: boolean, isNewGame: boolean, version: number } */ export function loadGame(gameStore, playerStore) { try { // 读取存档 const saveDataRaw = uni.getStorageSync(SAVE_KEY) if (!saveDataRaw) { console.log('No save data found, starting new game') return { success: false, isNewGame: true, version: 0 } } const saveData = JSON.parse(saveDataRaw) // 验证存档版本 if (saveData.version > SAVE_VERSION) { console.warn('Save version is newer than game version') return { success: false, isNewGame: false, error: 'version_mismatch' } } // 应用存档数据 applySaveData(gameStore, playerStore, saveData) console.log(`Game loaded successfully (version ${saveData.version})`) return { success: true, isNewGame: false, version: saveData.version } } catch (error) { console.error('Failed to load game:', error) return { success: false, isNewGame: true, error: error.message } } } /** * 重置游戏数据 * @param {Object} gameStore - 游戏Store * @param {Object} playerStore - 玩家Store * @returns {boolean} 是否重置成功 */ export function resetGame(gameStore, playerStore) { try { // 重置玩家数据 playerStore.$reset?.() || resetPlayerData(playerStore) // 重置游戏数据 gameStore.$reset?.() || resetGameData(gameStore) // 删除存档 uni.removeStorageSync(SAVE_KEY) console.log('Game reset successfully') return true } catch (error) { console.error('Failed to reset game:', error) return false } } /** * 应用存档数据到Store * @param {Object} gameStore - 游戏Store * @param {Object} playerStore - 玩家Store * @param {Object} saveData - 存档数据 */ export function applySaveData(gameStore, playerStore, saveData) { // 应用玩家数据 if (saveData.player) { applyPlayerData(playerStore, saveData.player) } // 应用游戏数据 if (saveData.game) { applyGameData(gameStore, saveData.game) } // 版本迁移(如果需要) if (saveData.version < SAVE_VERSION) { migrateSaveData(saveData.version, SAVE_VERSION, gameStore, playerStore) } } /** * 序列化玩家数据 * @param {Object} playerStore - 玩家Store * @returns {Object} 序列化的数据 */ function serializePlayerData(playerStore) { return { baseStats: { ...playerStore.baseStats }, currentStats: { ...playerStore.currentStats }, level: { ...playerStore.level }, skills: JSON.parse(JSON.stringify(playerStore.skills || {})), equipment: JSON.parse(JSON.stringify(playerStore.equipment || {})), inventory: JSON.parse(JSON.stringify(playerStore.inventory || [])), currency: { ...playerStore.currency }, currentLocation: playerStore.currentLocation, flags: { ...playerStore.flags }, // 额外数据 milestoneBonuses: playerStore.milestoneBonuses ? JSON.parse(JSON.stringify(playerStore.milestoneBonuses)) : {}, globalBonus: playerStore.globalBonus ? { ...playerStore.globalBonus } : null, equipmentStats: playerStore.equipmentStats ? { ...playerStore.equipmentStats } : null, killCount: playerStore.killCount ? { ...playerStore.killCount } : {} } } /** * 序列化游戏数据 * @param {Object} gameStore - 游戏Store * @returns {Object} 序列化的数据 */ function serializeGameData(gameStore) { return { currentTab: gameStore.currentTab, gameTime: { ...gameStore.gameTime }, activeTasks: JSON.parse(JSON.stringify(gameStore.activeTasks || [])), negativeStatus: JSON.parse(JSON.stringify(gameStore.negativeStatus || [])), marketPrices: JSON.parse(JSON.stringify(gameStore.marketPrices || {})), autoCombat: gameStore.autoCombat || false, // 保存自动战斗状态 // 不保存日志(logs不持久化) // 不保存战斗状态(重新登录时退出战斗) // 不保存当前事件(重新登录时清除) scheduledEvents: JSON.parse(JSON.stringify(gameStore.scheduledEvents || [])) } } /** * 应用玩家数据 * @param {Object} playerStore - 玩家Store * @param {Object} data - 序列化的玩家数据 */ function applyPlayerData(playerStore, data) { // 基础属性 if (data.baseStats) { Object.assign(playerStore.baseStats, data.baseStats) } // 当前资源 if (data.currentStats) { Object.assign(playerStore.currentStats, data.currentStats) } // 等级 if (data.level) { Object.assign(playerStore.level, data.level) } // 技能 if (data.skills) { playerStore.skills = JSON.parse(JSON.stringify(data.skills)) } // 装备 if (data.equipment) { playerStore.equipment = JSON.parse(JSON.stringify(data.equipment)) } // 背包 if (data.inventory) { playerStore.inventory = JSON.parse(JSON.stringify(data.inventory)) } // 货币 if (data.currency) { Object.assign(playerStore.currency, data.currency) } // 位置 if (data.currentLocation !== undefined) { playerStore.currentLocation = data.currentLocation } // 标志 if (data.flags) { Object.assign(playerStore.flags, data.flags) } // 额外数据 if (data.milestoneBonuses) { playerStore.milestoneBonuses = JSON.parse(JSON.stringify(data.milestoneBonuses)) } if (data.globalBonus) { playerStore.globalBonus = { ...data.globalBonus } } if (data.equipmentStats) { playerStore.equipmentStats = { ...data.equipmentStats } } if (data.killCount) { playerStore.killCount = { ...data.killCount } } } /** * 应用游戏数据 * @param {Object} gameStore - 游戏Store * @param {Object} data - 序列化的游戏数据 */ function applyGameData(gameStore, data) { // 当前标签 if (data.currentTab !== undefined) { gameStore.currentTab = data.currentTab } // 游戏时间 if (data.gameTime) { Object.assign(gameStore.gameTime, data.gameTime) } // 活动任务 if (data.activeTasks) { gameStore.activeTasks = JSON.parse(JSON.stringify(data.activeTasks)) } // 负面状态 if (data.negativeStatus) { gameStore.negativeStatus = JSON.parse(JSON.stringify(data.negativeStatus)) } // 市场价格 if (data.marketPrices) { gameStore.marketPrices = JSON.parse(JSON.stringify(data.marketPrices)) } // 自动战斗状态 if (data.autoCombat !== undefined) { gameStore.autoCombat = data.autoCombat } // 定时事件 if (data.scheduledEvents) { gameStore.scheduledEvents = JSON.parse(JSON.stringify(data.scheduledEvents)) } // 清除不持久化的状态 gameStore.logs = [] gameStore.inCombat = false gameStore.combatState = null gameStore.currentEvent = null } /** * 重置玩家数据 * @param {Object} playerStore - 玩家Store */ function resetPlayerData(playerStore) { // 基础属性 playerStore.baseStats = { strength: 10, agility: 8, dexterity: 8, intuition: 10, vitality: 10 } // 当前资源 playerStore.currentStats = { health: 100, maxHealth: 100, stamina: 100, maxStamina: 100, sanity: 100, maxSanity: 100 } // 等级 playerStore.level = { current: 1, exp: 0, maxExp: 100 } // 技能 playerStore.skills = {} // 装备 playerStore.equipment = { weapon: null, armor: null, shield: null, accessory: null } // 背包 playerStore.inventory = [] // 货币 playerStore.currency = { copper: 0 } // 位置 playerStore.currentLocation = 'camp' // 标志 playerStore.flags = {} // 清空额外数据 resetSkillSystem(playerStore) delete playerStore.equipmentStats delete playerStore.killCount } /** * 重置游戏数据 * @param {Object} gameStore - 游戏Store */ function resetGameData(gameStore) { gameStore.currentTab = 'status' gameStore.drawerState = { inventory: false, event: false } gameStore.logs = [] gameStore.gameTime = { day: 1, hour: 8, minute: 0, totalMinutes: 480 } gameStore.inCombat = false gameStore.combatState = null gameStore.activeTasks = [] gameStore.negativeStatus = [] gameStore.marketPrices = { lastRefreshDay: 1, prices: {} } gameStore.currentEvent = null gameStore.scheduledEvents = [] } /** * 版本迁移 * @param {Number} fromVersion - 源版本 * @param {Number} toVersion - 目标版本 * @param {Object} gameStore - 游戏Store * @param {Object} playerStore - 玩家Store */ function migrateSaveData(fromVersion, toVersion, gameStore, playerStore) { console.log(`Migrating save from v${fromVersion} to v${toVersion}`) // 版本1暂无迁移需求 // 未来版本可以在这里添加迁移逻辑 console.log('Save migration completed') } /** * 检查是否存在存档 * @returns {boolean} */ export function hasSaveData() { try { const saveData = uni.getStorageSync(SAVE_KEY) return !!saveData } catch (error) { return false } } /** * 获取存档信息 * @returns {Object|null} 存档信息 */ export function getSaveInfo() { try { const saveDataRaw = uni.getStorageSync(SAVE_KEY) if (!saveDataRaw) return null const saveData = JSON.parse(saveDataRaw) return { version: saveData.version, timestamp: saveData.timestamp, playTime: saveData.timestamp, gameTime: saveData.game?.gameTime } } catch (error) { return null } } /** * 导出存档(字符串) * @param {Object} gameStore - 游戏Store * @param {Object} playerStore - 玩家Store * @returns {string|null} 存档字符串 */ export function exportSave(gameStore, playerStore) { try { const saveData = { version: SAVE_VERSION, timestamp: Date.now(), player: serializePlayerData(playerStore), game: serializeGameData(gameStore) } return JSON.stringify(saveData) } catch (error) { console.error('Failed to export save:', error) return null } } /** * 导入存档(从字符串) * @param {Object} gameStore - 游戏Store * @param {Object} playerStore - 玩家Store * @param {string} saveString - 存档字符串 * @returns {boolean} 是否成功 */ export function importSave(gameStore, playerStore, saveString) { try { const saveData = JSON.parse(saveString) // 验证格式 if (!saveData.version || !saveData.player || !saveData.game) { return false } // 应用存档 applySaveData(gameStore, playerStore, saveData) // 保存到本地 uni.setStorageSync(SAVE_KEY, saveString) return true } catch (error) { console.error('Failed to import save:', error) return false } }