diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/System/Client/MainClient.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/System/Client/MainClient.py index e4dcd47..27533f9 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/System/Client/MainClient.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/System/Client/MainClient.py @@ -1,10 +1,23 @@ # coding=utf-8 +import time from ...BlueFoxTools.ModConfig import MOD_NAME from ...BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxClientSystem from ...BlueFoxTools.SystemTools import SystemTools from ...BlueFoxTools.ToolsConfig import * from ...BlueFoxTools.EventFilter import BlueFoxFilterEnum as ef +# ---- 循环火焰音效(任务六) ---- +# 点燃的壁炉/炉灶/烧烤架/烤炉 在客户端常驻循环播放 fire.fire: +# 开播 -> ModBlockEntityTickClientEvent(方块实体 client_tick) 首次收到该方块时 +# 续期 -> 之后每次 tick 刷新时间戳 +# 停止 -> 超过 FIRE_TICK_TIMEOUT 秒没收到 tick(方块被破坏/替换/区块卸载)由清理定时器停掉 +FIRE_LOOP_BLOCKS = ("rtdd:b_90", "rtdd:stove_2", "rtdd:barbecuegrill_1", "rtdd:oven") +FIRE_SOUND_NAME = "fire.fire" +FIRE_SOUND_VOLUME = 0.7 # 音量(多火源同时燃时避免太吵) +FIRE_TICK_INTERVAL = 0.4 # 同一方块最快每 0.4 秒刷新一次时间戳(避免每 tick 都写数据) +FIRE_TICK_TIMEOUT = 1.5 # 超过该秒数未收到 tick 即判定方块已不在 +FIRE_SWEEP_INTERVAL = 1.0 # 清理定时器周期(秒) + class MainClient(BlueFoxClientSystem): systemTools = SystemTools.GetTools('MainClient') @@ -19,6 +32,9 @@ class MainClient(BlueFoxClientSystem): super(MainClient, self).__init__(*args) self.systemTools.Binding(self) self.usingCd = False + # 循环火焰音效记录: {(dim, x, y, z): {"id": musicId, "time": 最近一次tick时间}} + self.fireLoops = {} + self.fireSweeping = False @blueFoxListener def PlaySound(self, args): @@ -29,6 +45,66 @@ class MainClient(BlueFoxClientSystem): args['soundName'], posDim[:3], pitch=pitch ) + # ======================================================================== + # 循环火焰音效(任务六) + # ======================================================================== + + @mcListener + def ModBlockEntityTickClientEvent(self, args): + """点燃方块(壁炉/炉灶/烧烤架/烤炉)的方块实体每 tick 触发。 + + 首次收到 -> 在该方块位置开启循环播放 fire.fire 并记下 musicId; + 之后每次 tick 刷新时间戳, 由 _sweepFireLoops 把超时(方块被破坏/ + 被替换/走远卸载)的音效停掉。 + """ + if args.get("blockName") not in FIRE_LOOP_BLOCKS: + return + key = (args.get("dimensionId"), args.get("posX"), args.get("posY"), args.get("posZ")) + now = time.time() + rec = self.fireLoops.get(key) + if rec is None: + self._startFireLoop(key, now) + elif now - rec["time"] >= FIRE_TICK_INTERVAL: + rec["time"] = now + + def _startFireLoop(self, key, now): + """在指定方块位置开启循环火焰音效, 并确保清理定时器已启动""" + dim, x, y, z = key + musicId = clientCompFactory.CreateCustomAudio(LevelId).PlayCustomMusic( + FIRE_SOUND_NAME, (x + 0.5, y + 0.5, z + 0.5), + volume=FIRE_SOUND_VOLUME, pitch=1.0, loop=True + ) + if not musicId: + return + self.fireLoops[key] = {"id": musicId, "time": now} + self._ensureFireSweeper() + + def _ensureFireSweeper(self): + """启动音效清理定时器(首个音效开启时启动, 队列清空后自动停)""" + if self.fireSweeping: + return + self.fireSweeping = True + self._addFireSweepTimer() + + def _addFireSweepTimer(self): + """挂一次清理定时器(客户端 AddTimer 递归实现轮询)""" + clientCompFactory.CreateGame(LevelId).AddTimer(FIRE_SWEEP_INTERVAL, self._sweepFireLoops) + + def _sweepFireLoops(self): + """清理超时未收到 tick 的音效(方块已破坏/被替换/区块卸载)""" + now = time.time() + audioComp = clientCompFactory.CreateCustomAudio(LevelId) + for key in list(self.fireLoops.keys()): + rec = self.fireLoops[key] + if now - rec["time"] <= FIRE_TICK_TIMEOUT: + continue + audioComp.StopCustomMusicById(rec["id"], 0.5) + del self.fireLoops[key] + if self.fireLoops: + self._addFireSweepTimer() + else: + self.fireSweeping = False + @blockUseListener(ef.ClientEvent.NormalEvent.NotInCd('rtdd:ItemUseOnEvent', 0.2)) def ClientItemUseOnEventNotInCd02(self, args): if args['itemName'] == 'rtdd:recipe_book': diff --git a/behavior_pack_v8jz0zSR/netease_blocks/b_90.json b/behavior_pack_v8jz0zSR/netease_blocks/b_90.json index 6f7be18..5276e2c 100644 --- a/behavior_pack_v8jz0zSR/netease_blocks/b_90.json +++ b/behavior_pack_v8jz0zSR/netease_blocks/b_90.json @@ -49,7 +49,7 @@ "type": "direction" }, "netease:block_entity": { - "client_tick": false, + "client_tick": true, "movable": false, "tick": false } diff --git a/behavior_pack_v8jz0zSR/netease_blocks/barbecuegrill_1.json b/behavior_pack_v8jz0zSR/netease_blocks/barbecuegrill_1.json index 64fbc5c..152041e 100644 --- a/behavior_pack_v8jz0zSR/netease_blocks/barbecuegrill_1.json +++ b/behavior_pack_v8jz0zSR/netease_blocks/barbecuegrill_1.json @@ -49,7 +49,7 @@ "type": "direction" }, "netease:block_entity": { - "client_tick": false, + "client_tick": true, "movable": false, "tick": false } diff --git a/behavior_pack_v8jz0zSR/netease_blocks/oven.json b/behavior_pack_v8jz0zSR/netease_blocks/oven.json index c13088e..9fc4a9d 100644 --- a/behavior_pack_v8jz0zSR/netease_blocks/oven.json +++ b/behavior_pack_v8jz0zSR/netease_blocks/oven.json @@ -50,7 +50,7 @@ "type": "direction" }, "netease:block_entity": { - "client_tick": false, + "client_tick": true, "movable": false, "tick": false } diff --git a/behavior_pack_v8jz0zSR/netease_blocks/stove_2.json b/behavior_pack_v8jz0zSR/netease_blocks/stove_2.json index 0d92b48..b48eb09 100644 --- a/behavior_pack_v8jz0zSR/netease_blocks/stove_2.json +++ b/behavior_pack_v8jz0zSR/netease_blocks/stove_2.json @@ -49,7 +49,7 @@ "type": "direction" }, "netease:block_entity": { - "client_tick": false, + "client_tick": true, "movable": false, "tick": false }