From cae9bcb19e8897b5f649324bfee63de710aa2928 Mon Sep 17 00:00:00 2001 From: wenhe <1046926120@qq.com> Date: Thu, 3 Sep 2026 14:09:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B8=82=E5=9C=BA=E8=B4=B8=E6=98=93=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=20bug=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Script_NeteaseModousIY5aSF/modMain.py | 2 + .../xiangyemod/BlockSwitchData.py | 31 +- .../xiangyemod/service/FeatureDispatcher.py | 68 ++- .../xiangyemod/shaokao/BarbecueData.py | 14 +- .../shaokao/service/BarbecueService.py | 75 +-- .../xiangyemod/shichangmaoyi/MarketData.py | 534 ++++++++++++++++++ .../xiangyemod/shichangmaoyi/__init__.py | 0 .../shichangmaoyi/service/MarketService.py | 265 +++++++++ .../shichangmaoyi/service/__init__.py | 0 .../xiangyemod/siwangshengwu/DeadmobData.py | 11 +- .../siwangshengwu/service/DeadmobService.py | 7 +- .../xiangyemod/yuanbanfangzhi/YuanbanData.py | 51 ++ .../xiangyemod/yuanbanfangzhi/__init__.py | 0 .../yuanbanfangzhi/service/YuanbanService.py | 205 +++++++ .../yuanbanfangzhi/service/__init__.py | 0 .../netease_blocks/b_30.json | 2 +- .../netease_blocks/clothbox_1.json | 2 +- .../netease_blocks/clothbox_2.json | 2 +- .../netease_group/market_groups.json | 3 +- resource_pack_Are13Lvd/texts/zh_CN.lang | 6 +- tuilun/ok/市场贸易转化关系.txt | 107 ++++ tuilun/{ => ok}/死亡生物转化关系.txt | 0 tuilun/全部功能做了什么.txt | 39 ++ tuilun/全部功能没做什么.txt | 4 - tuilun/市场贸易转化关系.txt | 59 -- 25 files changed, 1300 insertions(+), 187 deletions(-) create mode 100644 behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/MarketData.py create mode 100644 behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/__init__.py create mode 100644 behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/service/MarketService.py create mode 100644 behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/service/__init__.py create mode 100644 behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/YuanbanData.py create mode 100644 behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/__init__.py create mode 100644 behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/service/YuanbanService.py create mode 100644 behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/service/__init__.py create mode 100644 tuilun/ok/市场贸易转化关系.txt rename tuilun/{ => ok}/死亡生物转化关系.txt (100%) delete mode 100644 tuilun/市场贸易转化关系.txt diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py index ca38526..3fcaa0c 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py @@ -9,6 +9,8 @@ from xiangyemod.shaokao.service.BarbecueTimerService import BarbecueTimerService from xiangyemod.siwangshengwu.service.DeadmobService import DeadmobService from xiangyemod.siwangshengwu.service.DeadmobTimerService import DeadmobTimerService from xiangyemod.shouban.service.ShoubanService import ShoubanService +from xiangyemod.shichangmaoyi.service.MarketService import MarketService +from xiangyemod.yuanbanfangzhi.service.YuanbanService import YuanbanService if not serverApi.IsInServer(): pass diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/BlockSwitchData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/BlockSwitchData.py index 63240da..9cce812 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/BlockSwitchData.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/BlockSwitchData.py @@ -75,35 +75,10 @@ BLOCK_SWITCHES = [ }, - # 三、售卖箱 ↔ 鲑鱼箱 + # 三、售卖盒(鲑鱼) # ============================================================ - # 【放鲑鱼】售卖箱_1 → 鲑鱼箱 - { - "source": "rtdd:clothbox_1", - "item": "minecraft:salmon", - "target": "rtdd:b_30", - "consume": 1, - "type": "switch", - "giveItem": None, - }, - # 【放鲑鱼】售卖箱_2 → 鲑鱼箱 - { - "source": "rtdd:clothbox_2", - "item": "minecraft:salmon", - "target": "rtdd:b_30", - "consume": 1, - "type": "switch", - "giveItem": None, - }, - # 【取回鲑鱼】鲑鱼箱 → 售卖箱_2 - { - "source": "rtdd:b_30", - "item": None, - "target": "rtdd:clothbox_2", - "consume": 0, - "type": "switch", - "giveItem": "minecraft:salmon", - }, + # 旧"售卖箱↔鲑鱼箱"规则已移除: clothbox_1/2 已禁用, b_30(售卖盒(鲑鱼)) + # 归 市场贸易 MarketService 处理(空售卖盒+32条鲑鱼放入 / 空手右键取出)。 # 四、烧烤架 diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py index 503cf8f..90c4d1c 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/FeatureDispatcher.py @@ -64,6 +64,14 @@ class FeatureDispatcher(BlueFoxServerSystem): timerOwner = {} timerSet = set() + # ---- 拆方块掉落映射: 方块名 → 掉落对应的原版生食材 ---- + # 玩家左键破坏这些"放置的半成品/死鱼"方块时, 取消默认掉落, 改为掉对应的原版生食材 + DESTROY_DROP = { + "rtdd:killfish_0": "minecraft:salmon", # 死鲑鱼 → 原版生鲑鱼 + "rtdd:killcod_0": "minecraft:cod", # 死鳕鱼 → 原版生鳕鱼 + "rtdd:roastchickenplace_0": "minecraft:chicken", # 生鸡肉(放置后) → 原版生鸡肉 + } + # ============================================================================ # 注册接口(功能服务在 __init__ 里调用) # ============================================================================ @@ -128,11 +136,12 @@ class FeatureDispatcher(BlueFoxServerSystem): def ListenEvent(self): """ - 注册四个事件: + 注册五个事件: 1. ServerBlockUseEvent —— 玩家右键方块(所有功能的右键转换入口) 2. ServerItemUseOnEvent —— 手持物品右键方块表面(如放置生鸡肉) 3. ServerItemTryUseEvent —— 玩家尝试使用物品(拦截喝药水/吃食物等默认行为) 4. ServerBlockEntityTickEvent —— 计时方块每tick触发(烤制/饲料变空等,持久化计时) + 5. ServerPlayerTryDestroyBlockEvent —— 玩家拆方块(放置的死鱼/生鸡肉掉回原版生食材) """ self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), @@ -146,6 +155,9 @@ class FeatureDispatcher(BlueFoxServerSystem): self.ListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerBlockEntityTickEvent", self, self.OnBlockEntityTick) + self.ListenForEvent(serverApi.GetEngineNamespace(), + serverApi.GetEngineSystemName(), + "ServerPlayerTryDestroyBlockEvent", self, self.OnDestroy) def UnListenEvent(self): self.UnListenForEvent(serverApi.GetEngineNamespace(), @@ -160,6 +172,9 @@ class FeatureDispatcher(BlueFoxServerSystem): self.UnListenForEvent(serverApi.GetEngineNamespace(), serverApi.GetEngineSystemName(), "ServerBlockEntityTickEvent", self, self.OnBlockEntityTick) + self.UnListenForEvent(serverApi.GetEngineNamespace(), + serverApi.GetEngineSystemName(), + "ServerPlayerTryDestroyBlockEvent", self, self.OnDestroy) # ============================================================================ # 主入口1:玩家右键方块 → 按 blockOwner 路由到右键服务 @@ -204,11 +219,22 @@ class FeatureDispatcher(BlueFoxServerSystem): if not service: return + # 被点方块属于某个"右键方块"服务的管辖(条箱/挂肉钩/锅具等) → 该方块右键由 + # ServerBlockUseEvent 处理(放入/挂鱼/做菜), 不执行"手持物品右键表面放置", + # 避免与方块右键逻辑重复(如手持鲑鱼右键条箱应放入而非放置死鲑鱼)。 + playerId = args.get("playerId") or args.get("entityId") + try: + dim = comp.CreateDimension(playerId).GetEntityDimensionId() + b = comp.CreateBlockInfo(LevelId).GetBlockNew( + (args.get("x"), args.get("y"), args.get("z")), dim) + if b and b.get("name") in self.blockOwner: + return + except Exception: + pass + handled = service.handleItemUseOn(args) if handled: args['ret'] = True - # ServerItemUseOnEvent 的玩家键是 entityId,不是 playerId - playerId = args.get("playerId") or args.get("entityId") self._cancelItemUse[playerId] = True # ============================================================================ @@ -253,3 +279,39 @@ class FeatureDispatcher(BlueFoxServerSystem): if not service: return service.handleBlockEntityTick(args) + + # ============================================================================ + # 主入口5:玩家拆方块 → 放置的死鱼/生鸡肉掉回原版生食材 + # ============================================================================ + + def OnDestroy(self, args): + """ + 玩家拆方块时触发。 + 部分"放置的半成品/死鱼"方块被拆掉时, 取消默认掉落(不把方块本身掉出来), + 手动清空方块并掉落对应的原版生食材: + - killfish_0(死鲑鱼) → 原版生鲑鱼 + - killcod_0(死鳕鱼) → 原版生鳕鱼 + - roastchickenplace_0(生鸡肉放置后) → 原版生鸡肉 + """ + blockName = args.get("blockName") + itemName = self.DESTROY_DROP.get(blockName) + if not itemName: + return + playerId = args.get("playerId") + x, y, z = args.get("x"), args.get("y"), args.get("z") + dim = comp.CreateDimension(playerId).GetEntityDimensionId() + # 取消默认破坏(不让方块本身作为掉落物掉出来) + args['cancel'] = True + # 手动清空方块 + try: + comp.CreateBlockInfo(LevelId).SetBlockNew( + (x, y, z), blockDict={"name": "minecraft:air", "aux": 0}, + oldBlockHandling=0, dimensionId=dim) + except Exception: + pass + # 掉落对应的原版生食材 + try: + itemDict = {"itemName": itemName, "count": 1, "auxValue": 0} + self.CreateEngineItemEntity(itemDict, dim, (x, y + 0.5, z)) + except Exception: + pass diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/BarbecueData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/BarbecueData.py index baf1e31..37acec7 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/BarbecueData.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/BarbecueData.py @@ -311,14 +311,6 @@ BARBECUE_SWITCHES = [ # ============================================================ # 六、手持物品右键"方块表面"生成规则(ServerItemUseOnEvent) # ============================================================ -# 目前只有一条:手持"原版生鸡肉"右键任意方块表面 → 在其表面生成 -# "生鸡肉(原版生鸡肉右键放置后)"(roastchickenplace_0) 方块,消耗1个。 -# 该规则由 FeatureDispatcher 转发 ServerItemUseOnEvent 到 BarbecueService。 -ITEM_USE_ON_RULES = [ - { - "item": "minecraft:chicken", # 手持的原版生鸡肉 - "target": "rtdd:roastchickenplace_0", # 生成的目标方块 - "consume": 1, # 消耗1个生鸡肉 - "tip": "§a已放置生鸡肉,可右键支杆上杆烤制", - }, -] +# 原版生鸡肉右键放置"生鸡肉(放置后)"的规则已拆到 +# xiangyemod/yuanbanfangzhi/YuanbanData.py(原版放置统一管理)。 +# 本分类不再定义 ItemUseOn 规则。 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 edc1211..619d54d 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueService.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shaokao/service/BarbecueService.py @@ -17,14 +17,13 @@ 【事件监听在哪?】 本类【不】监听任何事件! 所有事件由 FeatureDispatcher(xiangyemod/service/FeatureDispatcher.py)统一监听: - - ServerBlockUseEvent → OnBlockUse → 按 blockOwner 路由到本类 handleBlockUse - - ServerItemUseOnEvent → OnItemUseOn → 按 itemUseOnOwner 路由到本类 handleItemUseOn + - ServerBlockUseEvent → OnBlockUse → 按 blockOwner 路由到本类 handleBlockUse - ServerBlockEntityTickEvent → OnBlockEntityTick → 按 timerOwner 路由到 BarbecueTimerService 本类只实现被分发器调用的接口方法,不关心事件来源。 + 注: 原版生鸡肉右键放置"生鸡肉(放置后)"已拆到 yuanbanfangzhi/YuanbanService。 【本类怎么做(自上而下的方法系列)】 - handleBlockUse ← 入口1:分发器转发右键方块事件 - handleItemUseOn ← 入口2:分发器转发"手持物品右键方块表面"事件(放置生鸡肉) + handleBlockUse ← 入口:分发器转发右键方块事件 ├─ findRecipe ← 匹配 (方块名, 物品名) 规则 ├─ checkCooldown ← 连点冷却(防刷提示) ├─ forwardStartTimer ← 计时源方块 → 转发给计时服务启动烤制 @@ -48,21 +47,11 @@ from ....BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxServerSystem from ....BlueFoxTools.ToolsConfig import LevelId # ---- 只导入烧烤自己的数据库 ---- -from ..BarbecueData import BARBECUE_SWITCHES, ITEM_USE_ON_RULES +from ..BarbecueData import BARBECUE_SWITCHES # ---- 统一分发器 ---- from ...service.FeatureDispatcher import FeatureDispatcher -# ---- 方块表面方向 → 相邻坐标偏移(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 BarbecueService(BlueFoxServerSystem): """ @@ -71,8 +60,11 @@ class BarbecueService(BlueFoxServerSystem): 【核心数据结构】 barbecueRecipes = {(方块名, 物品名): 规则dict} # O(1) 查找,含 switch+timer 规则 barbecueBlockSet = {方块名, ...} # O(1) 拦截/注册用(所有源方块) - itemUseOnRecipes = {物品名: 规则dict} # 手持物品右键方块表面 → 生成规则 cooldown = {key: 时间戳} # 连点冷却表 + + 【原版放置已拆出】 + 手持原版生鸡肉右键方块表面放置"生鸡肉(放置后)"的 ItemUseOn 逻辑 + 已拆到 xiangyemod/yuanbanfangzhi/YuanbanService。 """ def __init__(self, namespace, systemName): @@ -91,11 +83,6 @@ class BarbecueService(BlueFoxServerSystem): self.barbecueRecipes[key] = sw self.barbecueBlockSet.add(sw["source"]) - # ---- 手持物品右键方块表面规则:物品名 → 规则 ---- - self.itemUseOnRecipes = {} - for rule in ITEM_USE_ON_RULES: - self.itemUseOnRecipes[rule["item"]] = rule - # ---- 右键冷却表 ---- self.cooldown = {} @@ -111,8 +98,8 @@ class BarbecueService(BlueFoxServerSystem): return self.barbecueBlockSet def getItemUseOnRules(self): - """返回手持物品右键方块表面的规则:{物品名: 规则dict}(供分发器路由)""" - return self.itemUseOnRecipes + """返回"手持物品右键方块表面"的规则(原版放置已拆到 yuanbanfangzhi, 返回空)""" + return {} def handleBlockUse(self, args): """ @@ -153,48 +140,6 @@ class BarbecueService(BlueFoxServerSystem): self.handleSwitch(recipe, playerId, pos, dim, itemDict, key) return True - def handleItemUseOn(self, args): - """ - 由 FeatureDispatcher 转发的"手持物品右键方块表面"事件。 - 当前用于:手持原版生鸡肉右键任意方块表面 → 在其表面生成生鸡肉(放置后)方块。 - 返回 True=已处理,False=当前组合无匹配规则。 - """ - itemName = args.get("itemName") - # ServerItemUseOnEvent 的玩家键是 entityId,不是 playerId - playerId = args.get("playerId") or args.get("entityId") - rule = self.itemUseOnRecipes.get(itemName) - if not rule: - return False - - x, y, z = args.get("x"), args.get("y"), args.get("z") - face = args.get("face", 1) - dim = comp.CreateDimension(playerId).GetEntityDimensionId() - - # 计算被点方块表面相邻的目标格 - off = FACE_OFFSET.get(face, (0, 1, 0)) - targetPos = (x + off[0], y + off[1], z + off[2]) - - # 目标格必须为空(可放置) - try: - cur = comp.CreateBlockInfo(LevelId).GetBlockNew(targetPos, dim) - if cur and cur.get("name") != "minecraft:air": - return False - except Exception: - return False - - # 消耗 1 个生鸡肉 - itemDict = self.getCarriedItem(playerId) - if not itemDict: - return False - self.consumeItem(playerId, itemDict, rule.get("consume", 1)) - - # 生成生鸡肉(放置后)方块 - self.replaceBlock(targetPos, dim, rule["target"], playerId) - # 放置成功提示 - if rule.get("tip"): - comp.CreateMsg(playerId).NotifyOneMessage(playerId, rule["tip"]) - return True - # ============================================================================ # 二、规则匹配(O(1) 字典查找) # ============================================================================ diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/MarketData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/MarketData.py new file mode 100644 index 0000000..b547cc3 --- /dev/null +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/MarketData.py @@ -0,0 +1,534 @@ +# -*- coding: utf-8 -*- +""" +================================================================================ +市场贸易分类转换规则数据 +================================================================================ +只处理"市场贸易"(xy_market) 分类下的右键转换: + 1) 条箱/货桶/售卖盒 放入: 手持对应物品右键 空容器 → 消耗物品 → 变为对应容器 + 2) 条箱/货桶/售卖盒 取出: 空手右键 装满容器 → 变回空容器 + 以掉落物形式取回物品 + 3) 悬赏纸循环: 空手右键逐级切换 bountypaper → _1 → _2 → bountypaper +其余摊位设施(b_4/menus/vending_desk)为静态, 无转换。 +布料(clothbox_1/2)已按标注禁用, 不参与本分类转换。 + +【消耗数量】 + 除 南瓜/西瓜 消耗1个原版方块(minecraft:pumpkin / minecraft:melon_block)外, + 其余均消耗32个对应物品; 取出时按放入数量取回(南瓜/西瓜取回1个方块)。 + +字段说明(与 AnimalData/DeadmobData 一致): + source: 被右键的方块ID(必填) + item: 玩家手里必须拿的物品, None=空手 + target: 替换成什么方块 + consume: 消耗物品数量, 0=不消耗 + dropItem: 转换时以掉落物形式生成的物品列表(取出用) + tip: 转换成功提示 +================================================================================ +""" + +MARKET_SWITCHES = [ + + # ============================================================ + # 一、条箱 (woodenbox_0空 → woodenbox_1~7 各装一种) + # ============================================================ + # ---- 放入 (手持物品右键 空条箱) ---- + { + "source": "rtdd:woodenbox_0", + "item": "minecraft:apple", + "target": "rtdd:woodenbox_1", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个苹果", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_0", + "item": "minecraft:carrot", + "target": "rtdd:woodenbox_2", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个胡萝卜", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_0", + "item": "minecraft:potato", + "target": "rtdd:woodenbox_3", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个土豆", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_0", + "item": "rtdd:peach", + "target": "rtdd:woodenbox_4", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个桃子", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_0", + "item": "rtdd:orange", + "target": "rtdd:woodenbox_5", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个橘子", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_0", + "item": "minecraft:cod", + "target": "rtdd:woodenbox_6", + "consume": 32, + "type": "switch", + "tip": "§a已放入32条鳕鱼", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_0", + "item": "minecraft:salmon", + "target": "rtdd:woodenbox_7", + "consume": 32, + "type": "switch", + "tip": "§a已放入32条鲑鱼", + "giveItem": None, + }, + # ---- 取出 (空手右键 装满的条箱) ---- + { + "source": "rtdd:woodenbox_1", + "item": None, + "target": "rtdd:woodenbox_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:apple", "count": 32}], + "tip": "§a取出了32个苹果", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_2", + "item": None, + "target": "rtdd:woodenbox_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:carrot", "count": 32}], + "tip": "§a取出了32个胡萝卜", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_3", + "item": None, + "target": "rtdd:woodenbox_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:potato", "count": 32}], + "tip": "§a取出了32个土豆", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_4", + "item": None, + "target": "rtdd:woodenbox_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "rtdd:peach", "count": 32}], + "tip": "§a取出了32个桃子", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_5", + "item": None, + "target": "rtdd:woodenbox_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "rtdd:orange", "count": 32}], + "tip": "§a取出了32个橘子", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_6", + "item": None, + "target": "rtdd:woodenbox_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:cod", "count": 32}], + "tip": "§a取出了32条鳕鱼", + "giveItem": None, + }, + { + "source": "rtdd:woodenbox_7", + "item": None, + "target": "rtdd:woodenbox_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:salmon", "count": 32}], + "tip": "§a取出了32条鲑鱼", + "giveItem": None, + }, + + # ============================================================ + # 二、货桶 (fishbucket_0空 → 各装一种) + # ============================================================ + # ---- 放入 ---- + { + "source": "rtdd:fishbucket_0", + "item": "minecraft:cod", + "target": "rtdd:fishbucket_1", + "consume": 32, + "type": "switch", + "tip": "§a已放入32条鳕鱼", + "giveItem": None, + }, + { + "source": "rtdd:fishbucket_0", + "item": "minecraft:salmon", + "target": "rtdd:fishbucket_2", + "consume": 32, + "type": "switch", + "tip": "§a已放入32条鲑鱼", + "giveItem": None, + }, + { + "source": "rtdd:fishbucket_0", + "item": "minecraft:carrot", + "target": "rtdd:carrotbarrel", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个胡萝卜", + "giveItem": None, + }, + { + "source": "rtdd:fishbucket_0", + "item": "minecraft:potato", + "target": "rtdd:potatobarrel", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个土豆", + "giveItem": None, + }, + { + "source": "rtdd:fishbucket_0", + "item": "rtdd:peach", + "target": "rtdd:peachbarrel", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个桃子", + "giveItem": None, + }, + { + "source": "rtdd:fishbucket_0", + "item": "rtdd:orange", + "target": "rtdd:orangebarrel", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个橘子", + "giveItem": None, + }, + { + "source": "rtdd:fishbucket_0", + "item": "minecraft:apple", + "target": "rtdd:applebox", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个苹果", + "giveItem": None, + }, + # ---- 取出 ---- + { + "source": "rtdd:fishbucket_1", + "item": None, + "target": "rtdd:fishbucket_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:cod", "count": 32}], + "tip": "§a取出了32条鳕鱼", + "giveItem": None, + }, + { + "source": "rtdd:fishbucket_2", + "item": None, + "target": "rtdd:fishbucket_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:salmon", "count": 32}], + "tip": "§a取出了32条鲑鱼", + "giveItem": None, + }, + { + "source": "rtdd:carrotbarrel", + "item": None, + "target": "rtdd:fishbucket_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:carrot", "count": 32}], + "tip": "§a取出了32个胡萝卜", + "giveItem": None, + }, + { + "source": "rtdd:potatobarrel", + "item": None, + "target": "rtdd:fishbucket_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:potato", "count": 32}], + "tip": "§a取出了32个土豆", + "giveItem": None, + }, + { + "source": "rtdd:peachbarrel", + "item": None, + "target": "rtdd:fishbucket_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "rtdd:peach", "count": 32}], + "tip": "§a取出了32个桃子", + "giveItem": None, + }, + { + "source": "rtdd:orangebarrel", + "item": None, + "target": "rtdd:fishbucket_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "rtdd:orange", "count": 32}], + "tip": "§a取出了32个橘子", + "giveItem": None, + }, + { + "source": "rtdd:applebox", + "item": None, + "target": "rtdd:fishbucket_0", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:apple", "count": 32}], + "tip": "§a取出了32个苹果", + "giveItem": None, + }, + + # ============================================================ + # 三、售卖盒 (sellingboxes空 → 各装一种) + # 南瓜/西瓜消耗1个原版方块, 其余32个 + # ============================================================ + # ---- 放入 ---- + { + "source": "rtdd:sellingboxes", + "item": "rtdd:orange", + "target": "rtdd:orangebox", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个橘子", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "rtdd:peach", + "target": "rtdd:peachbox", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个桃子", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "minecraft:cod", + "target": "rtdd:sales_box_cod", + "consume": 32, + "type": "switch", + "tip": "§a已放入32条鳕鱼", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "minecraft:salmon", + "target": "rtdd:b_30", + "consume": 32, + "type": "switch", + "tip": "§a已放入32条鲑鱼", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "minecraft:carrot", + "target": "rtdd:sales_box_carrot", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个胡萝卜", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "minecraft:bread", + "target": "rtdd:sales_box_bread", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个面包", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "minecraft:apple", + "target": "rtdd:sales_box_apple", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个苹果", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "minecraft:pumpkin", + "target": "rtdd:sales_box_pumpkin", + "consume": 1, + "type": "switch", + "tip": "§a已放入1个原版南瓜", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "minecraft:melon_block", + "target": "rtdd:sales_box_watermelon", + "consume": 1, + "type": "switch", + "tip": "§a已放入1个原版西瓜", + "giveItem": None, + }, + { + "source": "rtdd:sellingboxes", + "item": "minecraft:potato", + "target": "rtdd:sales_box_potato", + "consume": 32, + "type": "switch", + "tip": "§a已放入32个土豆", + "giveItem": None, + }, + # ---- 取出 ---- + { + "source": "rtdd:orangebox", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "rtdd:orange", "count": 32}], + "tip": "§a取出了32个橘子", + "giveItem": None, + }, + { + "source": "rtdd:peachbox", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "rtdd:peach", "count": 32}], + "tip": "§a取出了32个桃子", + "giveItem": None, + }, + { + "source": "rtdd:sales_box_cod", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:cod", "count": 32}], + "tip": "§a取出了32条鳕鱼", + "giveItem": None, + }, + { + "source": "rtdd:b_30", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:salmon", "count": 32}], + "tip": "§a取出了32条鲑鱼", + "giveItem": None, + }, + { + "source": "rtdd:sales_box_carrot", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:carrot", "count": 32}], + "tip": "§a取出了32个胡萝卜", + "giveItem": None, + }, + { + "source": "rtdd:sales_box_bread", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:bread", "count": 32}], + "tip": "§a取出了32个面包", + "giveItem": None, + }, + { + "source": "rtdd:sales_box_apple", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:apple", "count": 32}], + "tip": "§a取出了32个苹果", + "giveItem": None, + }, + { + "source": "rtdd:sales_box_pumpkin", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:pumpkin", "count": 1}], + "tip": "§a取出了1个原版南瓜", + "giveItem": None, + }, + { + "source": "rtdd:sales_box_watermelon", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:melon_block", "count": 1}], + "tip": "§a取出了1个原版西瓜", + "giveItem": None, + }, + { + "source": "rtdd:sales_box_potato", + "item": None, + "target": "rtdd:sellingboxes", + "consume": 0, + "type": "switch", + "dropItem": [{"name": "minecraft:potato", "count": 32}], + "tip": "§a取出了32个土豆", + "giveItem": None, + }, + + # ============================================================ + # 四、悬赏纸循环 (空手右键逐级切换) + # ============================================================ + { + "source": "rtdd:bountypaper", + "item": None, + "target": "rtdd:bountypaper_1", + "consume": 0, + "type": "switch", + "tip": "§a切换到悬赏纸_1", + "giveItem": None, + }, + { + "source": "rtdd:bountypaper_1", + "item": None, + "target": "rtdd:bountypaper_2", + "consume": 0, + "type": "switch", + "tip": "§a切换到悬赏纸_2", + "giveItem": None, + }, + { + "source": "rtdd:bountypaper_2", + "item": None, + "target": "rtdd:bountypaper", + "consume": 0, + "type": "switch", + "tip": "§a切回农贸清单", + "giveItem": None, + }, +] diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/__init__.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/service/MarketService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/service/MarketService.py new file mode 100644 index 0000000..15ff7dd --- /dev/null +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/service/MarketService.py @@ -0,0 +1,265 @@ +# -*- coding: utf-8 -*- +""" +================================================================================ +市场贸易·右键转换引擎(服务端) +================================================================================ +只处理"市场贸易"(xy_market) 分类下的【右键切换型】转换: + 条箱/货桶/售卖盒 放入与取出、悬赏纸循环切换。 +全部为即时右键转换, 无计时, 因此只有一个服务类, 不需要拆分 TimerService。 + +【事件监听在哪?】 + 本类【不】监听任何事件! + 所有事件由 FeatureDispatcher(xiangyemod/service/FeatureDispatcher.py)统一监听: + - ServerBlockUseEvent → OnBlockUse → 按 blockOwner 路由到本类 handleBlockUse + 本类只实现被分发器调用的接口方法, 不关心事件来源。 + +【本类怎么做(自上而下的方法系列)】 + handleBlockUse ← 入口:分发器转发右键方块事件 + ├─ findRecipe ← 匹配 (方块名, 物品名);空手规则需确认真正空手 + ├─ checkCooldown← 连点冷却 + └─ handleSwitch ← 放入(消耗+替换) / 取出(掉落+替换) / 悬赏纸循环(替换) + ├─ checkCount ← 放入前检查物品数量足够(不足给红字提示) + ├─ consumeItem ← 消耗物品 + ├─ replaceBlock ← 替换方块 + └─ dropItems ← 取出时以掉落物形式生成物品 +================================================================================ +""" +import time +import mod.server.extraServerApi as serverApi + +# ---- 网易API基础对象 ---- +ServerSystem = serverApi.GetServerSystemCls() # 服务端系统基类 +comp = serverApi.GetEngineCompFactory() # 组件工厂 + +# ---- 继承 BlueFox 框架的系统基类(提供 CreateEngineItemEntity 等方法) ---- +from ....BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxServerSystem +from ....BlueFoxTools.ToolsConfig import LevelId + +# ---- 只导入市场贸易自己的数据库 ---- +from ..MarketData import MARKET_SWITCHES + +# ---- 统一分发器 ---- +from ...service.FeatureDispatcher import FeatureDispatcher + + +class MarketService(BlueFoxServerSystem): + """ + 市场贸易·右键转换引擎 + + 【核心数据结构】 + marketRecipes = {(方块名, 物品名): 规则dict} # O(1) 查找 + marketBlockSet = {方块名, ...} # O(1) 注册用 + cooldown = {key: 时间戳} # 连点冷却表 + """ + + def __init__(self, namespace, systemName): + """ + 初始化:构建规则字典,并注册到统一分发器。 + """ + super(MarketService, self).__init__(namespace, systemName) + print "===== MarketService init =====" + + # ---- 构建规则字典(O(1) 查找) ---- + self.marketRecipes = {} + self.marketBlockSet = set() + for sw in MARKET_SWITCHES: + key = (sw["source"], sw.get("item")) + self.marketRecipes[key] = sw + self.marketBlockSet.add(sw["source"]) + + # ---- 右键冷却表 ---- + self.cooldown = {} + + # ---- 注册到统一分发器 ---- + FeatureDispatcher.register(self) + + # ============================================================================ + # 一、给 FeatureDispatcher 的接口 + # ============================================================================ + + def getFeatureBlocks(self): + """返回本功能管辖的所有方块名集合(右键路由用)""" + return self.marketBlockSet + + def getItemUseOnRules(self): + """返回"手持物品右键方块表面"的规则(市场贸易没有, 返回空)""" + return {} + + def handleBlockUse(self, args): + """ + 由 FeatureDispatcher 转发的右键方块入口。 + 只有 blockName 在本功能的方块集合里才会被调用。 + + 返回 True = 本功能处理了这个右键(分发器取消默认行为) + 返回 False = 当前组合没有匹配规则(分发器不拦截) + """ + blockName = args.get("blockName") + playerId = args.get("playerId") + x, y, z = args.get("x"), args.get("y"), args.get("z") + pos = (x, y, z) + dim = comp.CreateDimension(playerId).GetEntityDimensionId() + key = (dim, x, y, z) + + itemDict = self.getCarriedItem(playerId) + + recipe = self.findRecipe(blockName, itemDict) + if not recipe: + return False + + # 连点冷却 + if not self.checkCooldown(key, recipe.get("switchCd", 0.5)): + return True + + # 放入前检查物品数量是否足够 + if recipe.get("item") is not None: + need = recipe.get("consume", 1) + if not self.checkCount(playerId, itemDict, need): + return True + + # 切换型规则:就地执行 + self.handleSwitch(recipe, playerId, pos, dim, itemDict) + return True + + # ============================================================================ + # 二、规则匹配(O(1) 字典查找) + # ============================================================================ + + def findRecipe(self, blockName, itemDict): + """ + 在市场中查找匹配规则: + 1. 先精确匹配 (方块名, 物品名) —— 放入(手持物品) / 悬赏纸循环 + 2. 没找到再匹配 (方块名, None) —— 空手触发的规则(取出) + 注意:只有确认玩家真正空手时才 fallback 到空手规则, 避免手持物品误触发取出。 + """ + itemName = itemDict.get("newItemName") if itemDict else None + recipe = self.marketRecipes.get((blockName, itemName)) + if recipe: + return recipe + # 空手规则:只有确认空手(无物品或手持空气)才 fallback + if not itemName or itemName == "minecraft:air": + return self.marketRecipes.get((blockName, None)) + return None + + # ============================================================================ + # 三、切换型规则处理 + # ============================================================================ + + def handleSwitch(self, recipe, playerId, pos, dim, itemDict): + """ + 处理"右键直接转换"类规则。 + - 放入(item 不为 None): 消耗物品 + 替换方块 + 提示 + - 取出(item 为 None): 掉落物 + 替换方块 + 提示(悬赏纸循环只替换+提示) + """ + # ---- 放入:消耗物品 ---- + if recipe.get("item") is not None and recipe.get("consume", 1) > 0: + self.consumeItem(playerId, itemDict, recipe.get("consume", 1)) + + # ---- 取出:掉落物 ---- + if recipe.get("dropItem"): + self.dropItems(dim, pos, recipe["dropItem"]) + + # ---- 替换方块 ---- + if recipe.get("target"): + self.replaceBlock(pos, dim, recipe["target"], playerId) + + # ---- 转换成功提示 ---- + if recipe.get("tip"): + comp.CreateMsg(playerId).NotifyOneMessage(playerId, recipe["tip"]) + + # ============================================================================ + # 四、工具方法:放入数量检查 + # ============================================================================ + + def checkCount(self, playerId, itemDict, need): + """放入前检查手中物品数量是否足够 need 个, 不足给红字提示并返回 False""" + if itemDict is None: + comp.CreateMsg(playerId).NotifyOneMessage(playerId, "§c需要至少%d个对应物品!" % need) + return False + count = itemDict.get("count", 0) + if count < need: + comp.CreateMsg(playerId).NotifyOneMessage(playerId, "§c数量不足,需要至少%d个对应物品!" % need) + return False + return True + + # ============================================================================ + # 五、工具方法:获取玩家主手物品 + # ============================================================================ + + def getCarriedItem(self, playerId): + itemComp = comp.CreateItem(playerId) + return itemComp.GetPlayerItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, 0) + + # ============================================================================ + # 六、工具方法:消耗物品 + # ============================================================================ + + def consumeItem(self, playerId, itemDict, amount=1): + if itemDict is None: + return + count = itemDict.get("count", 0) + if count <= amount: + comp.CreateItem(playerId).SetEntityItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, + {"itemName": "minecraft:air", "count": 0, "auxValue": 0}) + else: + itemDict["count"] = count - amount + comp.CreateItem(playerId).SetEntityItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, + {"itemName": itemDict["newItemName"], + "count": itemDict["count"], + "auxValue": itemDict.get("newAuxValue", 0)}) + + # ============================================================================ + # 七、工具方法:替换方块 + # ============================================================================ + + def replaceBlock(self, pos, dim, newBlockName, playerId=None): + """ + 替换指定位置的方块。 + 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) + + # ============================================================================ + # 八、工具方法:以掉落物形式生成物品(取出) + # ============================================================================ + + def dropItems(self, dim, pos, dropList): + """ + dropList 格式:[{"name": "xxx", "count": N}, ...] + 在方块上方生成掉落物实体, 让它自然掉到地上。 + """ + for d in dropList: + itemDict = { + "itemName": d["name"], + "count": d.get("count", 1), + "auxValue": d.get("aux", 0), + } + self.CreateEngineItemEntity(itemDict, dim, (pos[0], pos[1] + 0.5, pos[2])) + + # ============================================================================ + # 九、工具方法:冷却检查 + # ============================================================================ + + def checkCooldown(self, key, cd=0.5): + """ + 右键冷却:同一方块 cd 秒内只响应一次, 防止连点刷物品/刷提示。 + """ + now = time.time() + last = self.cooldown.get(key, 0) + if now - last < cd: + return False + self.cooldown[key] = now + return True diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/service/__init__.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shichangmaoyi/service/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/siwangshengwu/DeadmobData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/siwangshengwu/DeadmobData.py index 07e7079..18a1574 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/siwangshengwu/DeadmobData.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/siwangshengwu/DeadmobData.py @@ -12,10 +12,10 @@ → 挂上对应尸体(消耗1个)。鱼可挂两条。 2) 取下退回: 切肉开始前, 空手右键 整只/整头 → 空钩 + 掉落回尸体(不可逆前可退) 3) 挂肉钩切肉: 手持 菜刀(cleaver) 右键 逐级切割(不可逆), 以掉落物形式获得对应部位肉 - - 切肉每刀掉落数量: 常规肉 2~3 个; 四肢固定 4 个; 牛头骨固定 1 个 - - 牛: 去头去皮掉牛头骨1+原版牛肉4~5 → 去四肢掉牛腿肉4 → 去肉掉牛肋2~3+牛里脊2~3+原版牛肉4~5 → 空钩掉碎肉2~3+原版牛肉4~5 - - 猪: 去皮掉五花肉2~3+原版生猪排4~5 → 去四肢掉猪蹄4 → 去肉掉猪肋排2~3+原版生猪排4~5 → 空钩掉碎肉2~3+原版生猪排4~5 - - 羊: 去皮掉羊小排2~3+原版生羊肉4~5 → 去四肢掉羊腿4 → 去肉掉羊里脊2~3+原版生羊肉4~5 → 空钩掉碎肉2~3+原版生羊肉4~5 + - 切肉每刀掉落数量: 常规肉 2~3 个; 四肢固定 4 个; 牛头骨固定 1 个; 去皮额外掉原版皮革4~6 + - 牛: 去头去皮掉牛头骨1+原版牛肉4~5+皮革4~6 → 去四肢掉牛腿肉4 → 去肉掉牛肋2~3+牛里脊2~3+原版牛肉4~5 → 空钩掉碎肉2~3+原版牛肉4~5 + - 猪: 去皮掉五花肉2~3+原版生猪排4~5+皮革4~6 → 去四肢掉猪蹄4 → 去肉掉猪肋排2~3+原版生猪排4~5 → 空钩掉碎肉2~3+原版生猪排4~5 + - 羊: 去皮掉羊小排2~3+原版生羊肉4~5+皮革4~6 → 去四肢掉羊腿4 → 去肉掉羊里脊2~3+原版生羊肉4~5 → 空钩掉碎肉2~3+原版生羊肉4~5 4) 鱼晾干(计时): 鲑鱼/鳕鱼挂上后自动计时约300秒晾干(挂肉钩自动开始, autoStart=True) - 鲑鱼: 挂一条→干一条; 挂两条→干两条 - 鳕鱼: 挂两条→干两条 @@ -161,6 +161,7 @@ DEADMOB_SWITCHES = [ "dropItem": [ {"name": "rtdd:cow_skull", "count": 1}, {"name": "minecraft:beef", "count": (4, 5)}, + {"name": "minecraft:leather", "count": (4, 6)}, ], "tip": "§a砍下了牛头", "giveItem": None, @@ -212,6 +213,7 @@ DEADMOB_SWITCHES = [ "dropItem": [ {"name": "rtdd:porkloins", "count": (2, 3)}, {"name": "minecraft:porkchop", "count": (4, 5)}, + {"name": "minecraft:leather", "count": (4, 6)}, ], "tip": "§a已给猪去皮", "giveItem": None, @@ -262,6 +264,7 @@ DEADMOB_SWITCHES = [ "dropItem": [ {"name": "rtdd:sheepracks", "count": (2, 3)}, {"name": "minecraft:mutton", "count": (4, 5)}, + {"name": "minecraft:leather", "count": (4, 6)}, ], "tip": "§a已给羊去皮", "giveItem": None, diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/siwangshengwu/service/DeadmobService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/siwangshengwu/service/DeadmobService.py index 5aad921..aa74b00 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/siwangshengwu/service/DeadmobService.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/siwangshengwu/service/DeadmobService.py @@ -95,11 +95,8 @@ class DeadmobService(BlueFoxServerSystem): def getItemUseOnRules(self): """ - 返回"手持物品右键方块表面"的规则(当前返回空)。 - 挂鱼走 ServerBlockUseEvent(右键方块本身)即可,不需要 ItemUseOn: - 日志验证手持原版鲑鱼/鳕鱼右键肉钩会正常触发 ServerBlockUseEvent 并转换, - 若同时注册 ItemUseOn 会重复转换(多消耗一条鱼)且 ServerItemUseOnEvent 的 - 玩家键是 entityId 不是 playerId,易出错,故不再使用该路径。 + 返回"手持物品右键方块表面"的规则(原版放置已拆到 yuanbanfangzhi, 返回空)。 + 手持原版鲑鱼/鳕鱼右键方块表面放置 死鲑鱼/死鳕鱼 的逻辑由 YuanbanService 处理。 """ return {} diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/YuanbanData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/YuanbanData.py new file mode 100644 index 0000000..b4a9f9c --- /dev/null +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/YuanbanData.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +""" +================================================================================ +原版放置分类转换规则数据 +================================================================================ +统一管理"手持原版物品右键方块表面 → 放置对应方块"的规则(ServerItemUseOnEvent)。 +从各功能分类中剔除出来单独成目录, 避免散落在各处。 + +当前规则: + 1) 原版生鸡肉(minecraft:chicken) → 生鸡肉(放置后) roastchickenplace_0 [烧烤用] + 2) 原版生鲑鱼(minecraft:salmon) → 死鲑鱼 killfish_0 [死亡生物用] + 3) 原版生鳕鱼(minecraft:cod) → 死鳕鱼 killcod_0 [死亡生物用] + 4) minecraft:fish → 死鳕鱼 killcod_0 (网易端 ItemUseOn 事件对 + 生鳕鱼报的 itemName 是 minecraft:fish, 与 GetPlayerItem 的 minecraft:cod 不同) + +字段说明: + item: 手持的原版物品 + target: 放置成的方块 + consume: 消耗数量(默认1) + tip: 放置成功提示 +================================================================================ +""" + +ITEM_USE_ON_RULES = [ + { + "item": "minecraft:chicken", # 原版生鸡肉 + "target": "rtdd:roastchickenplace_0", # 生鸡肉(放置后) + "consume": 1, + "tip": "§a已放置生鸡肉,可右键支杆上杆烤制", + }, + { + "item": "minecraft:salmon", # 原版生鲑鱼 + "target": "rtdd:killfish_0", # 死鲑鱼 + "consume": 1, + "tip": "§a已放置死鲑鱼", + }, + { + "item": "minecraft:cod", # 原版生鳕鱼 + "target": "rtdd:killcod_0", # 死鳕鱼 + "consume": 1, + "tip": "§a已放置死鳕鱼", + }, + # 网易端 ServerItemUseOnEvent 对 原版生鳕鱼 报的 itemName 是 minecraft:fish + # (日志: [FD-ItemUseOn] minecraft:fish), 需额外注册一条, 否则生鳕鱼无法放置。 + { + "item": "minecraft:fish", + "target": "rtdd:killcod_0", # 死鳕鱼 + "consume": 1, + "tip": "§a已放置死鳕鱼", + }, +] diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/__init__.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/service/YuanbanService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/service/YuanbanService.py new file mode 100644 index 0000000..0f0b88b --- /dev/null +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/service/YuanbanService.py @@ -0,0 +1,205 @@ +# -*- coding: utf-8 -*- +""" +================================================================================ +原版放置·手持原版物品右键方块表面(服务端) +================================================================================ +统一处理"手持原版物品右键方块表面 → 放置对应方块"的转换(ServerItemUseOnEvent): + 原版生鸡肉 → 生鸡肉(放置后);原版生鲑鱼/鳕鱼 → 死鲑鱼/死鳕鱼。 +这些规则原本散落在 烧烤(BarbecueService) 和 死亡生物(DeadmobService) 里, +现在单独拆到本目录统一管理。 + +【事件监听在哪?】 + 本类【不】监听任何事件! + 所有事件由 FeatureDispatcher(xiangyemod/service/FeatureDispatcher.py)统一监听: + - ServerItemUseOnEvent → OnItemUseOn → 按 itemUseOnOwner 路由到本类 handleItemUseOn + 被点方块属于某个"右键方块"服务的管辖(肉钩/条箱/锅具等)时, 分发器会跳过本路径, + 交给 ServerBlockUseEvent 处理(挂鱼/放入/做菜), 避免重复。 + +【本类怎么做】 + handleItemUseOn ← 入口:分发器转发"手持物品右键方块表面"事件 + ├─ 匹配规则 ← 按手持物品名 O(1) 查找 + ├─ 算目标格 ← 被点方块表面相邻的空格 + ├─ checkCooldown← 连点冷却 + ├─ consumeItem ← 消耗1个原版物品 + └─ replaceBlock ← 放置对应方块 + 提示 +================================================================================ +""" +import time +import mod.server.extraServerApi as serverApi + +# ---- 网易API基础对象 ---- +ServerSystem = serverApi.GetServerSystemCls() # 服务端系统基类 +comp = serverApi.GetEngineCompFactory() # 组件工厂 + +# ---- 继承 BlueFox 框架的系统基类(提供 CreateEngineItemEntity 等方法) ---- +from ....BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxServerSystem +from ....BlueFoxTools.ToolsConfig import LevelId + +# ---- 只导入原版放置自己的数据库 ---- +from ..YuanbanData import ITEM_USE_ON_RULES + +# ---- 统一分发器 ---- +from ...service.FeatureDispatcher import FeatureDispatcher + +# ---- 方块表面方向 → 相邻坐标偏移(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 YuanbanService(BlueFoxServerSystem): + """ + 原版放置·手持原版物品右键方块表面引擎 + + 【核心数据结构】 + itemUseOnRecipes = {物品名: 规则dict} # O(1) 查找 + cooldown = {key: 时间戳} # 连点冷却表 + """ + + def __init__(self, namespace, systemName): + """ + 初始化:构建放置规则字典,并注册到统一分发器。 + """ + super(YuanbanService, self).__init__(namespace, systemName) + print "===== YuanbanService init =====" + + # ---- 构建放置规则字典(O(1) 查找) ---- + self.itemUseOnRecipes = {} + for rule in ITEM_USE_ON_RULES: + self.itemUseOnRecipes[rule["item"]] = rule + + # ---- 右键冷却表 ---- + self.cooldown = {} + + # ---- 注册到统一分发器(只注册 itemUseOn, 不注册任何右键方块) ---- + FeatureDispatcher.register(self) + + # ============================================================================ + # 一、给 FeatureDispatcher 的接口 + # ============================================================================ + + def getFeatureBlocks(self): + """本功能不管辖任何右键方块, 返回空""" + return set() + + def getItemUseOnRules(self): + """返回"手持物品右键方块表面"的规则: {物品名: 规则dict}""" + return self.itemUseOnRecipes + + def handleItemUseOn(self, args): + """ + 由 FeatureDispatcher 转发的"手持物品右键方块表面"事件。 + 在方块表面放置对应方块(生鸡肉/死鲑鱼/死鳕鱼)。 + 返回 True=已处理,False=当前组合无匹配规则。 + """ + itemName = args.get("itemName") + # ServerItemUseOnEvent 的玩家键是 entityId,不是 playerId + playerId = args.get("playerId") or args.get("entityId") + rule = self.itemUseOnRecipes.get(itemName) + if not rule: + return False + + x, y, z = args.get("x"), args.get("y"), args.get("z") + face = args.get("face", 1) + dim = comp.CreateDimension(playerId).GetEntityDimensionId() + + # 计算被点方块表面相邻的目标格 + off = FACE_OFFSET.get(face, (0, 1, 0)) + targetPos = (x + off[0], y + off[1], z + off[2]) + + # 目标格必须为空(可放置) + try: + cur = comp.CreateBlockInfo(LevelId).GetBlockNew(targetPos, dim) + if cur and cur.get("name") != "minecraft:air": + return False + except Exception: + return False + + # 连点冷却 + key = (dim, targetPos[0], targetPos[1], targetPos[2]) + if not self.checkCooldown(key, 0.5): + return True + + # 消耗 1 个原版物品 + itemDict = self.getCarriedItem(playerId) + if not itemDict: + return False + self.consumeItem(playerId, itemDict, rule.get("consume", 1)) + + # 放置对应方块 + self.replaceBlock(targetPos, dim, rule["target"], playerId) + # 放置成功提示 + if rule.get("tip"): + comp.CreateMsg(playerId).NotifyOneMessage(playerId, rule["tip"]) + return True + + # ============================================================================ + # 二、工具方法:获取玩家主手物品 + # ============================================================================ + + def getCarriedItem(self, playerId): + itemComp = comp.CreateItem(playerId) + return itemComp.GetPlayerItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, 0) + + # ============================================================================ + # 三、工具方法:消耗物品 + # ============================================================================ + + def consumeItem(self, playerId, itemDict, amount=1): + if itemDict is None: + return + count = itemDict.get("count", 0) + if count <= amount: + comp.CreateItem(playerId).SetEntityItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, + {"itemName": "minecraft:air", "count": 0, "auxValue": 0}) + else: + itemDict["count"] = count - amount + comp.CreateItem(playerId).SetEntityItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, + {"itemName": itemDict["newItemName"], + "count": itemDict["count"], + "auxValue": itemDict.get("newAuxValue", 0)}) + + # ============================================================================ + # 四、工具方法:替换方块 + # ============================================================================ + + def replaceBlock(self, pos, dim, newBlockName, playerId=None): + """ + 替换指定位置的方块。 + 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) + + # ============================================================================ + # 五、工具方法:冷却检查 + # ============================================================================ + + def checkCooldown(self, key, cd=0.5): + """ + 右键冷却:同一目标格 cd 秒内只响应一次, 防止连点刷方块/刷提示。 + """ + now = time.time() + last = self.cooldown.get(key, 0) + if now - last < cd: + return False + self.cooldown[key] = now + return True diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/service/__init__.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/yuanbanfangzhi/service/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/behavior_pack_v8jz0zSR/netease_blocks/b_30.json b/behavior_pack_v8jz0zSR/netease_blocks/b_30.json index 602e3a0..2acb08a 100644 --- a/behavior_pack_v8jz0zSR/netease_blocks/b_30.json +++ b/behavior_pack_v8jz0zSR/netease_blocks/b_30.json @@ -4,7 +4,7 @@ "description": { "identifier": "rtdd:b_30", "register_to_creative_menu": true, - "category": "xy_jinyong" + "category": "xy_market" }, "components": { "netease:aabb": { diff --git a/behavior_pack_v8jz0zSR/netease_blocks/clothbox_1.json b/behavior_pack_v8jz0zSR/netease_blocks/clothbox_1.json index cbc98aa..c44e0e7 100644 --- a/behavior_pack_v8jz0zSR/netease_blocks/clothbox_1.json +++ b/behavior_pack_v8jz0zSR/netease_blocks/clothbox_1.json @@ -4,7 +4,7 @@ "description": { "identifier": "rtdd:clothbox_1", "register_to_creative_menu": true, - "category": "xy_market" + "category": "xy_jinyong" }, "components": { "netease:aabb": { diff --git a/behavior_pack_v8jz0zSR/netease_blocks/clothbox_2.json b/behavior_pack_v8jz0zSR/netease_blocks/clothbox_2.json index 20e1ec9..f73c768 100644 --- a/behavior_pack_v8jz0zSR/netease_blocks/clothbox_2.json +++ b/behavior_pack_v8jz0zSR/netease_blocks/clothbox_2.json @@ -4,7 +4,7 @@ "description": { "identifier": "rtdd:clothbox_2", "register_to_creative_menu": true, - "category": "xy_market" + "category": "xy_jinyong" }, "components": { "netease:aabb": { diff --git a/behavior_pack_v8jz0zSR/netease_group/market_groups.json b/behavior_pack_v8jz0zSR/netease_group/market_groups.json index 4a3d4a1..6249452 100644 --- a/behavior_pack_v8jz0zSR/netease_group/market_groups.json +++ b/behavior_pack_v8jz0zSR/netease_group/market_groups.json @@ -5,8 +5,7 @@ "icon": "rtdd:sellingboxes", "list": [ "rtdd:sellingboxes", - "rtdd:clothbox_1", - "rtdd:clothbox_2", + "rtdd:b_30", "rtdd:orangebox", "rtdd:peachbox", "rtdd:sales_box_cod", diff --git a/resource_pack_Are13Lvd/texts/zh_CN.lang b/resource_pack_Are13Lvd/texts/zh_CN.lang index 43146c6..04dac8f 100644 --- a/resource_pack_Are13Lvd/texts/zh_CN.lang +++ b/resource_pack_Are13Lvd/texts/zh_CN.lang @@ -31,8 +31,8 @@ itemGroup.tabrbulid=乡野-建筑 tile.rtdd:codsoup.name=汤锅_30(鳕鱼汤) tile.rtdd:apple_leaves.name=苹果树树叶(苹果树叶) tile.rtdd:lambsoupwithturnips_1.name=汤锅_47(胡萝卜羊肉汤_四分熟) -tile.rtdd:clothbox_1.name=售卖盒(黄绿布料) -tile.rtdd:clothbox_2.name=售卖盒(棕色布料) +tile.rtdd:clothbox_1.name=售卖盒(黄绿布料)_禁用 +tile.rtdd:clothbox_2.name=售卖盒(棕色布料)_禁用 tile.rtdd:salmonsushicubes_1.name=鲑鱼寿司块(一个) tile.rtdd:lambsoupwithturnips_3.name=汤锅_49(胡萝卜羊肉汤_熟) tile.rtdd:plate_8a.name=黄酱牛肉_2(黄酱牛肉)禁用 @@ -1042,7 +1042,7 @@ tile.rtdd:norieggsoup_3.name=汤锅_59(瘦肉蛋花汤_熟) tile.rtdd:norieggsoup_2.name=汤锅_58(瘦肉蛋花汤_全熟) tile.rtdd:cookingcookedporkloin_1.name=炒锅_31(小炒五花肉_熟) tile.rtdd:b_31.name=稻草人1 -tile.rtdd:b_30.name=鲑鱼箱_禁用 +tile.rtdd:b_30.name=售卖盒(鲑鱼) tile.rtdd:cookingdought.name=炒锅_38(煎面饼_生) tile.rtdd:b_39.name=面包盒_1_禁用 tile.rtdd:b_38.name=面包堆_1_禁用 diff --git a/tuilun/ok/市场贸易转化关系.txt b/tuilun/ok/市场贸易转化关系.txt new file mode 100644 index 0000000..89bf26a --- /dev/null +++ b/tuilun/ok/市场贸易转化关系.txt @@ -0,0 +1,107 @@ +======================================== +【市场贸易】(xy_market) 转化关系 +======================================== +说明: +- 分为4个分组: 条箱 / 货桶 / 售卖盒 / 摊位设施 +- 条箱/货桶/售卖盒 均为"手持对应物品右键放入 → 变为对应容器", 可空手右键取出取回 +- 放入消耗: 除 南瓜/西瓜 消耗1个原版方块(南瓜方块/西瓜方块)外, 其余消耗32个对应物品 +- 布料两个(售卖盒(黄绿/棕色))已按标注: 名字加"禁用" 调到 禁用(xy_jinyong)标签, 不参与本分类转换 +- 摊位设施静态, 仅悬赏纸有循环转换 + +======================================== +一、条箱 (手持对应物品右键放入, 消耗32) +======================================== +对应方块: woodenbox_0(条箱_空)、woodenbox_1(条箱(苹果))、woodenbox_2(条箱(胡萝卜))、 + woodenbox_3(条箱(土豆))、woodenbox_4(条箱(桃子))、woodenbox_5(条箱(橘子))、 + woodenbox_6(条箱(鳕鱼))、woodenbox_7(条箱(鲑鱼)) +机制: 手持对应物品右键 条箱(空 woodenbox_0), 消耗32个对应物品, 变为对应条箱 +1. 条箱(空) + 苹果 -> 条箱(苹果) +转换条件:[手持 苹果 右键 进行转换, 消耗32个苹果] +2. 条箱(空) + 胡萝卜 -> 条箱(胡萝卜) +转换条件:[手持 胡萝卜 右键 进行转换, 消耗32个胡萝卜] +3. 条箱(空) + 土豆 -> 条箱(土豆) +转换条件:[手持 土豆 右键 进行转换, 消耗32个土豆] +4. 条箱(空) + 桃子 -> 条箱(桃子) +转换条件:[手持 桃子 右键 进行转换, 消耗32个桃子] +5. 条箱(空) + 橘子 -> 条箱(橘子) +转换条件:[手持 橘子 右键 进行转换, 消耗32个橘子] +6. 条箱(空) + 鳕鱼 -> 条箱(鳕鱼) +转换条件:[手持 鳕鱼 右键 进行转换, 消耗32个鳕鱼] +7. 条箱(空) + 鲑鱼 -> 条箱(鲑鱼) +转换条件:[手持 鲑鱼 右键 进行转换, 消耗32个鲑鱼] + +【取出】条箱(苹果/胡萝卜/土豆/桃子/橘子/鳕鱼/鲑鱼) -> 条箱(空) +转换条件:[空手右键 进行转换, 取回对应物品] +机制: 空手右键装满的条箱, 变回空条箱, 以掉落物形式取回 32个对应物品 + +======================================== +二、货桶 (手持对应物品右键放入, 消耗32) +======================================== +对应方块: fishbucket_0(货桶_空)、fishbucket_1(货桶(鳕鱼))、fishbucket_2(货桶(鲑鱼))、 + carrotbarrel(货桶(胡萝卜))、potatobarrel(货桶(土豆))、peachbarrel(货桶(桃子))、 + orangebarrel(货桶(橘子))、applebox(货桶(苹果)) +机制: 手持对应物品右键 货桶(空 fishbucket_0), 消耗32个对应物品, 变为对应货桶 +1. 货桶(空) + 鳕鱼 -> 货桶(鳕鱼) +转换条件:[手持 鳕鱼 右键 进行转换, 消耗32个鳕鱼] +2. 货桶(空) + 鲑鱼 -> 货桶(鲑鱼) +转换条件:[手持 鲑鱼 右键 进行转换, 消耗32个鲑鱼] +3. 货桶(空) + 胡萝卜 -> 货桶(胡萝卜) +转换条件:[手持 胡萝卜 右键 进行转换, 消耗32个胡萝卜] +4. 货桶(空) + 土豆 -> 货桶(土豆) +转换条件:[手持 土豆 右键 进行转换, 消耗32个土豆] +5. 货桶(空) + 桃子 -> 货桶(桃子) +转换条件:[手持 桃子 右键 进行转换, 消耗32个桃子] +6. 货桶(空) + 橘子 -> 货桶(橘子) +转换条件:[手持 橘子 右键 进行转换, 消耗32个橘子] +7. 货桶(空) + 苹果 -> 货桶(苹果) +转换条件:[手持 苹果 右键 进行转换, 消耗32个苹果] + +【取出】货桶(鳕鱼/鲑鱼/胡萝卜/土豆/桃子/橘子/苹果) -> 货桶(空) +转换条件:[空手右键 进行转换, 取回对应物品] +机制: 空手右键装满的货桶, 变回空货桶, 以掉落物形式取回 32个对应物品 + +======================================== +三、售卖盒 (手持对应物品右键放入) +======================================== +对应方块: sellingboxes(售卖盒_空)、orangebox(售卖盒(橘子))、peachbox(售卖盒(桃子))、 + sales_box_cod(售卖盒(鳕鱼盒))、sales_box_carrot(售卖盒(胡萝卜))、sales_box_bread(售卖盒(面包))、 + sales_box_apple(售卖盒(苹果))、sales_box_pumpkin(售卖盒(南瓜))、sales_box_watermelon(售卖盒(西瓜))、 + sales_box_potato(售卖盒(土豆)) +机制: 手持对应物品右键 售卖盒(空 sellingboxes), 除南瓜/西瓜消耗1个原版方块外, 其余消耗32个对应物品, 变为对应售卖盒 +1. 售卖盒(空) + 橘子 -> 售卖盒(橘子) +转换条件:[手持 橘子 右键 进行转换, 消耗32个橘子] +2. 售卖盒(空) + 桃子 -> 售卖盒(桃子) +转换条件:[手持 桃子 右键 进行转换, 消耗32个桃子] +3. 售卖盒(空) + 鳕鱼 -> 售卖盒(鳕鱼盒) +转换条件:[手持 鳕鱼 右键 进行转换, 消耗32个鳕鱼] +4. 售卖盒(空) + 胡萝卜 -> 售卖盒(胡萝卜) +转换条件:[手持 胡萝卜 右键 进行转换, 消耗32个胡萝卜] +5. 售卖盒(空) + 面包 -> 售卖盒(面包) +转换条件:[手持 面包 右键 进行转换, 消耗32个面包] +6. 售卖盒(空) + 苹果 -> 售卖盒(苹果) +转换条件:[手持 苹果 右键 进行转换, 消耗32个苹果] +7. 售卖盒(空) + 南瓜(原版方块) -> 售卖盒(南瓜) +转换条件:[手持 原版南瓜方块 右键 进行转换, 消耗1个原版南瓜方块] +8. 售卖盒(空) + 西瓜(原版方块) -> 售卖盒(西瓜) +转换条件:[手持 原版西瓜方块 右键 进行转换, 消耗1个原版西瓜方块] +9. 售卖盒(空) + 土豆 -> 售卖盒(土豆) +转换条件:[手持 土豆 右键 进行转换, 消耗32个土豆] + +【取出】售卖盒(橘子/桃子/鳕鱼/胡萝卜/面包/苹果/土豆) -> 售卖盒(空) +转换条件:[空手右键 进行转换, 取回对应物品] +机制: 空手右键装满的售卖盒, 变回空售卖盒, 以掉落物形式取回 32个对应物品 +- 南瓜/西瓜盒: 空手右键 → 空售卖盒 + 取回 1个原版方块(南瓜方块/西瓜方块) + +【已禁用】售卖盒(黄绿布料 clothbox_1)、售卖盒(棕色布料 clothbox_2) +- 按标注: 名字后面加"禁用", 调到 禁用(xy_jinyong) 标签, 不参与市场贸易转换 + +======================================== +四、摊位设施 (静态 + 悬赏纸循环) +======================================== +1. 静态摊位设施(无转换) +- b_4(摊位台)、menus(餐牌(菜单))、vending_desk(售货台) 为静态, 无转换 + +2. 悬赏纸循环转换 (空手右键逐级切换) +- bountypaper(农贸清单/悬赏纸) -> bountypaper_1(悬赏纸_1) -> bountypaper_2(悬赏纸_2) -> bountypaper(农贸清单/悬赏纸) +转换条件:[右键 进行转换, 循环切换] +机制: 空手右键悬赏纸, 逐级切换到下一张, 末尾回到农贸清单 diff --git a/tuilun/死亡生物转化关系.txt b/tuilun/ok/死亡生物转化关系.txt similarity index 100% rename from tuilun/死亡生物转化关系.txt rename to tuilun/ok/死亡生物转化关系.txt diff --git a/tuilun/全部功能做了什么.txt b/tuilun/全部功能做了什么.txt index f52d121..89ad916 100644 --- a/tuilun/全部功能做了什么.txt +++ b/tuilun/全部功能做了什么.txt @@ -88,6 +88,8 @@ - 事件由 FeatureDispatcher 统一监听路由 (blockOwner/itemUseOnOwner/timerOwner) [已实现] - 右键服务通过 FeatureDispatcher.startTimerFor 把计时启动转发给计时服务 [已实现] - 计时用绝对时间戳写入方块实体数据, 支持退出/重启后继续计时 [已实现] +- 原版放置(手持原版生鸡肉/鲑鱼/鳕鱼右键方块表面放置对应方块)已拆到独立目录 + xiangyemod/yuanbanfangzhi (YuanbanData/YuanbanService), 从烧烤/死亡生物中剔除 [已重构] ######################################## @@ -127,6 +129,21 @@ - 死鳕鱼: 3刀每刀掉1份生鱼片, 共3份 → 消失 [已实现] - 死鱿鱼: 切须掉5~6个鱿鱼须 → 变死鱿鱼(切掉鱿鱼须) [已实现] +七、手持原版鱼右键方块表面放置死鱼 (ServerItemUseOnEvent) +- 原版生鲑鱼(salmon) 右键方块表面 → 在其表面放置 死鲑鱼(killfish_0), 消耗1条 [已实现] +- 原版鳕鱼(cod) 右键方块表面 → 在其表面放置 死鳕鱼(killcod_0), 消耗1条 [已实现] +- 注意: 网易端 ItemUseOn 事件对生鳕鱼报的 itemName 是 minecraft:fish, 已额外注册, 否则放置不了 [已实现] +- 被点方块是挂肉钩/挂鱼钩/尸体等死亡生物方块时跳过, 交还挂鱼逻辑 [已实现] + +七之补、拆方块掉回原版生食材 (ServerPlayerTryDestroyBlockEvent) +- 破坏 死鲑鱼(killfish_0) → 掉落 原版生鲑鱼 1条 [已实现] +- 破坏 死鳕鱼(killcod_0) → 掉落 原版生鳕鱼 1条 [已实现] +- 破坏 生鸡肉(放置后 roastchickenplace_0) → 掉落 原版生鸡肉 1个 [已实现] +- 取消默认掉落, 不把方块本身掉出来 + +八、去皮额外掉落原版皮革 +- 牛/猪/羊 去皮步骤额外掉落 原版皮革(minecraft:leather) 4~6个 [已实现] + 【未做】尸体生成机制(玩家杀死生物生成尸体) 按txt标注暂时不搞 @@ -146,3 +163,25 @@ 三、静态手办 (无转换) - 赞助者手办_1~6(figurines~5) 仅由盲盒开出, 无右键转换 [已实现] + +######################################## +【市场贸易】(xy_market) 2026-09-03 +######################################## +一、条箱 放入/取出 (woodenbox_0~7) +- 放入: 手持对应物品右键 空条箱 → 消耗32个 → 变为对应条箱(苹果/胡萝卜/土豆/桃子/橘子/鳕鱼/鲑鱼) [已实现] +- 取出: 空手右键装满条箱 → 空条箱 + 掉落32个对应物品 [已实现] + +二、货桶 放入/取出 (fishbucket_0 等) +- 放入: 手持对应物品右键 空货桶 → 消耗32个 → 变为对应货桶(鳕鱼/鲑鱼/胡萝卜/土豆/桃子/橘子/苹果) [已实现] +- 取出: 空手右键装满货桶 → 空货桶 + 掉落32个对应物品 [已实现] + +三、售卖盒 放入/取出 (sellingboxes 等) +- 放入: 手持对应物品右键 空售卖盒 → 除南瓜/西瓜消耗1个原版方块外, 其余消耗32个 → 变为对应售卖盒(含 售卖盒(鲑鱼) b_30) [已实现] +- 取出: 空手右键装满售卖盒 → 空售卖盒 + 取回(南瓜/西瓜1个原版方块, 其余32个) [已实现] + +四、悬赏纸循环 (空手右键逐级切换) +- bountypaper → bountypaper_1 → bountypaper_2 → bountypaper [已实现] + +五、布料已按标注禁用 [已处理] +- 售卖盒(黄绿布料 clothbox_1)、售卖盒(棕色布料 clothbox_2): 名字带"禁用", 已调去 禁用(xy_jinyong) 标签, 移出市场分组, 旧切换规则已移除 + diff --git a/tuilun/全部功能没做什么.txt b/tuilun/全部功能没做什么.txt index 815f620..2dafe65 100644 --- a/tuilun/全部功能没做什么.txt +++ b/tuilun/全部功能没做什么.txt @@ -59,10 +59,6 @@ (死牛 dead_cow / 死猪 dead_pig / 死羊 dead_sheep / 死鱿鱼 deadsquida / 村民尸体 dead_villager) - 未做原因: 转化文档 todo 已标注"暂时不搞" (死亡生物转化关系.txt 末尾 todo) -二、死鲑鱼/死鳕鱼切块掉落物数量【已实现, 仅记录原设计】 -- 死鲑鱼: 4刀共得4份生鱼片; 死鳕鱼: 3刀共得3份生鱼片; 死鱿鱼: 切须得5~6个鱿鱼须 -- 说明: 均已按批注实现, 此处仅为对照记录, 无未做项 - ######################################## 【方块工具】(xy_blocktools) diff --git a/tuilun/市场贸易转化关系.txt b/tuilun/市场贸易转化关系.txt deleted file mode 100644 index b98538b..0000000 --- a/tuilun/市场贸易转化关系.txt +++ /dev/null @@ -1,59 +0,0 @@ -======================================== -【市场贸易】(xy_market) 转化关系 -======================================== -说明: -- 分为4个分组: 条箱 / 货桶 / 售卖盒 / 摊位设施 -- 只有售卖盒与鲑鱼箱之间存在明确交互转换 -- 条箱/货桶多为静态容器方块 -- 【待确认】表示该步骤所需的具体操作尚未最终确定 - -======================================== -一、售卖盒 ↔ 鲑鱼箱 -======================================== -1. 售卖盒(黄绿布料) -> 鲑鱼箱 -转换条件:[手持 鲑鱼 右键 进行转换,消耗1条] -机制: 手持鲑鱼右键,消耗1条,放入鲑鱼变为鲑鱼箱 - -2. 售卖盒(棕色布料) -> 鲑鱼箱 -转换条件:[手持 鲑鱼 右键 进行转换,消耗1条] -机制: 手持鲑鱼右键,消耗1条,放入鲑鱼变为鲑鱼箱 - -3. 鲑鱼箱 -> 售卖盒(棕色布料) -转换条件:[右键 进行转换,同时获得鲑鱼] -机制: 空手右键,取回鲑鱼,变回售卖盒(棕色布料) - -======================================== -二、条箱(静态容器) -======================================== -4. 条箱(空) -> 条箱(苹果) / 条箱(胡萝卜) / 条箱(土豆) / 条箱(桃子) / 条箱(橘子) / 条箱(鳕鱼) / 条箱(鲑鱼) -转换条件:【待确认】手持对应物品右键放入?或为静态装饰方块 -机制: 手持对应物品右键,放入后变为对应条箱(机制待确认) - -woodenbox_0(条箱)、woodenbox_1(条箱(苹果))、woodenbox_2(条箱(胡萝卜))、woodenbox_3(条箱(土豆))、 -woodenbox_4(条箱(桃子))、woodenbox_5(条箱(橘子))、woodenbox_6(条箱(鳕鱼))、woodenbox_7(条箱(鲑鱼)) - -======================================== -三、货桶(静态容器) -======================================== -5. 货桶(空) -> 货桶(鳕鱼) / 货桶(鲑鱼) / 货桶(胡萝卜) / 货桶(土豆) / 货桶(桃子) / 货桶(橘子) / 货桶(苹果) -转换条件:【待确认】手持对应物品右键放入?或为静态装饰方块 -机制: 手持对应物品右键,放入后变为对应货桶(机制待确认) - -fishbucket_0(货桶)、fishbucket_1(货桶(鳕鱼))、fishbucket_2(货桶(鲑鱼))、carrotbarrel(货桶(胡萝卜))、 -potatobarrel(货桶(土豆))、peachbarrel(货桶(桃子))、orangebarrel(货桶(橘子))、applebox(货桶(苹果)) - -======================================== -四、售卖盒(其他静态售卖盒) -======================================== -sellingboxes(售卖盒)、orangebox(售卖盒(橘子))、peachbox(售卖盒(桃子))、 -sales_box_cod(售卖盒(鳕鱼盒))、sales_box_carrot(售卖盒(胡萝卜))、sales_box_bread(售卖盒(面包))、 -sales_box_apple(售卖盒(苹果))、sales_box_pumpkin(售卖盒(南瓜))、sales_box_watermelon(售卖盒(西瓜))、 -sales_box_potato(售卖盒(土豆)) -以上售卖盒方块无明确转换关系【待确认】 - -======================================== -五、摊位设施(静态) -======================================== -b_4(摊位台)、bountypaper(农贸清单(悬赏纸))、bountypaper_1(悬赏纸_1)、bountypaper_2(悬赏纸_2)、 -menus(餐牌(菜单))、vending_desk(售货台) -以上为摊位静态设施,无转换关系