From cfb6819bc70daf9328f404264f87c0a03513ed0b Mon Sep 17 00:00:00 2001 From: walkpan Date: Sun, 19 Oct 2025 18:05:45 +0800 Subject: [PATCH] =?UTF-8?q?refactor(common):=20=E9=87=8D=E6=9E=84=E6=B8=B8?= =?UTF-8?q?=E6=88=8F=E6=95=B0=E6=8D=AE=E5=90=8C=E6=AD=A5=E4=B8=8E=E5=8D=95?= =?UTF-8?q?=E4=BE=8B=E6=A8=A1=E5=9D=97=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 GameDataSyncManager 类及相关依赖,简化数据同步管理逻辑 - 在 SingletonModuleComp 中集成数据管理功能,使用本地数组替代字典结构存储英雄数据 - 优化本地与云端数据同步方法,适配云函数接口改动 - 修改英雄判断逻辑,支持基于数组的查询方式 - 修正金币数据的增减接口,增加异步云调用与本地更新的统一处理 - 删除冗余注释及无用代码,提升代码可读性和维护性 - 调整数据结构定义和类型声明,保障类型安全与代码健壮性 --- assets/Scripts.meta | 9 + .../script/game/common/GameDataSyncManager.ts | 527 ---------- .../game/common/GameDataSyncManager.ts.meta | 9 - .../script/game/common/SingletonModuleComp.ts | 149 ++- assets/script/game/common/config/heroSet.ts | 4 +- assets/script/game/initialize/Initialize.ts | 8 +- .../game/wx_clound_client_api/WxCloudApi.ts | 886 +---------------- .../cloud_functions/cocos_cloud/API.md | 920 ------------------ .../cloud_functions/cocos_cloud/README.md | 270 ----- .../cloud_functions/cocos_cloud/index.js | 423 ++------ .../cocos_cloud/modules/auth.js | 283 ------ .../cocos_cloud/modules/fightHeros.js | 370 ------- .../cocos_cloud/modules/gameData.js | 386 -------- .../cocos_cloud/modules/heros.js | 440 --------- .../cocos_cloud/modules/inventory.js | 501 ---------- .../cocos_cloud/modules/response.js | 274 ------ .../cocos_cloud/user_init_data.js | 247 ----- 17 files changed, 232 insertions(+), 5474 deletions(-) create mode 100644 assets/Scripts.meta delete mode 100644 assets/script/game/common/GameDataSyncManager.ts delete mode 100644 assets/script/game/common/GameDataSyncManager.ts.meta delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/API.md delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/README.md delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/modules/auth.js delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/modules/fightHeros.js delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/modules/gameData.js delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/modules/heros.js delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/modules/inventory.js delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/modules/response.js delete mode 100644 build-templates/wechatgame/cloud_functions/cocos_cloud/user_init_data.js diff --git a/assets/Scripts.meta b/assets/Scripts.meta new file mode 100644 index 00000000..7479156b --- /dev/null +++ b/assets/Scripts.meta @@ -0,0 +1,9 @@ +{ + "ver": "1.2.0", + "importer": "directory", + "imported": true, + "uuid": "f784d67d-edb7-4b84-9ea8-de8d2eb4c174", + "files": [], + "subMetas": {}, + "userData": {} +} diff --git a/assets/script/game/common/GameDataSyncManager.ts b/assets/script/game/common/GameDataSyncManager.ts deleted file mode 100644 index 88c52872..00000000 --- a/assets/script/game/common/GameDataSyncManager.ts +++ /dev/null @@ -1,527 +0,0 @@ -import { oops } from "db://oops-framework/core/Oops"; -import { WxCloudApi ,UserGameData} from "../wx_clound_client_api/WxCloudApi"; -import { smc } from "./SingletonModuleComp"; -import { GameData } from "../wx_clound_client_api/WxCloudApi"; - -/** - * 游戏数据同步管理器 - * 负责管理fight_heros、heros、items、tals、equips的远程操作和本地同步 - * 只有在远程修改成功后才同步修改本地数据 - */ -export class GameDataSyncManager { - private static instance: GameDataSyncManager; - - private constructor() {} - - public static getInstance(): GameDataSyncManager { - if (!GameDataSyncManager.instance) { - GameDataSyncManager.instance = new GameDataSyncManager(); - } - return GameDataSyncManager.instance; - } - - /** - * 用远程数据覆盖本地数据(统一方法) - * @param remoteData 远程数据(云端或本地调试) - * @param dataSource 数据源描述 - */ - async overrideLocalDataWithRemote(remoteData: UserGameData, dataSource: string) { - try { - // console.log(`[Initialize]: 开始用${dataSource}数据覆盖客户端数据...`); - - // 直接覆盖基础游戏数据 - if (remoteData.data) { - Object.assign(smc.data, remoteData.data); - // console.log(`[Initialize]: 基础游戏数据已从${dataSource}覆盖`); - } - - // 直接覆盖出战英雄配置 - if (remoteData.fight_heros) { - Object.assign(smc.fight_heros, remoteData.fight_heros); - // console.log(`[Initialize]: 出战英雄配置已从${dataSource}覆盖`); - } - - // 直接覆盖英雄数据 - if (remoteData.heros) { - smc.heros = { ...remoteData.heros }; - // console.log(`[Initialize]: 英雄数据已从${dataSource}覆盖`); - } - - // 直接覆盖道具数据 - if (remoteData.items) { - Object.assign(smc.items, remoteData.items); - // console.log(`[Initialize]: 道具数据已从${dataSource}覆盖`); - } - - // 直接覆盖天赋数据 - if (remoteData.tals) { - Object.assign(smc.tals, remoteData.tals); - // console.log(`[Initialize]: 天赋数据已从${dataSource}覆盖`); - } - - // 直接覆盖装备数据 - if (remoteData.equips) { - Object.assign(smc.equips, remoteData.equips); - // console.log(`[Initialize]: 装备数据已从${dataSource}覆盖`); - } - - // 保存到本地存储(确保数据持久化) - // smc.saveGameData(); - - // console.log(`[Initialize]: ${dataSource}数据覆盖完成,已保存到本地`); - - } catch (error) { - console.error(`[Initialize]: ${dataSource}数据覆盖失败:`, error); - } -} - /** - * 批量更新出战英雄配置 - * @param fightHeros 出战英雄配置对象 - * @returns 是否成功 - */ - async updateFightHeros(fightHero: any): Promise { - try { - // console.log(`[GameDataSyncManager]: 批量更新出战英雄配置:`, fightHeros); - - const result = await WxCloudApi.updateFightHeros(fightHero); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - Object.assign(smc.fight_heros, fightHeros); - // console.log(`[GameDataSyncManager]: 出战英雄配置更新成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 出战英雄配置更新失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 更新出战英雄配置异常:`, error); - smc.error() - return false; - } - } - - - /** - * 重置出战英雄配置为默认值 - * @returns 是否成功 - */ - async resetFightHeros(): Promise { - try { - // console.log(`[GameDataSyncManager]: 重置出战英雄配置`); - - const result = await WxCloudApi.resetFightHeros(); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.fight_heros = result.result.data; - // console.log(`[GameDataSyncManager]: 出战英雄配置重置成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 出战英雄配置重置失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 重置出战英雄配置异常:`, error); - smc.error() - return false; - } - } - - // ==================== 英雄管理 ==================== - - /** - * 添加新英雄到用户库存 - * @param heroId 英雄ID - * @param heroData 英雄数据(可选) - * @returns 是否成功 - */ - async addHero(heroId: number, heroData?: any): Promise { - try { - // console.log(`[GameDataSyncManager]: 添加英雄 ID:${heroId}, 数据:`, heroData); - - const result = await WxCloudApi.addHero(heroId, heroData); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.heros[heroId] = result.result.data; - // console.log(`[GameDataSyncManager]: 英雄添加成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 英雄添加失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 添加英雄异常:`, error); - smc.error() - return false; - } - } - - /** - * 更新英雄的多个属性 - * @param heroId 英雄ID - * @param updateData 要更新的属性 - * @returns 是否成功 - */ - async updateHero(heroId: number, updateData: any): Promise { - try { - // console.log(`[GameDataSyncManager]: 更新英雄 ID:${heroId}, 更新数据:`, updateData); - - const result = await WxCloudApi.updateHero(heroId, updateData); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - Object.assign(smc.heros[heroId], result.result.data.new_data); - // console.log(`[GameDataSyncManager]: 英雄更新成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 英雄更新失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 更新英雄异常:`, error); - smc.error() - return false; - } - } - - /** - * 设置英雄的单个属性值 - * @param heroId 英雄ID - * @param property 属性名 - * @param value 属性值 - * @returns 是否成功 - */ - async setHeroProperty(heroId: number, property: any, value: any): Promise { - try { - // console.log(`[GameDataSyncManager]: 设置英雄属性 ID:${heroId}, 属性:${property}, 值:${value}`); - - const result = await WxCloudApi.setHeroProperty(heroId, property, value); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.heros[heroId][property] = value; - // console.log(`[GameDataSyncManager]: 英雄属性设置成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 英雄属性设置失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 设置英雄属性异常:`, error); - smc.error() - return false; - } - } - - /** - * 英雄升级指定级数 - * @param heroId 英雄ID - * @param levels 升级级数(默认1级) - * @returns 是否成功 - */ - async levelUpHero(heroId: number,levels: number = 1,): Promise { - try { - // console.log(`[GameDataSyncManager]: 英雄升级 ID:${heroId}, 级数:${levels}`); - - const result = await WxCloudApi.levelUpHero(heroId,levels); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.heros[heroId].lv = result.result.data.new_value; - // console.log(`[GameDataSyncManager]: 英雄升级成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 英雄升级失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 英雄升级异常:`, error); - smc.error() - return false; - } - } - - // ==================== 便捷方法 ==================== - - /** - * 增加道具 - * @param itemId 道具ID - * @param count 数量 - * @returns 是否成功 - */ - async addItem(itemId: number, count: number): Promise { - smc.items[itemId] = (smc.items[itemId] || 0) + count; - try { - // console.log(`[GameDataSyncManager]: 增加道具 ID:${itemId}, 数量:${count}`); - const result = await WxCloudApi.addInventoryItem('items', itemId, count); - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - // console.log(`[GameDataSyncManager]: 道具增加成功`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 道具增加失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 增加道具异常:`, error); - smc.error() - return false; - } - } - - /** - * 消耗道具 - * @param itemId 道具ID - * @param count 数量 - * @returns 是否成功 - */ - async consumeItem(itemId: number, count: number): Promise { - if(!smc.items[itemId]||smc.items[itemId] { - try { - // console.log(`[GameDataSyncManager]: 增加天赋点 ID:${talId}, 数量:${count}`); - - const result = await WxCloudApi.addInventoryItem('tals', talId, count); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.tals[talId] = (smc.tals[talId] || 0) + count; - // console.log(`[GameDataSyncManager]: 天赋点增加成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 天赋点增加失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 增加天赋点异常:`, error); - smc.error() - return false; - } - } - - /** - * 消耗天赋点 - * @param talId 天赋ID - * @param count 数量 - * @returns 是否成功 - */ - async consumeTalent(talId: number, count: number): Promise { - try { - // console.log(`[GameDataSyncManager]: 消耗天赋点 ID:${talId}, 数量:${count}`); - - const result = await WxCloudApi.consumeInventoryItem('tals', talId, count); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.tals[talId] = Math.max(0, (smc.tals[talId] || 0) - count); - // console.log(`[GameDataSyncManager]: 天赋点消耗成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 天赋点消耗失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 消耗天赋点异常:`, error); - smc.error() - return false; - } - } - - /** - * 增加装备 - * @param equipId 装备ID - * @param count 数量 - * @returns 是否成功 - */ - async addEquipment(equipId: number, count: number): Promise { - try { - // console.log(`[GameDataSyncManager]: 增加装备 ID:${equipId}, 数量:${count}`); - - const result = await WxCloudApi.addInventoryItem('equips', equipId, count); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.equips[equipId] = (smc.equips[equipId] || 0) + count; - // console.log(`[GameDataSyncManager]: 装备增加成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 装备增加失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 增加装备异常:`, error); - smc.error() - return false; - } - } - - /** - * 消耗装备 - * @param equipId 装备ID - * @param count 数量 - * @returns 是否成功 - */ - async consumeEquipment(equipId: number, count: number): Promise { - try { - // console.log(`[GameDataSyncManager]: 消耗装备 ID:${equipId}, 数量:${count}`); - - const result = await WxCloudApi.consumeInventoryItem('equips', equipId, count); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.equips[equipId] = Math.max(0, (smc.equips[equipId] || 0) - count); - // console.log(`[GameDataSyncManager]: 装备消耗成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 装备消耗失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 消耗装备异常:`, error); - smc.error() - return false; - } - } - - - - async addGameProperty(property: string, value: any): Promise { - try { - // console.log(`[GameDataSyncManager]: 增加游戏数据 ${property} = ${value}`); - const result = await WxCloudApi.addGameDataField(property, value); - if (result.result.code === 200) { - // console.log(`[GameDataSyncManager]: 游戏数据增加成功`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 游戏数据增加失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 增加游戏数据异常:`, error); - smc.error() - return false; - } - } - - async spendGameProperty(property: string|Record, value: any = undefined ): Promise { - try { - // console.log(`[GameDataSyncManager]: 消耗游戏数据 ${property} = ${value}`); - const result = await WxCloudApi.spendGameDataField(property, value); - if (result.result.code === 200) { - // console.log(`[GameDataSyncManager]: 游戏数据消耗成功`); - return true; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 消耗游戏数据异常:`, error); - smc.error() - return false; - } - } - - /** - * 从云端加载所有游戏数据并同步到本地 - * @returns 是否成功 - */ - async loadAllGameData(): Promise { - try { - // console.log(`[GameDataSyncManager]: 从云端加载所有游戏数据`); - - const result = await WxCloudApi.getAllGameData(); - - if (result.result.code === 200) { - // 远程数据获取成功,同步本地数据 - const cloudData = result.result.data; - smc.data = cloudData.data; - smc.fight_heros = cloudData.fight_heros; - smc.heros = cloudData.heros; - smc.items = cloudData.items; - smc.tals = cloudData.tals; - smc.equips = cloudData.equips; - - // console.log(`[GameDataSyncManager]: 云端数据加载成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 云端数据加载失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 加载云端数据异常:`, error); - smc.error() - return false; - } - } -} - - - - - - -// 导出单例实例 -export const gameDataSyncManager = GameDataSyncManager.getInstance(); - -/* -使用示例: - -// 1. 出战英雄管理 -await gameDataSyncManager.updateFightHeros({0: 5001, 1: 5005}); // 批量更新 -await gameDataSyncManager.resetFightHeros(); // 重置为默认配置 - -// 2. 英雄管理 -await gameDataSyncManager.addHero(5008, {uuid: 5008, lv: 1}); // 添加新英雄 -await gameDataSyncManager.levelUpHero(5001, 100, 50, 5); // 英雄升级5级 -await gameDataSyncManager.setHeroProperty(5001, "exp", 1000); // 设置英雄经验 - -// 3. 道具管理 (items) -await gameDataSyncManager.addItem(1001, 10); // 增加道具 -await gameDataSyncManager.consumeItem(1001, 2); // 消耗道具 -await gameDataSyncManager.setItem(1001, 5); // 设置道具数量 - -// 4. 天赋点管理 (tals) -await gameDataSyncManager.addTalent(2001, 5); // 增加天赋点 -await gameDataSyncManager.consumeTalent(2001, 2); // 消耗天赋点 -await gameDataSyncManager.setTalent(2001, 10); // 设置天赋点数量 - -// 5. 装备管理 (equips) -await gameDataSyncManager.addEquipment(3001, 2); // 增加装备 -await gameDataSyncManager.consumeEquipment(3001, 1); // 消耗装备 -await gameDataSyncManager.setEquipment(3001, 3); // 设置装备数量 - -// 6. 数据加载 -await gameDataSyncManager.loadAllGameData(); // 从云端加载所有数据 - -注意:所有方法都返回 Promise,true表示成功,false表示失败 -只有在远程修改成功后,本地数据才会被同步修改 -*/ diff --git a/assets/script/game/common/GameDataSyncManager.ts.meta b/assets/script/game/common/GameDataSyncManager.ts.meta deleted file mode 100644 index 53c176c7..00000000 --- a/assets/script/game/common/GameDataSyncManager.ts.meta +++ /dev/null @@ -1,9 +0,0 @@ -{ - "ver": "4.0.24", - "importer": "typescript", - "imported": true, - "uuid": "89c45a3b-d0bf-4e45-9e27-b7d714ba7e29", - "files": [], - "subMetas": {}, - "userData": {} -} diff --git a/assets/script/game/common/SingletonModuleComp.ts b/assets/script/game/common/SingletonModuleComp.ts index 512a325a..dbc483d8 100644 --- a/assets/script/game/common/SingletonModuleComp.ts +++ b/assets/script/game/common/SingletonModuleComp.ts @@ -3,14 +3,10 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec import { Initialize } from "../initialize/Initialize"; import { GameMap } from "../map/GameMap"; import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; -import { GameData, WxCloudApi } from "../wx_clound_client_api/WxCloudApi"; -import { gameDataSyncManager } from "./GameDataSyncManager"; +import { WxCloudApi, UserGameData } from "../wx_clound_client_api/WxCloudApi"; import { Test } from "./Test"; import { GameEvent } from "./config/GameEvent"; - -// import { Role } from "../role/Role"; -// import { data } from "../data/data"; /** 游戏模块 */ @ecs.register('SingletonModule') export class SingletonModuleComp extends ecs.Comp { @@ -18,8 +14,6 @@ export class SingletonModuleComp extends ecs.Comp { initialize: Initialize = null!; /** 游戏地图 */ map: GameMap = null!; - /** 游戏数据同步管理器 */ - private gameDataSyncManager = gameDataSyncManager; mission:any={ status:0, //0:未开始 1:进行中 2:胜利 3:失败 play:false, @@ -32,24 +26,17 @@ export class SingletonModuleComp extends ecs.Comp { data:any={ score:0, mission:1, - gold:100, //升级主要资源 diamond:100, //商店购买 及 双倍奖励资源 meat:0, exp:0, task:0, } - fight_hero: number = 5001; // 单个出战英雄 heros:any = { 5001:{uuid:5001,lv:1}, 5005:{uuid:5005,lv:1}, }; monsters:any = []; - sk_info:any = [] - monsters_dead:any = [] - heros_dead:any = [] - enhancements:any=[] - items: any = {}; // 物品数据 vmdata: any = { game_over:false, game_pause:false, @@ -61,7 +48,9 @@ export class SingletonModuleComp extends ecs.Comp { fight_time:0,//战斗时间 level:1,//关卡等级 max_mission:4,//最大关卡 + coin:0, }, + gold: 100, // 金币数据(MVVM绑定字段) }; vmAdd() { VM.add(this.vmdata, "data"); @@ -74,9 +63,9 @@ export class SingletonModuleComp extends ecs.Comp { // ==================== 数据管理方法 ==================== -/** - * 判断是否为微信客户端 - */ + /** + * 判断是否为微信客户端 + */ private isWxClient(): boolean { // 检查是否存在微信API return typeof wx !== 'undefined' && typeof (wx as any).getSystemInfoSync === 'function'; @@ -84,26 +73,63 @@ export class SingletonModuleComp extends ecs.Comp { finishGuide(index:number){ smc.guides[index]=1 - this.syncGuide() - } - - syncGuide(){ //存储到远程服务器 后续再添加 } + //调试用 syncDataFromLocal(){ if(this.isWxClient()) return const loginResult = new Test().load_data_from_local() - this.gameDataSyncManager.overrideLocalDataWithRemote(loginResult, "本地调试"); + this.overrideLocalDataWithRemote(loginResult, "本地调试"); + } + + /** + * 用远程数据覆盖本地数据(统一方法) + * @param remoteData 远程数据(云端或本地调试) + * @param dataSource 数据源描述 + */ + async overrideLocalDataWithRemote(remoteData: UserGameData, dataSource: string) { + try { + // 直接覆盖基础游戏数据 + if (remoteData.data) { + // 保留原有的data字段数据 + Object.assign(this.data, remoteData.data); + // 同步gold到vmdata + if (remoteData.data.gold !== undefined) { + this.vmdata.gold = remoteData.data.gold; + } + } + + // 直接覆盖出战英雄配置 + if (remoteData.fight_heros) { + this.fight_hero = remoteData.fight_heros[0] || this.fight_hero; + } + + // 直接覆盖英雄数据 + if (remoteData.heros) { + this.heros = { ...remoteData.heros }; + } + + } catch (error) { + console.error(`[SMC]: ${dataSource}数据覆盖失败:`, error); + } } addHero(hero_uuid:number,autoSave:boolean=true){ if(this.isWxClient()){ - if(this.gameDataSyncManager.addHero(hero_uuid)){ - this.heros[hero_uuid]={ uuid:hero_uuid, lv:1, } - return true - } - return false + // 适配原有接口,保持与云函数的兼容性 + const result = WxCloudApi.addHero(hero_uuid); + result.then((res) => { + if(res.result.code === 200) { + this.heros[hero_uuid]={ uuid:hero_uuid, lv:1, } + return true + } + return false + }).catch((error) => { + console.error(`[SMC]: 添加英雄异常:`, error); + this.error() + return false + }); } this.heros[hero_uuid]={ uuid:hero_uuid, lv:1, } return true @@ -113,7 +139,15 @@ export class SingletonModuleComp extends ecs.Comp { setFightHero(heroId: number, autoSave: boolean = true) { this.fight_hero = heroId; if (this.isWxClient()) { - this.gameDataSyncManager.updateFightHeros({ 0: heroId }); // 适配原有接口 + // 适配原有接口,保持与云函数的兼容性 + WxCloudApi.updateFightHeros({ 0: heroId }).then((result) => { + if (result.result.code !== 200) { + console.warn(`[SMC]: 出战英雄配置更新失败: ${result.result.msg}`); + } + }).catch((error) => { + console.error(`[SMC]: 更新出战英雄配置异常:`, error); + this.error() + }); } } @@ -122,35 +156,64 @@ export class SingletonModuleComp extends ecs.Comp { return this.fight_hero; } + getHasHeroUUID(){ + let heros=this.heros + let heros_uuid=[] + for(let key in heros){ + heros_uuid.push(heros[key].uuid) + } + return heros_uuid + } + error(){ oops.gui.toast("数据处理异常,请重试或重新登录") } addGold(gold:number,autoSave:boolean=true){ if(this.isWxClient()){ - if(this.gameDataSyncManager.addGameProperty("gold",gold)){ - this.data.gold+=gold - oops.message.dispatchEvent(GameEvent.GOLD_UPDATE) - return true - } - this.error() - return false + WxCloudApi.addGameDataField("gold",gold).then((result) => { + if(result.result.code === 200) { + this.vmdata.gold += gold; + this.data.gold = this.vmdata.gold; // 同步到data字段 + oops.message.dispatchEvent(GameEvent.GOLD_UPDATE) + return true + } else { + console.warn(`[SMC]: 游戏数据增加失败: ${result.result.msg}`); + this.error() + return false + } + }).catch((error) => { + console.error(`[SMC]: 增加游戏数据异常:`, error); + this.error() + return false + }); } - this.data.gold+=gold + this.vmdata.gold += gold; + this.data.gold = this.vmdata.gold; // 同步到data字段 oops.message.dispatchEvent(GameEvent.GOLD_UPDATE) return true } spendGold(gold:number,autoSave:boolean=true){ if(this.isWxClient()){ - if(this.gameDataSyncManager.spendGameProperty("gold",gold)){ - this.data.gold-=gold - oops.message.dispatchEvent(GameEvent.GOLD_UPDATE) - return true - } - return false + WxCloudApi.spendGameDataField("gold",gold).then((result) => { + if(result.result.code === 200) { + this.vmdata.gold -= gold; + this.data.gold = this.vmdata.gold; // 同步到data字段 + oops.message.dispatchEvent(GameEvent.GOLD_UPDATE) + return true + } else { + console.warn(`[SMC]: 游戏数据消耗失败: ${result.result.msg}`); + return false + } + }).catch((error) => { + console.error(`[SMC]: 消耗游戏数据异常:`, error); + this.error() + return false + }); } - this.data.gold-=gold + this.vmdata.gold -= gold; + this.data.gold = this.vmdata.gold; // 同步到data字段 oops.message.dispatchEvent(GameEvent.GOLD_UPDATE) return true } diff --git a/assets/script/game/common/config/heroSet.ts b/assets/script/game/common/config/heroSet.ts index 5a969aa2..cec3104f 100644 --- a/assets/script/game/common/config/heroSet.ts +++ b/assets/script/game/common/config/heroSet.ts @@ -30,8 +30,8 @@ export const getHeroList = (quality:number=0)=>{ }); // 分离拥有和未拥有的英雄 - const ownedHeros = filteredHeros.filter(item => smc.heros[item.uuid]); - const unownedHeros = filteredHeros.filter(item => !smc.heros[item.uuid]); + const ownedHeros = filteredHeros.filter(item => smc.heros.some(hero => hero.uuid === item.uuid)); + const unownedHeros = filteredHeros.filter(item => !smc.heros.some(hero => hero.uuid === item.uuid)); // 合并列表:拥有的在前,未拥有的在后 return [...ownedHeros, ...unownedHeros].map(item => item.uuid); diff --git a/assets/script/game/initialize/Initialize.ts b/assets/script/game/initialize/Initialize.ts index a7166abd..4e7e4b64 100644 --- a/assets/script/game/initialize/Initialize.ts +++ b/assets/script/game/initialize/Initialize.ts @@ -12,8 +12,8 @@ import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ec import { UIID } from "../common/config/GameUIConfig"; import { LoadingViewComp } from "./view/LoadingViewComp"; import { smc } from "../common/SingletonModuleComp"; -import { WxCloudApi, UserGameData } from "../wx_clound_client_api/WxCloudApi"; -import { GameDataSyncManager } from "../common/GameDataSyncManager"; +import { WxCloudApi } from "../wx_clound_client_api/WxCloudApi"; + import { Test } from "../common/Test"; // import {data} from "../data/data"; @@ -141,7 +141,7 @@ export class Initialize extends ecs.Entity { const cloudData = response.data; // 3. 用云端数据覆盖本地数据 - GameDataSyncManager.getInstance().overrideLocalDataWithRemote(cloudData, "云端"); + } else { console.warn("[Initialize]: 云端登录失败:", response.msg); // 登录失败时使用本地数据 游戏需要退出 @@ -163,7 +163,7 @@ export class Initialize extends ecs.Entity { const loginResult = new Test().load_data_from_local() // 用本地调试数据覆盖客户端数据 - GameDataSyncManager.getInstance().overrideLocalDataWithRemote(loginResult, "本地调试"); + } catch (error) { console.error("[Initialize]: 本地调试数据加载异常:", error); } diff --git a/assets/script/game/wx_clound_client_api/WxCloudApi.ts b/assets/script/game/wx_clound_client_api/WxCloudApi.ts index d421d8c4..3e8a02ef 100644 --- a/assets/script/game/wx_clound_client_api/WxCloudApi.ts +++ b/assets/script/game/wx_clound_client_api/WxCloudApi.ts @@ -1,84 +1,9 @@ -// 云函数返回类型定义 export type CloudReturnType = { - code: number, // 200成功,其他都是失败 - msg?: string, // 消息信息 - data?: T, // 返回数据 - timestamp?: number, // 时间戳 - version?: string, // 数据版本 - execution_time?: number // 执行时间(ms) + code: number,// 200成功 + msg?:string, + data?:T } -// 用户信息类型 -export type UserInfo = { - user_id: string, - openid: string, - regist_time: number, - init_time?: number, - data_version?: string, - last_save_time?: number -} - -// 完整用户数据类型 -export type UserGameData = UserInfo & { - data: GameData, - fight_heros: FightHeros, - heros: Heros, - items: Items, - tals: Tals, - equips: Equips -} - -// 基础游戏数据类型 -export type GameData = { - score: number, - mission: number, - gold: number, - diamond: number, - meat: number, - exp: number, -} - -// 出战英雄类型 -export type FightHeros = { - [position: number]: number // 位置 -> 英雄ID -} - -// 英雄数据类型 -export type HeroData = { - uuid: number, - lv: number, - exp?: number, - star?: number, - power?: number -} - -export type Heros = { - [heroId: number]: HeroData -} - -// 库存类型 -export type Items = { - [itemId: number]: number -} - -export type Tals = { - [talId: number]: number -} - -export type Equips = { - [equipId: number]: number -} - -// 版本兼容性检查结果 -export type VersionCompatibility = { - compatible: boolean, - needsUpgrade: boolean, - message: string -} - -// 库存类型枚举 -export type InventoryType = 'items' | 'tals' | 'equips' - export class WxCloudApi{ /** * @en init the cloud @@ -91,14 +16,30 @@ export class WxCloudApi{ }); } - // ==================== 认证相关接口 ==================== - /** * @en Login to the cloud - * @zh 用户登录,获取完整的用户和游戏数据 - * @return Promise>> + * @zh 登录云 + * @return 返回结果 + * 参考: + * result.result = { + * code: number, // 200成功,其他都是失败 + * msg: string, // 如果失败,这里是失败原因等信息 + * data: { // 成功才有 + * openid: string, // 用户微信平台openid + * regist_time: number, // 时间戳,用户注册时间 + * game_data: object, // 开发者自己保存的数据 + * } + * } + * 如果这个泛型令你报错(一般是因为你删了wx.api.d.ts导致),请使用以下签名: + * login():Promise<{result: CloudReturnType<{openid: string, regist_time: number, game_data: object}>}> + * 或者你是个“不拘小节”的老哥,可以用以下简洁版签名(参考上方的数据结构例子使用即可) + * login():Promise */ - public static async login(): Promise>> { + public static async login(): Promise>>{ return await wx?.cloud.callFunction({ name: 'cocos_cloud', data: { @@ -108,486 +49,29 @@ export class WxCloudApi{ } /** - * @en Get user basic info - * @zh 获取用户基本信息(不包含游戏数据) - * @return Promise>> - */ - public static async getUserInfo(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "user_info" - } - }); - } - - /** - * @en Check data version compatibility - * @zh 检查数据版本兼容性 - * @return Promise>> - */ - public static async checkVersion(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "version" - } - }); - } - - /** - * @en Force upgrade user data - * @zh 强制升级用户数据结构 - * @return Promise>> - */ - public static async upgradeUserData(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "upgrade" - } - }); - } - - // ==================== 基础游戏数据接口 ==================== - - /** - * @en Get game data - * @zh 获取基础游戏数据(金币、钻石、经验等) - * @return Promise>> - */ - public static async getGameData(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "data_get" - } - }); - } - - /** - * @en Update game data - * @zh 批量更新基础游戏数据 - * @param data 要更新的数据 - * @param merge 是否合并更新(默认true) - * @return Promise>> - */ - public static async updateGameData(data: Partial, merge: boolean = true): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "data_update", - data: data, - merge: merge - } - }); - } - - /** - * @en Add to game data field - * @zh 增加指定字段的数值 - * @param field 字段名 - * @param amount 增加的数量 - * @return Promise>> - */ - public static async addGameDataField(field:string, amount: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "data_add", - field: field, - amount: amount - } - }); - } - - /** - * @en Spend game data field - * @zh 消耗指定字段的数值(会检查是否足够) - * @param field 字段名 - * @param amount 消耗的数量 - * @return Promise>> - */ - public static async spendGameDataField(field:string|Record, amount: number): Promise, - old_value: number, - new_value: number, - change: number - }>>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "data_spend", - field: field, - amount: amount - } - }); - } - - /** - * @en Set game data field - * @zh 直接设置某个字段的值 - * @param field 字段名 - * @param value 新的值 - * @return Promise>> - */ - public static async setGameDataField(field: keyof GameData, value: any): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "data_set", - field: field, - value: value - } - }); - } - - /** - * @en Reset game data - * @zh 重置基础游戏数据为默认值 - * @return Promise>> - */ - public static async resetGameData(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "data_reset" - } - }); - } - - // 便捷方法:金币操作 - /** - * @en Add gold - * @zh 增加金币 - * @param amount 金币数量 - */ - public static async addGold(amount: number) { - return await this.addGameDataField('gold', amount); - } - - /** - * @en Spend gold - * @zh 消耗金币 - * @param amount 金币数量 - */ - public static async spendGold(amount: number) { - return await this.spendGameDataField('gold', amount); - } - - // 便捷方法:钻石操作 - /** - * @en Add diamond - * @zh 增加钻石 - * @param amount 钻石数量 - */ - public static async addDiamond(amount: number) { - return await this.addGameDataField('diamond', amount); - } - - /** - * @en Spend diamond - * @zh 消耗钻石 - * @param amount 钻石数量 - */ - public static async spendDiamond(amount: number) { - return await this.spendGameDataField('diamond', amount); - } - - // ==================== 出战英雄接口 ==================== - - /** - * @en Get fight heros - * @zh 获取出战英雄配置 - * @return Promise>> - */ - public static async getFightHeros(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "fight_heros_get" - } - }); - } - - /** - * @en Set fight hero - * @zh 设置指定位置的出战英雄 - * @param position 出战位置 (0-4) - * @param heroId 英雄ID,0表示移除 - * @return Promise>> - */ - public static async setFightHero(position: number, heroId: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "fight_hero_set", - position: position, - hero_id: heroId - } - }); - } - - /** - * @en Update fight heros - * @zh 批量更新出战英雄配置 - * @param fightHeros 出战英雄配置对象 - * @return Promise>> - */ - public static async updateFightHeros(fightHeros: Partial): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "fight_heros_update", - fight_heros: fightHeros - } - }); - } - - /** - * @en Get active fight heros - * @zh 获取当前出战的英雄列表(不包含空位) - * @return Promise, total_count: number}>>> - */ - public static async getActiveFightHeros(): Promise, - total_count: number - }>>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "fight_heros_active" - } - }); - } - - /** - * @en Swap fight heros - * @zh 交换两个出战位置的英雄 - * @param position1 位置1 (0-4) - * @param position2 位置2 (0-4) - * @return Promise>> - */ - public static async swapFightHeros(position1: number, position2: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "fight_heros_swap", - position1: position1, - position2: position2 - } - }); - } - - /** - * @en Reset fight heros - * @zh 重置出战英雄配置为默认值 - * @return Promise>> - */ - public static async resetFightHeros(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "fight_heros_reset" - } - }); - } - - // ==================== 英雄管理接口 ==================== - - /** - * @en Get all heros - * @zh 获取用户拥有的所有英雄数据 - * @return Promise>> - */ - public static async getHeros(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "heros_get" - } - }); - } - - /** - * @en Get single hero - * @zh 获取指定英雄的详细数据 - * @param heroId 英雄ID - * @return Promise>> - */ - public static async getHero(heroId: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "hero_get", - hero_id: heroId - } - }); - } - - /** - * @en Add new hero - * @zh 添加新英雄到用户库存 - * @param heroId 英雄ID - * @param heroData 英雄数据(可选) - * @return Promise>> - */ - public static async addHero(heroId: number, heroData?: Partial): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "hero_add", - hero_id: heroId, - hero_data: heroData - } - }); - } - - /** - * @en Update hero - * @zh 批量更新英雄的多个属性 - * @param heroId 英雄ID - * @param updateData 要更新的属性 - * @return Promise>> - */ - public static async updateHero(heroId: number, updateData: Partial): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "hero_update", - hero_id: heroId, - update_data: updateData - } - }); - } - - /** - * @en Set hero property - * @zh 设置英雄的单个属性值 - * @param heroId 英雄ID - * @param property 属性名 - * @param value 属性值 - * @return Promise>> - */ - public static async setHeroProperty(heroId: number, property: keyof HeroData, value: any): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "hero_property_set", - hero_id: heroId, - property: property, - value: value - } - }); - } - - /** - * @en Level up hero - * @zh 英雄升级指定级数 - * @param heroId 英雄ID - * @param levels 升级级数(默认1级) - * @return Promise>> - */ - public static async levelUpHero(heroId: number,levels: number = 1): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "hero_levelup", - hero_id: heroId, - levels: levels - } - }); - } - - /** - * @en Delete hero - * @zh 删除指定英雄(会检查是否在出战阵容中) - * @param heroId 英雄ID - * @return Promise>> - */ - public static async deleteHero(heroId: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "hero_delete", - hero_id: heroId - } - }); - } - - /** - * @en Get owned hero IDs - * @zh 获取用户拥有的所有英雄ID - * @return Promise>> - */ - public static async getOwnedHeroIds(): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "heros_owned" - } - }); - } - - // ==================== 兼容旧接口 ==================== - - /** - * @en Save game data to the cloud (Legacy) - * @zh 把客户端数据写入云,此为全覆盖写入,请自行管理完整数据(兼容旧接口) - * @param gameData 游戏数据 - * @return Promise>> + * @en Save game data to the cloud + * @zh 把客户端数据写入云,此为全覆盖写入,请自行管理完整数据 + * @return 返回结果 + * 参考: + * result.result = { + * code: number, // 200成功,其他都是失败 + * msg: string, // 如果失败,这里是失败原因等信息 + * data: { + * errMsg: "document.update:ok", // 数据库返回结果 + * stats: { + * updated: number, // 更新了几条数据(正常是1) + * } + * } + * 如果这个泛型令你报错(一般是因为你删了wx.api.d.ts导致),请使用以下签名: + * save(gameData: any): Promise<{resoult:CloudReturnType}> + * 或者你是个“不拘小节”的老哥,可以用以下简洁版签名(参考上方的数据结构例子使用即可) + * login():Promise */ public static async save(gameData: any): Promise>> { return await wx?.cloud.callFunction({ name: 'cocos_cloud', @@ -597,284 +81,4 @@ export class WxCloudApi{ } }); } - - // ==================== 库存管理接口 (items, tals, equips) ==================== - - /** - * @en Get inventory - * @zh 获取指定类型的所有库存数据 - * @param type 库存类型 ('items', 'tals', 'equips') - * @return Promise>> - */ - public static async getInventory(type: InventoryType): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "inventory_get", - type: type - } - }); - } - - /** - * @en Get inventory item - * @zh 获取指定物品的数量 - * @param type 库存类型 - * @param itemId 物品ID - * @return Promise>> - */ - public static async getInventoryItem(type: InventoryType, itemId: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "inventory_item_get", - type: type, - item_id: itemId - } - }); - } - - /** - * @en Add inventory item - * @zh 增加指定物品的数量 - * @param type 库存类型 - * @param itemId 物品ID - * @param count 添加数量 - * @return Promise>> - */ - public static async addInventoryItem(type: InventoryType, itemId: number, count: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "inventory_item_add", - type: type, - item_id: itemId, - count: count - } - }); - } - - /** - * @en Consume inventory item - * @zh 消耗指定数量的物品(会检查是否足够) - * @param type 库存类型 - * @param itemId 物品ID - * @param count 消耗数量 - * @return Promise>> - */ - public static async consumeInventoryItem(type: InventoryType, itemId: number, count: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "inventory_item_consume", - type: type, - item_id: itemId, - count: count - } - }); - } - - /** - * @en Set inventory item - * @zh 直接设置物品的数量 - * @param type 库存类型 - * @param itemId 物品ID - * @param count 新的数量 - * @return Promise>> - */ - public static async setInventoryItem(type: InventoryType, itemId: number, count: number): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "inventory_item_set", - type: type, - item_id: itemId, - count: count - } - }); - } - - /** - * @en Update inventory - * @zh 批量更新多个物品的数量 - * @param type 库存类型 - * @param data 更新数据对象 - * @param merge 是否合并更新(默认true) - * @return Promise>> - */ - public static async updateInventory(type: InventoryType, data: Partial, merge: boolean = true): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "inventory_update", - type: type, - data: data, - merge: merge - } - }); - } - - /** - * @en Reset inventory - * @zh 重置指定类型的库存为默认值 - * @param type 库存类型 - * @return Promise>> - */ - public static async resetInventory(type: InventoryType): Promise>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "inventory_reset", - type: type - } - }); - } - - /** - * @en Get owned items - * @zh 获取数量大于0的物品列表 - * @param type 库存类型 - * @return Promise, total_types: number}>>> - */ - public static async getOwnedItems(type: InventoryType): Promise, - total_types: number - }>>> { - return await wx?.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: "inventory_owned", - type: type - } - }); - } - - // ==================== 便捷方法:道具操作 ==================== - - /** - * @en Get items - * @zh 获取所有道具数据 - */ - public static async getItems() { - return await this.getInventory('items'); - } - - /** - * @en Add item - * @zh 添加道具 - * @param itemId 道具ID - * @param count 数量 - */ - public static async addItem(itemId: number, count: number) { - return await this.addInventoryItem('items', itemId, count); - } - - /** - * @en Consume item - * @zh 消耗道具 - * @param itemId 道具ID - * @param count 数量 - */ - public static async consumeItem(itemId: number, count: number) { - return await this.consumeInventoryItem('items', itemId, count); - } - - // ==================== 便捷方法:天赋操作 ==================== - - /** - * @en Get talents - * @zh 获取所有天赋数据 - */ - public static async getTalents() { - return await this.getInventory('tals'); - } - - /** - * @en Add talent - * @zh 添加天赋点 - * @param talId 天赋ID - * @param count 数量 - */ - public static async addTalent(talId: number, count: number) { - return await this.addInventoryItem('tals', talId, count); - } - - /** - * @en Consume talent - * @zh 消耗天赋点 - * @param talId 天赋ID - * @param count 数量 - */ - public static async consumeTalent(talId: number, count: number) { - return await this.consumeInventoryItem('tals', talId, count); - } - - // ==================== 便捷方法:装备操作 ==================== - - /** - * @en Get equipments - * @zh 获取所有装备数据 - */ - public static async getEquipments() { - return await this.getInventory('equips'); - } - - /** - * @en Add equipment - * @zh 添加装备 - * @param equipId 装备ID - * @param count 数量 - */ - public static async addEquipment(equipId: number, count: number) { - return await this.addInventoryItem('equips', equipId, count); - } - - /** - * @en Consume equipment - * @zh 消耗装备 - * @param equipId 装备ID - * @param count 数量 - */ - public static async consumeEquipment(equipId: number, count: number) { - return await this.consumeInventoryItem('equips', equipId, count); - } - - // ==================== 其他便捷方法 ==================== - - /** - * @en Load game data (Legacy compatible) - * @zh 加载游戏数据(兼容旧接口) - */ - public static async load() { - return await this.login(); - } - - /** - * @en Get all game data at once - * @zh 一次性获取所有游戏数据 - * @return Promise>> - */ - public static async getAllGameData(): Promise>> { - return await this.login(); - } } \ No newline at end of file diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/API.md b/build-templates/wechatgame/cloud_functions/cocos_cloud/API.md deleted file mode 100644 index cf192a72..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/API.md +++ /dev/null @@ -1,920 +0,0 @@ -# 游戏云函数 API 文档 - -## 📋 概述 - -本文档详细说明了游戏云函数的所有可用接口,包括认证、数据管理、英雄系统、库存管理等功能。 - -## 🏗️ 项目结构 - -``` -cocos_cloud/ -├── index.js # 路由入口文件 -├── user_init_data.js # 用户初始化数据配置 -├── modules/ # 功能模块目录 -│ ├── auth.js # 认证模块 -│ ├── gameData.js # 基础游戏数据模块 -│ ├── fightHeros.js # 出战英雄模块 -│ ├── heros.js # 英雄管理模块 -│ ├── inventory.js # 库存管理模块 -│ └── response.js # 响应处理模块 -├── README.md # 项目说明文档 -└── API.md # API接口文档 -``` - -## 🚀 通用调用格式 - -```javascript -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: '命令名', - // 其他参数... - } -}).then(res => { - console.log('调用结果:', res.result); -}).catch(err => { - console.error('调用失败:', err); -}); -``` - -## 📊 通用响应格式 - -```javascript -{ - code: 200, // 状态码 (200=成功, 负数=错误) - msg: "Success", // 响应消息 - data: { /* 返回数据 */ }, // 具体数据 - timestamp: 1234567890, // 时间戳 - version: "1.0.0", // 数据版本 - execution_time: 50 // 执行时间(ms) -} -``` - -## 🔐 认证相关接口 - -### 1. 用户登录 -获取用户完整信息和游戏数据。 - -```javascript -// 请求 -{ cmd: 'login' } - -// 响应 -{ - code: 200, - data: { - user_id: "用户ID", - openid: "微信OpenID", - regist_time: 1234567890, - data: { /* 基础游戏数据 */ }, - fight_heros: { /* 出战英雄配置 */ }, - heros: { /* 英雄属性数据 */ }, - items: { /* 道具数据 */ }, - tals: { /* 天赋数据 */ }, - equips: { /* 装备数据 */ }, - data_version: "1.0.0", - last_save_time: 1234567890 - } -} -``` - -### 2. 获取用户信息 -获取用户基本信息(不包含游戏数据)。 - -```javascript -// 请求 -{ cmd: 'user_info' } - -// 响应 -{ - code: 200, - data: { - user_id: "用户ID", - openid: "微信OpenID", - regist_time: 1234567890, - init_time: 1234567890, - data_version: "1.0.0", - last_save_time: 1234567890 - } -} -``` - -### 3. 检查版本信息 -检查用户数据版本兼容性。 - -```javascript -// 请求 -{ cmd: 'version' } - -// 响应 -{ - code: 200, - data: { - user_version: "1.0.0", - current_version: "1.1.0", - compatibility: { - compatible: true, - needsUpgrade: true, - message: "Minor version update available" - }, - init_time: 1234567890, - regist_time: 1234567890, - last_save_time: 1234567890 - } -} -``` - -### 4. 强制升级数据 -手动触发用户数据结构升级。 - -```javascript -// 请求 -{ cmd: 'upgrade' } - -// 响应 -{ - code: 200, - data: { - old_version: "1.0.0", - new_version: "1.1.0", - upgrade_time: 1234567890, - // ... 升级后的完整数据 - } -} -``` - -## 🎮 基础游戏数据接口 - -### 1. 获取游戏数据 -获取用户的基础游戏数据(金币、钻石、经验等)。 - -```javascript -// 请求 -{ cmd: 'data_get' } - -// 响应 -{ - code: 200, - data: { - score: 0, - mission: 1, - gold: 100, - diamond: 100, - meat: 0, - exp: 0, - // ... 更多字段 - } -} -``` - -### 2. 更新游戏数据 -批量更新基础游戏数据。 - -```javascript -// 请求 -{ - cmd: 'data_update', - data: { - gold: 1000, - diamond: 200, - exp: 500 - }, - merge: true // 可选,默认true(合并更新) -} - -// 响应 -{ - code: 200, - data: { - // 更新后的完整数据 - } -} -``` - -### 3. 增加指定字段 -增加某个字段的数值。 - -```javascript -// 请求 -{ - cmd: 'data_add', - field: 'gold', - amount: 100 -} - -// 响应 -{ - code: 200, - data: { - field: 'gold', - old_value: 1000, - new_value: 1100, - change: 100 - } -} -``` - -### 4. 消耗指定字段 -消耗某个字段的数值(会检查是否足够)。 - -```javascript -// 请求 -{ - cmd: 'data_spend', - field: 'gold', - amount: 50 -} - -// 响应 -{ - code: 200, - data: { - field: 'gold', - old_value: 1100, - new_value: 1050, - change: -50 - } -} -``` - -### 5. 设置指定字段 -直接设置某个字段的值。 - -```javascript -// 请求 -{ - cmd: 'data_set', - field: 'mission', - value: 5 -} - -// 响应 -{ - code: 200, - data: { - field: 'mission', - old_value: 1, - new_value: 5 - } -} -``` - -### 6. 重置游戏数据 -重置基础游戏数据为默认值。 - -```javascript -// 请求 -{ cmd: 'data_reset' } - -// 响应 -{ - code: 200, - data: { - // 重置后的默认数据 - } -} -``` - -## ⚔️ 出战英雄接口 - -### 1. 获取出战英雄配置 -获取当前的出战英雄配置。 - -```javascript -// 请求 -{ cmd: 'fight_heros_get' } - -// 响应 -{ - code: 200, - data: { - 0: 5001, // 位置0: 英雄5001 - 1: 5005, // 位置1: 英雄5005 - 2: 0, // 位置2: 空 - 3: 0, // 位置3: 空 - 4: 0 // 位置4: 空 - } -} -``` - -### 2. 设置单个出战英雄 -设置指定位置的出战英雄。 - -```javascript -// 请求 -{ - cmd: 'fight_hero_set', - position: 2, - hero_id: 5007 -} - -// 响应 -{ - code: 200, - data: { - position: 2, - old_hero_id: 0, - new_hero_id: 5007 - } -} -``` - -### 3. 批量更新出战英雄 -批量更新多个位置的出战英雄。 - -```javascript -// 请求 -{ - cmd: 'fight_heros_update', - fight_heros: { - 0: 5001, - 1: 5005, - 2: 5007 - } -} - -// 响应 -{ - code: 200, - data: { - // 更新后的完整出战配置 - } -} -``` - -### 4. 获取激活的出战英雄 -获取当前出战的英雄列表(不包含空位)。 - -```javascript -// 请求 -{ cmd: 'fight_heros_active' } - -// 响应 -{ - code: 200, - data: { - active_heros: [ - { - position: 0, - hero_id: 5001, - hero_data: { /* 英雄详细数据 */ } - }, - { - position: 1, - hero_id: 5005, - hero_data: { /* 英雄详细数据 */ } - } - ], - total_count: 2 - } -} -``` - -### 5. 交换出战英雄位置 -交换两个位置的英雄。 - -```javascript -// 请求 -{ - cmd: 'fight_heros_swap', - position1: 0, - position2: 2 -} - -// 响应 -{ - code: 200, - data: { - position1: 0, - position2: 2, - hero1_moved_to: 5007, - hero2_moved_to: 5001 - } -} -``` - -### 6. 重置出战英雄 -重置出战英雄配置为默认值。 - -```javascript -// 请求 -{ cmd: 'fight_heros_reset' } - -// 响应 -{ - code: 200, - data: { - // 重置后的默认配置 - } -} -``` - -## 🦸 英雄管理接口 - -### 1. 获取所有英雄 -获取用户拥有的所有英雄数据。 - -```javascript -// 请求 -{ cmd: 'heros_get' } - -// 响应 -{ - code: 200, - data: { - 5001: { uuid: 5001, lv: 10, exp: 500, star: 2, power: 150 }, - 5005: { uuid: 5005, lv: 8, exp: 300, star: 1, power: 120 }, - 5007: { uuid: 5007, lv: 1, exp: 0, star: 1, power: 90 } - } -} -``` - -### 2. 获取单个英雄 -获取指定英雄的详细数据。 - -```javascript -// 请求 -{ - cmd: 'hero_get', - hero_id: 5001 -} - -// 响应 -{ - code: 200, - data: { - uuid: 5001, - lv: 10, - exp: 500, - star: 2, - power: 150 - } -} -``` - -### 3. 添加新英雄 -添加新英雄到用户库存。 - -```javascript -// 请求 -{ - cmd: 'hero_add', - hero_id: 5008, - hero_data: { // 可选,不提供则使用默认数据 - lv: 1, - exp: 0, - star: 1, - power: 110 - } -} - -// 响应 -{ - code: 200, - data: { - uuid: 5008, - lv: 1, - exp: 0, - star: 1, - power: 110 - } -} -``` - -### 4. 更新英雄属性 -批量更新英雄的多个属性。 - -```javascript -// 请求 -{ - cmd: 'hero_update', - hero_id: 5001, - update_data: { - lv: 15, - exp: 800, - star: 3 - } -} - -// 响应 -{ - code: 200, - data: { - old_data: { /* 更新前的数据 */ }, - new_data: { /* 更新后的数据 */ } - } -} -``` - -### 5. 设置英雄单个属性 -设置英雄的单个属性值。 - -```javascript -// 请求 -{ - cmd: 'hero_property_set', - hero_id: 5001, - property: 'lv', - value: 20 -} - -// 响应 -{ - code: 200, - data: { - hero_id: 5001, - property: 'lv', - old_value: 15, - new_value: 20 - } -} -``` - -### 6. 英雄升级 -英雄升级指定级数。 - -```javascript -// 请求 -{ - cmd: 'hero_levelup', - hero_id: 5001, - levels: 3 // 可选,默认1级 -} - -// 响应 -{ - code: 200, - data: { - hero_id: 5001, - property: 'lv', - old_value: 20, - new_value: 23 - } -} -``` - -### 7. 删除英雄 -删除指定英雄(会检查是否在出战阵容中)。 - -```javascript -// 请求 -{ - cmd: 'hero_delete', - hero_id: 5008 -} - -// 响应 -{ - code: 200, - data: { - // 被删除的英雄数据 - } -} -``` - -### 8. 获取拥有的英雄ID列表 -获取用户拥有的所有英雄ID。 - -```javascript -// 请求 -{ cmd: 'heros_owned' } - -// 响应 -{ - code: 200, - data: { - hero_ids: [5001, 5005, 5007], - total_count: 3 - } -} -``` - -## 🎒 库存管理接口 - -库存管理接口支持三种类型的数据: -- `items`: 道具 -- `tals`: 天赋 -- `equips`: 装备 - -### 1. 获取库存数据 -获取指定类型的所有库存数据。 - -```javascript -// 请求 -{ - cmd: 'inventory_get', - type: 'items' // 'items', 'tals', 'equips' -} - -// 响应 -{ - code: 200, - data: { - 1001: 5, // 道具1001: 5个 - 1002: 3, // 道具1002: 3个 - 1003: 0, // 道具1003: 0个 - // ... - } -} -``` - -### 2. 获取单个物品 -获取指定物品的数量。 - -```javascript -// 请求 -{ - cmd: 'inventory_item_get', - type: 'items', - item_id: 1001 -} - -// 响应 -{ - code: 200, - data: { - item_id: 1001, - count: 5 - } -} -``` - -### 3. 添加物品 -增加指定物品的数量。 - -```javascript -// 请求 -{ - cmd: 'inventory_item_add', - type: 'items', - item_id: 1001, - count: 10 -} - -// 响应 -{ - code: 200, - data: { - item_id: 1001, - old_count: 5, - new_count: 15, - added: 10 - } -} -``` - -### 4. 消耗物品 -消耗指定数量的物品(会检查是否足够)。 - -```javascript -// 请求 -{ - cmd: 'inventory_item_consume', - type: 'items', - item_id: 1001, - count: 3 -} - -// 响应 -{ - code: 200, - data: { - item_id: 1001, - old_count: 15, - new_count: 12, - added: -3 - } -} -``` - -### 5. 设置物品数量 -直接设置物品的数量。 - -```javascript -// 请求 -{ - cmd: 'inventory_item_set', - type: 'items', - item_id: 1001, - count: 20 -} - -// 响应 -{ - code: 200, - data: { - item_id: 1001, - old_count: 12, - new_count: 20 - } -} -``` - -### 6. 批量更新库存 -批量更新多个物品的数量。 - -```javascript -// 请求 -{ - cmd: 'inventory_update', - type: 'items', - data: { - 1001: 25, - 1002: 10, - 1003: 5 - }, - merge: true // 可选,默认true(合并更新) -} - -// 响应 -{ - code: 200, - data: { - // 更新后的完整库存数据 - } -} -``` - -### 7. 重置库存 -重置指定类型的库存为默认值。 - -```javascript -// 请求 -{ - cmd: 'inventory_reset', - type: 'items' -} - -// 响应 -{ - code: 200, - data: { - // 重置后的默认库存数据 - } -} -``` - -### 8. 获取拥有的物品 -获取数量大于0的物品列表。 - -```javascript -// 请求 -{ - cmd: 'inventory_owned', - type: 'items' -} - -// 响应 -{ - code: 200, - data: { - owned_items: [ - { item_id: 1001, count: 25 }, - { item_id: 1002, count: 10 }, - { item_id: 1003, count: 5 } - ], - total_types: 3 - } -} -``` - -## 🔄 兼容旧接口 - -为了保持向后兼容,保留了一些旧接口: - -### 1. 加载数据 (兼容) -等同于 `login` 命令。 - -```javascript -// 请求 -{ cmd: 'load' } - -// 响应:与login相同 -``` - -### 2. 保存数据 (兼容) -批量保存多种类型的数据。 - -```javascript -// 请求 -{ - cmd: 'save', - data: { - data: { gold: 1000, diamond: 200 }, - fight_heros: { 0: 5001, 1: 5005 }, - heros: { 5001: { lv: 10, exp: 500 } }, - items: { 1001: 10, 1002: 5 }, - tals: { 1001: 1 }, - equips: { 1001: 2 } - } -} - -// 响应 -{ - code: 200, - data: { - results: [ - // 各个模块的保存结果 - ] - }, - msg: "All data saved successfully" -} -``` - -## ❌ 错误码说明 - -| 错误码 | 说明 | 示例 | -|-------|------|------| -| 200 | 成功 | 操作成功完成 | -| -1 | 操作失败 | 数据库更新失败 | -| -2 | 未知命令 | 命令不存在 | -| -3 | 参数错误 | 缺少必需参数或参数格式错误 | -| -4 | 用户未找到 | 用户不存在或创建失败 | -| -5 | 系统错误 | 服务器内部错误 | -| -6 | 资源不足 | 金币、道具等资源不够 | -| -7 | 资源已存在 | 英雄已存在等 | -| -8 | 操作被拒绝 | 英雄正在出战中无法删除等 | - -## 📝 使用示例 - -### 完整的游戏流程示例 - -```javascript -// 1. 用户登录 -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { cmd: 'login' } -}).then(res => { - console.log('用户登录成功:', res.result.data); - - // 2. 增加金币 - return wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: 'data_add', - field: 'gold', - amount: 100 - } - }); -}).then(res => { - console.log('金币增加成功:', res.result.data); - - // 3. 添加新英雄 - return wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: 'hero_add', - hero_id: 5008 - } - }); -}).then(res => { - console.log('英雄添加成功:', res.result.data); - - // 4. 设置出战英雄 - return wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: 'fight_hero_set', - position: 2, - hero_id: 5008 - } - }); -}).then(res => { - console.log('出战英雄设置成功:', res.result.data); -}).catch(err => { - console.error('操作失败:', err); -}); -``` - -## 🔧 开发调试 - -### 1. 启用调试日志 -在开发环境中,云函数会输出详细的调试日志: - -```javascript -// 请求日志 -[data_add] Request from oxxx: { field: 'gold', amount: 100 } - -// 响应日志 -[data_add] Response (45ms): 200 gold updated successfully -``` - -### 2. 性能监控 -每个响应都包含 `execution_time` 字段,显示接口执行时间。 - -### 3. 版本管理 -使用 `version` 命令检查数据版本兼容性,确保客户端和服务端数据结构一致。 - ---- - -**版本**: 1.0.0 -**更新时间**: 2024年 -**维护者**: 游戏开发团队 - - - - - - - - diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/README.md b/build-templates/wechatgame/cloud_functions/cocos_cloud/README.md deleted file mode 100644 index f0cafa11..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/README.md +++ /dev/null @@ -1,270 +0,0 @@ -# 微信云函数游戏数据管理系统 - -## 📁 文件结构 - -``` -cocos_cloud/ -├── index.js # 主云函数文件 -├── user_init_data.js # 新用户初始化数据配置 -└── README.md # 说明文档 -``` - -## 🎮 功能特性 - -### 1. 数据结构管理 -- **平级数据存储**: 所有游戏数据字段与用户基本信息平级存储 -- **版本控制**: 支持数据结构版本管理和自动升级 -- **数据验证**: 完整的数据结构和类型验证 -- **默认值管理**: 集中管理新用户初始化数据 - -### 2. 支持的命令 - -| 命令 | 功能 | 说明 | -|------|------|------| -| `login` | 用户登录 | 返回完整的用户和游戏数据 | -| `load` | 加载游戏数据 | 获取用户的所有游戏数据 | -| `save` | 保存游戏数据 | 支持增量更新,自动合并数据 | -| `reset` | 重置游戏数据 | 恢复为默认初始值 | -| `backup` | 创建数据备份 | 在独立集合中创建备份记录 | -| `version` | 查看版本信息 | 检查数据版本兼容性 | -| `upgrade` | 强制升级数据 | 手动触发数据结构升级 | - -## 📊 数据结构 - -### 用户数据库结构 (cocos_users 集合) -```javascript -{ - _id: "用户ID", - _openid: "微信OpenID", - regist_time: "注册时间戳", - init_time: "初始化时间戳", - last_save_time: "最后保存时间", - data_version: "数据版本号", - - // 游戏数据字段(与基本信息平级) - data: { - score: 0, // 游戏分数 - mission: 1, // 当前关卡 - gold: 100, // 金币 - diamond: 100, // 钻石 - meat: 0, // 肉类资源 - exp: 0, // 升级经验 - ghstone: 0, // 绿色英雄石 - bhstone: 0, // 蓝色英雄石 - phlestone: 0, // 紫色英雄石 - rhstone: 0, // 红色英雄石 - herocard: 0, // 英雄卡 - ckey: 0, // 铜钥匙 - skey: 0, // 银钥匙 - gkey: 0 // 金钥匙 - }, - fight_heros: { - 0: 5001, // 出战位置1 - 1: 5005, // 出战位置2 - 2: 0, // 出战位置3(空) - 3: 0, // 出战位置4(空) - 4: 0 // 出战位置5(空) - }, - heros: { - 5001: { uuid: 5001, lv: 1, exp: 0, star: 1, power: 100 }, - 5005: { uuid: 5005, lv: 1, exp: 0, star: 1, power: 120 }, - 5007: { uuid: 5007, lv: 1, exp: 0, star: 1, power: 90 } - }, - items: { - 1001: 0, // 生命药水 - 1002: 0, // 魔法药水 - 1003: 0, // 力量药水 - // ... 更多道具 - }, - tals: { - 1001: 0, // 攻击强化 - 1002: 0, // 防御强化 - 1003: 0, // 生命强化 - // ... 更多天赋 - }, - equips: { - 1001: 0, // 武器 - 1002: 0, // 头盔 - 1003: 0, // 胸甲 - // ... 更多装备 - } -} -``` - -### 备份数据库结构 (game_backups 集合) -```javascript -{ - user_id: "用户ID", - openid: "微信OpenID", - data: { /* 基础游戏数据 */ }, - fight_heros: { /* 出战英雄配置 */ }, - heros: { /* 英雄属性数据 */ }, - items: { /* 道具数据 */ }, - tals: { /* 天赋数据 */ }, - equips: { /* 装备数据 */ }, - backup_time: "备份时间戳", - original_save_time: "原始保存时间" -} -``` - -## 🚀 使用示例 - -### 客户端调用示例 - -#### 1. 用户登录 -```javascript -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { cmd: 'login' } -}).then(res => { - console.log('登录成功:', res.result); - // res.result.data 包含完整的用户和游戏数据 -}); -``` - -#### 2. 保存游戏数据 -```javascript -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { - cmd: 'save', - data: { - data: { gold: 1000, diamond: 50 }, - fight_heros: { 0: 5001, 1: 5005 }, - heros: { 5001: { lv: 10, exp: 100 } }, - items: { 1001: 5 } - } - } -}); -``` - -#### 3. 加载游戏数据 -```javascript -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { cmd: 'load' } -}).then(res => { - const gameData = res.result.data; - console.log('游戏数据:', gameData); -}); -``` - -#### 4. 检查版本信息 -```javascript -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { cmd: 'version' } -}).then(res => { - console.log('版本信息:', res.result.data); - if (res.result.data.compatibility.needsUpgrade) { - console.log('需要升级数据'); - } -}); -``` - -#### 5. 创建数据备份 -```javascript -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { cmd: 'backup' } -}).then(res => { - console.log('备份成功:', res.result.data.backup_id); -}); -``` - -## 🔧 配置管理 - -### 修改默认数据 -编辑 `user_init_data.js` 文件中的常量: - -```javascript -// 修改默认金币数量 -const DEFAULT_GAME_DATA = { - // ... - gold: 200, // 从100改为200 - // ... -}; - -// 添加新英雄 -const DEFAULT_HEROS = { - // 现有英雄... - 5008: { uuid: 5008, lv: 1, exp: 0, star: 1, power: 110 } -}; -``` - -### 版本升级 -当数据结构发生变化时,更新版本号: - -```javascript -// 在 user_init_data.js 中 -const DATA_VERSION = "1.1.0"; // 从1.0.0升级到1.1.0 -``` - -## 📈 版本控制 - -### 版本号格式 -- **MAJOR.MINOR.PATCH** (如: 1.2.3) -- **MAJOR**: 重大结构变更,不向后兼容 -- **MINOR**: 新增字段,向后兼容 -- **PATCH**: 数值调整,完全兼容 - -### 自动升级机制 -- 用户登录时自动检查版本兼容性 -- 如需升级,自动合并新的默认数据 -- 保留用户的现有数据,只补充缺失字段 - -## 🛡️ 错误处理 - -### 错误码说明 -- `200`: 成功 -- `-1`: 操作失败 -- `-2`: 未知命令 -- `-3`: 数据结构无效 -- `-4`: 用户创建/获取失败 -- `-5`: 系统错误 - -### 日志记录 -- 新用户创建日志 -- 数据版本升级日志 -- 错误操作日志 -- 性能监控日志 - -## 🔍 调试和监控 - -### 查看用户数据版本 -```javascript -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { cmd: 'version' } -}); -``` - -### 强制升级用户数据 -```javascript -wx.cloud.callFunction({ - name: 'cocos_cloud', - data: { cmd: 'upgrade' } -}); -``` - -## 📝 注意事项 - -1. **数据备份**: 重要操作前建议创建备份 -2. **版本兼容**: 升级数据结构时注意向后兼容性 -3. **性能优化**: 大量数据操作时注意性能影响 -4. **安全验证**: 所有输入数据都经过严格验证 -5. **错误处理**: 完善的错误处理和日志记录 - -## 🚀 部署说明 - -1. 将整个 `cocos_cloud` 文件夹上传到微信云开发 -2. 在微信开发者工具中部署云函数 -3. 确保数据库权限配置正确 -4. 测试各项功能是否正常工作 - ---- - -**版本**: 1.0.0 -**更新时间**: 2024年 -**维护者**: 游戏开发团队 - diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/index.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/index.js index 6a808a4f..e94f1fcf 100644 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/index.js +++ b/build-templates/wechatgame/cloud_functions/cocos_cloud/index.js @@ -1,371 +1,80 @@ -// 云函数路由入口文件 +// 云函数入口文件 const cloud = require('wx-server-sdk'); -// 导入各个模块 -const authModule = require('./modules/auth'); -const gameDataModule = require('./modules/gameData'); -const fightHerosModule = require('./modules/fightHeros'); -const herosModule = require('./modules/heros'); -const inventoryModule = require('./modules/inventory'); -const itemsModule = require('./modules/items'); -const talsModule = require('./modules/tals'); -const equipsModule = require('./modules/equips'); -const responseModule = require('./modules/response'); - +const user_db_name = "cocos_users"; cloud.init({ env: cloud.DYNAMIC_CURRENT_ENV }); // 使用当前云环境 // 云函数入口函数 exports.main = async (event, context) => { - const startTime = Date.now(); - - try { - // 验证命令参数 - const validation = responseModule.validateRequiredParams(event, ['cmd']); - if (validation) { - return validation; - } - - const { cmd, ...params } = event; + let cmd = event.cmd; + if (cmd == null) { + return { + code: -1, + msg: "no cmd!" + }; + } + const wxContext = cloud.getWXContext(); const db = cloud.database({ env: cloud.DYNAMIC_CURRENT_ENV, throwOnNotFound: false }); - - console.log(`[${cmd}] Request from ${wxContext.OPENID}:`, params); - - // 路由分发 - let result; - switch (cmd) { - // ==================== 认证相关 ==================== - case 'login': - result = await authModule.login(db, wxContext); - break; - - case 'user_info': - result = await authModule.getUserInfo(db, wxContext.OPENID); - break; - - case 'version': - result = await authModule.checkVersion(db, wxContext.OPENID); - break; - - case 'upgrade': - result = await authModule.upgradeUserData(db, wxContext.OPENID); - break; - - // ==================== 基础游戏数据 ==================== - case 'data_get': - result = await gameDataModule.getData(db, wxContext.OPENID); - break; - - case 'data_update': - const merge = params.merge !== false; // 默认合并 - result = await gameDataModule.updateData(db, wxContext.OPENID, params.data, merge); - break; - - case 'data_add': - const fieldValidation = responseModule.validateRequiredParams(params, ['field', 'amount']); - if (fieldValidation) return fieldValidation; - result = await gameDataModule.addDataField(db, wxContext.OPENID, params.field, params.amount); - break; - - case 'data_spend': - const spendValidation = responseModule.validateRequiredParams(params, ['field', 'amount']); - if (spendValidation) return spendValidation; - result = await gameDataModule.spendDataField(db, wxContext.OPENID, params.field, params.amount); - break; + const _ = db.command; - case 'data_reset': - result = await gameDataModule.resetData(db, wxContext.OPENID); - break; - - // ==================== 出战英雄 ==================== - case 'fight_heros_get': - result = await fightHerosModule.getFightHeros(db, wxContext.OPENID); - break; - - case 'fight_hero_set': - const heroSetValidation = responseModule.validateRequiredParams(params, ['position', 'hero_id']); - if (heroSetValidation) return heroSetValidation; - result = await fightHerosModule.setFightHero(db, wxContext.OPENID, params.position, params.hero_id); - break; - - case 'fight_heros_update': - const herosUpdateValidation = responseModule.validateRequiredParams(params, ['fight_heros']); - if (herosUpdateValidation) return herosUpdateValidation; - result = await fightHerosModule.updateFightHeros(db, wxContext.OPENID, params.fight_heros); - break; - - case 'fight_heros_active': - result = await fightHerosModule.getActiveFightHeros(db, wxContext.OPENID); - break; - - case 'fight_heros_swap': - const swapValidation = responseModule.validateRequiredParams(params, ['position1', 'position2']); - if (swapValidation) return swapValidation; - result = await fightHerosModule.swapFightHeros(db, wxContext.OPENID, params.position1, params.position2); - break; - - case 'fight_heros_reset': - result = await fightHerosModule.resetFightHeros(db, wxContext.OPENID); - break; - - // ==================== 英雄管理 ==================== - case 'heros_get': - result = await herosModule.getHeros(db, wxContext.OPENID); - break; - - case 'hero_get': - const heroGetValidation = responseModule.validateRequiredParams(params, ['hero_id']); - if (heroGetValidation) return heroGetValidation; - result = await herosModule.getHero(db, wxContext.OPENID, params.hero_id); - break; - - case 'hero_add': - const heroAddValidation = responseModule.validateRequiredParams(params, ['hero_id']); - if (heroAddValidation) return heroAddValidation; - result = await herosModule.addHero(db, wxContext.OPENID, params.hero_id, params.hero_data); - break; - - case 'hero_update': - const heroUpdateValidation = responseModule.validateRequiredParams(params, ['hero_id', 'update_data']); - if (heroUpdateValidation) return heroUpdateValidation; - result = await herosModule.updateHero(db, wxContext.OPENID, params.hero_id, params.update_data); - break; - - case 'hero_property_set': - const propValidation = responseModule.validateRequiredParams(params, ['hero_id', 'property', 'value']); - if (propValidation) return propValidation; - result = await herosModule.setHeroProperty(db, wxContext.OPENID, params.hero_id, params.property, params.value); - break; - - case 'hero_levelup': - const levelValidation = responseModule.validateRequiredParams(params, ['hero_id']); - if (levelValidation) return levelValidation; - result = await herosModule.levelUpHero(db, wxContext.OPENID, params.hero_id, params.levels); - break; - - case 'hero_delete': - const deleteValidation = responseModule.validateRequiredParams(params, ['hero_id']); - if (deleteValidation) return deleteValidation; - result = await herosModule.deleteHero(db, wxContext.OPENID, params.hero_id); - break; - - case 'heros_owned': - result = await herosModule.getOwnedHeroIds(db, wxContext.OPENID); - break; - - // ==================== 库存管理 (通用接口) ==================== - case 'inventory_get': - const invGetValidation = responseModule.validateRequiredParams(params, ['type']); - if (invGetValidation) return invGetValidation; - result = await inventoryModule.getInventory(db, wxContext.OPENID, params.type); - break; - - case 'inventory_item_get': - const itemGetValidation = responseModule.validateRequiredParams(params, ['type', 'item_id']); - if (itemGetValidation) return itemGetValidation; - result = await inventoryModule.getInventoryItem(db, wxContext.OPENID, params.type, params.item_id); - break; - - case 'inventory_item_add': - const itemAddValidation = responseModule.validateRequiredParams(params, ['type', 'item_id', 'count']); - if (itemAddValidation) return itemAddValidation; - result = await inventoryModule.addInventoryItem(db, wxContext.OPENID, params.type, params.item_id, params.count); - break; - - case 'inventory_item_consume': - const itemConsumeValidation = responseModule.validateRequiredParams(params, ['type', 'item_id', 'count']); - if (itemConsumeValidation) return itemConsumeValidation; - result = await inventoryModule.consumeInventoryItem(db, wxContext.OPENID, params.type, params.item_id, params.count); - break; - - case 'inventory_item_set': - const itemSetValidation = responseModule.validateRequiredParams(params, ['type', 'item_id', 'count']); - if (itemSetValidation) return itemSetValidation; - result = await inventoryModule.setInventoryItem(db, wxContext.OPENID, params.type, params.item_id, params.count); - break; - - case 'inventory_update': - const invUpdateValidation = responseModule.validateRequiredParams(params, ['type', 'data']); - if (invUpdateValidation) return invUpdateValidation; - const invMerge = params.merge !== false; - result = await inventoryModule.updateInventory(db, wxContext.OPENID, params.type, params.data, invMerge); - break; - - case 'inventory_reset': - const invResetValidation = responseModule.validateRequiredParams(params, ['type']); - if (invResetValidation) return invResetValidation; - result = await inventoryModule.resetInventory(db, wxContext.OPENID, params.type); - break; - - case 'inventory_owned': - const invOwnedValidation = responseModule.validateRequiredParams(params, ['type']); - if (invOwnedValidation) return invOwnedValidation; - result = await inventoryModule.getOwnedItems(db, wxContext.OPENID, params.type); - break; - - // ==================== 物品管理 (items) ==================== - case 'items_get': - result = await itemsModule.getItems(db, wxContext.OPENID); - break; - - case 'item_get': - const itemIdValidation = responseModule.validateRequiredParams(params, ['item_id']); - if (itemIdValidation) return itemIdValidation; - result = await itemsModule.getItem(db, wxContext.OPENID, params.item_id); - break; - - case 'item_add': - const addItemValidation = responseModule.validateRequiredParams(params, ['item_id', 'count']); - if (addItemValidation) return addItemValidation; - result = await itemsModule.addItem(db, wxContext.OPENID, params.item_id, params.count); - break; - - case 'item_consume': - const consumeItemValidation = responseModule.validateRequiredParams(params, ['item_id', 'count']); - if (consumeItemValidation) return consumeItemValidation; - result = await itemsModule.consumeItem(db, wxContext.OPENID, params.item_id, params.count); - break; - - case 'item_set': - const setItemValidation = responseModule.validateRequiredParams(params, ['item_id', 'count']); - if (setItemValidation) return setItemValidation; - result = await itemsModule.setItem(db, wxContext.OPENID, params.item_id, params.count); - break; - - case 'items_update': - const updateItemsValidation = responseModule.validateRequiredParams(params, ['data']); - if (updateItemsValidation) return updateItemsValidation; - const itemsMerge = params.merge !== false; - result = await itemsModule.updateItems(db, wxContext.OPENID, params.data, itemsMerge); - break; - - case 'items_reset': - result = await itemsModule.resetItems(db, wxContext.OPENID); - break; - - case 'items_owned': - result = await itemsModule.getOwnedItems(db, wxContext.OPENID); - break; - - // ==================== 天赋管理 (tals) ==================== - case 'tals_get': - result = await talsModule.getTals(db, wxContext.OPENID); - break; - - case 'tal_get': - const talIdValidation = responseModule.validateRequiredParams(params, ['tal_id']); - if (talIdValidation) return talIdValidation; - result = await talsModule.getTal(db, wxContext.OPENID, params.tal_id); - break; - - case 'tal_add': - const addTalValidation = responseModule.validateRequiredParams(params, ['tal_id', 'count']); - if (addTalValidation) return addTalValidation; - result = await talsModule.addTal(db, wxContext.OPENID, params.tal_id, params.count); - break; - - case 'tal_consume': - const consumeTalValidation = responseModule.validateRequiredParams(params, ['tal_id', 'count']); - if (consumeTalValidation) return consumeTalValidation; - result = await talsModule.consumeTal(db, wxContext.OPENID, params.tal_id, params.count); - break; - - case 'tal_set': - const setTalValidation = responseModule.validateRequiredParams(params, ['tal_id', 'count']); - if (setTalValidation) return setTalValidation; - result = await talsModule.setTal(db, wxContext.OPENID, params.tal_id, params.count); - break; - - case 'tals_update': - const updateTalsValidation = responseModule.validateRequiredParams(params, ['data']); - if (updateTalsValidation) return updateTalsValidation; - const talsMerge = params.merge !== false; - result = await talsModule.updateTals(db, wxContext.OPENID, params.data, talsMerge); - break; - - case 'tals_reset': - result = await talsModule.resetTals(db, wxContext.OPENID); - break; - - case 'tals_owned': - result = await talsModule.getOwnedTals(db, wxContext.OPENID); - break; - - // ==================== 装备管理 (equips) ==================== - case 'equips_get': - result = await equipsModule.getEquips(db, wxContext.OPENID); - break; - - case 'equip_get': - const equipIdValidation = responseModule.validateRequiredParams(params, ['equip_id']); - if (equipIdValidation) return equipIdValidation; - result = await equipsModule.getEquip(db, wxContext.OPENID, params.equip_id); - break; - - case 'equip_add': - const addEquipValidation = responseModule.validateRequiredParams(params, ['equip_id', 'count']); - if (addEquipValidation) return addEquipValidation; - result = await equipsModule.addEquip(db, wxContext.OPENID, params.equip_id, params.count); - break; - - case 'equip_consume': - const consumeEquipValidation = responseModule.validateRequiredParams(params, ['equip_id', 'count']); - if (consumeEquipValidation) return consumeEquipValidation; - result = await equipsModule.consumeEquip(db, wxContext.OPENID, params.equip_id, params.count); - break; - - case 'equip_set': - const setEquipValidation = responseModule.validateRequiredParams(params, ['equip_id', 'count']); - if (setEquipValidation) return setEquipValidation; - result = await equipsModule.setEquip(db, wxContext.OPENID, params.equip_id, params.count); - break; - - case 'equips_update': - const updateEquipsValidation = responseModule.validateRequiredParams(params, ['data']); - if (updateEquipsValidation) return updateEquipsValidation; - const equipsMerge = params.merge !== false; - result = await equipsModule.updateEquips(db, wxContext.OPENID, params.data, equipsMerge); - break; - - case 'equips_reset': - result = await equipsModule.resetEquips(db, wxContext.OPENID); - break; - - case 'equips_owned': - result = await equipsModule.getOwnedEquips(db, wxContext.OPENID); - break; - - - default: - const availableCommands = [ - 'login', 'user_info', 'version', 'upgrade', - 'data_get', 'data_update', 'data_add', 'data_spend', 'data_set', 'data_reset', - 'fight_heros_get', 'fight_hero_set', 'fight_heros_update', 'fight_heros_active', 'fight_heros_swap', 'fight_heros_reset', - 'heros_get', 'hero_get', 'hero_add', 'hero_update', 'hero_property_set', 'hero_levelup', 'hero_delete', 'heros_owned', - 'inventory_get', 'inventory_item_get', 'inventory_item_add', 'inventory_item_consume', 'inventory_item_set', 'inventory_update', 'inventory_reset', 'inventory_owned', - 'items_get', 'item_get', 'item_add', 'item_consume', 'item_set', 'items_update', 'items_reset', 'items_owned', - 'tals_get', 'tal_get', 'tal_add', 'tal_consume', 'tal_set', 'tals_update', 'tals_reset', 'tals_owned', - 'equips_get', 'equip_get', 'equip_add', 'equip_consume', 'equip_set', 'equips_update', 'equips_reset', 'equips_owned', - 'load', 'save' - ]; - result = responseModule.unknownCommand(cmd, availableCommands); - break; + if (cmd === "login") { + let user = await getOrCreaterUser(db, wxContext.OPENID); + return { + code: 200, + data: user, + }; + } else if (cmd === "save") { + let data = event.data; + let user = await getOrCreaterUser(db, wxContext.OPENID); + let saveDataRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + game_data: _.set(data) + } + }); + + console.log("Save data:", saveDataRes, data); + if (saveDataRes?.stats?.updated >= 1) { + return { + code: 200, + data: saveDataRes + }; + } else { + return { + code: -1, + msg: `Save fail, ${JSON.stringify(saveDataRes)}` + }; } - - // 添加执行时间 - const executionTime = Date.now() - startTime; - if (result && typeof result === 'object') { - result.execution_time = executionTime; - } - - console.log(`[${cmd}] Response (${executionTime}ms):`, result.code, result.msg); - return result; - - } catch (error) { - console.error("Cloud function error:", error); - return responseModule.systemError("Cloud function execution failed", error); } -}; \ No newline at end of file + + return { + code: -2, + msg: `Unknow cmd: ${event?.cmd}`, + }; +}; + +async function getOrCreaterUser(db, openid) { + try { + let res = await db.collection(user_db_name).where({ _openid: openid }).get(); + let userData = null; + if (res == null || res.data == null || res.data.length <= 0) { + userData = { + _openid: openid, + regist_time: Date.now(), + }; + let addResult = await db.collection(user_db_name).add({ + data: userData + }); + userData._id = addResult._id; + } else { + userData = res.data[0]; + } + return userData; + } catch (err) { + console.error(`Get or create user err`, err); + return null; + } +} \ No newline at end of file diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/auth.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/auth.js deleted file mode 100644 index a10dfabc..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/auth.js +++ /dev/null @@ -1,283 +0,0 @@ -// 登录认证模块 -const { - getNewUserInitData, - mergeUserDataWithDefaults, - checkDataVersionCompatibility -} = require('../user_init_data'); - -const user_db_name = "cocos_users"; - -/** - * 用户登录处理 - * @param {Object} db 数据库实例 - * @param {Object} wxContext 微信上下文 - * @returns {Object} 登录结果 - */ -async function login(db, wxContext) { - try { - let user = await getOrCreaterUser(db, wxContext.OPENID); - if (!user) { - return { - code: -4, - msg: "获取或创建用户失败" - }; - } - - return { - code: 200, - data: { - user_id: user._id, - openid: user._openid, - regist_time: user.regist_time, - data: user.data, - fight_heros: user.fight_heros, - heros: user.heros, - items: user.items, - tals: user.tals, - equips: user.equips, - data_version: user.data_version, - last_save_time: user.last_save_time || null - }, - msg: "登录成功" - }; - } catch (error) { - console.error("登录错误:", error); - return { - code: -5, - msg: `登录错误: ${error.message}` - }; - } -} - -/** - * 获取或创建用户 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 用户数据 - */ -async function getOrCreaterUser(db, openid) { - try { - let res = await db.collection(user_db_name).where({ _openid: openid }).get(); - let userData = null; - - if (res == null || res.data == null || res.data.length <= 0) { - // 创建新用户时使用初始化数据配置 - let initData = getNewUserInitData(); - userData = { - _openid: openid, - regist_time: Date.now(), - data: initData.data, - fight_heros: initData.fight_heros, - heros: initData.heros, - items: initData.items, - tals: initData.tals, - equips: initData.equips, - data_version: initData.data_version, - init_time: initData.init_time - }; - - let addResult = await db.collection(user_db_name).add({ - data: userData - }); - userData._id = addResult._id; - - // console.log(`新用户已创建: ${openid}, 版本: ${initData.data_version}`); - } else { - userData = res.data[0]; - - // 检查数据版本兼容性 - const versionCheck = checkDataVersionCompatibility(userData.data_version); - // console.log(`用户 ${openid} 数据版本检查:`, versionCheck); - - if (versionCheck.needsUpgrade) { - // 使用新的数据管理系统合并和升级数据 - const upgradedData = mergeUserDataWithDefaults({ - data: userData.data, - fight_heros: userData.fight_heros, - heros: userData.heros, - items: userData.items, - tals: userData.tals, - equips: userData.equips, - data_version: userData.data_version - }); - - // 更新用户数据 - userData.data = upgradedData.data; - userData.fight_heros = upgradedData.fight_heros; - userData.heros = upgradedData.heros; - userData.items = upgradedData.items; - userData.tals = upgradedData.tals; - userData.equips = upgradedData.equips; - userData.data_version = upgradedData.data_version; - - // console.log(`用户 ${openid} 数据已升级到版本: ${upgradedData.data_version}`); - } - } - - return userData; - } catch (err) { - console.error(`获取或创建用户错误`, err); - return null; - } -} - -/** - * 获取用户基本信息 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 用户基本信息 - */ -async function getUserInfo(db, openid) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - return { - code: 200, - data: { - user_id: user._id, - openid: user._openid, - regist_time: user.regist_time, - init_time: user.init_time, - data_version: user.data_version, - last_save_time: user.last_save_time - }, - msg: "用户信息获取成功" - }; - } catch (error) { - console.error("获取用户信息错误:", error); - return { - code: -5, - msg: `获取用户信息错误: ${error.message}` - }; - } -} - -/** - * 检查用户数据版本 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 版本检查结果 - */ -async function checkVersion(db, openid) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - const versionCheck = checkDataVersionCompatibility(user.data_version); - - return { - code: 200, - data: { - user_version: user.data_version || "unknown", - current_version: require('../user_init_data').DATA_VERSION, - compatibility: versionCheck, - init_time: user.init_time, - regist_time: user.regist_time, - last_save_time: user.last_save_time - }, - msg: "版本信息获取成功" - }; - } catch (error) { - console.error("检查版本错误:", error); - return { - code: -5, - msg: `检查版本错误: ${error.message}` - }; - } -} - -/** - * 强制升级用户数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 升级结果 - */ -async function upgradeUserData(db, openid) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "User not found" - }; - } - - // 强制升级用户数据 - const upgradedData = mergeUserDataWithDefaults({ - data: user.data, - fight_heros: user.fight_heros, - heros: user.heros, - items: user.items, - tals: user.tals, - equips: user.equips, - data_version: user.data_version - }); - - let upgradeDataRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - data: _.set(upgradedData.data), - fight_heros: _.set(upgradedData.fight_heros), - heros: _.set(upgradedData.heros), - items: _.set(upgradedData.items), - tals: _.set(upgradedData.tals), - equips: _.set(upgradedData.equips), - data_version: _.set(upgradedData.data_version), - last_save_time: _.set(Date.now()), - upgrade_time: _.set(Date.now()) - } - }); - - if (upgradeDataRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - old_version: user.data_version || "unknown", - new_version: upgradedData.data_version, - upgrade_time: Date.now(), - data: upgradedData.data, - fight_heros: upgradedData.fight_heros, - heros: upgradedData.heros, - items: upgradedData.items, - tals: upgradedData.tals, - equips: upgradedData.equips - }, - msg: "数据升级成功完成" - }; - } else { - return { - code: -1, - msg: `升级失败, ${JSON.stringify(upgradeDataRes)}` - }; - } - } catch (error) { - console.error("升级用户数据错误:", error); - return { - code: -5, - msg: `升级错误: ${error.message}` - }; - } -} - -module.exports = { - login, - getOrCreaterUser, - getUserInfo, - checkVersion, - upgradeUserData -}; - - - - diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/fightHeros.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/fightHeros.js deleted file mode 100644 index 5ffe33d6..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/fightHeros.js +++ /dev/null @@ -1,370 +0,0 @@ -// 出战英雄操作模块 -const { getOrCreaterUser } = require('./auth'); - -const user_db_name = "cocos_users"; - -/** - * 获取出战英雄配置 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 操作结果 - */ -async function getFightHeros(db, openid) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - return { - code: 200, - data: user.fight_heros, - msg: "出战英雄获取成功" - }; - } catch (error) { - console.error("获取出战英雄错误:", error); - return { - code: -5, - msg: `获取出战英雄错误: ${error.message}` - }; - } -} - -/** - * 设置出战英雄 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {number} position 出战位置 (0-4) - * @param {number} heroId 英雄ID,0表示移除 - * @returns {Object} 操作结果 - */ -async function setFightHero(db, openid, position, heroId) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - // 验证位置参数 - if (position < 0 || position > 4) { - return { - code: -3, - msg: "无效的位置,必须是0-4" - }; - } - - // 验证英雄ID - if (typeof heroId !== 'number' || heroId < 0) { - return { - code: -3, - msg: "无效的英雄ID" - }; - } - - // 如果不是移除操作,检查英雄是否存在 - if (heroId > 0 && !user.heros[heroId]) { - return { - code: -6, - msg: "未拥有该英雄" - }; - } - - const oldHeroId = user.fight_heros[position]; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`fight_heros.${position}`]: _.set(heroId), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - position: position, - old_hero_id: oldHeroId, - new_hero_id: heroId - }, - msg: `出战英雄位置 ${position} 更新成功` - }; - } else { - return { - code: -1, - msg: `设置出战英雄失败` - }; - } - } catch (error) { - console.error("设置出战英雄错误:", error); - return { - code: -5, - msg: `设置出战英雄错误: ${error.message}` - }; - } -} - -/** - * 批量设置出战英雄 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {Object} fightHeros 出战英雄配置对象 - * @returns {Object} 操作结果 - */ -async function updateFightHeros(db, openid, fightHeros) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - // 验证数据格式 - if (!fightHeros || typeof fightHeros !== 'object') { - return { - code: -3, - msg: "无效的出战英雄数据格式" - }; - } - - // 验证每个位置和英雄ID - for (const pos in fightHeros) { - const position = parseInt(pos); - const heroId = fightHeros[pos]; - - if (isNaN(position) || position < 0 || position > 4) { - return { - code: -3, - msg: `无效的位置: ${pos}` - }; - } - - if (typeof heroId !== 'number' || heroId < 0) { - return { - code: -3, - msg: `位置 ${pos} 的英雄ID无效: ${heroId}` - }; - } - - // 如果不是移除操作,检查英雄是否存在 - if (heroId > 0 && !user.heros[heroId]) { - return { - code: -6, - msg: `位置 ${pos} 未拥有英雄 ${heroId}` - }; - } - } - - const newFightHeros = { ...user.fight_heros, ...fightHeros }; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - fight_heros: _.set(newFightHeros), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: newFightHeros, - msg: "出战英雄更新成功" - }; - } else { - return { - code: -1, - msg: `更新出战英雄失败` - }; - } - } catch (error) { - console.error("更新出战英雄错误:", error); - return { - code: -5, - msg: `更新出战英雄错误: ${error.message}` - }; - } -} - -/** - * 获取当前出战英雄列表(不包含空位) - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 操作结果 - */ -async function getActiveFightHeros(db, openid) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - const activeHeros = []; - for (let i = 0; i < 5; i++) { - const heroId = user.fight_heros[i]; - if (heroId && heroId > 0) { - activeHeros.push({ - position: i, - hero_id: heroId, - hero_data: user.heros[heroId] || null - }); - } - } - - return { - code: 200, - data: { - active_heros: activeHeros, - total_count: activeHeros.length - }, - msg: "获取活跃出战英雄成功" - }; - } catch (error) { - console.error("获取活跃出战英雄错误:", error); - return { - code: -5, - msg: `获取活跃出战英雄错误: ${error.message}` - }; - } -} - -/** - * 交换两个出战位置的英雄 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {number} position1 位置1 (0-4) - * @param {number} position2 位置2 (0-4) - * @returns {Object} 操作结果 - */ -async function swapFightHeros(db, openid, position1, position2) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - // 验证位置参数 - if (position1 < 0 || position1 > 4 || position2 < 0 || position2 > 4) { - return { - code: -3, - msg: "无效的位置,必须是0-4" - }; - } - - if (position1 === position2) { - return { - code: -3, - msg: "不能交换相同位置" - }; - } - - const hero1 = user.fight_heros[position1]; - const hero2 = user.fight_heros[position2]; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`fight_heros.${position1}`]: _.set(hero2), - [`fight_heros.${position2}`]: _.set(hero1), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - position1: position1, - position2: position2, - hero1_moved_to: hero1, - hero2_moved_to: hero2 - }, - msg: `出战英雄交换成功` - }; - } else { - return { - code: -1, - msg: `交换出战英雄失败` - }; - } - } catch (error) { - console.error("交换出战英雄错误:", error); - return { - code: -5, - msg: `交换出战英雄错误: ${error.message}` - }; - } -} - -/** - * 重置出战英雄配置 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 操作结果 - */ -async function resetFightHeros(db, openid) { - try { - const _ = db.command; - const { getNewUserInitData } = require('../user_init_data'); - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - const defaultData = getNewUserInitData(); - - let resetRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - fight_heros: _.set(defaultData.fight_heros), - last_save_time: _.set(Date.now()), - reset_time: _.set(Date.now()) - } - }); - - if (resetRes?.stats?.updated >= 1) { - return { - code: 200, - data: defaultData.fight_heros, - msg: "出战英雄重置成功" - }; - } else { - return { - code: -1, - msg: `重置失败, ${JSON.stringify(resetRes)}` - }; - } - } catch (error) { - console.error("重置出战英雄错误:", error); - return { - code: -5, - msg: `重置出战英雄错误: ${error.message}` - }; - } -} - -module.exports = { - getFightHeros, - setFightHero, - updateFightHeros, - getActiveFightHeros, - swapFightHeros, - resetFightHeros -}; - diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/gameData.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/gameData.js deleted file mode 100644 index f4b1f1be..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/gameData.js +++ /dev/null @@ -1,386 +0,0 @@ -// 基础游戏数据操作模块 (data字段) -const { getOrCreaterUser } = require('./auth'); -const { validateDataStructure, mergeUserDataWithDefaults } = require('../user_init_data'); - -const user_db_name = "cocos_users"; - -/** - * 获取基础游戏数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 操作结果 - */ -async function getData(db, openid) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "用户未找到" - }; - } - - return { - code: 200, - data: user.data, - msg: "游戏数据获取成功" - }; - } catch (error) { - console.error("获取游戏数据错误:", error); - return { - code: -5, - msg: `获取游戏数据错误: ${error.message}` - }; - } -} - -/** - * 更新基础游戏数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {Object} updateData 要更新的数据 - * @param {boolean} merge 是否合并更新(默认true) - * @returns {Object} 操作结果 - */ -async function updateData(db, openid, updateData, merge = true) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "用户未找到" - }; - } - - // 验证数据格式 - if (!updateData || typeof updateData !== 'object') { - return { - code: -3, - msg: "无效的更新数据格式" - }; - } - - let newData; - if (merge) { - // 合并更新 - newData = { ...user.data, ...updateData }; - } else { - // 完全替换 - newData = updateData; - } - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - data: _.set(newData), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: newData, - msg: "游戏数据更新成功" - }; - } else { - return { - code: -1, - msg: `更新失败, ${JSON.stringify(updateRes)}` - }; - } - } catch (error) { - console.error("更新游戏数据错误:", error); - return { - code: -5, - msg: `更新游戏数据错误: ${error.message}` - }; - } -} - -/** - * 增加指定字段的数值 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} field 字段名 - * @param {number} amount 增加的数量 - * @returns {Object} 操作结果 - */ -async function addDataField(db, openid, field, amount) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "用户未找到" - }; - } - - if (typeof amount !== 'number') { - return { - code: -3, - msg: "数量必须是数字" - }; - } - - const currentValue = user.data[field] || 0; - const newValue = Math.max(0, currentValue + amount); - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`data.${field}`]: _.set(newValue), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - field: field, - old_value: currentValue, - new_value: newValue, - change: amount - }, - msg: `${field} 更新成功` - }; - } else { - return { - code: -1, - msg: `更新 ${field} 失败` - }; - } - } catch (error) { - console.error(`增加 ${field} 错误:`, error); - return { - code: -5, - msg: `增加 ${field} 错误: ${error.message}` - }; - } -} - -/** - * 消耗指定字段的数值 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string|Object[]} field 字段名或字段对象数组 [{field: 字段名, amount: 数量}] - * @param {number} [amount] 消耗的数量 (当field为字符串时使用) - * @returns {Object} 操作结果 - */ -async function spendDataField(db, openid, field, amount) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "用户未找到" - }; - } - - // 处理单个字段的情况 - if (typeof field === 'string') { - if (typeof amount !== 'number' || amount < 0) { - return { - code: -3, - msg: "数量必须是正数" - }; - } - - const currentValue = user.data[field] || 0; - if (currentValue < amount) { - return { - code: -6, - msg: `${field} 不足, 当前: ${currentValue}, 需要: ${amount}` - }; - } - - return await addDataField(db, openid, field, -amount); - } - - // 处理多个字段的情况 - if (Array.isArray(field)) { - const fieldsToSpend = field; - - // 验证参数格式 - for (const item of fieldsToSpend) { - if (!item.field || typeof item.amount !== 'number' || item.amount < 0) { - return { - code: -3, - msg: "字段参数格式错误,需要 {field, amount} 结构,且amount必须是正数" - }; - } - } - - // 检查所有资源是否足够 - for (const item of fieldsToSpend) { - const currentValue = user.data[item.field] || 0; - if (currentValue < item.amount) { - return { - code: -6, - msg: `${item.field} 不足, 当前: ${currentValue}, 需要: ${item.amount}` - }; - } - } - - // 所有资源都足够,开始扣除 - const updateData = {}; - const changes = []; - - for (const item of fieldsToSpend) { - const currentValue = user.data[item.field] || 0; - const newValue = Math.max(0, currentValue - item.amount); - updateData[`data.${item.field}`] = _.set(newValue); - - changes.push({ - field: item.field, - old_value: currentValue, - new_value: newValue, - change: -item.amount - }); - } - - // 更新数据库 - updateData['last_save_time'] = _.set(Date.now()); - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: updateData - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: changes, - msg: "资源消耗成功" - }; - } else { - return { - code: -1, - msg: "资源消耗失败" - }; - } - } - - return { - code: -3, - msg: "参数格式错误" - }; - } catch (error) { - console.error(`消耗资源错误:`, error); - return { - code: -5, - msg: `消耗资源错误: ${error.message}` - }; - } -} - -/** - * 设置指定字段的数值 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} field 字段名 - * @param {any} value 新的值 - * @returns {Object} 操作结果 - */ -async function setDataField(db, openid, field, value) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "用户未找到" - }; - } - - const oldValue = user.data[field]; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`data.${field}`]: _.set(value), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - field: field, - old_value: oldValue, - new_value: value - }, - msg: `${field} 设置成功` - }; - } else { - return { - code: -1, - msg: `设置 ${field} 失败` - }; - } - } catch (error) { - console.error(`设置 ${field} 错误:`, error); - return { - code: -5, - msg: `设置 ${field} 错误: ${error.message}` - }; - } -} - -/** - * 重置基础游戏数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 操作结果 - */ -async function resetData(db, openid) { - try { - const _ = db.command; - const { getNewUserInitData } = require('../user_init_data'); - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "用户未找到" - }; - } - - const defaultData = getNewUserInitData(); - - let resetRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - data: _.set(defaultData.data), - last_save_time: _.set(Date.now()), - reset_time: _.set(Date.now()) - } - }); - - if (resetRes?.stats?.updated >= 1) { - return { - code: 200, - data: defaultData.data, - msg: "游戏数据重置成功" - }; - } else { - return { - code: -1, - msg: `重置失败, ${JSON.stringify(resetRes)}` - }; - } - } catch (error) { - console.error("重置游戏数据错误:", error); - return { - code: -5, - msg: `重置游戏数据错误: ${error.message}` - }; - } -} - -module.exports = { - getData, - updateData, - addDataField, - spendDataField, - setDataField, - resetData -}; diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/heros.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/heros.js deleted file mode 100644 index 523d8f7b..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/heros.js +++ /dev/null @@ -1,440 +0,0 @@ -// 英雄数据操作模块 -const { getOrCreaterUser } = require('./auth'); - -const user_db_name = "cocos_users"; - -/** - * 获取所有英雄数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 操作结果 - */ -async function getHeros(db, openid) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - return { - code: 200, - data: user.heros, - msg: "获取英雄列表成功" - }; - } catch (error) { - console.error("获取英雄列表错误:", error); - return { - code: -5, - msg: `获取英雄列表错误: ${error.message}` - }; - } -} - -/** - * 获取单个英雄数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {number} heroId 英雄ID - * @returns {Object} 操作结果 - */ -async function getHero(db, openid, heroId) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - const hero = user.heros[heroId]; - if (!hero) { - return { - code: -6, - msg: "未找到英雄" - }; - } - - return { - code: 200, - data: hero, - msg: "获取英雄成功" - }; - } catch (error) { - console.error("获取英雄错误:", error); - return { - code: -5, - msg: `获取英雄错误: ${error.message}` - }; - } -} - -/** - * 添加新英雄 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {number} heroId 英雄ID - * @param {Object} heroData 英雄数据(可选) - * @returns {Object} 操作结果 - */ -async function addHero(db, openid, heroId, heroData = null) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - // 检查英雄是否已存在 - if (user.heros[heroId]) { - return { - code: -7, - msg: "英雄已存在" - }; - } - - // 使用提供的数据或默认数据 - const newHero = heroData || { - uuid: heroId, - lv: 1, - exp: 0, - star: 1, - power: 100 - }; - - // 确保uuid字段正确 - newHero.uuid = heroId; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`heros.${heroId}`]: _.set(newHero), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: newHero, - msg: `英雄 ${heroId} 添加成功` - }; - } else { - return { - code: -1, - msg: `添加英雄失败` - }; - } - } catch (error) { - console.error("添加英雄错误:", error); - return { - code: -5, - msg: `添加英雄错误: ${error.message}` - }; - } -} - -/** - * 更新英雄属性 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {number} heroId 英雄ID - * @param {Object} updateData 要更新的属性 - * @returns {Object} 操作结果 - */ -async function updateHero(db, openid, heroId, updateData) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - // 检查英雄是否存在 - if (!user.heros[heroId]) { - return { - code: -6, - msg: "未找到英雄" - }; - } - - // 验证更新数据 - if (!updateData || typeof updateData !== 'object') { - return { - code: -3, - msg: "无效的更新数据格式" - }; - } - - const currentHero = user.heros[heroId]; - const newHero = { ...currentHero, ...updateData }; - - // 确保uuid字段不被修改 - newHero.uuid = heroId; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`heros.${heroId}`]: _.set(newHero), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - old_data: currentHero, - new_data: newHero - }, - msg: `英雄 ${heroId} 更新成功` - }; - } else { - return { - code: -1, - msg: `更新英雄失败` - }; - } - } catch (error) { - console.error("更新英雄错误:", error); - return { - code: -5, - msg: `更新英雄错误: ${error.message}` - }; - } -} - -/** - * 设置英雄属性 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {number} heroId 英雄ID - * @param {string} property 属性名 - * @param {any} value 属性值 - * @returns {Object} 操作结果 - */ -async function setHeroProperty(db, openid, heroId, property, value) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - // 检查英雄是否存在 - if (!user.heros[heroId]) { - return { - code: -6, - msg: "未找到英雄" - }; - } - - // 防止修改uuid - if (property === 'uuid') { - return { - code: -3, - msg: "不可修改英雄UUID" - }; - } - - const oldValue = user.heros[heroId][property]; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`heros.${heroId}.${property}`]: _.set(value), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - hero_id: heroId, - property: property, - old_value: oldValue, - new_value: value - }, - msg: `英雄 ${heroId} 属性 ${property} 更新成功` - }; - } else { - return { - code: -1, - msg: `设置英雄属性失败` - }; - } - } catch (error) { - console.error("设置英雄属性错误:", error); - return { - code: -5, - msg: `设置英雄属性错误: ${error.message}` - }; - } -} - -/** - * 英雄升级 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {number} heroId 英雄ID - * @param {number} levels 升级级数(默认1级) - * @returns {Object} 操作结果 - */ -async function levelUpHero(db, openid, heroId,levels = 1) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - // 检查英雄是否存在 - if (!user.heros[heroId]) { - return { - code: -6, - msg: "未找到英雄" - }; - } - - if (typeof levels !== 'number' || levels < 1) { - return { - code: -3, - msg: "等级必须为正数" - }; - } - const currentLevel = user.heros[heroId].lv || 1; - const newLevel = currentLevel + levels; - return await setHeroProperty(db, openid, heroId, 'lv', newLevel); - } catch (error) { - console.error("英雄升级错误:", error); - return { - code: -5, - msg: `英雄升级错误: ${error.message}` - }; - } -} - -/** - * 删除英雄 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {number} heroId 英雄ID - * @returns {Object} 操作结果 - */ -async function deleteHero(db, openid, heroId) { - try { - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - // 检查英雄是否存在 - if (!user.heros[heroId]) { - return { - code: -6, - msg: "未找到英雄" - }; - } - - // 检查英雄是否在出战阵容中 - for (let pos = 0; pos < 5; pos++) { - if (user.fight_heros[pos] === heroId) { - return { - code: -8, - msg: `英雄位于出战位置 ${pos},请先从出战阵容移除` - }; - } - } - - const deletedHero = user.heros[heroId]; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`heros.${heroId}`]: _.remove(), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: deletedHero, - msg: `英雄 ${heroId} 删除成功` - }; - } else { - return { - code: -1, - msg: `删除英雄失败` - }; - } - } catch (error) { - console.error("删除英雄错误:", error); - return { - code: -5, - msg: `删除英雄错误: ${error.message}` - }; - } -} - -/** - * 获取已拥有的英雄ID列表 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @returns {Object} 操作结果 - */ -async function getOwnedHeroIds(db, openid) { - try { - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - const heroIds = Object.keys(user.heros).map(Number); - - return { - code: 200, - data: { - hero_ids: heroIds, - total_count: heroIds.length - }, - msg: "获取已拥有英雄ID成功" - }; - } catch (error) { - console.error("获取已拥有英雄ID错误:", error); - return { - code: -5, - msg: `获取已拥有英雄ID错误: ${error.message}` - }; - } -} - -module.exports = { - getHeros, - getHero, - addHero, - updateHero, - setHeroProperty, - levelUpHero, - deleteHero, - getOwnedHeroIds -}; - diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/inventory.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/inventory.js deleted file mode 100644 index 96d4a3fa..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/inventory.js +++ /dev/null @@ -1,501 +0,0 @@ -// 通用库存操作模块 (items, tals, equips) -const { getOrCreaterUser } = require('./auth'); - -const user_db_name = "cocos_users"; - -// 支持的数据类型 -const SUPPORTED_TYPES = ['items', 'tals', 'equips']; - -/** - * 验证数据类型 - * @param {string} dataType 数据类型 - * @returns {boolean} 是否有效 - */ -function validateDataType(dataType) { - return SUPPORTED_TYPES.includes(dataType); -} - -/** - * 获取库存数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} dataType 数据类型 ('items', 'tals', 'equips') - * @returns {Object} 操作结果 - */ -async function getInventory(db, openid, dataType) { - try { - if (!validateDataType(dataType)) { - return { - code: -3, - msg: `无效的数据类型: ${dataType}` - }; - } - - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - return { - code: 200, - data: user[dataType], - msg: `${dataType}获取成功` - }; - } catch (error) { - console.error(`获取${dataType}错误:`, error); - return { - code: -5, - msg: `获取${dataType}错误: ${error.message}` - }; - } -} - -/** - * 获取单个物品数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} dataType 数据类型 - * @param {number} itemId 物品ID - * @returns {Object} 操作结果 - */ -async function getInventoryItem(db, openid, dataType, itemId) { - try { - if (!validateDataType(dataType)) { - return { - code: -3, - msg: `无效的数据类型: ${dataType}` - }; - } - - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - const itemCount = user[dataType][itemId]; - if (itemCount === undefined) { - return { - code: -6, - msg: `${dataType.slice(0, -1)} ${itemId} 未找到` - }; - } - - return { - code: 200, - data: { - item_id: itemId, - count: itemCount - }, - msg: `${dataType.slice(0, -1)} ${itemId} 获取成功` - }; - } catch (error) { - console.error(`获取${dataType}物品错误:`, error); - return { - code: -5, - msg: `获取${dataType}物品错误: ${error.message}` - }; - } -} - -/** - * 添加物品 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} dataType 数据类型 - * @param {number} itemId 物品ID - * @param {number} count 添加数量 - * @returns {Object} 操作结果 - */ -async function addInventoryItem(db, openid, dataType, itemId, count) { - try { - if (!validateDataType(dataType)) { - return { - code: -3, - msg: `无效的数据类型: ${dataType}` - }; - } - - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - if (typeof count !== 'number' || count < 0) { - return { - code: -3, - msg: "数量必须是非负数" - }; - } - - const currentCount = user[dataType][itemId] || 0; - const newCount = currentCount + count; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`${dataType}.${itemId}`]: _.set(newCount), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - item_id: itemId, - old_count: currentCount, - new_count: newCount, - added: count - }, - msg: `${dataType.slice(0, -1)} ${itemId} 添加成功` - }; - } else { - return { - code: -1, - msg: `添加 ${dataType.slice(0, -1)} 失败` - }; - } - } catch (error) { - console.error(`添加${dataType}物品错误:`, error); - return { - code: -5, - msg: `添加${dataType}物品错误: ${error.message}` - }; - } -} - -/** - * 消耗物品 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} dataType 数据类型 - * @param {number} itemId 物品ID - * @param {number} count 消耗数量 - * @returns {Object} 操作结果 - */ -async function consumeInventoryItem(db, openid, dataType, itemId, count) { - try { - if (!validateDataType(dataType)) { - return { - code: -3, - msg: `无效的数据类型: ${dataType}` - }; - } - - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - if (typeof count !== 'number' || count < 0) { - return { - code: -3, - msg: "数量必须是非负数" - }; - } - - const currentCount = user[dataType][itemId] || 0; - if (currentCount < count) { - return { - code: -6, - msg: `${dataType.slice(0, -1)} ${itemId}不足, 当前: ${currentCount}, 需要: ${count}` - }; - } - - return await addInventoryItem(db, openid, dataType, itemId, -count); - } catch (error) { - console.error(`消耗${dataType}物品错误:`, error); - return { - code: -5, - msg: `消耗${dataType}物品错误: ${error.message}` - }; - } -} - -/** - * 设置物品数量 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} dataType 数据类型 - * @param {number} itemId 物品ID - * @param {number} count 新的数量 - * @returns {Object} 操作结果 - */ -async function setInventoryItem(db, openid, dataType, itemId, count) { - try { - if (!validateDataType(dataType)) { - return { - code: -3, - msg: `无效的数据类型: ${dataType}` - }; - } - - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "未找到用户" - }; - } - - if (typeof count !== 'number' || count < 0) { - return { - code: -3, - msg: "数量必须是非负数" - }; - } - - const oldCount = user[dataType][itemId] || 0; - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [`${dataType}.${itemId}`]: _.set(count), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: { - item_id: itemId, - old_count: oldCount, - new_count: count - }, - msg: `${dataType.slice(0, -1)} ${itemId} 设置成功` - }; - } else { - return { - code: -1, - msg: `设置 ${dataType.slice(0, -1)} 失败` - }; - } - } catch (error) { - console.error(`设置${dataType}物品错误:`, error); - return { - code: -5, - msg: `设置${dataType}物品错误: ${error.message}` - }; - } -} - -/** - * 批量更新库存 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} dataType 数据类型 - * @param {Object} updateData 更新数据对象 - * @param {boolean} merge 是否合并更新(默认true) - * @returns {Object} 操作结果 - */ -async function updateInventory(db, openid, dataType, updateData, merge = true) { - try { - if (!validateDataType(dataType)) { - return { - code: -3, - msg: `Invalid data type: ${dataType}` - }; - } - - const _ = db.command; - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "User not found" - }; - } - - // 验证更新数据 - if (!updateData || typeof updateData !== 'object') { - return { - code: -3, - msg: "Invalid update data format" - }; - } - - // 验证所有值都是非负数 - for (const itemId in updateData) { - const count = updateData[itemId]; - if (typeof count !== 'number' || count < 0) { - return { - code: -3, - msg: `Invalid count for item ${itemId}: ${count}` - }; - } - } - - let newData; - if (merge) { - // 合并更新 - newData = { ...user[dataType], ...updateData }; - } else { - // 完全替换 - newData = updateData; - } - - let updateRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [dataType]: _.set(newData), - last_save_time: _.set(Date.now()) - } - }); - - if (updateRes?.stats?.updated >= 1) { - return { - code: 200, - data: newData, - msg: `${dataType} updated successfully` - }; - } else { - return { - code: -1, - msg: `Update ${dataType} fail` - }; - } - } catch (error) { - console.error(`Update ${dataType} error:`, error); - return { - code: -5, - msg: `Update ${dataType} error: ${error.message}` - }; - } -} - -/** - * 重置库存数据 - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} dataType 数据类型 - * @returns {Object} 操作结果 - */ -async function resetInventory(db, openid, dataType) { - try { - if (!validateDataType(dataType)) { - return { - code: -3, - msg: `Invalid data type: ${dataType}` - }; - } - - const _ = db.command; - const { getNewUserInitData } = require('../user_init_data'); - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "User not found" - }; - } - - const defaultData = getNewUserInitData(); - - let resetRes = await db.collection(user_db_name).doc(user._id).update({ - data: { - [dataType]: _.set(defaultData[dataType]), - last_save_time: _.set(Date.now()), - reset_time: _.set(Date.now()) - } - }); - - if (resetRes?.stats?.updated >= 1) { - return { - code: 200, - data: defaultData[dataType], - msg: `${dataType} reset successfully` - }; - } else { - return { - code: -1, - msg: `Reset ${dataType} fail` - }; - } - } catch (error) { - console.error(`Reset ${dataType} error:`, error); - return { - code: -5, - msg: `Reset ${dataType} error: ${error.message}` - }; - } -} - -/** - * 获取拥有的物品列表(数量大于0的) - * @param {Object} db 数据库实例 - * @param {string} openid 用户openid - * @param {string} dataType 数据类型 - * @returns {Object} 操作结果 - */ -async function getOwnedItems(db, openid, dataType) { - try { - if (!validateDataType(dataType)) { - return { - code: -3, - msg: `Invalid data type: ${dataType}` - }; - } - - let user = await getOrCreaterUser(db, openid); - if (!user) { - return { - code: -4, - msg: "User not found" - }; - } - - const ownedItems = []; - for (const itemId in user[dataType]) { - const count = user[dataType][itemId]; - if (count > 0) { - ownedItems.push({ - item_id: parseInt(itemId), - count: count - }); - } - } - - return { - code: 200, - data: { - owned_items: ownedItems, - total_types: ownedItems.length - }, - msg: `Owned ${dataType} retrieved successfully` - }; - } catch (error) { - console.error(`Get owned ${dataType} error:`, error); - return { - code: -5, - msg: `Get owned ${dataType} error: ${error.message}` - }; - } -} - -module.exports = { - getInventory, - getInventoryItem, - addInventoryItem, - consumeInventoryItem, - setInventoryItem, - updateInventory, - resetInventory, - getOwnedItems, - SUPPORTED_TYPES -}; - - - - diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/response.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/response.js deleted file mode 100644 index 5ea3a23d..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/response.js +++ /dev/null @@ -1,274 +0,0 @@ -// 统一响应处理模块 -const { DATA_VERSION } = require('../user_init_data'); - -/** - * 成功响应 - * @param {any} data 返回数据 - * @param {string} message 成功消息 - * @param {Object} extra 额外信息 - * @returns {Object} 响应对象 - */ -function success(data = null, message = "成功", extra = {}) { - return { - code: 200, - data: data, - msg: message, - timestamp: Date.now(), - version: DATA_VERSION, - ...extra - }; -} - -/** - * 错误响应 - * @param {number} code 错误码 - * @param {string} message 错误消息 - * @param {any} data 错误相关数据 - * @returns {Object} 响应对象 - */ -function error(code, message, data = null) { - return { - code: code, - msg: message, - data: data, - timestamp: Date.now(), - version: DATA_VERSION - }; -} - -/** - * 参数错误响应 - * @param {string} message 错误消息 - * @param {any} data 错误相关数据 - * @returns {Object} 响应对象 - */ -function badRequest(message = "请求参数错误", data = null) { - return error(-3, message, data); -} - -/** - * 用户未找到响应 - * @param {string} message 错误消息 - * @returns {Object} 响应对象 - */ -function userNotFound(message = "未找到用户") { - return error(-4, message); -} - -/** - * 系统错误响应 - * @param {string} message 错误消息 - * @param {Error} err 错误对象 - * @returns {Object} 响应对象 - */ -function systemError(message = "系统错误", err = null) { - const errorData = err ? { - error_message: err.message, - error_stack: process.env.NODE_ENV === 'development' ? err.stack : undefined - } : null; - - return error(-5, message, errorData); -} - -/** - * 资源不足响应 - * @param {string} resource 资源名称 - * @param {number} current 当前数量 - * @param {number} required 需要数量 - * @returns {Object} 响应对象 - */ -function insufficientResource(resource, current = 0, required = 0) { - return error(-6, `${resource}不足`, { - resource: resource, - current: current, - required: required, - shortage: required - current - }); -} - -/** - * 资源已存在响应 - * @param {string} resource 资源名称 - * @param {any} identifier 资源标识 - * @returns {Object} 响应对象 - */ -function resourceExists(resource, identifier = null) { - return error(-7, `${resource}已存在`, { - resource: resource, - identifier: identifier - }); -} - -/** - * 操作被拒绝响应 - * @param {string} reason 拒绝原因 - * @param {any} data 相关数据 - * @returns {Object} 响应对象 - */ -function operationDenied(reason, data = null) { - return error(-8, `操作被拒绝: ${reason}`, data); -} - -/** - * 未知命令响应 - * @param {string} command 命令名 - * @param {Array} availableCommands 可用命令列表 - * @returns {Object} 响应对象 - */ -function unknownCommand(command, availableCommands = []) { - return error(-2, `未知命令: ${command}`, { - command: command, - available_commands: availableCommands - }); -} - -/** - * 包装异步操作,统一错误处理 - * @param {Function} operation 异步操作函数 - * @param {string} operationName 操作名称 - * @returns {Function} 包装后的函数 - */ -function wrapAsync(operation, operationName = "Operation") { - return async (...args) => { - try { - const result = await operation(...args); - - // 如果操作返回的是错误格式,直接返回 - if (result && typeof result === 'object' && result.code !== undefined) { - return result; - } - - // 如果是成功结果,包装为成功响应 - return success(result, `${operationName}成功完成`); - } catch (error) { - console.error(`${operationName}错误:`, error); - return systemError(`${operationName}失败`, error); - } - }; -} - -/** - * 验证必需参数 - * @param {Object} params 参数对象 - * @param {Array} requiredFields 必需字段列表 - * @returns {Object|null} 如果验证失败返回错误响应,否则返回null - */ -function validateRequiredParams(params, requiredFields) { - if (!params || typeof params !== 'object') { - return badRequest("Invalid parameters"); - } - - const missingFields = []; - for (const field of requiredFields) { - if (params[field] === undefined || params[field] === null) { - missingFields.push(field); - } - } - - if (missingFields.length > 0) { - return badRequest(`Missing required parameters: ${missingFields.join(', ')}`, { - missing_fields: missingFields, - required_fields: requiredFields - }); - } - - return null; -} - -/** - * 验证数值参数 - * @param {any} value 要验证的值 - * @param {string} fieldName 字段名 - * @param {Object} options 验证选项 - * @returns {Object|null} 如果验证失败返回错误响应,否则返回null - */ -function validateNumber(value, fieldName, options = {}) { - const { - min = Number.NEGATIVE_INFINITY, - max = Number.POSITIVE_INFINITY, - integer = false - } = options; - - if (typeof value !== 'number' || isNaN(value)) { - return badRequest(`${fieldName} must be a number`); - } - - if (integer && !Number.isInteger(value)) { - return badRequest(`${fieldName} must be an integer`); - } - - if (value < min) { - return badRequest(`${fieldName} must be at least ${min}`); - } - - if (value > max) { - return badRequest(`${fieldName} must be at most ${max}`); - } - - return null; -} - -/** - * 创建分页响应 - * @param {Array} items 数据项 - * @param {number} total 总数 - * @param {number} page 当前页 - * @param {number} pageSize 页大小 - * @param {string} message 成功消息 - * @returns {Object} 响应对象 - */ -function paginated(items, total, page, pageSize, message = "Data retrieved successfully") { - const totalPages = Math.ceil(total / pageSize); - - return success({ - items: items, - pagination: { - current_page: page, - page_size: pageSize, - total_items: total, - total_pages: totalPages, - has_next: page < totalPages, - has_prev: page > 1 - } - }, message); -} - -/** - * 错误码常量 - */ -const ERROR_CODES = { - SUCCESS: 200, - OPERATION_FAILED: -1, - UNKNOWN_COMMAND: -2, - BAD_REQUEST: -3, - USER_NOT_FOUND: -4, - SYSTEM_ERROR: -5, - INSUFFICIENT_RESOURCE: -6, - RESOURCE_EXISTS: -7, - OPERATION_DENIED: -8 -}; - -module.exports = { - success, - error, - badRequest, - userNotFound, - systemError, - insufficientResource, - resourceExists, - operationDenied, - unknownCommand, - wrapAsync, - validateRequiredParams, - validateNumber, - paginated, - ERROR_CODES -}; - - - - - - - - diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/user_init_data.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/user_init_data.js deleted file mode 100644 index 07a5f68a..00000000 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/user_init_data.js +++ /dev/null @@ -1,247 +0,0 @@ -// 新用户初始化数据配置文件 -// 用于管理新用户注册时的默认游戏数据 - -/** - * 数据版本号 - 用于数据结构升级和兼容性管理 - * 格式: MAJOR.MINOR.PATCH - * MAJOR: 重大结构变更,不向后兼容 - * MINOR: 新增字段,向后兼容 - * PATCH: 数值调整,完全兼容 - */ -const DATA_VERSION = "1.0.0"; - -/** - * 基础游戏数据默认值 - */ -const DEFAULT_GAME_DATA = { - score: 0, // 游戏分数 - mission: 1, // 当前关卡 - gold: 100, // 金币 - 升级主要资源 - diamond: 100, // 钻石 - 商店购买及双倍奖励资源 - meat: 0, // 肉类资源 - exp: 0, // 升级经验 - -}; - -/** - * 默认出战英雄配置 - * 位置 0-4 对应 5个出战位置 - * 0 表示该位置为空 - */ -const DEFAULT_FIGHT_HEROS = { - 0: 5001, // 第1个位置:默认英雄5001 - 1: 5005, // 第2个位置:默认英雄5005 - 2: 0, // 第3个位置:空 - 3: 0, // 第4个位置:空 - 4: 0 // 第5个位置:空 -}; - -/** - * 默认英雄属性数据 - * 每个英雄包含: uuid(唯一标识), lv(等级), 其他属性可扩展 - */ -const DEFAULT_HEROS = { - 5001: { - uuid: 5001, - lv: 1, // 初始等级 - exp: 0, // 英雄经验 - star: 1, // 星级 - power: 100 // 战力 - }, - 5005: { - uuid: 5005, - lv: 1, - exp: 0, - star: 1, - power: 120 - }, - 5007: { - uuid: 5007, - lv: 1, - exp: 0, - star: 1, - power: 90 - } -}; - -/** - * 默认道具数据 - * ID 1001-1007 对应不同类型的道具 - */ -const DEFAULT_ITEMS = { - -}; - -/** - * 默认天赋数据 - * ID 1001-1007 对应不同的天赋技能 - */ -const DEFAULT_TALS = { - -}; - -/** - * 默认装备数据 - * ID 1001-1005 对应不同部位的装备 - */ -const DEFAULT_EQUIPS = { - -}; - -/** - * 获取完整的新用户初始化数据 - * @returns {Object} 包含所有默认数据的对象 - */ -function getNewUserInitData() { - return { - data_version: DATA_VERSION, - init_time: Date.now(), - data: { ...DEFAULT_GAME_DATA }, - fight_heros: { ...DEFAULT_FIGHT_HEROS }, - heros: JSON.parse(JSON.stringify(DEFAULT_HEROS)), // 深拷贝避免引用问题 - items: { ...DEFAULT_ITEMS }, - tals: { ...DEFAULT_TALS }, - equips: { ...DEFAULT_EQUIPS } - }; -} - -/** - * 获取特定类型的默认数据 - * @param {string} dataType 数据类型: 'data', 'fight_heros', 'heros', 'items', 'tals', 'equips' - * @returns {Object} 指定类型的默认数据 - */ -function getDefaultDataByType(dataType) { - const dataMap = { - data: DEFAULT_GAME_DATA, - fight_heros: DEFAULT_FIGHT_HEROS, - heros: DEFAULT_HEROS, - items: DEFAULT_ITEMS, - tals: DEFAULT_TALS, - equips: DEFAULT_EQUIPS - }; - - const defaultData = dataMap[dataType]; - if (!defaultData) { - throw new Error(`Unknown data type: ${dataType}`); - } - - // 返回深拷贝以避免修改原始数据 - return JSON.parse(JSON.stringify(defaultData)); -} - -/** - * 检查数据版本兼容性 - * @param {string} userDataVersion 用户数据版本 - * @returns {Object} 兼容性检查结果 - */ -function checkDataVersionCompatibility(userDataVersion) { - if (!userDataVersion) { - return { - compatible: false, - needsUpgrade: true, - message: "No version found, needs full upgrade" - }; - } - - const [userMajor, userMinor, userPatch] = userDataVersion.split('.').map(Number); - const [currentMajor, currentMinor, currentPatch] = DATA_VERSION.split('.').map(Number); - - if (userMajor < currentMajor) { - return { - compatible: false, - needsUpgrade: true, - message: "Major version mismatch, needs full upgrade" - }; - } - - if (userMajor === currentMajor && userMinor < currentMinor) { - return { - compatible: true, - needsUpgrade: true, - message: "Minor version update available" - }; - } - - if (userMajor === currentMajor && userMinor === currentMinor && userPatch < currentPatch) { - return { - compatible: true, - needsUpgrade: true, - message: "Patch update available" - }; - } - - return { - compatible: true, - needsUpgrade: false, - message: "Data version is up to date" - }; -} - -/** - * 合并用户数据和默认数据 - * 确保用户数据包含所有必需的字段 - * @param {Object} userData 用户现有数据 - * @returns {Object} 合并后的完整数据 - */ -function mergeUserDataWithDefaults(userData) { - const defaultData = getNewUserInitData(); - const mergedData = { - data_version: DATA_VERSION, - init_time: userData.init_time || Date.now(), - data: { ...defaultData.data, ...userData.data }, - fight_heros: { ...defaultData.fight_heros, ...userData.fight_heros }, - heros: { ...defaultData.heros, ...userData.heros }, - items: { ...defaultData.items, ...userData.items }, - tals: { ...defaultData.tals, ...userData.tals }, - equips: { ...defaultData.equips, ...userData.equips } - }; - - return mergedData; -} - -/** - * 验证数据结构完整性 - * @param {Object} gameData 要验证的游戏数据 - * @returns {Object} 验证结果 - */ -function validateDataStructure(gameData) { - const requiredFields = ['data', 'fight_heros', 'heros', 'items', 'tals', 'equips']; - const missingFields = []; - - for (const field of requiredFields) { - if (!gameData[field] || typeof gameData[field] !== 'object') { - missingFields.push(field); - } - } - - if (missingFields.length > 0) { - return { - valid: false, - missingFields, - message: `Missing or invalid fields: ${missingFields.join(', ')}` - }; - } - - return { - valid: true, - message: "Data structure is valid" - }; -} - -// 导出所有功能函数 -module.exports = { - DATA_VERSION, - getNewUserInitData, - getDefaultDataByType, - checkDataVersionCompatibility, - mergeUserDataWithDefaults, - validateDataStructure, - - // 导出原始数据常量(只读) - DEFAULT_GAME_DATA: Object.freeze({ ...DEFAULT_GAME_DATA }), - DEFAULT_FIGHT_HEROS: Object.freeze({ ...DEFAULT_FIGHT_HEROS }), - DEFAULT_HEROS: Object.freeze(JSON.parse(JSON.stringify(DEFAULT_HEROS))), - DEFAULT_ITEMS: Object.freeze({ ...DEFAULT_ITEMS }), - DEFAULT_TALS: Object.freeze({ ...DEFAULT_TALS }), - DEFAULT_EQUIPS: Object.freeze({ ...DEFAULT_EQUIPS }) -};