代码测试 2026年7月30日 减少bug 处理
This commit is contained in:
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
|
||||
|
||||
# ---- 方块实体数据组件 ----
|
||||
# 根据网易文档:
|
||||
# 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))
|
||||
|
||||
|
||||
Reference in new issue
Block a user