From 379a1c87e959e83b7b8eb12cef4a67124cc22c9f Mon Sep 17 00:00:00 2001 From: wenhe <1046926120@qq.com> Date: Tue, 22 Sep 2026 16:03:30 +0800 Subject: [PATCH] =?UTF-8?q?=E7=83=A4=E7=8C=AA=201?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xiangyemod/service/FeatureDispatcher.py | 65 ++++++++++++++++++- .../xiangyemod/shaokao/BarbecueData.py | 39 ++++++----- .../shaokao/service/BarbecueService.py | 61 ++++++++++------- .../shaokao/service/BarbecueTimerService.py | 55 +++++++++++++--- 4 files changed, 170 insertions(+), 50 deletions(-) diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py index 12cc763..4452301 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py @@ -45,6 +45,17 @@ from ...BlueFoxTools.ToolsConfig import LevelId # ---- 方块实体数据组件(计时持久化:记录开始时间戳,重启后继续计时) ---- blockEntityDataComp = comp.CreateBlockEntityData(LevelId) +# ---- 方块表面方向 → 相邻坐标偏移(0下 1上 2北 3南 4西 5东) ---- +# 用于放置后事件计算"落点"(被点方块的相邻格) +FACE_OFFSET = { + 0: (0, -1, 0), + 1: (0, 1, 0), + 2: (0, 0, -1), + 3: (0, 0, 1), + 4: (-1, 0, 0), + 5: (1, 0, 0), +} + class FeatureDispatcher(BlueFoxServerSystem): """ @@ -157,12 +168,15 @@ class FeatureDispatcher(BlueFoxServerSystem): def ListenEvent(self): """ - 注册五个事件: + 注册六个事件: 1. ServerBlockUseEvent —— 玩家右键方块(所有功能的右键转换入口) 2. ServerItemUseOnEvent —— 手持物品右键方块表面(如放置生鸡肉) 3. ServerItemTryUseEvent —— 玩家尝试使用物品(拦截喝药水/吃食物等默认行为) 4. ServerBlockEntityTickEvent —— 计时方块每tick触发(烤制/饲料变空等,持久化计时) 5. ServerPlayerTryDestroyBlockEvent —— 玩家拆方块(放置的死鱼/生鸡肉掉回原版生食材) + 6. ItemUseOnAfterServerEvent —— 放置方块/生态后触发(携带放置者 entityId)。 + 用于"创造模式直接放生态"也能拿到是谁放的 → 记录到计时源方块 rtdd_tp, + 让计时源服务能"谁放提示发给谁"(如烧烤直接放烤乳猪也提示营火)。 """ self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), @@ -179,6 +193,9 @@ class FeatureDispatcher(BlueFoxServerSystem): self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerPlayerTryDestroyBlockEvent", self, self.OnDestroy) + self.ListenForEvent(serverApi.GetEngineNamespace(), + serverApi.GetEngineSystemName(), + "ItemUseOnAfterServerEvent", self, self.OnItemPlaceAfter) def UnListenEvent(self): self.UnListenForEvent(serverApi.GetEngineNamespace(), @@ -196,6 +213,9 @@ class FeatureDispatcher(BlueFoxServerSystem): self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerPlayerTryDestroyBlockEvent", self, self.OnDestroy) + self.UnListenForEvent(serverApi.GetEngineNamespace(), + serverApi.GetEngineSystemName(), + "ItemUseOnAfterServerEvent", self, self.OnItemPlaceAfter) # ============================================================================ # 主入口1:玩家右键方块 → 按 blockOwner 路由到右键服务 @@ -290,6 +310,49 @@ class FeatureDispatcher(BlueFoxServerSystem): self._cancelItemUse[playerId] = True return + # ============================================================================ + # 主入口2.5:放置方块/生态后 → 给计时源补记录放置者(谁放提示发给谁) + # ============================================================================ + + def OnItemPlaceAfter(self, args): + """ + 玩家放置方块/生态后触发(ItemUseOnAfterServerEvent)。 + 用途:创造模式"直接放烤乳猪等计时源生态"时,没有右键上杆,拿不到放置者。 + 这里拿到 放置者(entityId) + 落点方块,若落点是某个计时源的方块, + 就带 playerId 调 startTimerFor → startTimer 会判断下方营火并提示"谁放的"。 + 这样"创造直接放"也能做到谁放提示发给谁(不依赖右键路径)。 + """ + playerId = args.get("entityId") + if not playerId: + return + # 被点方块的坐标 + 朝向面 + try: + face = args.get("face", 1) + x, y, z = args.get("x"), args.get("y"), args.get("z") + except Exception: + return + # 落点 = 被点方块相邻的那一格(0下 1上 2北 3南 4西 5东) + off = FACE_OFFSET.get(face, (0, 1, 0)) + targetPos = (x + off[0], y + off[1], z + off[2]) + dim = args.get("dimensionId") + if dim is None: + try: + dim = comp.CreateDimension(playerId).GetEntityDimensionId() + except Exception: + return + # 读取落点方块名 + try: + b = comp.CreateBlockInfo(LevelId).GetBlockNew(targetPos, dim) + blockName = b.get("name") if b else "" + except Exception: + return + if not blockName: + return + # 落点是计时源方块 → 带放置者启动(判断营火 + 谁放提示发给谁) + service = self.timerOwner.get(blockName) + if service and hasattr(service, "startTimer"): + service.startTimer(dim, targetPos, blockName, playerId) + # ============================================================================ # 主入口3:拦截物品使用(防止喝药水/吃食物等默认行为) # ============================================================================ diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/BarbecueData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/BarbecueData.py index 37acec7..33ac2dd 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/BarbecueData.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/BarbecueData.py @@ -36,7 +36,8 @@ tip: 转换成功时给玩家的提示(绿色§a开头) startTip: 计时型规则启动计时时给玩家的提示(仅玩家主动触发时发) doneTip: 计时到点完成时给启动者的提示(如"烤鸡烤熟了!") - autoStart: 放置时是否自动开始计时,默认True(自动);烧烤烤制设为False=必须右键激活 + autoStart: 放置/上杆后是否自动开始计时,默认True(自动);烧烤设为True=下方 + 出现营火即自动开始烤制,无需右键启动 ================================================================================ """ @@ -179,13 +180,14 @@ BARBECUE_SWITCHES = [ # 三、上杆(手持生食材右键 支杆b_34) # ============================================================ # 【上烤鸡】支杆 + 生鸡肉(放置后方块物品) → 烤鸡(上烤架_生) + # 提示不说"开始烤制"——下方是不是营火由运行时判断(aotoStartRoast)。 { "source": "rtdd:b_34", "item": "rtdd:roastchickenplace_0", "target": "rtdd:roastchicken_0", "consume": 1, "type": "switch", - "tip": "§a烤鸡已上杆,右键开始烤制", + "tip": "§a烤鸡已上杆", "giveItem": None, }, # 【上烤乳猪】支杆 + 死猪 → 烤乳猪(生) @@ -195,7 +197,7 @@ BARBECUE_SWITCHES = [ "target": "rtdd:roastpig_0", "consume": 1, "type": "switch", - "tip": "§a烤乳猪已上杆,右键开始烤制", + "tip": "§a烤乳猪已上杆", "giveItem": None, }, # 【上烤鳕鱼】支杆 + 鳕鱼 → 烤鳕鱼(生) @@ -205,7 +207,7 @@ BARBECUE_SWITCHES = [ "target": "rtdd:grilledcod_0", "consume": 1, "type": "switch", - "tip": "§a烤鳕鱼已上杆,右键开始烤制", + "tip": "§a烤鳕鱼已上杆", "giveItem": None, }, # 【上烤鲑鱼】支杆 + 鲑鱼 → 烤鲑鱼(生) @@ -215,15 +217,16 @@ BARBECUE_SWITCHES = [ "target": "rtdd:grilled_fish", "consume": 1, "type": "switch", - "tip": "§a烤鲑鱼已上杆,右键开始烤制", + "tip": "§a烤鲑鱼已上杆", "giveItem": None, }, # ============================================================ # 四、计时烤制(上杆后,支杆下方篝火,计时自动转换) # ============================================================ - # 【烤熟】烤鸡(上烤架_生) → 烤鸡(上烤架_熟),下方需篝火,约60秒 - # autoStart=False:放置/上杆后必须右键一下才开始烤制 + # 【烤熟】烤鸡(上烤架_生) → 烤鸡(上烤架_熟),下方需篝火 + # autoStart=True:下方出现营火即自动开始烤制,无需右键 + # startTip=下方已是营火时的提示(aotoStartRoast 动态判断下发) { "source": "rtdd:roastchicken_0", "item": None, @@ -232,12 +235,12 @@ BARBECUE_SWITCHES = [ "type": "timer", "time": 60, "below": ["minecraft:campfire"], - "autoStart": False, - "startTip": "§e开始烤制烤鸡,约60秒…", + "autoStart": True, + "startTip": "§a下方是营火,烤鸡开始烤制", "doneTip": "§e烤鸡烤熟了!", "giveItem": None, }, - # 【烤熟】烤乳猪(生) → 烤乳猪(熟),下方需篝火,约60秒 + # 【烤熟】烤乳猪(生) → 烤乳猪(熟),下方需篝火 { "source": "rtdd:roastpig_0", "item": None, @@ -246,12 +249,12 @@ BARBECUE_SWITCHES = [ "type": "timer", "time": 60, "below": ["minecraft:campfire"], - "autoStart": False, - "startTip": "§e开始烤制烤乳猪,约60秒…", + "autoStart": True, + "startTip": "§a下方是营火,烤乳猪开始烤制", "doneTip": "§e烤乳猪烤熟了!", "giveItem": None, }, - # 【烤熟】烤鳕鱼(生) → 烤鳕鱼(熟),下方需篝火,约60秒 + # 【烤熟】烤鳕鱼(生) → 烤鳕鱼(熟),下方需篝火 { "source": "rtdd:grilledcod_0", "item": None, @@ -260,12 +263,12 @@ BARBECUE_SWITCHES = [ "type": "timer", "time": 60, "below": ["minecraft:campfire"], - "autoStart": False, - "startTip": "§e开始烤制烤鳕鱼,约60秒…", + "autoStart": True, + "startTip": "§a下方是营火,烤鳕鱼开始烤制", "doneTip": "§e烤鳕鱼烤熟了!", "giveItem": None, }, - # 【烤熟】烤鲑鱼(生) → 烤鲑鱼(熟),下方需篝火,约60秒 + # 【烤熟】烤鲑鱼(生) → 烤鲑鱼(熟),下方需篝火 { "source": "rtdd:grilled_fish", "item": None, @@ -274,8 +277,8 @@ BARBECUE_SWITCHES = [ "type": "timer", "time": 60, "below": ["minecraft:campfire"], - "autoStart": False, - "startTip": "§e开始烤制烤鲑鱼,约60秒…", + "autoStart": True, + "startTip": "§a下方是营火,烤鲑鱼开始烤制", "doneTip": "§e烤鲑鱼烤熟了!", "giveItem": None, }, diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueService.py index 619d54d..f7d87a8 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueService.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueService.py @@ -10,8 +10,10 @@ 同分类的"计时自动转换"(烤鸡/烤乳猪/烤鱼 上杆后下方篝火烤熟)已拆到独立类: BarbecueTimerService —— 处理 ServerBlockEntityTickEvent 转发的计时逻辑 本类只负责右键事件,两者通过 FeatureDispatcher 协作: - - 本类右键碰到"计时源方块"(如烤鸡(生))→ 调 FeatureDispatcher.startTimerFor - 转发给 BarbecueTimerService 启动烤制(篝火检查也在计时服务里做) + - 本类上杆/放置成"计时源方块"(烤鸡/烤乳猪/烤鱼 生态)→ 调 autoStartRoast + → FeatureDispatcher.startTimerFor 转发给 BarbecueTimerService 自动启动烤制 + (下方营火判定 + 提示都在计时服务里做) + - 计时源方块的 tick 也会自动检测下方营火并补写计时(即使玩家先放生态再放营火) - 计时到点转换完全由 BarbecueTimerService 负责,本类不碰任何计时数据 【事件监听在哪?】 @@ -26,13 +28,13 @@ handleBlockUse ← 入口:分发器转发右键方块事件 ├─ findRecipe ← 匹配 (方块名, 物品名) 规则 ├─ checkCooldown ← 连点冷却(防刷提示) - ├─ forwardStartTimer ← 计时源方块 → 转发给计时服务启动烤制 - ├─ checkBelow ← 切换型规则的下方方块检查(烤串需点燃的烧烤炉) - └─ handleSwitch ← 切换型规则具体执行(点火/烤串/上杆/取下) - ├─ consumeItem ← 消耗物品 - ├─ replaceBlock ← 替换方块 - ├─ giveItem ← 直接给物品(塞背包) - └─ dropItems ← 掉落物形式给物品(取下整只成品) + ├─ handleSwitch ← 切换型规则具体执行(点火/烤串/上杆/取下) + │ └─ autoStartRoast← 上杆/放置计时源方块后自动判定下方营火并启动烤制 + │ └─ checkBelow ← 切换型规则的下方方块检查(烤串需点燃的烧烤炉) + │ └─ consumeItem ← 消耗物品 + │ └─ replaceBlock ← 替换方块 + │ └─ giveItem ← 直接给物品(塞背包) + └─ dropItems ← 掉落物形式给物品(取下整只成品) ================================================================================ """ import time @@ -78,10 +80,14 @@ class BarbecueService(BlueFoxServerSystem): # switch 和 timer 规则都收进来:右键"计时源方块"时才能识别并转发给计时服务 self.barbecueRecipes = {} self.barbecueBlockSet = set() + # 计时源方块集合(上杆/放置后需要自动判定下方营火并启动烤制) + self.timerSourceSet = set() for sw in BARBECUE_SWITCHES: key = (sw["source"], sw.get("item")) self.barbecueRecipes[key] = sw self.barbecueBlockSet.add(sw["source"]) + if sw.get("type") == "timer": + self.timerSourceSet.add(sw["source"]) # ---- 右键冷却表 ---- self.cooldown = {} @@ -122,15 +128,17 @@ class BarbecueService(BlueFoxServerSystem): if not recipe: return False + # 计时型规则【不再通过右键启动】。烤制改为"放置/上杆后自动判定下方营火" + # (见 handleSwitch 正向; 营火放上去也会由 tick 自动检测启动)。 + # 因此右键计时源方块(烤乳猪生态等)一律放行,不拦截 —— 否则玩家想在上面 + # 放方块时会被一直拦截并弹"需要营火",造成互斥。 + if recipe.get("type") == "timer": + return False + # 冷却检查(烤串"右键2次"用 switchCd 调小冷却以便快速连点) if not self.checkCooldown(key, recipe.get("switchCd", 0.5)): return True - # 计时型规则:右键"计时源方块"(如烤鸡(生))→ 转发给计时服务启动烤制。 - # 下方篝火检查在 BarbecueTimerService.startTimer 里做(失败会提示玩家) - if recipe.get("type") == "timer": - return self.forwardStartTimer(blockName, dim, pos, playerId) - # 切换型规则:先检查下方方块(烤串要求下方是点燃的烧烤炉) if not self.checkBelow(recipe, dim, pos): comp.CreateMsg(playerId).NotifyOneMessage(playerId, "§c下方不是点燃的烧烤炉,无法翻烤!") @@ -157,15 +165,18 @@ class BarbecueService(BlueFoxServerSystem): return self.barbecueRecipes.get((blockName, None)) # ============================================================================ - # 三、计时转发(把"计时源方块"的烤制启动任务交给 BarbecueTimerService) + # 三、计时自动启动(上杆/放置计时源方块后,判定下方营火并启动烤制) # ============================================================================ - def forwardStartTimer(self, blockName, dim, pos, playerId): + def autoStartRoast(self, blockName, dim, pos, playerId): """ - 右键碰到"计时源方块"(如烤鸡(生))时,把启动烤制转交给计时服务。 - 通过 FeatureDispatcher.startTimerFor 按方块名 O(1) 路由到 BarbecueTimerService。 + 上杆/放置成"计时源方块"(烤乳猪生态等)后自动判定并启动烤制: + - 下方是营火 → 启动计时,提示开始烤制 + - 下方不是营火 → 提示需要营火 + 通过 FeatureDispatcher.startTimerFor 按方块名 O(1) 路由到 BarbecueTimerService, + 由它的 startTimer 统一做营火判定 + 提示 + 写计时数据。 """ - return FeatureDispatcher.startTimerFor(blockName, dim, pos, playerId) + FeatureDispatcher.startTimerFor(blockName, dim, pos, playerId) # ============================================================================ # 四、切换型规则处理 @@ -178,9 +189,8 @@ class BarbecueService(BlueFoxServerSystem): 正向(item 不为 None):点火/上杆 → 消耗 → 替换 → 给奖励 逆向(item 为 None) :烤串2次/取下 → 掉落 → 替换 - 注意:上杆/点火后【不自动启动烤制】。 - 烧烤计时规则 autoStart=False,必须玩家右键"计时源方块"才激活烤制 - (见 handleBlockUse → forwardStartTimer)。 + 注意:上杆/放置成"计时源方块"(烤鸡/烤乳猪/烤鱼 生态)后会自动调用 + autoStartRoast 检测下方营火并启动烤制(无需右键,见下方正向分支)。 """ # ---- 正向操作 ---- if recipe.get("item") is not None: @@ -200,6 +210,13 @@ class BarbecueService(BlueFoxServerSystem): if recipe.get("tip"): comp.CreateMsg(playerId).NotifyOneMessage(playerId, recipe["tip"]) + # 【自动烤制】:若上杆/放置成的方块是计时源(烤乳猪生态/烤鸡/烤鱼), + # 立即判定下方是否营火:是→开始计时;否→提示需要营火。 + # (不再需要玩家右键启动,避免与"放方块"互斥。) + target = recipe.get("target") + if target and target in self.timerSourceSet: + self.autoStartRoast(target, dim, pos, playerId) + return # ---- 逆向操作 ---- diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueTimerService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueTimerService.py index 223c137..8d0a63c 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueTimerService.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueTimerService.py @@ -9,14 +9,17 @@ 【与右键转换解耦】 同分类的"右键切换"(烧烤架点火/灭火、烤串翻烤、上杆、取下)在 BarbecueService。 本类只负责计时,两者通过 FeatureDispatcher 协作: - - BarbecueService 右键"计时源方块"(如烤鸡(生))→ 调 FeatureDispatcher.startTimerFor - 转发到本类的 startTimer 启动烤制(下方篝火检查也在这里做) + - BarbecueService 上杆/放置成"计时源方块"→ 调 autoStartRoast → + FeatureDispatcher.startTimerFor 转发到本类的 startTimer 启动烤制 + (下方篝火检查 + 提示也在这里做) + - 计时源方块的 tick 也会自动检测下方营火并补写计时(先放生态再放营火也成立) - 服务器 tick(ServerBlockEntityTickEvent)由 FeatureDispatcher 按 timerOwner 路由到本类的 handleBlockEntityTick,到点即烤熟 【烤制规则】 - - autoStart=False:上杆/放置后【不会】自动开始烤制,必须右键激活(startTimer) + - autoStart=True:放置/上杆后,只要下方是营火就【自动】开始烤制(无需右键启动) - 启动前检查下方是否为篝火(minecraft:campfire),不是则拒绝并提示 + - tick 也会自动检测:即使玩家先放"生态"再放营火,下方出现营火后下一 tick 自动补写计时 - 烤制中若下方篝火被拿走 → 暂停(到点时不转换);篝火放回后继续 - 完成后清除计时数据,并给"启动烤制的玩家"发送"烤熟了"提示 @@ -63,6 +66,8 @@ from ..BarbecueData import BARBECUE_SWITCHES # ---- 统一分发器(本类把自己注册进计时路由表,让分发器把 tick 事件转发过来) ---- from ...service.FeatureDispatcher import FeatureDispatcher +gameComp = comp.CreateGame(LevelId) # 便捷取游戏组件(延时写 owner 用) + class BarbecueTimerService(BlueFoxServerSystem): """ @@ -116,7 +121,9 @@ class BarbecueTimerService(BlueFoxServerSystem): def startTimer(self, dim, pos, blockName, playerId=None): """ 启动烤制计时:先检查下方篝火,通过后写 开始时间戳+时长 到方块实体数据。 - - 启动前检查:下方不是篝火 → 拒绝并提示(烧烤必须右键激活,不会自动烤) + - 由 BarbecueService 上杆/放置计时源方块时调用(autoStartRoast), + 也用于其他计时源主动启动。 + - 启动前检查:下方不是篝火 → 拒绝并提示"支杆下方需要放一个篝火(营火)" - 已在本规则计时中的方块不会重复重置时间(保持原剩余时间) 返回 True=找到规则并处理(含已计时中/篝火检查失败);False=不属于本计时功能 """ @@ -124,6 +131,11 @@ class BarbecueTimerService(BlueFoxServerSystem): if not recipe: return False + # 先记录"放置者"(rtdd_tp),即使下方还没营火也记 —— 这样等营火放上去后 + # tick 自动补写开始计时时,能拿到这位玩家并发"开始烤制"提示。 + if playerId: + self._recordOwner(dim, pos, playerId) + # 启动前检查下方篝火(烧烤必须下方是篝火才能开始烤制) if not self.checkBelow(recipe, dim, pos): if playerId: @@ -151,8 +163,8 @@ class BarbecueTimerService(BlueFoxServerSystem): """ tick 主逻辑: 1) 按事件自带的当前方块名判断是否计时源(创造直接放置也会进来) - 2) 是计时源但没有计时数据 → 只有 autoStart=True 才自动补写。 - 烧烤 autoStart=False:上杆后不会自动烤,必须右键激活,这里不补写 + 2) 是计时源但没有计时数据 → autoStart=True 时自动补写开始计时, + 前提是下方是营火(玩家先放生态再放营火,下方出现营火后下一 tick 自动开始烤制) 3) 有计时数据 → 到点执行转换(重启后时间戳照常生效) 方块被拆掉后 tick 停止、数据随方块消失,不会在原位置继续计时转换。 注意:GetBlockEntityData 返回的对象不支持 .get(),这里统一用 [] 读取。 @@ -172,9 +184,20 @@ class BarbecueTimerService(BlueFoxServerSystem): except Exception: tid = "" if tid != blockName: - # 烧烤必须右键激活烤制:autoStart=False 时不自动补写计时 - if recipe.get("autoStart", True): - self._writeTimerData(dim, pos, recipe, None) + # 无计时数据(刚上杆/刚放置生态/刚被清过计时)。 + # 烧烤自动烤制:只要下方是营火就自动补写开始计时 —— 这样玩家无论 + # 先放烤乳猪还是先放营火,只要下方出现营火就会自动开始烤制, + # 彻底免去手动右键启动。 + if recipe.get("autoStart", True) and self.checkBelow(recipe, dim, pos): + owner = "" + try: + owner = blockData["rtdd_tp"] or "" + except Exception: + owner = "" + self._writeTimerData(dim, pos, recipe, owner if owner else None) + # 只发序号给记录到的放置者(rtdd_tp),绝不群发 + if owner and recipe.get("startTip"): + self._notifyIfOnline(owner, recipe["startTip"]) return tstart = blockData["rtdd_tstart"] @@ -264,6 +287,20 @@ class BarbecueTimerService(BlueFoxServerSystem): except Exception: pass + def _recordOwner(self, dim, pos, playerId): + """记录"放置者"到方块实体数据 rtdd_tp。 + 放置时方块实体数据可能刚建好,延时 0.1 秒再写入(足够比 tick 首批补写快), + 这样之后 tick 自动补写开始计时时能取到 owner 并发提示。""" + gameComp.AddTimer(0.1, self._recordOwnerDelayed, dim, pos, playerId) + + def _recordOwnerDelayed(self, dim, pos, playerId): + try: + blockData = blockEntityDataComp.GetBlockEntityData(dim, pos) + if blockData is not None: + blockData["rtdd_tp"] = playerId + except Exception: + pass + # ============================================================================ # 六、工具方法:完成提示 # ============================================================================