diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/ceshi/service/CookingService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/ceshi/service/CookingService.py index fadc933..815fa78 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/ceshi/service/CookingService.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/ceshi/service/CookingService.py @@ -41,14 +41,9 @@ from ...BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxServerSystem from ...BlueFoxTools.ToolsConfig import LevelId # ---- 方块实体数据组件 ---- -# 根据网易文档: -# GetBlockEntityData 在 blockEntityExDataCompServer 组件上(CreateBlockEntityData) -# SetBlockEntityData 在 blockInfoCompServer 组件上(CreateBlockInfo) -# 两个 API 在不同组件上,所以要创建两个组件: -# blockEntityDataComp → 读数据(GetBlockEntityData) -# blockInfoComp → 写数据(SetBlockEntityData) +# GetBlockEntityData 返回的 BlockEntityData 对象支持 [] 操作,直接赋值即可持久化。 +# 参考官方文档:方块实体数据组件只有 GetBlockEntityData,没有 SetBlockEntityData。 blockEntityDataComp = comp.CreateBlockEntityData(LevelId) -blockInfoComp = comp.CreateBlockInfo(LevelId) # ---- 导入所有配方 ---- # RECIPES 是一个列表,每条配方是一个 dict,格式见 RecipeData.py 顶部注释 @@ -135,6 +130,7 @@ class CookingService(BlueFoxServerSystem): self.stirData = {} # 内存中的翻炒数据字典 self.switchRecord = {} # 工具方块的记录数据(箭桶数量、药水架顺序等) self.switchCooldown = {} # 工具方块切换冷却时间(防止连点) + self._cancelItemUse = {} # 将要取消下一次物品使用的玩家ID集合(防止喝药水等) self.ListenEvent() # 注册游戏事件监听 # ---- 构建统一配方字典(O(1) 查找) ---- @@ -162,9 +158,10 @@ class CookingService(BlueFoxServerSystem): def ListenEvent(self): """ - 注册两个游戏事件: + 注册三个游戏事件: 1. ServerBlockUseEvent —— 玩家右键方块(做菜、翻炒、加油等) - 2. ServerPlayerTryDestroyBlockEvent —— 玩家拆方块(拆锅时掉落食材) + 2. ServerPlayerTryDestroyBlockEvent —— 玩家拆方块(掉落食材) + 3. ServerItemTryUseEvent —— 玩家尝试使用物品(拦截喝药水等默认行为) """ # 事件1:玩家右键方块 self.ListenForEvent(serverApi.GetEngineNamespace(), @@ -174,6 +171,10 @@ class CookingService(BlueFoxServerSystem): self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerPlayerTryDestroyBlockEvent", self, self.OnDestroy) + # 事件3:玩家尝试使用物品(拦截喝药水) + self.ListenForEvent(serverApi.GetEngineNamespace(), + serverApi.GetEngineSystemName(), + "ServerItemTryUseEvent", self, self.OnItemTryUse) def UnListenEvent(self): """ @@ -185,6 +186,9 @@ class CookingService(BlueFoxServerSystem): self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerPlayerTryDestroyBlockEvent", self, self.OnDestroy) + self.UnListenForEvent(serverApi.GetEngineNamespace(), + serverApi.GetEngineSystemName(), + "ServerItemTryUseEvent", self, self.OnItemTryUse) # ============================================================================ # 主入口:玩家右键方块 @@ -227,6 +231,8 @@ class CookingService(BlueFoxServerSystem): # 找到配方后,取消默认行为(如喝药水、吃食物等),由本 Mod 全权接管 args['cancel'] = True + # 同时标记该玩家下一次物品使用事件也要取消,防止喝药水等默认行为 + self._cancelItemUse[playerId] = True # ---- 第四步:判断是不是工具切换类型 ---- recipeType = recipe.get("type", "cook") @@ -265,6 +271,15 @@ class CookingService(BlueFoxServerSystem): # 没有 stirCount → 普通替换流程(比如加油、加水、盖盖) self.executeRecipe(recipe, playerId, pos, dim, itemDict, key) + # ============================================================================ + # 拦截物品使用事件(防止喝药水等默认行为) + # ============================================================================ + + def OnItemTryUse(self, args): + playerId = args.get("playerId") + if self._cancelItemUse.pop(playerId, False): + args['cancel'] = True + # ============================================================================ # 配方匹配(O(1) 字典查找) # ============================================================================ @@ -354,19 +369,6 @@ class CookingService(BlueFoxServerSystem): # 检查是否满了 maxCount = recipe.get("maxCount", 999) if record["count"] >= maxCount: - # 满了,自动转向取回操作 - takeRecipe = self.allRecipes.get((blockName, None)) - if takeRecipe and record["count"] > 0: - self.giveItem(playerId, record["itemName"]) - record["count"] -= 1 - if takeRecipe.get("giveItem"): - self.giveItem(playerId, takeRecipe["giveItem"]) - if takeRecipe.get("target"): - self.replaceBlock(pos, dim, takeRecipe["target"], playerId) - if record["count"] <= 0: - self.clearSwitchRecord(key, playerId, pos, dim) - else: - self._saveRecord(key, playerId, pos, dim, record) return # 记录物品+1 record["count"] += 1 @@ -378,31 +380,6 @@ class CookingService(BlueFoxServerSystem): record = {"stack": []} maxCount = recipe.get("maxCount", 999) if len(record["stack"]) >= maxCount: - # 满了,自动转向取回操作 - takeRecipe = self.allRecipes.get((blockName, None)) - if takeRecipe: - needSave = False - needClear = False - if record["stack"]: - topItem = record["stack"].pop() - comp.CreateItem(playerId).SpawnItemToPlayerInv( - {"itemName": topItem["itemName"], - "count": topItem["count"], - "auxValue": topItem["auxValue"], - "userData": topItem.get("userData", {})}, - playerId) - if not record["stack"]: - needClear = True - else: - needSave = True - if takeRecipe.get("giveItem"): - self.giveItem(playerId, takeRecipe["giveItem"]) - if takeRecipe.get("target"): - self.replaceBlock(pos, dim, takeRecipe["target"], playerId) - if needClear: - self.clearSwitchRecord(key, playerId, pos, dim) - elif needSave: - self._saveRecord(key, playerId, pos, dim, record) return # 把物品信息压入堆栈 record["stack"].append({ @@ -664,26 +641,26 @@ class CookingService(BlueFoxServerSystem): def consumeItem(self, playerId, itemDict, amount=1): """ - 消耗玩家手里物品的指定数量。 + 消耗玩家主手物品的指定数量。 - 如果数量不够 → 直接清空这个格子 + 如果数量不够 → 清空主手(SetEntityItem 传 None) 如果数量够 → 减少对应数量 - 重要:网易API里 GetPlayerItem 返回的 key 是 newItemName/newAuxValue, - 但 SetEntityItem 接收的 key 是 itemName/auxValue, - 所以这里需要做字段名转换。 + 重要:SetInvItemNum 的参数是背包槽位索引(int),不是 ItemPosType 枚举。 + 清空主手必须用 SetEntityItem(CARRIED, None),不能用 SetInvItemNum。 """ count = itemDict.get("count", 0) if count <= amount: - # 数量不够或刚好用完 → 清空这个格子 - comp.CreateItem(playerId).SetInvItemNum( - serverApi.GetMinecraftEnum().ItemPosType.CARRIED, 0) + # 数量不够或刚好用完 → 清空主手 + comp.CreateItem(playerId).SetEntityItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, + None) else: # 数量够 → 减少 amount 个 itemDict["count"] = count - amount comp.CreateItem(playerId).SetEntityItem( serverApi.GetMinecraftEnum().ItemPosType.CARRIED, - {"itemName": itemDict["newItemName"], # 注意:这里是 itemName 不是 newItemName + {"itemName": itemDict["newItemName"], "count": itemDict["count"], "auxValue": itemDict.get("newAuxValue", 0)}) @@ -783,14 +760,16 @@ class CookingService(BlueFoxServerSystem): """ 通用方块实体数据写入。 - 读用 blockEntityDataComp(GetBlockEntityData),写用 blockInfoComp(SetBlockEntityData)。 - 两个 API 在不同组件上,所以要分开调用。 + GetBlockEntityData 返回的 BlockEntityData 对象支持 [] 操作, + 直接赋值即可持久化。官方没有 SetBlockEntityData 方法。 """ try: blockData = blockEntityDataComp.GetBlockEntityData(dim, pos) + if blockData is None: + print "[CookingService] _writeBlockData blockData is None: pos=%s dim=%s" % (pos, dim) + return for key, value in kwargs.items(): blockData[key] = value - blockInfoComp.SetBlockEntityData(dim, pos, blockData) except Exception as e: print "[CookingService] _writeBlockData 写入失败: pos=%s dim=%s err=%s" % (pos, dim, str(e))