diff --git a/assets/script/game/common/GameDataSyncManager.ts b/assets/script/game/common/GameDataSyncManager.ts index b397d59c..6f0fb06b 100644 --- a/assets/script/game/common/GameDataSyncManager.ts +++ b/assets/script/game/common/GameDataSyncManager.ts @@ -1,6 +1,7 @@ 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"; /** * 游戏数据同步管理器 @@ -296,7 +297,7 @@ export class GameDataSyncManager { } - + /** * 增加天赋点 * @param talId 天赋ID @@ -351,33 +352,6 @@ export class GameDataSyncManager { } } - /** - * 设置天赋点数量 - * @param talId 天赋ID - * @param count 数量 - * @returns 是否成功 - */ - async setTalent(talId: number, count: number): Promise { - try { - console.log(`[GameDataSyncManager]: 设置天赋点数量 ID:${talId}, 数量:${count}`); - - const result = await WxCloudApi.setInventoryItem('tals', talId, count); - - if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.tals[talId] = count; - console.log(`[GameDataSyncManager]: 天赋点数量设置成功,本地数据已同步`); - return true; - } else { - console.warn(`[GameDataSyncManager]: 天赋点数量设置失败: ${result.result.msg}`); - return false; - } - } catch (error) { - console.error(`[GameDataSyncManager]: 设置天赋点数量异常:`, error); - return false; - } - } - /** * 增加装备 * @param equipId 装备ID @@ -432,34 +406,37 @@ export class GameDataSyncManager { } } - /** - * 设置装备数量 - * @param equipId 装备ID - * @param count 数量 - * @returns 是否成功 - */ - async setEquipment(equipId: number, count: number): Promise { + + async addGameProperty(property: string, value: any): Promise { try { - console.log(`[GameDataSyncManager]: 设置装备数量 ID:${equipId}, 数量:${count}`); - - const result = await WxCloudApi.setInventoryItem('equips', equipId, count); - + console.log(`[GameDataSyncManager]: 增加游戏数据 ${property} = ${value}`); + const result = await WxCloudApi.addGameDataField(property, value); if (result.result.code === 200) { - // 远程修改成功,同步本地数据 - smc.equips[equipId] = count; - console.log(`[GameDataSyncManager]: 装备数量设置成功,本地数据已同步`); + console.log(`[GameDataSyncManager]: 游戏数据增加成功`); return true; } else { - console.warn(`[GameDataSyncManager]: 装备数量设置失败: ${result.result.msg}`); + console.warn(`[GameDataSyncManager]: 游戏数据增加失败: ${result.result.msg}`); return false; } } catch (error) { - console.error(`[GameDataSyncManager]: 设置装备数量异常:`, error); + console.error(`[GameDataSyncManager]: 增加游戏数据异常:`, error); return false; } } - + async spendGameProperty(property: string, value: any): 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); + return false; + } + } /** * 从云端加载所有游戏数据并同步到本地 diff --git a/assets/script/game/common/SingletonModuleComp.ts b/assets/script/game/common/SingletonModuleComp.ts index ed62e407..7b5cf865 100644 --- a/assets/script/game/common/SingletonModuleComp.ts +++ b/assets/script/game/common/SingletonModuleComp.ts @@ -4,7 +4,7 @@ import { Initialize } from "../initialize/Initialize"; import { GameMap } from "../map/GameMap"; import { HeroUI, VmInfo } from "./config/Mission"; import { oops } from "../../../../extensions/oops-plugin-framework/assets/core/Oops"; -import { WxCloudApi } from "../wx_clound_client_api/WxCloudApi"; +import { GameData, WxCloudApi } from "../wx_clound_client_api/WxCloudApi"; import { gameDataSyncManager } from "./GameDataSyncManager"; import { GameSet } from "./config/BoxSet"; import { Test } from "./Test"; @@ -166,17 +166,63 @@ export class SingletonModuleComp extends ecs.Comp { * @param autoSave 是否自动保存 (默认true) * @returns 操作结果 */ - async addGameProperty(property: string, value: any, autoSave: boolean = true): Promise { - const currentValue = this.data[property] || 0; - const newValue = currentValue + value; - - this.data[property] = newValue; - this.vmdata.data[property] = newValue; - - console.log(`[SMC]: 增加游戏数据 ${property} = ${value}, 当前值: ${newValue}`); - return newValue; + addExp(exp:number,autoSave:boolean=true){ + this.data.exp+=exp + this.vmdata.data.exp+=exp + if(this.isWxClient()){ + this.gameDataSyncManager.addGameProperty("exp",exp) + } } - + addGold(gold:number,autoSave:boolean=true){ + this.data.gold+=gold + this.vmdata.data.gold+=gold + if(this.isWxClient()){ + this.gameDataSyncManager.addGameProperty("gold",gold) + } + } + addDiamond(diamond:number,autoSave:boolean=true){ + this.data.diamond+=diamond + this.vmdata.data.diamond+=diamond + if(this.isWxClient()){ + this.gameDataSyncManager.addGameProperty("diamond",diamond) + } + } + addMission(mission:number,autoSave:boolean=true){ + this.data.mission+=mission + this.vmdata.data.mission+=mission + if(this.isWxClient()){ + this.gameDataSyncManager.addGameProperty("mission",mission) + } + } + spendMission(mission:number,autoSave:boolean=true){ + this.data.mission-=mission + this.vmdata.data.mission-=mission + if(this.isWxClient()){ + this.gameDataSyncManager.spendGameProperty("mission",mission) + } + } + spendExp(exp:number,autoSave:boolean=true){ + this.data.exp-=exp + this.vmdata.data.exp-=exp + if(this.isWxClient()){ + this.gameDataSyncManager.spendGameProperty("exp",exp) + } + } + spendGold(gold:number,autoSave:boolean=true){ + this.data.gold-=gold + this.vmdata.data.gold-=gold + if(this.isWxClient()){ + this.gameDataSyncManager.spendGameProperty("gold",gold) + } + } + spendDiamond(diamond:number,autoSave:boolean=true){ + this.data.diamond-=diamond + this.vmdata.data.diamond-=diamond + if(this.isWxClient()){ + this.gameDataSyncManager.spendGameProperty("diamond",diamond) + } + } + /** * 消耗游戏数据属性(统一接口) * - 支持单个字段:spendGameProperty('gold', 10) @@ -228,6 +274,7 @@ export class SingletonModuleComp extends ecs.Comp { return true; } + addItem(item_uuid:number,count:number,autoSave:boolean=true){ if(this.isWxClient()){ this.gameDataSyncManager.addItem(item_uuid,count); diff --git a/assets/script/game/common/config/Items.ts b/assets/script/game/common/config/Items.ts index f3147581..3a8df959 100644 --- a/assets/script/game/common/config/Items.ts +++ b/assets/script/game/common/config/Items.ts @@ -116,6 +116,93 @@ export const MonsterDropTable: { [monsterId: number]: [number, number, number, n ] }; +// 基础资源掉落配置表 - 以普通怪为基础值 +export const BaseResourceDropConfig = { + // 经验值配置 + exp: { + baseValue: 100, // 普通怪基础经验值 + stageMultiplier: 1.15, // 关卡倍数 (降低增长) + randomRange: 0.2, // 随机范围 (±20%) + baseProbability: 1.0 // 基础掉落概率 (100%) + }, + // 金币配置 + gold: { + baseValue: 50, // 普通怪基础金币值 + stageMultiplier: 1.12, // 关卡倍数 (降低增长) + randomRange: 0.25, // 随机范围 (±25%) + baseProbability: 0.7 // 基础掉落概率 (70%) + }, + // 钻石配置 + diamond: { + baseValue: 2, // 基础钻石值 + stageMultiplier: 1.05, // 关卡倍数 (大幅降低增长) + randomRange: 0.2, // 随机范围 (±20%) + baseProbability: 0.0 // 基础掉落概率 (0%,需要品质加成) + } +}; + +// 怪物品质加成配置表 - 使用加法权重 +export const QualityBonusConfig = { + [QualitySet.GREEN]: { + // 绿色品质:基础值 + 加成 + expBonus: 0, // 经验值加成 + goldBonus: 0, // 金币加成 + diamondBonus: 0, // 钻石加成 + expProbabilityBonus: 0, // 经验掉落概率加成 + goldProbabilityBonus: 0, // 金币掉落概率加成 + diamondProbabilityBonus: 0 // 钻石掉落概率加成 + }, + [QualitySet.BLUE]: { + // 蓝色品质:基础值 + 加成 + expBonus: 50, // 经验值 +50 + goldBonus: 25, // 金币 +25 + diamondBonus: 0, // 钻石加成 0 + expProbabilityBonus: 0, // 经验掉落概率加成 + goldProbabilityBonus: 0.1, // 金币掉落概率 +10% + diamondProbabilityBonus: 0.2 // 钻石掉落概率 +20% + }, + [QualitySet.PURPLE]: { + // 紫色品质:基础值 + 加成 + expBonus: 100, // 经验值 +100 + goldBonus: 50, // 金币 +50 + diamondBonus: 1, // 钻石 +1 + expProbabilityBonus: 0, // 经验掉落概率加成 + goldProbabilityBonus: 0.2, // 金币掉落概率 +20% + diamondProbabilityBonus: 0.1 // 钻石掉落概率 +10%(精英10%) + }, + [QualitySet.ORANGE]: { + // 橙色品质:基础值 + 加成 + expBonus: 200, // 经验值 +200 + goldBonus: 100, // 金币 +100 + diamondBonus: 3, // 钻石 +3 + expProbabilityBonus: 0, // 经验掉落概率加成 + goldProbabilityBonus: 0.3, // 金币掉落概率 +30% + diamondProbabilityBonus: 1.0 // 钻石掉落概率 +100%(BOSS必掉) + } +}; + +// 关卡和buff加成配置表 - 使用加法权重 +export const StageBuffBonusConfig = { + // 关卡加成配置 + stage: { + expBonusPerStage: 5, // 每关经验值加成 + goldBonusPerStage: 2, // 每关金币加成 + diamondBonusPerStage: 0.1, // 每关钻石加成 + expProbabilityBonusPerStage: 0, // 每关经验掉落概率加成 + goldProbabilityBonusPerStage: 0, // 每关金币掉落概率加成 + diamondProbabilityBonusPerStage: 0 // 每关钻石掉落概率加成 + }, + // buff数量加成配置 + buff: { + expBonusPerBuff: 10, // 每个buff经验值加成 + goldBonusPerBuff: 5, // 每个buff金币加成 + diamondBonusPerBuff: 0.5, // 每个buff钻石加成 + expProbabilityBonusPerBuff: 0, // 每个buff经验掉落概率加成 + goldProbabilityBonusPerBuff: 0.01, // 每个buff金币掉落概率加成 + diamondProbabilityBonusPerBuff: 0.005 // 每个buff钻石掉落概率加成 + } +}; + // 怪物掉落管理器 export class MonsterDropManager { @@ -213,5 +300,68 @@ export class MonsterDropManager { return result; } + + /** + * 计算怪物基础资源掉落(经验、金币、钻石) + * @param monsterQuality 怪物品质 + * @param stageNumber 关卡数 + * @param buffCount buff数量 + * @returns 基础资源掉落结果 + */ + static calculateBaseResourceDrops(monsterQuality: QualitySet, stageNumber: number, buffCount: number = 0): {exp: number, gold?: number, diamond?: number} { + const result: {exp: number, gold?: number, diamond?: number} = {exp: 0}; + + // 获取品质加成 + const qualityBonus = QualityBonusConfig[monsterQuality]; + + // 计算经验值(必出) + const expConfig = BaseResourceDropConfig.exp; + const expValue = (expConfig.baseValue + + qualityBonus.expBonus + + StageBuffBonusConfig.stage.expBonusPerStage * stageNumber + + StageBuffBonusConfig.buff.expBonusPerBuff * buffCount) * + Math.pow(expConfig.stageMultiplier, stageNumber - 1); + + // 添加随机范围 + const expRandomFactor = 1 + (Math.random() - 0.5) * 2 * expConfig.randomRange; + result.exp = Math.floor(expValue * expRandomFactor); + + // 金币与钻石独立判定,可同时掉落: + // 使用加法权重系统:基础值 + 品质加成 + 关卡加成 + buff加成 + 关卡增长 + + // 金币判定 + const goldProbability = BaseResourceDropConfig.gold.baseProbability + + qualityBonus.goldProbabilityBonus + + StageBuffBonusConfig.stage.goldProbabilityBonusPerStage * stageNumber + + StageBuffBonusConfig.buff.goldProbabilityBonusPerBuff * buffCount; + if (Math.random() < goldProbability) { + const goldConfig = BaseResourceDropConfig.gold; + const goldValue = (goldConfig.baseValue + + qualityBonus.goldBonus + + StageBuffBonusConfig.stage.goldBonusPerStage * stageNumber + + StageBuffBonusConfig.buff.goldBonusPerBuff * buffCount) * + Math.pow(goldConfig.stageMultiplier, stageNumber - 1); + const goldRandomFactor = 1 + (Math.random() - 0.5) * 2 * goldConfig.randomRange; + result.gold = Math.floor(goldValue * goldRandomFactor); + } + + // 钻石判定 + const diamondProbability = BaseResourceDropConfig.diamond.baseProbability + + qualityBonus.diamondProbabilityBonus + + StageBuffBonusConfig.stage.diamondProbabilityBonusPerStage * stageNumber + + StageBuffBonusConfig.buff.diamondProbabilityBonusPerBuff * buffCount; + if (Math.random() < diamondProbability) { + const diamondConfig = BaseResourceDropConfig.diamond; + const diamondValue = (diamondConfig.baseValue + + qualityBonus.diamondBonus + + StageBuffBonusConfig.stage.diamondBonusPerStage * stageNumber + + StageBuffBonusConfig.buff.diamondBonusPerBuff * buffCount) * + Math.pow(diamondConfig.stageMultiplier, stageNumber - 1); + const diamondRandomFactor = 1 + (Math.random() - 0.5) * 2 * diamondConfig.randomRange; + result.diamond = Math.floor(diamondValue * diamondRandomFactor); + } + + return result; + } } diff --git a/assets/script/game/hero/HeroViewComp.ts b/assets/script/game/hero/HeroViewComp.ts index e91ff5dc..aeca6c3b 100644 --- a/assets/script/game/hero/HeroViewComp.ts +++ b/assets/script/game/hero/HeroViewComp.ts @@ -14,6 +14,7 @@ import { FightSet, getExpDrops, getStoneDrops, TooltipTypes } from "../common/co import { RandomManager } from "db://oops-framework/core/common/random/RandomManager"; import { EnhancementType } from "../common/config/LevelUp"; import { MonsterDropManager } from "../common/config/Items"; +import { HeroInfo } from "../common/config/heroSet"; const { ccclass, property } = _decorator; @@ -255,10 +256,7 @@ export class HeroViewComp extends CCComp { this.is_count_dead=true if(this.fac==FacSet.MON){ this.scheduleOnce(()=>{ - let drop_item=this.do_drop() - if(drop_item.length>0){ - oops.message.dispatchEvent(GameEvent.MonDead,{mon_uuid:this.hero_uuid,drops:drop_item}) - } + this.do_drop() },0.1) } if(this.fac==FacSet.HERO){ @@ -276,8 +274,24 @@ export class HeroViewComp extends CCComp { } do_drop(){ let drop_item=MonsterDropManager.calculateMonsterDrops(this.hero_uuid,smc.data.mission,1) - console.log("[HeroViewComp]:do_drop",this.hero_uuid,drop_item) - return drop_item + let {exp,gold,diamond}=MonsterDropManager.calculateBaseResourceDrops(HeroInfo[this.hero_uuid].quality,smc.data.mission,this.BUFFS.length) + oops.message.dispatchEvent(GameEvent.MonDead,{mon_uuid:this.hero_uuid,drops:drop_item,game_data:{exp:exp, gold:gold, diamond:diamond}}) + if(drop_item.length>0){ + for(let i=0;i0){ + smc.addExp(exp) + } + if(gold>0){ + smc.addGold(gold) + } + if(diamond>0){ + smc.addDiamond(diamond) + } + console.log("[HeroViewComp]:do_drop",this.hero_uuid,drop_item,exp,gold,diamond) } add_debuff(type:number,deV:number,deC:number,deR:number){ let n_deR=deR-this.Attrs[BuffAttr.DEBUFF_DOWN] diff --git a/assets/script/game/map/HInfoComp.ts b/assets/script/game/map/HInfoComp.ts index e7fdca88..2a288a3d 100644 --- a/assets/script/game/map/HInfoComp.ts +++ b/assets/script/game/map/HInfoComp.ts @@ -65,8 +65,8 @@ export class HInfoComp extends Component { smc.spendGameProperty({exp:experience,gold:gold},false) let result=smc.levelUpHero(this.h_uuid,experience,gold) if(!result){ - smc.addGameProperty("exp",experience,false) - smc.addGameProperty("gold",gold,false) + smc.addExp(experience,false) + smc.addGold(gold,false) oops.gui.toast("网络出错了,升级失败,请重试") return } diff --git a/assets/script/game/map/MissionComp.ts b/assets/script/game/map/MissionComp.ts index 3bb437f8..26da6cfe 100644 --- a/assets/script/game/map/MissionComp.ts +++ b/assets/script/game/map/MissionComp.ts @@ -71,7 +71,6 @@ export class MissionComp extends CCComp { if(d_item.item_uuid==hitem.item_uuid){ hitem.addItemCount(d_item.count) drop_item.splice(j,1) - smc.addItem(d_item.item_uuid,d_item.count) break } } @@ -89,7 +88,6 @@ export class MissionComp extends CCComp { const node = instantiate(prefab) as unknown as Node; node.parent=parent node.getComponent(ItemComp)!.update_data(d_item.item_uuid,d_item.count) - smc.addItem(d_item.item_uuid,d_item.count) } } } @@ -107,7 +105,7 @@ export class MissionComp extends CCComp { oops.message.dispatchEvent(GameEvent.NewWave) return } - smc.addGameProperty("mission",1) + smc.addMission(1) oops.message.dispatchEvent(GameEvent.FightEnd,{victory:true}) oops.gui.open(UIID.Victory,{victory:true,rewards:this.rewards}) } diff --git a/assets/script/game/wx_clound_client_api/WxCloudApi.ts b/assets/script/game/wx_clound_client_api/WxCloudApi.ts index 83c3000f..2c492846 100644 --- a/assets/script/game/wx_clound_client_api/WxCloudApi.ts +++ b/assets/script/game/wx_clound_client_api/WxCloudApi.ts @@ -36,14 +36,6 @@ export type GameData = { diamond: number, meat: number, exp: number, - ghstone: number, // 绿色英雄石 - bhstone: number, // 蓝色英雄石 - phlestone: number, // 紫色英雄石 - rhstone: number, // 红色英雄石 - herocard: number, // 英雄卡 - ckey: number, // 铜钥匙 - skey: number, // 银钥匙 - gkey: number // 金钥匙 } // 出战英雄类型 @@ -209,7 +201,7 @@ export class WxCloudApi{ * @param amount 增加的数量 * @return Promise>> */ - public static async addGameDataField(field: keyof GameData, amount: number): Promise>> */ - public static async spendGameDataField(field: keyof GameData, amount: number): Promise { if (spendValidation) return spendValidation; result = await gameDataModule.spendDataField(db, wxContext.OPENID, params.field, params.amount); break; - - case 'data_set': - const setValidation = responseModule.validateRequiredParams(params, ['field', 'value']); - if (setValidation) return setValidation; - result = await gameDataModule.setDataField(db, wxContext.OPENID, params.field, params.value); - break; - + case 'data_reset': result = await gameDataModule.resetData(db, wxContext.OPENID); break; @@ -159,7 +156,7 @@ exports.main = async (event, context) => { result = await herosModule.getOwnedHeroIds(db, wxContext.OPENID); break; - // ==================== 库存管理 (items, tals, equips) ==================== + // ==================== 库存管理 (通用接口) ==================== case 'inventory_get': const invGetValidation = responseModule.validateRequiredParams(params, ['type']); if (invGetValidation) return invGetValidation; @@ -209,40 +206,139 @@ exports.main = async (event, context) => { result = await inventoryModule.getOwnedItems(db, wxContext.OPENID, params.type); break; - // ==================== 兼容旧接口 ==================== - case 'load': - result = await authModule.login(db, wxContext); + // ==================== 物品管理 (items) ==================== + case 'items_get': + result = await itemsModule.getItems(db, wxContext.OPENID); break; - case 'save': - // 兼容旧的保存接口 - if (params.data) { - const tasks = []; - if (params.data.data) tasks.push(gameDataModule.updateData(db, wxContext.OPENID, params.data.data)); - if (params.data.fight_heros) tasks.push(fightHerosModule.updateFightHeros(db, wxContext.OPENID, params.data.fight_heros)); - if (params.data.heros) { - // 批量更新英雄 - for (const heroId in params.data.heros) { - tasks.push(herosModule.updateHero(db, wxContext.OPENID, parseInt(heroId), params.data.heros[heroId])); - } - } - if (params.data.items) tasks.push(inventoryModule.updateInventory(db, wxContext.OPENID, 'items', params.data.items)); - if (params.data.tals) tasks.push(inventoryModule.updateInventory(db, wxContext.OPENID, 'tals', params.data.tals)); - if (params.data.equips) tasks.push(inventoryModule.updateInventory(db, wxContext.OPENID, 'equips', params.data.equips)); - - const results = await Promise.all(tasks); - const hasError = results.some(r => r.code !== 200); - - if (hasError) { - result = responseModule.error(-1, "Partial save failed", { results }); - } else { - result = responseModule.success({ results }, "All data saved successfully"); - } - } else { - result = responseModule.badRequest("No data to save"); - } + 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', @@ -250,6 +346,9 @@ exports.main = async (event, context) => { '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); diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/equips.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/equips.js new file mode 100644 index 00000000..fb3b33af --- /dev/null +++ b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/equips.js @@ -0,0 +1,421 @@ +// 装备库存操作模块 (equips) +const { getOrCreaterUser } = require('./auth'); + +const user_db_name = "cocos_users"; +const DATA_TYPE = 'equips'; + +/** + * 获取装备库存数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function getEquips(db, openid) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + return { + code: 200, + data: user[DATA_TYPE], + msg: `${DATA_TYPE}获取成功` + }; + } catch (error) { + console.error(`获取${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `获取${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 获取单个装备数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} equipId 装备ID + * @returns {Object} 操作结果 + */ +async function getEquip(db, openid, equipId) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + const equipCount = user[DATA_TYPE][equipId]; + if (equipCount === undefined) { + return { + code: -6, + msg: `${DATA_TYPE.slice(0, -1)} ${equipId} 未找到` + }; + } + + return { + code: 200, + data: { + item_id: equipId, + count: equipCount + }, + msg: `${DATA_TYPE.slice(0, -1)} ${equipId} 获取成功` + }; + } catch (error) { + console.error(`获取${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `获取${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 添加装备 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} equipId 装备ID + * @param {number} count 添加数量 + * @returns {Object} 操作结果 + */ +async function addEquip(db, openid, equipId, count) { + try { + 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[DATA_TYPE][equipId] || 0; + const newCount = currentCount + count; + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [`${DATA_TYPE}.${equipId}`]: _.set(newCount), + last_save_time: _.set(Date.now()) + } + }); + + if (updateRes?.stats?.updated >= 1) { + return { + code: 200, + data: { + item_id: equipId, + old_count: currentCount, + new_count: newCount, + added: count + }, + msg: `${DATA_TYPE.slice(0, -1)} ${equipId} 添加成功` + }; + } else { + return { + code: -1, + msg: `添加 ${DATA_TYPE.slice(0, -1)} 失败` + }; + } + } catch (error) { + console.error(`添加${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `添加${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 消耗装备 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} equipId 装备ID + * @param {number} count 消耗数量 + * @returns {Object} 操作结果 + */ +async function consumeEquip(db, openid, equipId, count) { + try { + 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[DATA_TYPE][equipId] || 0; + if (currentCount < count) { + return { + code: -6, + msg: `${DATA_TYPE.slice(0, -1)} ${equipId}不足, 当前: ${currentCount}, 需要: ${count}` + }; + } + + return await addEquip(db, openid, equipId, -count); + } catch (error) { + console.error(`消耗${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `消耗${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 设置装备数量 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} equipId 装备ID + * @param {number} count 新的数量 + * @returns {Object} 操作结果 + */ +async function setEquip(db, openid, equipId, count) { + try { + 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[DATA_TYPE][equipId] || 0; + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [`${DATA_TYPE}.${equipId}`]: _.set(count), + last_save_time: _.set(Date.now()) + } + }); + + if (updateRes?.stats?.updated >= 1) { + return { + code: 200, + data: { + item_id: equipId, + old_count: oldCount, + new_count: count + }, + msg: `${DATA_TYPE.slice(0, -1)} ${equipId} 设置成功` + }; + } else { + return { + code: -1, + msg: `设置 ${DATA_TYPE.slice(0, -1)} 失败` + }; + } + } catch (error) { + console.error(`设置${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `设置${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 批量更新装备库存 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {Object} updateData 更新数据对象 + * @param {boolean} merge 是否合并更新(默认true) + * @returns {Object} 操作结果 + */ +async function updateEquips(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: "无效的更新数据格式" + }; + } + + // 验证所有值都是非负数 + for (const equipId in updateData) { + const count = updateData[equipId]; + if (typeof count !== 'number' || count < 0) { + return { + code: -3, + msg: `装备 ${equipId} 的数量无效: ${count}` + }; + } + } + + let newData; + if (merge) { + // 合并更新 + newData = { ...user[DATA_TYPE], ...updateData }; + } else { + // 完全替换 + newData = updateData; + } + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [DATA_TYPE]: _.set(newData), + last_save_time: _.set(Date.now()) + } + }); + + if (updateRes?.stats?.updated >= 1) { + return { + code: 200, + data: newData, + msg: `${DATA_TYPE} 更新成功` + }; + } else { + return { + code: -1, + msg: `更新 ${DATA_TYPE} 失败` + }; + } + } catch (error) { + console.error(`更新${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `更新${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 重置装备库存数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function resetEquips(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_TYPE]: _.set(defaultData[DATA_TYPE]), + last_save_time: _.set(Date.now()), + reset_time: _.set(Date.now()) + } + }); + + if (resetRes?.stats?.updated >= 1) { + return { + code: 200, + data: defaultData[DATA_TYPE], + msg: `${DATA_TYPE} 重置成功` + }; + } else { + return { + code: -1, + msg: `重置 ${DATA_TYPE} 失败` + }; + } + } catch (error) { + console.error(`重置${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `重置${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 获取拥有的装备列表(数量大于0的) + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function getOwnedEquips(db, openid) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + const ownedEquips = []; + for (const equipId in user[DATA_TYPE]) { + const count = user[DATA_TYPE][equipId]; + if (count > 0) { + ownedEquips.push({ + item_id: parseInt(equipId), + count: count + }); + } + } + + return { + code: 200, + data: { + owned_items: ownedEquips, + total_types: ownedEquips.length + }, + msg: `拥有的${DATA_TYPE}获取成功` + }; + } catch (error) { + console.error(`获取拥有的${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `获取拥有的${DATA_TYPE}错误: ${error.message}` + }; + } +} + +module.exports = { + getEquips, + getEquip, + addEquip, + consumeEquip, + setEquip, + updateEquips, + resetEquips, + getOwnedEquips +}; \ No newline at end of file diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/inventory.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/inventory.js index 96d4a3fa..f9abe694 100644 --- a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/inventory.js +++ b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/inventory.js @@ -1,7 +1,8 @@ // 通用库存操作模块 (items, tals, equips) -const { getOrCreaterUser } = require('./auth'); - -const user_db_name = "cocos_users"; +// 现在作为统一接口,调用各个独立模块 +const itemsModule = require('./items'); +const talsModule = require('./tals'); +const equipsModule = require('./equips'); // 支持的数据类型 const SUPPORTED_TYPES = ['items', 'tals', 'equips']; @@ -15,6 +16,24 @@ function validateDataType(dataType) { return SUPPORTED_TYPES.includes(dataType); } +/** + * 根据数据类型获取对应的模块 + * @param {string} dataType 数据类型 + * @returns {Object} 对应的模块 + */ +function getModuleByType(dataType) { + switch(dataType) { + case 'items': + return itemsModule; + case 'tals': + return talsModule; + case 'equips': + return equipsModule; + default: + return null; + } +} + /** * 获取库存数据 * @param {Object} db 数据库实例 @@ -23,33 +42,26 @@ function validateDataType(dataType) { * @returns {Object} 操作结果 */ async function getInventory(db, openid, dataType) { - try { - if (!validateDataType(dataType)) { + if (!validateDataType(dataType)) { + return { + code: -3, + msg: `无效的数据类型: ${dataType}` + }; + } + + const module = getModuleByType(dataType); + switch(dataType) { + case 'items': + return await module.getItems(db, openid); + case 'tals': + return await module.getTals(db, openid); + case 'equips': + return await module.getEquips(db, openid); + default: 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}` - }; } } @@ -62,44 +74,26 @@ async function getInventory(db, openid, dataType) { * @returns {Object} 操作结果 */ async function getInventoryItem(db, openid, dataType, itemId) { - try { - if (!validateDataType(dataType)) { + if (!validateDataType(dataType)) { + return { + code: -3, + msg: `无效的数据类型: ${dataType}` + }; + } + + const module = getModuleByType(dataType); + switch(dataType) { + case 'items': + return await module.getItem(db, openid, itemId); + case 'tals': + return await module.getTal(db, openid, itemId); + case 'equips': + return await module.getEquip(db, openid, itemId); + default: 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}` - }; } } @@ -113,63 +107,26 @@ async function getInventoryItem(db, openid, dataType, itemId) { * @returns {Object} 操作结果 */ async function addInventoryItem(db, openid, dataType, itemId, count) { - try { - if (!validateDataType(dataType)) { + if (!validateDataType(dataType)) { + return { + code: -3, + msg: `无效的数据类型: ${dataType}` + }; + } + + const module = getModuleByType(dataType); + switch(dataType) { + case 'items': + return await module.addItem(db, openid, itemId, count); + case 'tals': + return await module.addTal(db, openid, itemId, count); + case 'equips': + return await module.addEquip(db, openid, itemId, count); + default: 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}` - }; } } @@ -183,44 +140,26 @@ async function addInventoryItem(db, openid, dataType, itemId, count) { * @returns {Object} 操作结果 */ async function consumeInventoryItem(db, openid, dataType, itemId, count) { - try { - if (!validateDataType(dataType)) { + if (!validateDataType(dataType)) { + return { + code: -3, + msg: `无效的数据类型: ${dataType}` + }; + } + + const module = getModuleByType(dataType); + switch(dataType) { + case 'items': + return await module.consumeItem(db, openid, itemId, count); + case 'tals': + return await module.consumeTal(db, openid, itemId, count); + case 'equips': + return await module.consumeEquip(db, openid, itemId, count); + default: 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}` - }; } } @@ -234,61 +173,26 @@ async function consumeInventoryItem(db, openid, dataType, itemId, count) { * @returns {Object} 操作结果 */ async function setInventoryItem(db, openid, dataType, itemId, count) { - try { - if (!validateDataType(dataType)) { + if (!validateDataType(dataType)) { + return { + code: -3, + msg: `无效的数据类型: ${dataType}` + }; + } + + const module = getModuleByType(dataType); + switch(dataType) { + case 'items': + return await module.setItem(db, openid, itemId, count); + case 'tals': + return await module.setTal(db, openid, itemId, count); + case 'equips': + return await module.setEquip(db, openid, itemId, count); + default: 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}` - }; } } @@ -302,77 +206,27 @@ async function setInventoryItem(db, openid, dataType, itemId, count) { * @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); + if (!validateDataType(dataType)) { return { - code: -5, - msg: `Update ${dataType} error: ${error.message}` + code: -3, + msg: `无效的数据类型: ${dataType}` }; } + + const module = getModuleByType(dataType); + switch(dataType) { + case 'items': + return await module.updateItems(db, openid, updateData, merge); + case 'tals': + return await module.updateTals(db, openid, updateData, merge); + case 'equips': + return await module.updateEquips(db, openid, updateData, merge); + default: + return { + code: -3, + msg: `无效的数据类型: ${dataType}` + }; + } } /** @@ -383,52 +237,26 @@ async function updateInventory(db, openid, dataType, updateData, merge = true) { * @returns {Object} 操作结果 */ async function resetInventory(db, openid, dataType) { - try { - if (!validateDataType(dataType)) { + if (!validateDataType(dataType)) { + return { + code: -3, + msg: `无效的数据类型: ${dataType}` + }; + } + + const module = getModuleByType(dataType); + switch(dataType) { + case 'items': + return await module.resetItems(db, openid); + case 'tals': + return await module.resetTals(db, openid); + case 'equips': + return await module.resetEquips(db, openid); + default: return { code: -3, - msg: `Invalid data type: ${dataType}` + msg: `无效的数据类型: ${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}` - }; } } @@ -440,47 +268,26 @@ async function resetInventory(db, openid, dataType) { * @returns {Object} 操作结果 */ async function getOwnedItems(db, openid, dataType) { - try { - if (!validateDataType(dataType)) { + if (!validateDataType(dataType)) { + return { + code: -3, + msg: `无效的数据类型: ${dataType}` + }; + } + + const module = getModuleByType(dataType); + switch(dataType) { + case 'items': + return await module.getOwnedItems(db, openid); + case 'tals': + return await module.getOwnedTals(db, openid); + case 'equips': + return await module.getOwnedEquips(db, openid); + default: return { code: -3, - msg: `Invalid data type: ${dataType}` + msg: `无效的数据类型: ${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}` - }; } } diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/items.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/items.js new file mode 100644 index 00000000..dc102f78 --- /dev/null +++ b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/items.js @@ -0,0 +1,421 @@ +// 物品库存操作模块 (items) +const { getOrCreaterUser } = require('./auth'); + +const user_db_name = "cocos_users"; +const DATA_TYPE = 'items'; + +/** + * 获取物品库存数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function getItems(db, openid) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + return { + code: 200, + data: user[DATA_TYPE], + msg: `${DATA_TYPE}获取成功` + }; + } catch (error) { + console.error(`获取${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `获取${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 获取单个物品数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} itemId 物品ID + * @returns {Object} 操作结果 + */ +async function getItem(db, openid, itemId) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + const itemCount = user[DATA_TYPE][itemId]; + if (itemCount === undefined) { + return { + code: -6, + msg: `${DATA_TYPE.slice(0, -1)} ${itemId} 未找到` + }; + } + + return { + code: 200, + data: { + item_id: itemId, + count: itemCount + }, + msg: `${DATA_TYPE.slice(0, -1)} ${itemId} 获取成功` + }; + } catch (error) { + console.error(`获取${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `获取${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 添加物品 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} itemId 物品ID + * @param {number} count 添加数量 + * @returns {Object} 操作结果 + */ +async function addItem(db, openid, itemId, count) { + try { + 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[DATA_TYPE][itemId] || 0; + const newCount = currentCount + count; + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [`${DATA_TYPE}.${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: `${DATA_TYPE.slice(0, -1)} ${itemId} 添加成功` + }; + } else { + return { + code: -1, + msg: `添加 ${DATA_TYPE.slice(0, -1)} 失败` + }; + } + } catch (error) { + console.error(`添加${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `添加${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 消耗物品 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} itemId 物品ID + * @param {number} count 消耗数量 + * @returns {Object} 操作结果 + */ +async function consumeItem(db, openid, itemId, count) { + try { + 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[DATA_TYPE][itemId] || 0; + if (currentCount < count) { + return { + code: -6, + msg: `${DATA_TYPE.slice(0, -1)} ${itemId}不足, 当前: ${currentCount}, 需要: ${count}` + }; + } + + return await addItem(db, openid, itemId, -count); + } catch (error) { + console.error(`消耗${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `消耗${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 设置物品数量 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} itemId 物品ID + * @param {number} count 新的数量 + * @returns {Object} 操作结果 + */ +async function setItem(db, openid, itemId, count) { + try { + 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[DATA_TYPE][itemId] || 0; + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [`${DATA_TYPE}.${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: `${DATA_TYPE.slice(0, -1)} ${itemId} 设置成功` + }; + } else { + return { + code: -1, + msg: `设置 ${DATA_TYPE.slice(0, -1)} 失败` + }; + } + } catch (error) { + console.error(`设置${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `设置${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 批量更新物品库存 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {Object} updateData 更新数据对象 + * @param {boolean} merge 是否合并更新(默认true) + * @returns {Object} 操作结果 + */ +async function updateItems(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: "无效的更新数据格式" + }; + } + + // 验证所有值都是非负数 + for (const itemId in updateData) { + const count = updateData[itemId]; + if (typeof count !== 'number' || count < 0) { + return { + code: -3, + msg: `物品 ${itemId} 的数量无效: ${count}` + }; + } + } + + let newData; + if (merge) { + // 合并更新 + newData = { ...user[DATA_TYPE], ...updateData }; + } else { + // 完全替换 + newData = updateData; + } + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [DATA_TYPE]: _.set(newData), + last_save_time: _.set(Date.now()) + } + }); + + if (updateRes?.stats?.updated >= 1) { + return { + code: 200, + data: newData, + msg: `${DATA_TYPE} 更新成功` + }; + } else { + return { + code: -1, + msg: `更新 ${DATA_TYPE} 失败` + }; + } + } catch (error) { + console.error(`更新${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `更新${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 重置物品库存数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function resetItems(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_TYPE]: _.set(defaultData[DATA_TYPE]), + last_save_time: _.set(Date.now()), + reset_time: _.set(Date.now()) + } + }); + + if (resetRes?.stats?.updated >= 1) { + return { + code: 200, + data: defaultData[DATA_TYPE], + msg: `${DATA_TYPE} 重置成功` + }; + } else { + return { + code: -1, + msg: `重置 ${DATA_TYPE} 失败` + }; + } + } catch (error) { + console.error(`重置${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `重置${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 获取拥有的物品列表(数量大于0的) + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function getOwnedItems(db, openid) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + const ownedItems = []; + for (const itemId in user[DATA_TYPE]) { + const count = user[DATA_TYPE][itemId]; + if (count > 0) { + ownedItems.push({ + item_id: parseInt(itemId), + count: count + }); + } + } + + return { + code: 200, + data: { + owned_items: ownedItems, + total_types: ownedItems.length + }, + msg: `拥有的${DATA_TYPE}获取成功` + }; + } catch (error) { + console.error(`获取拥有的${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `获取拥有的${DATA_TYPE}错误: ${error.message}` + }; + } +} + +module.exports = { + getItems, + getItem, + addItem, + consumeItem, + setItem, + updateItems, + resetItems, + getOwnedItems +}; \ No newline at end of file diff --git a/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/tals.js b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/tals.js new file mode 100644 index 00000000..925eb66b --- /dev/null +++ b/build-templates/wechatgame/cloud_functions/cocos_cloud/modules/tals.js @@ -0,0 +1,421 @@ +// 天赋库存操作模块 (tals) +const { getOrCreaterUser } = require('./auth'); + +const user_db_name = "cocos_users"; +const DATA_TYPE = 'tals'; + +/** + * 获取天赋库存数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function getTals(db, openid) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + return { + code: 200, + data: user[DATA_TYPE], + msg: `${DATA_TYPE}获取成功` + }; + } catch (error) { + console.error(`获取${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `获取${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 获取单个天赋数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} talId 天赋ID + * @returns {Object} 操作结果 + */ +async function getTal(db, openid, talId) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + const talCount = user[DATA_TYPE][talId]; + if (talCount === undefined) { + return { + code: -6, + msg: `${DATA_TYPE.slice(0, -1)} ${talId} 未找到` + }; + } + + return { + code: 200, + data: { + item_id: talId, + count: talCount + }, + msg: `${DATA_TYPE.slice(0, -1)} ${talId} 获取成功` + }; + } catch (error) { + console.error(`获取${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `获取${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 添加天赋 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} talId 天赋ID + * @param {number} count 添加数量 + * @returns {Object} 操作结果 + */ +async function addTal(db, openid, talId, count) { + try { + 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[DATA_TYPE][talId] || 0; + const newCount = currentCount + count; + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [`${DATA_TYPE}.${talId}`]: _.set(newCount), + last_save_time: _.set(Date.now()) + } + }); + + if (updateRes?.stats?.updated >= 1) { + return { + code: 200, + data: { + item_id: talId, + old_count: currentCount, + new_count: newCount, + added: count + }, + msg: `${DATA_TYPE.slice(0, -1)} ${talId} 添加成功` + }; + } else { + return { + code: -1, + msg: `添加 ${DATA_TYPE.slice(0, -1)} 失败` + }; + } + } catch (error) { + console.error(`添加${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `添加${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 消耗天赋 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} talId 天赋ID + * @param {number} count 消耗数量 + * @returns {Object} 操作结果 + */ +async function consumeTal(db, openid, talId, count) { + try { + 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[DATA_TYPE][talId] || 0; + if (currentCount < count) { + return { + code: -6, + msg: `${DATA_TYPE.slice(0, -1)} ${talId}不足, 当前: ${currentCount}, 需要: ${count}` + }; + } + + return await addTal(db, openid, talId, -count); + } catch (error) { + console.error(`消耗${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `消耗${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 设置天赋数量 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {number} talId 天赋ID + * @param {number} count 新的数量 + * @returns {Object} 操作结果 + */ +async function setTal(db, openid, talId, count) { + try { + 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[DATA_TYPE][talId] || 0; + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [`${DATA_TYPE}.${talId}`]: _.set(count), + last_save_time: _.set(Date.now()) + } + }); + + if (updateRes?.stats?.updated >= 1) { + return { + code: 200, + data: { + item_id: talId, + old_count: oldCount, + new_count: count + }, + msg: `${DATA_TYPE.slice(0, -1)} ${talId} 设置成功` + }; + } else { + return { + code: -1, + msg: `设置 ${DATA_TYPE.slice(0, -1)} 失败` + }; + } + } catch (error) { + console.error(`设置${DATA_TYPE}物品错误:`, error); + return { + code: -5, + msg: `设置${DATA_TYPE}物品错误: ${error.message}` + }; + } +} + +/** + * 批量更新天赋库存 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @param {Object} updateData 更新数据对象 + * @param {boolean} merge 是否合并更新(默认true) + * @returns {Object} 操作结果 + */ +async function updateTals(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: "无效的更新数据格式" + }; + } + + // 验证所有值都是非负数 + for (const talId in updateData) { + const count = updateData[talId]; + if (typeof count !== 'number' || count < 0) { + return { + code: -3, + msg: `天赋 ${talId} 的数量无效: ${count}` + }; + } + } + + let newData; + if (merge) { + // 合并更新 + newData = { ...user[DATA_TYPE], ...updateData }; + } else { + // 完全替换 + newData = updateData; + } + + let updateRes = await db.collection(user_db_name).doc(user._id).update({ + data: { + [DATA_TYPE]: _.set(newData), + last_save_time: _.set(Date.now()) + } + }); + + if (updateRes?.stats?.updated >= 1) { + return { + code: 200, + data: newData, + msg: `${DATA_TYPE} 更新成功` + }; + } else { + return { + code: -1, + msg: `更新 ${DATA_TYPE} 失败` + }; + } + } catch (error) { + console.error(`更新${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `更新${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 重置天赋库存数据 + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function resetTals(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_TYPE]: _.set(defaultData[DATA_TYPE]), + last_save_time: _.set(Date.now()), + reset_time: _.set(Date.now()) + } + }); + + if (resetRes?.stats?.updated >= 1) { + return { + code: 200, + data: defaultData[DATA_TYPE], + msg: `${DATA_TYPE} 重置成功` + }; + } else { + return { + code: -1, + msg: `重置 ${DATA_TYPE} 失败` + }; + } + } catch (error) { + console.error(`重置${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `重置${DATA_TYPE}错误: ${error.message}` + }; + } +} + +/** + * 获取拥有的天赋列表(数量大于0的) + * @param {Object} db 数据库实例 + * @param {string} openid 用户openid + * @returns {Object} 操作结果 + */ +async function getOwnedTals(db, openid) { + try { + let user = await getOrCreaterUser(db, openid); + if (!user) { + return { + code: -4, + msg: "未找到用户" + }; + } + + const ownedTals = []; + for (const talId in user[DATA_TYPE]) { + const count = user[DATA_TYPE][talId]; + if (count > 0) { + ownedTals.push({ + item_id: parseInt(talId), + count: count + }); + } + } + + return { + code: 200, + data: { + owned_items: ownedTals, + total_types: ownedTals.length + }, + msg: `拥有的${DATA_TYPE}获取成功` + }; + } catch (error) { + console.error(`获取拥有的${DATA_TYPE}错误:`, error); + return { + code: -5, + msg: `获取拥有的${DATA_TYPE}错误: ${error.message}` + }; + } +} + +module.exports = { + getTals, + getTal, + addTal, + consumeTal, + setTal, + updateTals, + resetTals, + getOwnedTals +}; \ No newline at end of file