diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py index a140cd3..6796f12 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py @@ -12,7 +12,6 @@ from xiangyemod.shichangmaoyi.service.MarketService import MarketService from xiangyemod.yuanbanfangzhi.service.YuanbanService import YuanbanService from xiangyemod.jiaju.service.FurnitureService import FurnitureService from xiangyemod.yinliao.service.YinliaoService import YinliaoService -from xiangyemod.yinliao.service.YinliaoTimerService import YinliaoTimerService from xiangyemod.chuju.service.ChujuService import ChujuService from xiangyemod.chuju.service.ChujuTimerService import ChujuTimerService from xiangyemod.ziran.service.NaturalService import NaturalService diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py index d220cdf..5663490 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py @@ -195,11 +195,10 @@ class FeatureDispatcher(BlueFoxServerSystem): def startTimerFor(cls, blockName, dim, pos, playerId=None): """ 右键服务调用:把"计时源方块"的计时启动任务转发给对应的计时服务。 - - 例如:烧烤右键"烤鸡(生)"开始烤制;动物装满饲料盆后自动开始变空计时; - 饮料冰棍盒手持冰块右键未定型启动定型计时 + - 例如:烧烤右键"烤鸡(生)"开始烤制;动物装满饲料盆后自动开始变空计时 - 内部通过 timerOwner 路由表 O(1) 找到计时服务,调它的 startTimer, 并返回计时服务的实际返回值: - True = 本次真正启动了计时(如饮料冰棍盒据此消耗冰块) + True = 本次真正启动了计时 False = 没有计时服务 / 该方块已在计时中(不重复启动) """ service = cls.timerOwner.get(blockName) diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/YinliaoData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/YinliaoData.py index 29b2ad0..b942e05 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/YinliaoData.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/YinliaoData.py @@ -4,7 +4,7 @@ 乡野饮料(xy_drink)转化规则数据 ================================================================================ 所有"乡野饮料"(xy_drink) 分类下的转化规则常量都在这里。 -只被 YinliaoService / YinliaoTimerService 读取,FeatureDispatcher 通过方块名/物品名 +只被 YinliaoService 读取,FeatureDispatcher 通过方块名/物品名 集合路由到对应服务,不会去查其他功能的数据库。 【三大分组】 @@ -12,7 +12,7 @@ 果汁由第一步放入的水果决定并【持久化到方块实体数据】, 退出游戏重进后 榨汁完成仍取回正确果汁(详见 YinliaoService._readFruit / _writeFruit)。 2) 冰棍(冰棍盒 icelollybox_1/2 + 各水果盒 icelollyboxb~f) - 未定型 → (手持冰块右键启动) 计时30秒 → 定型 → (手持水果x2) → 各水果盒 + 未定型 → (手持冰块右键) 立即定型 → (手持水果x2) → 各水果盒 → (空手右键) 取出2根冰棍, 还原未定型。 冰棍堆 popsiclepile_2/3: 组合式(苹果冰棍+堆 → 堆2, 空手取回 LIFO)。 3) 冰棍盒·炒冰盒(frytheicebox / frytheicebox_1 + 各水果炒冰盒) @@ -86,13 +86,11 @@ for _it in [GLASS_CUP] + list(JUICE_FRUITS.keys()): # ============================================================================ # 三、冰棍盒(冰棍) # ============================================================================ -# 冰棍盒(未定型) icelollybox_1 → 冰棍盒(定型) icelollybox_2 的计时规则: -# 手持冰块右键启动(消耗1个冰块), 约30秒定型; autoStart=False 不自动开始 -ICE_LOLLY_TIMER = { +# 冰棍盒(未定型) icelollybox_1 → 冰棍盒(定型) icelollybox_2 的直接转换规则: +# 手持冰块(广义的冰)右键未定型, 消耗1个冰块, 立即定型(不计时, 与炒冰盒放冰同机制) +ICE_LOLLY_FREEZE = { "source": "rtdd:icelollybox_1", "target": "rtdd:icelollybox_2", - "time": 30, - "autoStart": False, } # 水果物品名 → (各水果冰棍盒, 冰棍方块, 口味名) diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/client/YinliaoClient.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/client/YinliaoClient.py index c1ce936..f486c09 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/client/YinliaoClient.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/client/YinliaoClient.py @@ -2,9 +2,9 @@ """ 乡野饮料客户端(预留) ===================== -目前乡野饮料功能的服务端逻辑已由 YinliaoService + YinliaoTimerService 处理, +目前乡野饮料功能的服务端逻辑已由 YinliaoService 处理, 客户端暂不需要额外的 UI 工作。 -如果以后需要榨汁进度提示、冰棍定型倒计时等 UI,可以在这里扩展。 +如果以后需要榨汁进度提示等 UI,可以在这里扩展。 """ import mod.client.extraClientApi as clientApi diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/service/YinliaoService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/service/YinliaoService.py index 0a8b2e2..4324a4b 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/service/YinliaoService.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/service/YinliaoService.py @@ -12,7 +12,7 @@ 换态(SetBlockNew 会清空方块实体)都【先读旧→替换→写回新】, 因此玩家 在 榨汁2→榨汁3 过程中退出游戏, 重进后取出的果汁仍是第一步放入的水果。 2) 冰棍盒(冰棍): - 未定型(icelollybox_1) + 冰块 → 启动30秒定型计时(转发给计时服务, 消耗1冰) + 未定型(icelollybox_1) + 冰块 → 立即定型(消耗1冰, 与炒冰盒放冰同机制) 定型(icelollybox_2) + 水果x2 → 各水果冰棍盒(icelollyboxb~f) 各水果冰棍盒 空手右键 → 取出2根冰棍, 还原未定型 3) 炒冰盒(冰棍盒·炒冰盒): @@ -26,11 +26,6 @@ 空手右键: 冰棍堆2 取出 苹果冰棍 → 退回 冰棍堆; 冰棍堆 取出 西瓜冰棍 → 变回 单根橙子冰棍 -【与计时转换解耦】 - 冰棍盒"未定型→定型"的 30 秒计时拆到独立类 YinliaoTimerService。 - 本类右键到计时源方块(icelollybox_1 + 冰块)时, 调 FeatureDispatcher.startTimerFor - 转发给计时服务启动(冰块消耗由本类处理)。 - 【事件监听在哪?】 本类【不】监听任何事件! 所有事件由 FeatureDispatcher 统一监听, 按 blockOwner 路由到本类 handleBlockUse。 @@ -39,7 +34,7 @@ handleBlockUse ← 入口:分发器转发右键方块事件 ├─ _handleJuicer ← 榨汁机: 放入水果/逐级榨汁/手持玻璃杯取出果汁 │ ├─ _readFruit / _writeFruit ← 水果类型 读/写(持久化) - ├─ _handleLollyBox ← 冰棍盒: 加冰块(启动计时)/加水果/取冰棍 + ├─ _handleLollyBox ← 冰棍盒: 加冰块(立即定型)/加水果/取冰棍 ├─ _handleFryIceBox ← 炒冰盒: 加冰块/加水果/取冰沙 └─ _handlePopsiclePile ← 冰棍堆: 单根+另一根叠堆/插苹果冰棍/空手取回 (通用工具) getCarriedItem / consumeItem / replaceBlock / dropItems / checkCooldown @@ -65,7 +60,7 @@ gameComp = comp.CreateGame(LevelId) from ..YinliaoData import ( ICE_ITEMS, JUICE_FRUITS, JUICER_CHAIN, JUICER_ADVANCE_TIPS, - ICE_LOLLY_TIMER, POPSICLE_FRUITS, POPSICLE_BOX_INFO, + ICE_LOLLY_FREEZE, POPSICLE_FRUITS, POPSICLE_BOX_INFO, POPSICLE_SINGLE_ORANGE, POPSICLE_SINGLE_MELON, POPSICLE_PILE_ADD, POPSICLE_PILE_2, POPSICLE_PILE_3, FRYICE_FRUITS, FRYICE_BOX_INFO, @@ -211,21 +206,18 @@ class YinliaoService(BlueFoxServerSystem): return False # ============================================================================ - # 三、冰棍盒(加冰块启动定型计时 / 加水果 / 取冰棍) + # 三、冰棍盒(加冰块定型 / 加水果 / 取冰棍) # ============================================================================ def _handleLollyBox(self, blockName, playerId, pos, dim, itemDict, itemName, key): - # ---- 未定型 + 冰块 → 启动30秒定型计时(消耗1块冰) ---- - if blockName == "rtdd:icelollybox_1": + # ---- 未定型 + 冰块 → 立即定型(消耗1块冰, 与炒冰盒放冰同机制) ---- + if blockName == ICE_LOLLY_FREEZE["source"]: if itemName not in ICE_ITEMS: return False if not self.checkCooldown(key, 0.5): return True - # 转发给计时服务: True=本次启动, False=已在定型中(不重复消耗冰块) - started = FeatureDispatcher.startTimerFor(blockName, dim, pos, playerId) - if not started: - return True # 已在定型中, 拦截但不消耗 self.consumeItem(playerId, itemDict, 1) + self.replaceBlock(pos, dim, ICE_LOLLY_FREEZE["target"], playerId) return True # ---- 定型 + 水果x2 → 各水果冰棍盒 ---- diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/service/YinliaoTimerService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/service/YinliaoTimerService.py deleted file mode 100644 index 89aa5e7..0000000 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yinliao/service/YinliaoTimerService.py +++ /dev/null @@ -1,232 +0,0 @@ -# -*- coding: utf-8 -*- -""" -================================================================================ -乡野饮料·计时转换引擎(服务端) -================================================================================ -只处理"乡野饮料"(xy_drink) 分类下的【计时自动转换】: - 冰棍盒(未定型 icelollybox_1) → 冰棍盒(定型 icelollybox_2) 约30秒 - -【与右键转换解耦】 - 同分类的"右键切换"(榨汁/冰棍盒加水果/炒冰盒/冰棍堆)在 YinliaoService。 - 本类只负责计时,两者通过 FeatureDispatcher 协作: - - YinliaoService 手持冰块右键 未定型 → 调 FeatureDispatcher.startTimerFor - 转发到本类的 startTimer 启动定型计时(冰块消耗由右键服务处理) - - 服务器 tick(ServerBlockEntityTickEvent)由 FeatureDispatcher 按 timerOwner - 路由到本类的 handleBlockEntityTick,到点即转换为 定型 - -【计时怎么做到"退出游戏继续计时"】 - 不做倒计时,只记"开始时刻": - - 启动时把 开始时间戳(rtdd_tstart)+总时长(rtdd_tdur) 写进方块实体数据 - - 每帧 tick 判断 当前时间-开始时刻 >= 总时长 → 到点转换 - - 时间戳是绝对时间(time.time()),服务器重启/玩家离线,真实时间仍在流逝, - 回来后 tick 直接算差值,剩余时间自然准确 - -【事件监听在哪?】 - 本类【不】监听任何事件! - ServerBlockEntityTickEvent 由 FeatureDispatcher 统一监听,再按 timerOwner - 路由到本类的 handleBlockEntityTick。 - -【本类怎么做(自上而下的方法系列)】 - handleBlockEntityTick ← 入口:分发器转发 tick 事件 - └─ _tickProcess ← 判断是否到点 / autoStart=False 不自动补写 - └─ _finishTimer ← 到点执行转换 + 完成提示 - startTimer ← 入口:YinliaoService 转发过来启动定型 - └─ _writeTimerData ← 写 开始时刻+时长+启动者 到方块实体 - _clearTimerData ← 清理方块上的计时数据 -================================================================================ -""" -import time -import mod.server.extraServerApi as serverApi - -# ---- 网易API基础对象 ---- -ServerSystem = serverApi.GetServerSystemCls() # 服务端系统基类 -comp = serverApi.GetEngineCompFactory() # 组件工厂 - -# ---- 继承 BlueFox 框架的系统基类 ---- -from ....BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxServerSystem -from ....BlueFoxTools.ToolsConfig import LevelId - -# ---- 方块实体数据组件(计时持久化:把开始时间戳+时长写进方块,重启后继续计时) ---- -blockEntityDataComp = comp.CreateBlockEntityData(LevelId) - -# ---- 只导入乡野饮料自己的数据库 ---- -from ..YinliaoData import ICE_LOLLY_TIMER - -# ---- 统一分发器(本类把自己注册进计时路由表,让分发器把 tick 事件转发过来) ---- -from ...service.FeatureDispatcher import FeatureDispatcher - - -class YinliaoTimerService(BlueFoxServerSystem): - """ - 乡野饮料·计时转换引擎 - - 【核心数据结构】 - iceLollyTimers = {计时源方块名: 规则dict} # 目前只有 冰棍盒未定型 - """ - - def __init__(self, namespace, systemName): - super(YinliaoTimerService, self).__init__(namespace, systemName) - print "===== YinliaoTimerService init =====" - - # ---- 收集计时型规则(source → 规则) ---- - self.iceLollyTimers = {ICE_LOLLY_TIMER["source"]: ICE_LOLLY_TIMER} - - # ---- 注册到分发器的计时路由表(tick 事件按方块名路由到这里) ---- - FeatureDispatcher.registerTimer(self) - - # ============================================================================ - # 一、给 FeatureDispatcher 的接口 - # ============================================================================ - - def getTimerBlocks(self): - """返回本功能的所有"计时源方块"集合(tick 路由用)""" - return set(self.iceLollyTimers.keys()) - - def handleBlockEntityTick(self, args): - """由 FeatureDispatcher 转发的计时方块 tick 入口""" - dim = args.get("dimension") - pos = (args.get("posX"), args.get("posY"), args.get("posZ")) - blockName = args.get("blockName", "") - self._tickProcess(dim, pos, blockName) - - # ============================================================================ - # 二、定型计时启动(YinliaoService 手持冰块右键未定型后转发调用) - # ============================================================================ - - def startTimer(self, dim, pos, blockName, playerId=None): - """ - 启动定型计时:把 开始时间戳+时长 写入方块实体数据。 - 返回 True = 本次真正启动(右键服务据此消耗冰块) - 返回 False = 已在定型中 / 无规则(不重复消耗) - """ - recipe = self.iceLollyTimers.get(blockName) - if not recipe: - return False - # 去重:如果该方块已经在本规则计时中,不重置(保持原剩余时间) - try: - data = blockEntityDataComp.GetBlockEntityData(dim, pos) - if data and data["rtdd_tid"] == blockName: - return False - except Exception: - pass - self._writeTimerData(dim, pos, recipe, playerId) - return True - - # ============================================================================ - # 三、tick 检查与到点转换 - # ============================================================================ - - def _tickProcess(self, dim, pos, blockName): - """ - tick 主逻辑: - 1) 按事件自带的当前方块名判断是否计时源 - 2) 是计时源但没有计时数据 → 只有 autoStart=True 才自动补写。 - 冰棍盒定型 autoStart=False:必须右键(放冰块)激活, 这里不补写 - 3) 有计时数据 → 到点执行转换(重启后时间戳照常生效) - 注意:GetBlockEntityData 返回的对象不支持 .get(),统一用 [] 读取。 - """ - try: - recipe = self.iceLollyTimers.get(blockName) - if not recipe: - return # 当前方块不是计时源 - - blockData = blockEntityDataComp.GetBlockEntityData(dim, pos) - if blockData is None: - return - - try: - tid = blockData["rtdd_tid"] - except Exception: - tid = "" - if tid != blockName: - # 冰棍盒必须右键(放冰块)激活定型: autoStart=False 时不自动补写计时 - if recipe.get("autoStart", True): - self._writeTimerData(dim, pos, recipe, None) - return - - tstart = blockData["rtdd_tstart"] - tdur = blockData["rtdd_tdur"] - - if time.time() - tstart >= tdur: - self._finishTimer(dim, pos, recipe, blockData) - except Exception: - pass - - def _finishTimer(self, dim, pos, recipe, data): - """计时到点:确认方块仍是计时源,才执行转换并清除计时数据""" - try: - cur = comp.CreateBlockInfo(LevelId).GetBlockNew(pos, dim) - if cur and cur.get("name") != recipe["source"]: - # 方块已被玩家改变 → 清掉过期计时 - self._clearTimerData(dim, pos) - return - # 替换方块为定型 - self.replaceBlock(pos, dim, recipe["target"], None) - self._clearTimerData(dim, pos) - except Exception: - pass - - # ============================================================================ - # 四、计时数据读写(存在方块实体数据里,重启不丢) - # ============================================================================ - - def _writeTimerData(self, dim, pos, recipe, playerId=None): - """把 计时标识+开始时刻+时长+启动者 写进方块实体数据""" - try: - blockData = blockEntityDataComp.GetBlockEntityData(dim, pos) - if blockData is None: - return - now = time.time() - blockData["rtdd_tid"] = recipe["source"] - blockData["rtdd_tstart"] = now - blockData["rtdd_tdur"] = recipe.get("time", 60) - blockData["rtdd_tp"] = playerId if playerId else "" - except Exception: - pass - - def _clearTimerData(self, dim, pos): - """清除方块上的计时数据""" - try: - blockData = blockEntityDataComp.GetBlockEntityData(dim, pos) - if blockData is None: - return - blockData["rtdd_tid"] = "" - blockData["rtdd_tstart"] = 0 - blockData["rtdd_tdur"] = 0 - blockData["rtdd_tp"] = "" - except Exception: - pass - - # ============================================================================ - # 五、工具方法:完成提示 - # ============================================================================ - - def _notifyIfOnline(self, playerId, tip): - """若启动者在线,发送完成提示(离线则跳过)""" - if not tip or not playerId: - return - try: - ids = comp.CreateGame(LevelId).GetAllPlayerIds() - if playerId in ids: - comp.CreateMsg(playerId).NotifyOneMessage(playerId, tip) - except Exception: - pass - - # ============================================================================ - # 六、工具方法:替换方块 - # ============================================================================ - - def replaceBlock(self, pos, dim, newBlockName, playerId=None): - """替换指定位置的方块(计时回调时没有玩家, 用 LevelId 创建组件)""" - creator = playerId if playerId is not None else LevelId - aux = 0 - try: - oldBlock = comp.CreateBlockInfo(creator).GetBlockNew(pos, dim) - aux = oldBlock.get("aux", 0) - except Exception: - aux = 0 - comp.CreateBlockInfo(creator).SetBlockNew( - pos, - blockDict={"name": newBlockName, "aux": aux}, - oldBlockHandling=0, - dimensionId=dim) diff --git a/behavior_pack_v8jz0zSR/netease_blocks/icelollybox_1.json b/behavior_pack_v8jz0zSR/netease_blocks/icelollybox_1.json index 7dd5f9e..cabaeb7 100644 --- a/behavior_pack_v8jz0zSR/netease_blocks/icelollybox_1.json +++ b/behavior_pack_v8jz0zSR/netease_blocks/icelollybox_1.json @@ -48,7 +48,7 @@ "netease:block_entity": { "client_tick": false, "movable": false, - "tick": true + "tick": false } } } diff --git a/resource_pack_Are13Lvd/texts/zh_CN.lang b/resource_pack_Are13Lvd/texts/zh_CN.lang index ad45c97..a659284 100644 --- a/resource_pack_Are13Lvd/texts/zh_CN.lang +++ b/resource_pack_Are13Lvd/texts/zh_CN.lang @@ -744,7 +744,7 @@ tile.rtdd:cookingscallions.name=炒锅_51(葱花锅底) tile.rtdd:codsushi_6.name=鳕鱼寿司块(三个) tile.rtdd:codsushi_4.name=鳕鱼寿司(卷_3) tile.rtdd:codsushi_5.name=鳕鱼寿司(卷_4) -tile.rtdd:barbecuegrill_1.name=烧烤架_2(烧烤架点燃) +tile.rtdd:barbecuegrill_1.name=点燃的烧烤架 tile.rtdd:codsushi_2.name=鳕鱼寿司(卷_1) tile.rtdd:codsushi_3.name=鳕鱼寿司(卷_2) tile.rtdd:fishbucket_1.name=鳕鱼货桶 diff --git a/tuilun/ok/乡野饮料转化关系.txt b/tuilun/ok/乡野饮料转化关系.txt index 83964fc..48fd358 100644 --- a/tuilun/ok/乡野饮料转化关系.txt +++ b/tuilun/ok/乡野饮料转化关系.txt @@ -49,9 +49,9 @@ todo 功能实现的时候需要考虑 玩家退出游戏后 我的步骤已经 ======================================== 二、冰棍(冰棍盒系列) ======================================== -7. 冰棍盒(冰棍未定型) -> 冰棍盒(冰棍定型) +7. 冰棍盒 -> 冰棍盒(冰棍定型) 转换条件:[手持 原版冰块[广义的冰] 右键 进行转换, 消耗1个] -机制: 手持冰块右键冰棍盒(未定型), 消耗1个, 计时约30秒定型 +机制: 手持冰块右键冰棍盒, 消耗1个 8. 冰棍盒(冰棍定型) -> 冰棍盒(苹果/桃子/橙子/葡萄/西瓜冰棍) 转换条件:[手持 对应水果 右键 进行转换, 消耗2个] diff --git a/tuilun/全部功能做了什么.txt b/tuilun/全部功能做了什么.txt index 46b29b1..0ac3dcb 100644 --- a/tuilun/全部功能做了什么.txt +++ b/tuilun/全部功能做了什么.txt @@ -282,7 +282,7 @@ FurnitureData+FurnitureService 实现, 注册到 FeatureDispatcher) ######################################## 【乡野饮料】(xy_drink) 2026-09-04 ######################################## -实现于 xiangyemod/yinliao (YinliaoData + YinliaoService + YinliaoTimerService, 注册到 FeatureDispatcher) +实现于 xiangyemod/yinliao (YinliaoData + YinliaoService, 注册到 FeatureDispatcher) 一、榨汁机 (果汁·榨汁饮品, juicer 系列, 全流程右键) - 空(juicer) + 水果(消耗1) → 放入水果(juicer_0), 并把水果类型写入方块实体数据(rtdd_jf) [已实现] @@ -295,11 +295,10 @@ FurnitureData+FurnitureService 实现, 注册到 FeatureDispatcher) - 黄豆(rtdd:soybean) 物品已从Java版迁入(物品/纹理/名称齐全) [已实现] 二、冰棍盒 (冰棍, icelollybox 系列) -- 未定型(icelollybox_1) + 冰块(消耗1, 原版冰/冰砖/蓝冰/霜冰) → 启动30秒定型计时 - (autoStart=False, 右键激活; 已在定型中不重复消耗) → 定型(icelollybox_2) [已实现] +- 未定型(icelollybox_1) + 冰块(消耗1, 原版冰/冰砖/蓝冰/霜冰) → 立即定型(不计时, 与炒冰盒放冰同机制) + → 定型(icelollybox_2) [已实现] - 定型 + 对应水果(消耗2) → 各口味冰棍盒(icelollyboxb 橙子/c 苹果/d 桃子/e 葡萄/f 西瓜) [已实现] - 各口味冰棍盒 空手右键 → 掉落2根对应冰棍 + 还原未定型 [已实现] -- 定型计时用绝对时间戳写方块实体数据, 退出重进继续计时 [已实现] 三、冰棍堆 (组合, 顺序无关, 空手取回按方块状态固定, 不存数据) - 单根 橙子冰棍/西瓜冰棍 放地上 + 手持另一根右键(消耗1) → 冰棍堆(橙子+西瓜 popsiclepile_2)