Files
pixelheros/.qoder/repowiki/zh/content/数据管理/本地存储管理.md
panw 4235e3b776 refactor(game): 移除已弃用的事件常量
- 删除 UpdateHero 和 UpdateFightHero 事件
- 移除 MISSION_UPDATE 事件常量
- 优化游戏事件枚举定义
2025-10-28 16:15:47 +08:00

218 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 本地存储管理
<cite>
**本文档引用文件**
- [config.json](file://assets/resources/config.json)
- [Oops.ts](file://extensions/oops-plugin-framework/assets/core/Oops.ts)
- [Root.ts](file://extensions/oops-plugin-framework/assets/core/Root.ts)
- [StorageManager.ts](file://extensions/oops-plugin-framework/assets/core/common/storage/StorageManager.ts)
- [Initialize.ts](file://assets/script/game/initialize/Initialize.ts)
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts)
- [WxCloudApi.ts](file://assets/script/game/wx_clound_client_api/WxCloudApi.ts)
- [Main.ts](file://assets/script/Main.ts)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心配置项解析](#核心配置项解析)
4. [本地数据加密机制](#本地数据加密机制)
5. [配置加载与初始化流程](#配置加载与初始化流程)
6. [本地缓存与云端数据策略](#本地缓存与云端数据策略)
7. [性能与网络配置](#性能与网络配置)
8. [故障处理机制](#故障处理机制)
9. [结论](#结论)
## 简介
本文档深入解析基于 Cocos 引擎的 `heros` 项目中的本地存储机制。重点围绕 `config.json` 文件中的核心配置项,包括 `version``package``localDataKey``localDataIv``httpServer``httpTimeout``frameRate` 的作用、加载时机及使用场景。文档详细阐述了基于 `crypto-es` 库的本地数据加密存储方案的设计思路,以及如何通过 `localDataKey``localDataIv` 实现数据保护。同时,分析了本地缓存与云端数据的优先级策略,以及在离线模式下的容错处理机制。
**Section sources**
- [config.json](file://assets/resources/config.json)
## 项目结构
项目采用模块化设计,主要结构如下:
- `assets/resources/config.json`:核心配置文件,包含游戏版本、包名、加密密钥、网络地址等全局配置。
- `assets/script/`:存放所有 TypeScript 脚本,其中 `game/initialize/` 是游戏初始化逻辑的核心。
- `extensions/oops-plugin-framework/`:项目所依赖的 `Oops` 框架提供了本地存储、网络、ECS 等核心功能的封装。
- `assets/resources/language/json/`:多语言资源文件。
- `build-templates/wechatgame/cloud_functions/`:微信云函数相关配置。
**Section sources**
- [config.json](file://assets/resources/config.json)
- [Main.ts](file://assets/script/Main.ts)
## 核心配置项解析
`config.json` 文件位于 `assets/resources/` 目录下,是整个游戏的配置中心。其 `config` 对象下的各个字段具有明确的用途。
```json
{
"config": {
"version": "1.0.0",
"package": "com.oops.game",
"localDataKey": "oops",
"localDataIv": "framework",
"httpServer": "http://192.168.0.150/main/",
"httpTimeout": 10000,
"frameRate": 60
}
}
```
- **`version`**: 标识当前游戏的版本号。此信息可用于版本控制、热更新判断以及与云端数据进行兼容性校验。
- **`package`**: 定义游戏的包标识符,遵循反向域名命名规则。在发布到应用商店或进行平台集成时,此标识符必须全局唯一。
- **`localDataKey`**: 本地数据加密所使用的密钥Key。该密钥与 `localDataIv` 一起,作为 `crypto-es` 库进行 AES 加密的参数,确保存储在用户设备上的数据安全。
- **`localDataIv`**: 本地数据加密所使用的初始化向量Initialization Vector。它增加了加密的随机性即使相同的数据在不同时间加密其密文也会不同从而提高安全性。
- **`httpServer`**: 指定 HTTP 请求的服务器基础地址。所有通过 `oops.http` 模块发起的请求,其 URL 都会以此地址为前缀。
- **`httpTimeout`**: 设置 HTTP 请求的超时时间(单位:毫秒)。当网络请求超过此时间仍未收到响应时,将被视为失败,防止应用因网络问题而长时间无响应。
- **`frameRate`**: 定义游戏的帧率,即每秒渲染的帧数。较高的帧率(如 60能提供更流畅的视觉体验但对设备性能要求更高较低的帧率如 30则更省电适合性能较弱的设备。
**Section sources**
- [config.json](file://assets/resources/config.json)
- [Root.ts](file://extensions/oops-plugin-framework/assets/core/Root.ts#L50-L55)
## 本地数据加密机制
项目的本地数据加密方案基于 `crypto-es` 库实现,由 `Oops` 框架的 `StorageManager` 类进行封装。
### 设计思路
1. **依赖库**:项目通过 `package.json` 明确依赖了 `crypto-es` 库,这是一个轻量级的 JavaScript 加密库,支持 AES 等多种加密算法。
2. **框架集成**`Oops` 框架在 `Root.ts``onLoad` 方法中,通过 `oops.config.game` 读取 `config.json` 中的 `localDataKey``localDataIv`,并调用 `oops.storage.init()` 方法进行初始化。
3. **条件加密**:根据 `Oops` 框架的设计,在开发调试模式(`DEBUG``true`)下,数据以明文形式存储,便于开发者调试。而在发布模式下,数据会自动使用 AES 算法进行加密后存储。
### 加密实现
`StorageManager` 类在初始化后,会拦截所有对 `sys.localStorage` 的读写操作。当调用 `set` 方法存储数据时,它会:
1. 将 JavaScript 对象序列化为 JSON 字符串。
2. 使用 `localDataKey` 作为密钥,`localDataIv` 作为初始化向量,通过 `crypto-es` 的 AES 算法对字符串进行加密。
3. 将加密后的密文(通常为 Base64 编码)存储到 `localStorage` 中。
当调用 `get` 方法读取数据时,流程则相反:
1.`localStorage` 中读取密文。
2. 使用相同的密钥和初始化向量进行解密。
3. 将解密后的明文 JSON 字符串反序列化为 JavaScript 对象并返回。
```mermaid
flowchart TD
A[调用 oops.storage.set(key, value)] --> B[序列化为JSON]
B --> C[使用localDataKey和localDataIv进行AES加密]
C --> D[Base64编码]
D --> E[存入localStorage]
F[调用 oops.storage.get(key)] --> G[从localStorage读取]
G --> H[Base64解码]
H --> I[使用localDataKey和localDataIv进行AES解密]
I --> J[反序列化为对象]
J --> K[返回数据]
```
**Diagram sources**
- [config.json](file://assets/resources/config.json)
- [Root.ts](file://extensions/oops-plugin-framework/assets/core/Root.ts#L55)
- [StorageManager.ts](file://extensions/oops-plugin-framework/assets/core/common/storage/StorageManager.ts)
**Section sources**
- [package.json](file://package.json)
- [Root.ts](file://extensions/oops-plugin-framework/assets/core/Root.ts#L55)
- [Oops.ts](file://extensions/oops-plugin-framework/assets/core/Oops.ts#L25)
## 配置加载与初始化流程
游戏的配置加载和初始化是一个有序的过程,由 `Main.ts``Root.ts` 共同驱动。
### 流程图
```mermaid
sequenceDiagram
participant Main as Main.ts
participant Root as Root.ts
participant Config as config.json
participant Storage as StorageManager
participant Initialize as Initialize.ts
Main->>Root : director.loadScene("main")
Root->>Root : onLoad()
Root->>Root : 加载config.json资源
Root->>Root : 解析JsonAsset
loop 初始化框架模块
Root->>Root : oops.config.game = new GameConfig(config)
Root->>Root : oops.http.server = oops.config.game.httpServer
Root->>Root : oops.http.timeout = oops.config.game.httpTimeout
Root->>Storage : oops.storage.init(localDataKey, localDataIv)
Root->>Root : game.frameRate = oops.config.game.frameRate
end
Root->>Root : enabled = true
Root->>Root : init() 和 run()
Root->>Initialize : smc.initialize = ecs.getEntity<Initialize>(Initialize)
Initialize->>Initialize : protected init()
Initialize->>Initialize : loadCustom -> loadLanguage
Initialize->>Storage : oops.storage.get("language")
alt 语言存在
Initialize->>Initialize : 使用存储的语言
else 语言不存在
Initialize->>Initialize : 默认设为"zh"
Initialize->>Storage : oops.storage.set("language", "zh")
end
Initialize->>Initialize : 继续加载公共资源和游戏数据
```
**Diagram sources**
- [Main.ts](file://assets/script/Main.ts)
- [Root.ts](file://extensions/oops-plugin-framework/assets/core/Root.ts)
- [Initialize.ts](file://assets/script/game/initialize/Initialize.ts)
**Section sources**
- [Main.ts](file://assets/script/Main.ts)
- [Root.ts](file://extensions/oops-plugin-framework/assets/core/Root.ts)
- [Initialize.ts](file://assets/script/game/initialize/Initialize.ts)
## 本地缓存与云端数据策略
项目采用了一套混合数据存储策略,结合了本地缓存和云端同步,以平衡性能、用户体验和数据安全。
### 优先级策略
1. **本地优先(读取)**:游戏启动时,会优先从本地存储中读取用户偏好设置,如语言选择 (`oops.storage.get("language")`)。这确保了即使在离线状态下,用户也能获得个性化的体验。
2. **云端优先(写入与同步)**:对于核心的游戏进度数据(如金币、英雄信息、出战阵容),项目优先使用云端存储。在微信客户端中,通过 `WxCloudApi` 与微信云函数交互,实现数据的持久化和跨设备同步。
### 数据同步流程
- **初始化同步**:在 `Initialize.ts``loadGameDataUnified` 方法中,程序首先判断是否为微信客户端。如果是,则调用 `loadFromCloud()`,通过 `WxCloudApi.login()` 获取云端数据,并用 `overrideLocalDataWithRemote()` 方法覆盖本地的 `smc` (SingletonModuleComp) 单例数据。
- **运行时同步**:在游戏运行过程中,当用户数据发生变化(如获得金币、升级英雄),会立即调用 `WxCloudApi.save()` 将最新数据保存到云端,确保数据的实时性和安全性。
```mermaid
graph TD
A[游戏启动] --> B{是否为微信客户端?}
B -- 是 --> C[调用 WxCloudApi.login()]
C --> D{登录成功?}
D -- 是 --> E[获取云端数据]
E --> F[覆盖本地 smc 数据]
D -- 否 --> G[使用本地调试数据]
B -- 否 --> G
F --> H[进入游戏]
G --> H
```
**Diagram sources**
- [Initialize.ts](file://assets/script/game/initialize/Initialize.ts#L67-L105)
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts#L81-L121)
- [WxCloudApi.ts](file://assets/script/game/wx_clound_client_api/WxCloudApi.ts)
**Section sources**
- [Initialize.ts](file://assets/script/game/initialize/Initialize.ts)
- [SingletonModuleComp.ts](file://assets/script/game/common/SingletonModuleComp.ts)
- [WxCloudApi.ts](file://assets/script/game/wx_clound_client_api/WxCloudApi.ts)
## 性能与网络配置
除了数据存储,`config.json` 中的配置也直接影响游戏的性能和网络行为。
- **`frameRate` 对性能的影响**`frameRate` 设置为 60意味着游戏引擎会尽量每秒更新和渲染 60 帧。这能提供非常流畅的动画效果,但会持续占用较高的 CPU 和 GPU 资源,可能导致设备发热和耗电加快。开发者需要在流畅度和性能消耗之间做出权衡,对于性能要求不高的场景,可以考虑降低此值。
- **`httpServer``httpTimeout` 的用途**`httpServer` 定义了所有 HTTP 请求的根地址,实现了请求地址的集中管理,便于在开发、测试和生产环境之间切换。`httpTimeout` 是一个关键的容错配置,它防止了因网络延迟或服务器无响应而导致的 UI 卡死。当请求超时后,应用可以捕获错误并给出友好的提示,提升用户体验。
**Section sources**
- [Root.ts](file://extensions/oops-plugin-framework/assets/core/Root.ts#L54-L55)
- [config.json](file://assets/resources/config.json)
## 故障处理机制
项目在数据处理和网络通信方面设计了多层次的容错机制。
- **本地存储容错**:在 `Initialize.ts` 中读取语言设置时,代码明确检查了 `oops.storage.get("language")` 的返回值是否为 `null` 或空字符串。如果不存在,则使用默认值 `"zh"` 并将其写回存储。这是一种典型的“降级”策略,确保了关键配置的可用性。
- **云端数据容错**`loadFromCloud``loadFromLocalDebug` 方法都使用了 `try-catch` 语句包裹。当云端登录或数据获取失败时,程序会捕获异常,记录错误日志,并尝试使用本地调试数据作为后备方案,避免游戏因数据加载失败而无法启动。
- **网络请求容错**`httpTimeout` 配置本身就是一种网络容错。此外,`WxCloudApi` 的调用通常会检查返回的 `code` 字段(如 `200` 表示成功),并根据不同的错误码(如 `-3` 参数错误,`-6` 资源不足)执行相应的处理逻辑,例如提示用户或回滚操作。
**Section sources**
- [Initialize.ts](file://assets/script/game/initialize/Initialize.ts)
- [WxCloudApi.ts](file://assets/script/game/wx_clound_client_api/WxCloudApi.ts)
## 结论
该项目的本地存储机制设计完善,通过 `config.json` 实现了配置的集中化管理。利用 `Oops` 框架和 `crypto-es` 库,实现了安全的本地数据加密。项目采用了“本地缓存 + 云端同步”的混合策略,既保证了离线可用性和启动速度,又确保了核心数据的安全与跨设备同步。整个初始化流程清晰,配置项的加载和应用时机合理,并且在各个环节都考虑了容错处理,构建了一个健壮、可靠的游戏数据管理方案。