Files
text-adventure-game/utils/storage.js

465 lines
11 KiB
JavaScript
Raw Normal View History

/**
* 存档系统 - 保存加载重置游戏数据
* 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 || {})),
// 不保存日志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.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
}
}