代码测试 2026年7月30日 减少bug 处理

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