# 本地存储管理 **本文档引用文件** - [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) ## 目录 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 : 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` 库,实现了安全的本地数据加密。项目采用了“本地缓存 + 云端同步”的混合策略,既保证了离线可用性和启动速度,又确保了核心数据的安全与跨设备同步。整个初始化流程清晰,配置项的加载和应用时机合理,并且在各个环节都考虑了容错处理,构建了一个健壮、可靠的游戏数据管理方案。