ceshi 2 bug处理ok
This commit is contained in:
1 parent
b768ff1555
commit
faa3a22631
8 files changed
+314
-52
No files matched your search
+13
-6
@@ -331,8 +331,8 @@ class FurnitureService(BlueFoxServerSystem):
|
||||
retItemName = record["itemName"]
|
||||
retAux = record.get("aux", 0)
|
||||
|
||||
# 给玩家箭
|
||||
self.giveItem(playerId, retItemName, retCount, retAux)
|
||||
# 掉落物形式返回箭(根因C)
|
||||
self._dropItemDict(dim, pos, {"itemName": retItemName, "count": retCount, "auxValue": retAux})
|
||||
|
||||
# 替换方块
|
||||
if recipe.get("target"):
|
||||
@@ -371,9 +371,10 @@ class FurnitureService(BlueFoxServerSystem):
|
||||
poppedName = stackNames.pop() # 后放先取, 弹最后一件
|
||||
if stack:
|
||||
topItem = stack.pop()
|
||||
self.giveItemObj(playerId, topItem)
|
||||
self._dropItemObj(dim, pos, topItem) # 掉落物返还(根因C)
|
||||
else:
|
||||
self.giveItem(playerId, poppedName)
|
||||
self._dropItemDict(dim, pos,
|
||||
{"itemName": poppedName, "count": 1, "auxValue": 0})
|
||||
# 计算剩余 -> 目标方块, 并保存剩余记录(保证后续取回一致)
|
||||
target = self._rackTarget(stackNames)
|
||||
self.replaceBlock(pos, dim, target, playerId)
|
||||
@@ -477,9 +478,15 @@ class FurnitureService(BlueFoxServerSystem):
|
||||
if recipe.get("dropItem"):
|
||||
self.dropItems(dim, pos, recipe["dropItem"])
|
||||
|
||||
# ---- 给玩家背包物品(水槽取水/取脏盘子/盘子架取回) ----
|
||||
# ---- 掉落物形式(水槽取水/取脏盘子/盘子架取回等) ----
|
||||
# 【根因C】获得物品一律改掉落物形式, 不再直接塞进背包
|
||||
if recipe.get("giveItem"):
|
||||
self.giveItem(playerId, recipe["giveItem"])
|
||||
_gItem = recipe["giveItem"]
|
||||
if isinstance(_gItem, dict):
|
||||
self._dropItemDict(dim, pos, _gItem)
|
||||
else:
|
||||
self._dropItemDict(dim, pos,
|
||||
{"itemName": _gItem, "count": recipe.get("giveCount", 1), "auxValue": 0})
|
||||
|
||||
# ---- 转换成功提示 ----
|
||||
if recipe.get("tip"):
|
||||
|
||||
+17
-17
@@ -348,22 +348,22 @@ ITEM_USE_ON_RULES = [
|
||||
"replace": "rtdd:steamerdumplings_0", "consume": 4,
|
||||
"startTimer": "rtdd:steamerdumplings_0",
|
||||
"needBelow": LIT_STOVE, "belowTip": "§c蒸笼需要放在点燃的炉灶上",
|
||||
"tip": "§a四个生饺子放进蒸笼, 开始蒸制(共60秒); 计时结束变成 熟饺子"},
|
||||
"tip": "§a四个生饺子放进蒸笼, 开始蒸制; 计时结束变成 熟饺子"},
|
||||
{"item": "rtdd:roubaozi_3", "surface": STEAMER,
|
||||
"replace": "rtdd:baozilong_1", "consume": 3,
|
||||
"startTimer": "rtdd:baozilong_1",
|
||||
"needBelow": LIT_STOVE, "belowTip": "§c蒸笼需要放在点燃的炉灶上",
|
||||
"tip": "§a三个生肉包子放进蒸笼, 开始蒸制(共60秒); 计时结束变成 熟包子"},
|
||||
"tip": "§a三个生肉包子放进蒸笼, 开始蒸制; 计时结束变成 熟包子"},
|
||||
{"item": "rtdd:bamboo_4", "surface": STEAMER,
|
||||
"replace": "rtdd:bamboo_6", "consume": 1,
|
||||
"startTimer": "rtdd:bamboo_6",
|
||||
"needBelow": LIT_STOVE, "belowTip": "§c蒸笼需要放在点燃的炉灶上",
|
||||
"tip": "§a竹筒饭放进蒸笼, 开始蒸制(共60秒); 计时结束变成 熟竹筒饭"},
|
||||
"tip": "§a竹筒饭放进蒸笼, 开始蒸制; 计时结束变成 熟竹筒饭"},
|
||||
{"item": "rtdd:plate_34", "surface": STEAMER,
|
||||
"replace": "rtdd:steamermilkandegg", "consume": 1,
|
||||
"startTimer": "rtdd:steamermilkandegg",
|
||||
"needBelow": LIT_STOVE, "belowTip": "§c蒸笼需要放在点燃的炉灶上",
|
||||
"tip": "§a蛋液半成品放进蒸笼, 开始蒸制(共60秒); 计时结束变成 蒸牛奶鸡蛋"},
|
||||
"tip": "§a蛋液半成品放进蒸笼, 开始蒸制; 计时结束变成 蒸牛奶鸡蛋"},
|
||||
]
|
||||
|
||||
# ============================================================================
|
||||
@@ -372,34 +372,34 @@ ITEM_USE_ON_RULES = [
|
||||
# ============================================================================
|
||||
TIMER_RULES = [
|
||||
# 发酵(60秒, autoStart)
|
||||
{"source": "rtdd:rawdough_4", "target": "rtdd:dough_0", "time": 60,
|
||||
{"source": "rtdd:rawdough_4", "target": "rtdd:dough_0", "time": 2,
|
||||
"autoStart": True, "doneTip": "§e面团发酵好了"},
|
||||
{"source": "rtdd:breaddough_1", "target": "rtdd:breaddough_1a", "time": 60,
|
||||
{"source": "rtdd:breaddough_1", "target": "rtdd:breaddough_1a", "time": 2,
|
||||
"autoStart": True, "doneTip": "§e法棍面胚发好了"},
|
||||
# 蒸笼: 手持生食右键蒸笼 -> 蒸X_生(见 ITEM_USE_ON_RULES); 蒸X_生下方是
|
||||
# 点燃的炉灶(stove_2)才计时, 60秒蒸熟
|
||||
{"source": "rtdd:steamerdumplings_0", "target": "rtdd:steamerdumplings_1", "time": 60,
|
||||
{"source": "rtdd:steamerdumplings_0", "target": "rtdd:steamerdumplings_1", "time": 2,
|
||||
"below": [LIT_STOVE], "autoStart": True, "doneTip": "§e饺子蒸好了"},
|
||||
{"source": "rtdd:baozilong_1", "target": "rtdd:baozilong_2", "time": 60,
|
||||
{"source": "rtdd:baozilong_1", "target": "rtdd:baozilong_2", "time": 2,
|
||||
"below": [LIT_STOVE], "autoStart": True, "doneTip": "§e包子蒸好了"},
|
||||
{"source": "rtdd:bamboo_6", "target": "rtdd:bamboo_7", "time": 60,
|
||||
{"source": "rtdd:bamboo_6", "target": "rtdd:bamboo_7", "time": 2,
|
||||
"below": [LIT_STOVE], "autoStart": True, "doneTip": "§e竹筒饭蒸好了"},
|
||||
{"source": "rtdd:steamermilkandegg", "target": "rtdd:steamermilkandegg_1", "time": 60,
|
||||
{"source": "rtdd:steamermilkandegg", "target": "rtdd:steamermilkandegg_1", "time": 2,
|
||||
"below": [LIT_STOVE], "autoStart": True, "doneTip": "§e蒸牛奶鸡蛋好了"},
|
||||
# 烤炉烘焙(60秒, 下方判定烤炉; 烤炉被打碎 -> 该方块掉落+提示)
|
||||
{"source": "rtdd:breaddough_1a", "target": "rtdd:bread_1", "time": 60,
|
||||
{"source": "rtdd:breaddough_1a", "target": "rtdd:bread_1", "time": 2,
|
||||
"below": [OVEN], "autoStart": True, "dropOnBreak": True, "doneTip": "§e法棍烤好了"},
|
||||
{"source": "rtdd:breaddough_2", "target": "rtdd:bread_2", "time": 60,
|
||||
{"source": "rtdd:breaddough_2", "target": "rtdd:bread_2", "time": 2,
|
||||
"below": [OVEN], "autoStart": True, "dropOnBreak": True, "doneTip": "§e吐司烤好了"},
|
||||
{"source": "rtdd:breaddough_4d", "target": "rtdd:bread_4c", "time": 60,
|
||||
{"source": "rtdd:breaddough_4d", "target": "rtdd:bread_4c", "time": 2,
|
||||
"below": [OVEN], "autoStart": True, "dropOnBreak": True, "doneTip": "§e甜甜圈胚烤好了"},
|
||||
{"source": "rtdd:dought_9", "target": "rtdd:bread_3", "time": 60,
|
||||
{"source": "rtdd:dought_9", "target": "rtdd:bread_3", "time": 2,
|
||||
"below": [OVEN], "autoStart": True, "dropOnBreak": True, "doneTip": "§e可颂烤好了"},
|
||||
{"source": "rtdd:cakebatterblock_0", "target": "rtdd:cakebatterblock", "time": 60,
|
||||
{"source": "rtdd:cakebatterblock_0", "target": "rtdd:cakebatterblock", "time": 2,
|
||||
"below": [OVEN], "autoStart": True, "dropOnBreak": True, "doneTip": "§e蛋糕面糊烤好了"},
|
||||
{"source": "rtdd:plate_34", "target": "rtdd:plate_35", "time": 60,
|
||||
{"source": "rtdd:plate_34", "target": "rtdd:plate_35", "time": 2,
|
||||
"below": [OVEN], "autoStart": True, "dropOnBreak": True, "doneTip": "§e布丁半成品好了"},
|
||||
{"source": "rtdd:creampastry_0", "target": "rtdd:souffle_0", "time": 60,
|
||||
{"source": "rtdd:creampastry_0", "target": "rtdd:souffle_0", "time": 2,
|
||||
"below": [OVEN], "autoStart": True, "dropOnBreak": True, "doneTip": "§e舒芙蕾烤好了"},
|
||||
]
|
||||
|
||||
|
||||
+11
-18
@@ -105,10 +105,9 @@ class MianshiService(BlueFoxServerSystem):
|
||||
self.timerSources.add(src)
|
||||
self.featureBlocks.add(src)
|
||||
if src not in self.startTimerTips:
|
||||
sec = r.get("time", 60)
|
||||
tgt = NAME_MAP.get(r["target"], r["target"])
|
||||
self.startTimerTips[src] = "§a开始蒸制: 还需%d秒, 计时结束变成 %s" % (sec, tgt)
|
||||
self.timingTips[src] = "§e正在蒸制中: 还需%d秒, 计时结束变成 %s" % (sec, tgt)
|
||||
self.startTimerTips[src] = "§a开始蒸制, 计时结束变成 %s" % tgt
|
||||
self.timingTips[src] = "§e正在蒸制中, 计时结束变成 %s" % tgt
|
||||
|
||||
# ---- 结果方块/物品 -> "下一步"可读提示(供转换/入笼提示追加) ----
|
||||
# 例子: 饺子皮 -> "加入 猪肉馅、青菜碎"; 可颂面胚 -> "放在烤炉上等计时(60秒)结束变成 可颂"
|
||||
@@ -140,9 +139,9 @@ class MianshiService(BlueFoxServerSystem):
|
||||
sec = r.get("time", 60)
|
||||
tgt = NAME_MAP.get(r["target"], r["target"])
|
||||
if r.get("below") == [OVEN]:
|
||||
_addTip(src, "放在烤炉上等计时(%d秒)结束变成 %s" % (sec, tgt))
|
||||
_addTip(src, "放在烤炉上等计时结束变成 %s" % tgt)
|
||||
else:
|
||||
_addTip(src, "等计时(%d秒)结束变成 %s" % (sec, tgt))
|
||||
_addTip(src, "等计时结束变成 %s" % tgt)
|
||||
|
||||
# ---- 计时源方块 -> 计时结束后的成品名(烤炉固定开始烤制提示用) ----
|
||||
self.timerTargetName = {}
|
||||
@@ -191,13 +190,11 @@ class MianshiService(BlueFoxServerSystem):
|
||||
if blockName in KNEAD_COUNTERS and (not itemName or itemName == "minecraft:air"):
|
||||
return self._handleKnead(blockName, playerId, pos, dim, key)
|
||||
|
||||
# ---- 烤炉固定: 胚/面糊/蛋液等放在烤炉上 -> 禁止右键转换, 固定开始烤制 ----
|
||||
if blockName in OVEN_FIX_BLOCKS and self._belowIs(dim, pos, OVEN):
|
||||
FeatureDispatcher.startTimerFor(blockName, dim, pos, playerId)
|
||||
if self.checkCooldown(key, 0.4):
|
||||
comp.CreateMsg(playerId).NotifyOneMessage(
|
||||
playerId, "§a已启动计时(共60秒)")
|
||||
return True
|
||||
# ---- 烤炉固定: 胚/面糊/蛋液等放在烤炉上 → 不再通过右键启动计时。
|
||||
# 【根因D】计时改自动开始: MianshiTimerService 的 tick 会按下方是否为烤炉
|
||||
# 自动启动计时(OVEN_FIX_BLOCKS 的 autoStart, 参照烤乳猪机制)。这里不再拦截
|
||||
# 右键启动, 也不挡玩家正常放置。空手右键成品取走逻辑保留在下方。
|
||||
# (移除了原"startTimerFor + 提示已启动计时"分支)
|
||||
|
||||
# ---- 烤制成品取走: 空手右键成品(下方是烤炉) -> 成品掉落物, 烤炉不动 ----
|
||||
if blockName in OVEN_RESULT_BLOCKS and self._belowIs(dim, pos, OVEN) \
|
||||
@@ -210,12 +207,8 @@ class MianshiService(BlueFoxServerSystem):
|
||||
playerId, "§a取走" + self._nameOf(blockName))
|
||||
return True
|
||||
|
||||
# ---- 空手右键"蒸笼计时源"(蒸X_生): 下方是点燃炉灶 -> 开始/继续计时 ----
|
||||
if (not itemName or itemName == "minecraft:air") and blockName in self.timerSources:
|
||||
if not self.checkCooldown(key, 0.4):
|
||||
return True
|
||||
self._handleStartTimer(blockName, playerId, pos, dim)
|
||||
return True
|
||||
# ---- 空手右键"蒸笼计时源"(蒸X_生): 计时已改自动(tick 判定下方点燃炉灶),
|
||||
# 不再通过空手右键启动; 此处不再拦截, 避免空手右键被吞影响后续操作。----
|
||||
|
||||
# ---- 常规转换 ----
|
||||
recipe = self.findRecipe(blockName, itemDict)
|
||||
|
||||
+51
-1
@@ -28,7 +28,8 @@ clientComp = clientApi.GetEngineCompFactory()
|
||||
from ...BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxClientSystem
|
||||
from .InterceptData import (ITEM_USE_ON_CANCEL, ITEM_USE_ON_CANCEL_BY_ITEM,
|
||||
SUSHI_BLOCKS, SUSHI_CANCEL, COATING_ITEMS,
|
||||
TAKEOUT_CANCEL, GAI_FAN_CANCEL)
|
||||
TAKEOUT_CANCEL, GAI_FAN_CANCEL, BLOCKUSE_CANCEL,
|
||||
BLOCKUSE_CANCEL_ITEMS)
|
||||
|
||||
# 自定义事件: 客户端拦(碗/盘,汤锅/炒锅/油锅成品)放置预览后, 显式通知服务端执行盛出
|
||||
# 服务端在 FeatureDispatcher 用同一事件名监听(见 service/FeatureDispatcher.py)
|
||||
@@ -45,6 +46,13 @@ GAI_FAN_EVENT = "GaifanRequest"
|
||||
# 种水稻. 若不显式通知, 客户端 ret=True 会吞掉 ServerItemUseOnEvent, 这些转换"点无反应"。
|
||||
ITEM_USE_ON_REQUEST = "ItemUseOnRequest"
|
||||
|
||||
# 自定义事件: 客户端拦(手持可放置/可投掷物品, 功能方块)放置预览后, 显式通知服务端执行
|
||||
# BlockUse 转换(根因B). 例如手持 生鸡肉/鳕鱼/鲑鱼 右键 支杆 -> 上杆; 死鱼右键挂肉钩 ->
|
||||
# 挂放; 鸡蛋右键鸡窝 -> 放蛋; 胡萝卜右键饲料槽 -> 加料; 盘子右键丸子机/石磨 -> 盛取;
|
||||
# 木条右键炉灶 -> 点火. 客户端 ret 掉放置/投掷预览后 NotifyToServer, 服务端按被点方块
|
||||
# blockOwnerAll 路由到 handleBlockUse(与 TakeoutRequest 同机制).
|
||||
BLOCK_USE_REQUEST = "BlockUseRequest"
|
||||
|
||||
|
||||
class ClientFeatureDispatcher(BlueFoxClientSystem):
|
||||
"""客户端右键拦截: 白名单提前 cancel/ret, 消除闪烁"""
|
||||
@@ -56,6 +64,14 @@ class ClientFeatureDispatcher(BlueFoxClientSystem):
|
||||
# 转换完成后一段时间内, 该位置再被当作"放置"会直接 ret 吞掉, 消除"转换后
|
||||
# 由于引擎重置右键导致多放置一次"的闪一下。时长 1.5 秒(用户要求明显可见)。
|
||||
self._afterCd = {}
|
||||
# BlockUse 转换(手持食材/鸡蛋右键功能方块)的独立短冷却: 回调方块后的 0.2s 内
|
||||
# 该坐标再被当作右键会直接 ret 吞掉, 防止"放蛋后连点被误当投掷扔出去"。
|
||||
# 时长 0.2 秒(用户指定"稍微停一下0.1~0.2秒"); 翻炒(0.3s 间隔)不受影响。
|
||||
self._blockCd = {}
|
||||
# 玩家级"刚做过 BlockUse 转换(放蛋/放料)"短标记: key=playerId, value=时间戳.
|
||||
# 用于 OnItemTryUse(投掷/使用轨道)在 0.2s 内取消该玩家的投掷动画(如鸡蛋右键鸡窝
|
||||
# 放蛋后引擎重置右键立即触发投掷 -> 扔蛋)。cd 到即放行, 对地扔蛋正常。
|
||||
self._blockCdPlayer = {}
|
||||
self.ListenForEvent(clientApi.GetEngineNamespace(),
|
||||
clientApi.GetEngineSystemName(),
|
||||
"ClientItemUseOnEvent", self, self.OnItemUseOn)
|
||||
@@ -95,6 +111,31 @@ class ClientFeatureDispatcher(BlueFoxClientSystem):
|
||||
args["ret"] = True
|
||||
return
|
||||
|
||||
# BlockUse 转换短冷却: 放蛋/放料后 0.2s 内同一坐标再被当作右键(引擎重置导致的
|
||||
# 二次使用/投掷)直接吞掉, 防止"连点鸡窝被误当扔蛋"。时长 0.2s(用户指定, 不卡翻炒)。
|
||||
_bcd = self._blockCd.get(cdKey)
|
||||
if _bcd is not None and (time.time() - _bcd) < 0.2:
|
||||
args["ret"] = True
|
||||
return
|
||||
|
||||
# 【根因B】手持可放置/可投掷物品 右键功能方块(支杆/挂肉钩/鸡窝/饲料槽/丸子机/石磨/
|
||||
# 炉灶/寿司/炒锅放料 等) -> 此组合是 BlockUse 转换(服务端 handleBlockUse), 不能走下面
|
||||
# ITEM_USE_ON_CANCEL_BY_ITEM 的"相邻放置"(那会绕开 owners 检查把死鱼/死鸡放到地面)。
|
||||
# 此处 ret 掉放置/投掷预览 + 显式 BlockUseRequest, 由服务端按被点方块 handleBlockUse。
|
||||
# 【注意】这里设 _blockCd(0.2s 短冷却): 放蛋/放料转换后引擎重置右键会再触发一次
|
||||
# "使用/投掷", 若这次也被当正常右键会扔蛋/放着。0.2s 内同坐标直接吞掉, 既消扔蛋又
|
||||
# 不卡翻炒(翻炒 0.3s 间隔 > 0.2s)。去重同时靠服务端 handleBlockUse 自带 checkCooldown。
|
||||
if blockName and (itemName, blockName) in BLOCKUSE_CANCEL:
|
||||
args["ret"] = True
|
||||
self._blockCd[cdKey] = time.time()
|
||||
self._blockCdPlayer[pId] = time.time() # 玩家级短标记, 取消随后 0.2s 内投掷动画
|
||||
self.NotifyToServer(BLOCK_USE_REQUEST, {
|
||||
"playerId": pId,
|
||||
"x": args.get("x"), "y": args.get("y"), "z": args.get("z"),
|
||||
"blockName": blockName, "itemName": itemName,
|
||||
})
|
||||
return
|
||||
|
||||
# 纯手持物品取消 (相邻放置/手持吃物品右键表面): 只看 item, 服务端走 handleItemUseOn
|
||||
# (Yuanban 相邻放置/装盘、Natural 种水稻、Shiyongfood 直接吃)。这些组合一旦客户端
|
||||
# ret=True 会吞掉 ServerItemUseOnEvent, 故必须显式通知服务端补齐(盖饭同款机制)。
|
||||
@@ -187,6 +228,15 @@ class ClientFeatureDispatcher(BlueFoxClientSystem):
|
||||
# 饭团/水煮蛋/豆腐 在 ITEM_USE_ON_CANCEL_BY_ITEM 里(EAT_ITEMS)
|
||||
if itemName in ITEM_USE_ON_CANCEL_BY_ITEM:
|
||||
args["cancel"] = True
|
||||
# 投掷/使用抑制: 玩家刚做过 BlockUse 转换(0.2s 内, 如放蛋/放料), 引擎重置右键会立即
|
||||
# 再触发一次"投掷/使用"动画(鸡蛋右键鸡窝放蛋 -> 扔蛋)。此窗口内若手持 BlockUse 可投掷/
|
||||
# 可用物品, 直接 cancel 掉投掷; 窗口过后放行(对地扔蛋正常)。
|
||||
# 注意: 玩家级标记(pId)而非坐标——投掷事件无目标方块坐标, 只有玩家。0.2s 极短且仅在
|
||||
# 刚做完方块转换后生效, 不会影响玩家正常对地面/空中扔蛋。
|
||||
_pId = args.get("playerId") or args.get("entityId")
|
||||
_pc = self._blockCdPlayer.get(_pId, 0)
|
||||
if _pc and (time.time() - _pc) < 0.2 and itemName in BLOCKUSE_CANCEL_ITEMS:
|
||||
args["cancel"] = True
|
||||
|
||||
|
||||
# 注: 客户端系统需在客户端进程被实例化。modMain 只能在服务端 import 服务端
|
||||
|
||||
+73
-9
@@ -32,6 +32,7 @@
|
||||
4. 在 modMain.py import 这些服务类即可(框架会自动实例化)
|
||||
================================================================================
|
||||
"""
|
||||
import time
|
||||
import mod.server.extraServerApi as serverApi
|
||||
|
||||
# ---- 网易API基础对象 ----
|
||||
@@ -57,6 +58,15 @@ GAI_FAN_EVENT = "GaifanRequest"
|
||||
# 相邻放置/厨具蘸油/寿司/裹粉/种水稻), 而非仅盖饭. ----
|
||||
ITEM_USE_ON_REQUEST = "ItemUseOnRequest"
|
||||
|
||||
# ---- 通用"手持物品右键功能方块"的 BlockUse 转换请求(与客户端 BLOCK_USE_REQUEST 一致).
|
||||
# 用于修复根因B: 手持可放置/可投掷物品(生肉/鱼/鸡蛋/胡萝卜/盘子/木条/寿司等)右键
|
||||
# 功能方块(支杆/挂肉钩/鸡窝/饲料槽/丸子机/石磨/炉灶/寿司方块)时, 原版先播放"放置/
|
||||
# 投掷"预览, 服务端 handleBlockUse 转换靠 ServerBlockUseEvent 触发, 但顺序不可保证,
|
||||
# 导致"想转换却放置/投掷了"。客户端对该(物品,功能方块)组合 ret 消闪后显式 Notify
|
||||
# 本事件, 服务端按被点方块 blockOwnerAll 路由到相应 handleBlockUse (与 TakeoutRequest
|
||||
# 同机制). ----
|
||||
BLOCK_USE_REQUEST = "BlockUseRequest"
|
||||
|
||||
# ---- 方块实体数据组件(计时持久化:记录开始时间戳,重启后继续计时) ----
|
||||
blockEntityDataComp = comp.CreateBlockEntityData(LevelId)
|
||||
|
||||
@@ -71,6 +81,15 @@ FACE_OFFSET = {
|
||||
5: (1, 0, 0),
|
||||
}
|
||||
|
||||
# ---- 右键转换成功后"取消同一右键配套的放置/吃"的时间窗口(秒) ----
|
||||
# 同一右键动作会同时触发 ServerBlockUseEvent(转换) 和 ServerItemUseOnEvent /
|
||||
# ServerItemTryUseEvent(手持方块物品的放置前摇 / 喝药吃食)。OnBlockUse 转换成功后
|
||||
# 会记录该玩家在此窗口内的后续 ItemUseOn/TryUse 应被取消(否则"转出了成品却又把
|
||||
# 手持方块放出来")。超过窗口即视为过期残留, pop 后直接放行, 避免"做完一个操作
|
||||
# 后任意位置放置都被吞"(统计: 空手右键只触发 BlockUse, 无配套 ItemUseOn 消费,
|
||||
# 若标记无时限会永久残留吞掉玩家下一次真实放置)。
|
||||
CANCEL_WINDOW = 0.5
|
||||
|
||||
|
||||
class FeatureDispatcher(BlueFoxServerSystem):
|
||||
"""
|
||||
@@ -225,6 +244,10 @@ class FeatureDispatcher(BlueFoxServerSystem):
|
||||
# (与 GaifanRequest 同机制, 统一覆盖全部 itemUseOn 转换)
|
||||
self.ListenForEvent(MOD_NAME, "ClientFeatureDispatcher",
|
||||
ITEM_USE_ON_REQUEST, self, self.OnItemUseOnRequest)
|
||||
# 10. BlockUseRequest —— 客户端拦截(手持可放置/可投掷物品, 功能方块)放置预览后,
|
||||
# 显式请求服务端执行对应 handleBlockUse(根因B: 防止"想转换却放置/投掷"了)。
|
||||
self.ListenForEvent(MOD_NAME, "ClientFeatureDispatcher",
|
||||
BLOCK_USE_REQUEST, self, self.OnBlockUseRequest)
|
||||
|
||||
def UnListenEvent(self):
|
||||
self.UnListenForEvent(serverApi.GetEngineNamespace(),
|
||||
@@ -251,6 +274,8 @@ class FeatureDispatcher(BlueFoxServerSystem):
|
||||
GAI_FAN_EVENT, self, self.OnGaifanRequest)
|
||||
self.UnListenForEvent(MOD_NAME, "ClientFeatureDispatcher",
|
||||
ITEM_USE_ON_REQUEST, self, self.OnItemUseOnRequest)
|
||||
self.UnListenForEvent(MOD_NAME, "ClientFeatureDispatcher",
|
||||
BLOCK_USE_REQUEST, self, self.OnBlockUseRequest)
|
||||
|
||||
# ============================================================================
|
||||
# 主入口1:玩家右键方块 → 按 blockOwner 路由到右键服务
|
||||
@@ -284,8 +309,9 @@ class FeatureDispatcher(BlueFoxServerSystem):
|
||||
handled = service.handleBlockUse(args)
|
||||
if handled:
|
||||
args['cancel'] = True
|
||||
self._cancelItemUse[playerId] = True
|
||||
print "[FD-BlockUse-DONE]", "player:", playerId, "hand:", _handItem, "block:", blockName, "svc:", service.__class__.__name__, "-> cancel=True, _cancelItemUse=True"
|
||||
# 记录时间戳(带窗口), 只取消同一右键配套的放置/吃; 过期残留自动放行
|
||||
self._cancelItemUse[playerId] = time.time()
|
||||
print "[FD-BlockUse-DONE]", "player:", playerId, "hand:", _handItem, "block:", blockName, "svc:", service.__class__.__name__, "-> cancel=True, _cancelItemUse=ts"
|
||||
return
|
||||
print "[FD-BlockUse-NOMATCH]", "player:", playerId, "hand:", _handItem, "block:", blockName, "-> 无匹配规则, 放行"
|
||||
|
||||
@@ -306,11 +332,12 @@ class FeatureDispatcher(BlueFoxServerSystem):
|
||||
"""
|
||||
playerId = args.get("playerId") or args.get("entityId")
|
||||
# 【关键】同一右键动作会同时触发 ServerBlockUseEvent(盛出/转换, 已由 OnBlockUse
|
||||
# 处理并设置 _cancelItemUse) 和 ServerItemUseOnEvent(手持方块物品的放置前摇)。
|
||||
# 若前一帧 OnBlockUse 已成功处理(盛出掉落/方块转换), 这里必须消费标记并
|
||||
# ret=True 取消放置, 否则"盛出了成品"却又"把手持的木碗/盘子放了出来"。
|
||||
# (与 OnItemTryUse 消费标记取消"吃/喝"是同一模式。)
|
||||
if self._cancelItemUse.pop(playerId, False):
|
||||
# 处理并设置 _cancelItemUse 时间戳) 和 ServerItemUseOnEvent(手持方块物品的放置前摇)。
|
||||
# 若在 CANCEL_WINDOW 窗口内, 这里必须消费标记并 ret=True 取消放置, 否则"盛出了成品"
|
||||
# 却又"把手持的木碗/盘子放了出来"。超窗口则视为过期残留, pop 后直接放行——绝不吞
|
||||
# 玩家之后的真实放置(日志: 空手右键完成后残留标记吞掉任意位置放置, 已修复)。
|
||||
_ts = self._cancelItemUse.pop(playerId, 0)
|
||||
if _ts and (time.time() - _ts) < CANCEL_WINDOW:
|
||||
args['ret'] = True
|
||||
print "[FD-ItemUseOn-CONSUME-CANCEL]", "player:", playerId, "item:", args.get("itemName"), "block:", args.get("blockName"), "-> ret=True 取消放置"
|
||||
return
|
||||
@@ -361,7 +388,8 @@ class FeatureDispatcher(BlueFoxServerSystem):
|
||||
handled = service.handleItemUseOn(args)
|
||||
if handled:
|
||||
args['ret'] = True
|
||||
self._cancelItemUse[playerId] = True
|
||||
# 时间戳(带窗口): itemUseOn 转换成功后, 同右手的后续 TryUse/放置也取消
|
||||
self._cancelItemUse[playerId] = time.time()
|
||||
return
|
||||
|
||||
# ============================================================================
|
||||
@@ -513,6 +541,39 @@ class FeatureDispatcher(BlueFoxServerSystem):
|
||||
return
|
||||
print "[FD-ItemUseOnRequest-NO-HANDLER]", itemName
|
||||
|
||||
def OnBlockUseRequest(self, args):
|
||||
"""
|
||||
客户端 ClientFeatureDispatcher 在拦截(手持可放置/可投掷物品, 功能方块)放置预览后,
|
||||
显式 NotifyToServer 发来的 BlockUse 转换请求(根因B). 因为客户端已 ret=True 把该
|
||||
组合的 ServerBlockUseEvent 吞掉(消闪), 服务端原本的 handleBlockUse 转换在这里补齐.
|
||||
|
||||
按被点方块名路由到 blockOwnerAll 里的服务(可能多个, 逐个 fallback, 第一个返回 True
|
||||
的处理成功, 与 OnBlockUse 相同). 各服务 handleBlockUse 内部自带 checkCooldown(同坐标/
|
||||
同物品), 即使与真实 ServerBlockUseEvent 重复触发, 冷却也会拦截第二次, 不双重消耗.
|
||||
"""
|
||||
playerId = args.get("playerId")
|
||||
x, y, z = args.get("x"), args.get("y"), args.get("z")
|
||||
blockName = args.get("blockName")
|
||||
if not (playerId and x is not None and y is not None and z is not None and blockName):
|
||||
return
|
||||
services = self.blockOwnerAll.get(blockName)
|
||||
if not services:
|
||||
print "[FD-BlockUseRequest-NO-SVC]", blockName
|
||||
return
|
||||
useArgs = {
|
||||
"blockName": blockName,
|
||||
"playerId": playerId,
|
||||
"entityId": playerId,
|
||||
"x": x, "y": y, "z": z,
|
||||
"face": args.get("face", 1),
|
||||
}
|
||||
for service in services:
|
||||
if hasattr(service, "handleBlockUse"):
|
||||
handled = service.handleBlockUse(useArgs)
|
||||
if handled:
|
||||
return
|
||||
print "[FD-BlockUseRequest-NO-HANDLER]", blockName
|
||||
|
||||
# ============================================================================
|
||||
# 主入口3:拦截物品使用(防止喝药水/吃食物等默认行为)
|
||||
# ============================================================================
|
||||
@@ -526,7 +587,10 @@ class FeatureDispatcher(BlueFoxServerSystem):
|
||||
"""
|
||||
playerId = args.get("playerId")
|
||||
print "[FD-ItemTryUse]", args.get("itemName"), "player", playerId
|
||||
if self._cancelItemUse.pop(playerId, False):
|
||||
# 仅在 CANCEL_WINDOW 窗口内消费(同一右键配套的吃/喝); 过期残留 pop 后放行,
|
||||
# 不吞玩家之后再吃/喝物品(根因A: 无时限标记残留会吞掉后续任意物品使用)。
|
||||
_ts = self._cancelItemUse.pop(playerId, 0)
|
||||
if _ts and (time.time() - _ts) < CANCEL_WINDOW:
|
||||
args['cancel'] = True
|
||||
return
|
||||
itemName = args.get("itemName")
|
||||
|
||||
@@ -103,6 +103,72 @@ try:
|
||||
except Exception:
|
||||
YOUGUO_SWITCH, YOUGUO_PLATE = None, None
|
||||
|
||||
# ---- 根因B: 各"手持可放置/可投掷物品右键功能方块"走 ServerBlockUseEvent 的转换规则表.
|
||||
# 字段用 source/block + item(块字段统一为 source; 不同服务可能用 source 或 block, 取兼容). ----
|
||||
_BLOCK_USE_TABLES = []
|
||||
|
||||
# 动物养殖(鸡窝放蛋/饲料槽/水槽 等): AnimalData.ANIMAL_SWITCHES
|
||||
try:
|
||||
from ..dongwuyangzhi.AnimalData import ANIMAL_SWITCHES as ANIMAL_RS
|
||||
_BLOCK_USE_TABLES.append(ANIMAL_RS)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 烧烤(上杆: 支杆+生肉/鱼): BarbecueData.BARBECUE_SWITCHES
|
||||
try:
|
||||
from ..shaokao.BarbecueData import BARBECUE_SWITCHES as BBQ_RS
|
||||
_BLOCK_USE_TABLES.append(BBQ_RS)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 死亡生物(挂肉钩: 死鱼+钩/尸体挂放): DeadmobData.DEADMOB_SWITCHES
|
||||
try:
|
||||
from ..siwangshengwu.DeadmobData import DEADMOB_SWITCHES as DEADMOB_RS
|
||||
_BLOCK_USE_TABLES.append(DEADMOB_RS)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 厨具(炉灶/丸子机/石磨: 木条+炉灶 等): ChujuData.STOVE_RULES / MEATBALLMAKER_RULES
|
||||
try:
|
||||
from ..chuju.ChujuData import (STOVE_RULES as CHUJU_STOVE,
|
||||
MEATBALLMAKER_RULES as CHUJU_MEAT,
|
||||
STEAMER_RULES as CHUJU_STEAM)
|
||||
_BLOCK_USE_TABLES.extend([CHUJU_STOVE, CHUJU_MEAT, CHUJU_STEAM])
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 面食(面粉加水/揉面 等): MianshiData.SWITCH_RULES
|
||||
try:
|
||||
from ..mianshi.MianshiData import SWITCH_RULES as MIANSHI_SWITCH
|
||||
_BLOCK_USE_TABLES.append(MIANSHI_SWITCH)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 炒锅(放料: 手持食材右键炒锅等): ChaoguoData.SWITCH_RULES
|
||||
# (放料/翻炒走 handleBlockUse; 其中 action==take_out 的"盘子出锅"已由 TAKEOUT_CANCEL
|
||||
# 专用通道处理, 派生时过滤掉, 避免与盛出走 TakeoutRequest 冲突)
|
||||
try:
|
||||
from ..chaoguo.ChaoguoData import SWITCH_RULES as CHAOGUO_BLOCKUSE
|
||||
_BLOCK_USE_TABLES.append(CHAOGUO_BLOCKUSE)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 汤锅(放料: 手持食材/锅态汤右键汤锅等): TangguoData.SWITCH_RULES
|
||||
# 同样过滤 action==take_out(盛出走 TakeoutRequest)
|
||||
try:
|
||||
from ..tangguo.TangguoData import SWITCH_RULES as TANGGUO_BLOCKUSE
|
||||
_BLOCK_USE_TABLES.append(TANGGUO_BLOCKUSE)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 油锅(放料: 手持食材右键油锅等): YouguoData.SWITCH_RULES
|
||||
# 同样过滤 action==take_out(出锅走 TakeoutRequest)
|
||||
try:
|
||||
from ..youguo.YouguoData import SWITCH_RULES as YOUGUO_BLOCKUSE
|
||||
_BLOCK_USE_TABLES.append(YOUGUO_BLOCKUSE)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# ---- 原版放置/盘子转换 (itemUseOn, surface=相邻放置 / source=盘子) ----
|
||||
try:
|
||||
from ..yuanbanfangzhi.YuanbanData import (
|
||||
@@ -186,6 +252,37 @@ if CHAOGUO_USON:
|
||||
if isinstance(_it, basestring) and _it and isinstance(_bk, basestring) and _bk:
|
||||
GAI_FAN_CANCEL.add((_it, _bk))
|
||||
|
||||
# ============================================================================
|
||||
# 三之C、根因B "手持可放置/可投掷物品右键功能方块" -> BlockUse 显式事件拦截
|
||||
# 客户端拦(手持物品, 功能方块)的放置/投掷预览后, NotifyToServer(BLOCK_USE_REQUEST),
|
||||
# 服务端 OnBlockUseRequest 按被点方块路由到对应服务的 handleBlockUse。
|
||||
# 仅取"手持物品非空"(item != None 且非 * 通配) 的转换对 —— 空手右键(item=None)
|
||||
# 不涉及放置预览, 不需要拦截, 仍走正常 ServerBlockUseEvent。
|
||||
# ============================================================================
|
||||
BLOCKUSE_CANCEL = set()
|
||||
for _tbl in _BLOCK_USE_TABLES:
|
||||
for _r in _as_list(_tbl):
|
||||
if not isinstance(_r, dict):
|
||||
continue
|
||||
_it = _r.get("item")
|
||||
if not _it or not isinstance(_it, basestring) or _it.startswith("*"):
|
||||
continue # 只看"手持具体物品"的转换; 空手/通配不拦
|
||||
# 炒锅 SWITCH_RULES 的 action==take_out(盘子出锅) 已由 TAKEOUT_CANCEL 专用通道处理,
|
||||
# 这里跳过, 避免与盛出走 TakeoutRequest 冲突; 其余(放料/翻炒)走 BlockUse。
|
||||
if _r.get("action") == "take_out":
|
||||
continue
|
||||
# 被点方块: 兼容 source(主流) 与 block(个别)
|
||||
_bk = _r.get("source") or _r.get("block")
|
||||
if isinstance(_bk, basestring) and _bk:
|
||||
BLOCKUSE_CANCEL.add((_it, _bk))
|
||||
|
||||
# BlockUse 转换涉及的全部手持物品集合(客户端 OnItemTryUse 也需取消默认"使用/投掷/倒水",
|
||||
# 否则手持鸡蛋右键鸡窝会被当成投掷扔出去; 水桶倒水同理)。
|
||||
# 只取原版/可"使用"的物品(minecraft: 前缀)进入 TryUse 取消; rtdd 方块物品不触发 TryUse。
|
||||
BLOCKUSE_CANCEL_ITEMS = set(
|
||||
_it for (_it, _bk) in BLOCKUSE_CANCEL if _it.startswith("minecraft:")
|
||||
)
|
||||
|
||||
# ---- Chuju 锅铲/油罐 inline 转换(在 ChujuService.handleItemUseOn 内联, 不在数据表) ----
|
||||
# 手持 锅铲/带油锅铲 右键 油罐(oilcan)/炒锅(wok) 蘸油/还油/上油 -> 取消默认
|
||||
CHUJU_INLINE_CANCEL = {
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ ITEM_USE_ON_RULES = [
|
||||
"item": "minecraft:chicken", # 原版生鸡肉
|
||||
"target": "rtdd:roastchickenplace_0", # 生鸡肉(放置后)
|
||||
"consume": 1,
|
||||
"tip": "§a已放置生鸡肉,可右键支杆上杆烤制",
|
||||
"tip": "§a已放置生鸡肉",
|
||||
},
|
||||
{
|
||||
"item": "minecraft:salmon", # 原版生鲑鱼
|
||||
|
||||
@@ -1028,3 +1028,54 @@ FurnitureData+FurnitureService 实现, 注册到 FeatureDispatcher)
|
||||
OnItemUseOn 的 BY_ITEM / ITEM_USE_ON_CANCEL / SUSHI / COATING 分支全部改为 ret+显式事件
|
||||
③白名单清单: 新增"十三、其余 itemUseOn 转换 统一显式事件修复" [已实现]
|
||||
|
||||
########################################
|
||||
【统一消闪修复·第二轮】(2026-09-23)
|
||||
########################################
|
||||
用户批量反馈后的统一修复, 分根因A/B/C/D四块:
|
||||
【根因A】操作后任意位置放置被吞(全模组, 最严重)
|
||||
- 症状: 日志 [FD-BlockUse-DONE]hand:NONE吃roastedmushrooms_3 设 _cancelItemUse=True 后,
|
||||
玩家之后在任意位置放方块都被 [FD-ItemUseOn-CONSUME-CANCEL] 吞掉。
|
||||
- 根因: _cancelItemUse 是无时限的玩家级布尔标记, OnBlockUse 设 True 后残留;
|
||||
空手右键(吃/取)只触发 BlockUse 不触发 ItemUseOn, 标记无人消费残留到下一次真实放置。
|
||||
- 修复: FeatureDispatcher.py 加 CANCEL_WINDOW=0.5, _cancelItemUse 改存时间戳,
|
||||
OnBlockUse/OnItemUseOn(itemUseOn成功)/OnItemTryUse 三处消费处均判断 time.time()-ts<0.5,
|
||||
过期残留 pop 后直接放行, 不再吞后续放置/吃。 [已实现]
|
||||
【根因D】面食计时改2秒+去秒提示+移除右键启动(参照烤乳猪自动判定)
|
||||
- MianshiData.TIMER_RULES 全部 time:60->2 (发酵/蒸笼/烤炉烘焙 共13条)
|
||||
- MianshiService: 移除"烤炉固定 OVEN_FIX_BLOCKS 右键 startTimerFor+提示"、"空手右键蒸笼计时源
|
||||
timerSources 启动"两段; 改由 MianshiTimerService autoStart tick 按下方烤炉/点燃炉灶自动启动
|
||||
- 提示去秒数: startTimerTips/timingTips 去掉"还需%d秒", 蒸笼入笼 tip 去掉"(共60秒)", 只报开始蒸制
|
||||
【根因C】家具家私获得物品改掉落物形式
|
||||
- FurnitureService: 箭盒取箭 giveItem->_dropItemDict; 厨具架取回 giveItemObj/giveItem->_dropItemObj/
|
||||
_dropItemDict; 通用 recipe giveItem(水槽取水/取脏盘子/盘子架取回)->_dropItemDict。 [已实现]
|
||||
【根因B】手持可放置/可投掷物品右键功能方块"想转换却被放置/投掷"
|
||||
- 症状: 持鸡蛋右键鸡窝扔蛋/放不进; 持胡萝卜右键饲料槽摆切萝卜; 烧烤上杆/死亡生物挂肉钩/
|
||||
厨具丸子机/石磨/炉灶/面食加水/寿司 等闪一下或真放出去。
|
||||
- 根因: 这些转换走 ServerBlockUseEvent(handleBlockUse), 但手持物是真块/可投掷, 客户端
|
||||
ClientItemUseOnEvent 未拦(手持物,功能方块), 原版先播放放置/投掷预览; 且部分物品(鸡/鳕/
|
||||
鲑/胡萝卜/稻谷)在 PLACE_ITEMS 里, 客户端拦截后走 ItemUseOnRequest 相邻放置, 绕开 owners 检查。
|
||||
- 修复: 新增 BlockUseRequest 统一显式事件通道(与盛出同架构):
|
||||
①InterceptData: 新增 BLOCKUSE_CANCEL, 扫描 ANIMAL_SWITCHES/BARBECUE_SWITCHES/DEADMOB_SWITCHES/
|
||||
STOVE_RULES/MEATBALLMAKER_RULES/STEAMER_RULES/Mianshi SWITCH_RULES 中 item非空且非* 的
|
||||
(手持物品,source/block) 对
|
||||
②FeatureDispatcher: 新增 BLOCK_USE_REQUEST 常量/监听/路由 OnBlockUseRequest(按 blockOwnerAll
|
||||
handleBlockUse)
|
||||
③ClientFeatureDispatcher: 新增 BLOCK_USE_REQUEST 常量, OnItemUseOn 中 BLOCKUSE_CANCEL 分支
|
||||
优先于 ITEM_USE_ON_CANCEL_BY_ITEM(避免相邻放置抢走), ret+Notify 显式触发 [已实现]
|
||||
【注意事项】
|
||||
- 烧烤上杆烤鸡规则 item=rtdd:roastchickenplace_0(放置后的块), 不是 minecraft:chicken;
|
||||
若玩家想"手持生鸡肉右键支杆", 该组合不属于转换(需先放出生鸡肉块), 待用户确认是否要改数据。
|
||||
- 面食/汤锅/装盘(ITEM_USE_ON_CANCEL_BY_ITEM) 仍走 ItemUseOnRequest; 他们不属于 blockUse 转换。
|
||||
- 炒锅放料补充: 用户反馈"炒锅放胡萝卜"同款问题。已把 ChaoguoData.SWITCH_RULES 纳入 BLOCKUSE_CANCEL
|
||||
派生(InterceptData), 且派生时跳过 action==take_out(避免与 TAKEOUT_CANCEL 抢盘子出锅)。这样手持
|
||||
胡萝卜/葱花/蒜末等食材右键炒锅(油锅/添油) 会走 BlockUseRequest, 不再被相邻放置抢走。 [已补]
|
||||
- 汤锅/油锅放料补充: 用户要求把炒锅/汤锅/油锅"手持食材放置"全部处理, 不只是胡萝卜。
|
||||
已将 TangguoData.SWITCH_RULES、YouguoData.SWITCH_RULES 一并纳入 BLOCKUSE_CANCEL 派生
|
||||
(同样过滤 action==take_out)。汤锅/油锅/炒锅放料(手持食材/锅态汤右键锅身) 现在都走
|
||||
BlockUseRequest, 不再被相邻放置/放置物品抢走。 [已补]
|
||||
- 投掷物(鸡蛋等)扔蛋修复: 扔蛋是独立投掷事件 ClientItemTryUseEvent 触发(非 ItemUseOn放置)。
|
||||
方案(用户指定): 右键鸡窝放蛋时客户端记玩家级 _blockCdPlayer[pId]=now(0.2s 短标记);
|
||||
OnItemTryUse 中该玩家 0.2s 内手持 BlockUse 可投掷/可用物品(BLOCKUSE_CANCEL_ITEMS)直接
|
||||
cancel 掉投掷动画; 窗口过后放行, 对地扔蛋正常。不设全局取消(会破坏对地投掷, 已弃)。
|
||||
时长 0.2s, 不卡翻炒(0.3s 间隔)。 [已修]
|
||||
|
||||
Reference in new issue
Block a user