diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py index 6796f12..94fdf3b 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/modMain.py @@ -27,6 +27,7 @@ from xiangyemod.tangguo.service.TangguoTimerService import TangguoTimerService from xiangyemod.chaoguo.service.ChaoguoService import ChaoguoService from xiangyemod.chaoguo.service.ChaoguoTimerService import ChaoguoTimerService from xiangyemod.shiyongfood.service.ShiyongfoodService import ShiyongfoodService +from xiangyemod.placeblock.service.PlaceBlockService import PlaceBlockService if not serverApi.IsInServer(): # 客户端进程: 导入客户端拦截系统(继承 BlueFoxClientSystem, 框架自动注册), diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/chaoguo/ChaoguoData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/chaoguo/ChaoguoData.py index 5b7f2b0..66010e2 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/chaoguo/ChaoguoData.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/chaoguo/ChaoguoData.py @@ -619,7 +619,7 @@ SWITCH_RULES = [ # 盖饭转换清单(正向+反向共用): dish=成品菜, target=盖饭 GAI_FAN_ITEMS = [ - {"dish": PLATE_47, "target": PLATE_48, + {"dish": PLATE_47, "target": PLATE_48, "giveItem": PLATE_48, "name": "辣子鸡丁", "gaiName": "辣子鸡丁盖饭(全份)"}, {"dish": PLATE_54, "target": PLATE_55, "name": "香菇滑鸡", "gaiName": "香菇滑鸡盖饭(全份)"}, @@ -635,16 +635,17 @@ for _g in GAI_FAN_ITEMS: _target = _g["target"] _name = _g["name"] _gai = _g["gaiName"] + _give = _g.get("giveItem") # 给定则"被点方块消失 + 给玩家物品", 否则原位替换成 target 方块 # 正向: 手持成品菜 右键 米饭(三形态任一) -> 米饭变盖饭 for _rice in RICE_FORMS: ITEM_USE_ON_RULES.append({ "item": _dish, "surface": _rice, "target": _target, "consume": 1, - "tip": None}) + "giveItem": _give, "tip": None}) # 反向: 手持 米饭(三形态任一) 右键 成品菜 -> 菜品变盖饭 for _rice in RICE_FORMS: ITEM_USE_ON_RULES.append({ "item": _rice, "surface": _dish, "target": _target, "consume": 1, - "tip": None}) + "giveItem": _give, "tip": None}) # 蛋炒饭 加米饭(形态1/2/3都行) -> 炒锅_87(蛋炒饭_加米饭_熟) for _rice in RICE_FORMS: ITEM_USE_ON_RULES.append({ diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/chaoguo/service/ChaoguoService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/chaoguo/service/ChaoguoService.py index 46015e3..e9f3fb6 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/chaoguo/service/ChaoguoService.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/chaoguo/service/ChaoguoService.py @@ -198,7 +198,13 @@ class ChaoguoService(BlueFoxServerSystem): self.consumeItem(playerId, itemDict, consume) # 替换被右键的表面方块(米饭变盖饭 / 菜品变盖饭 / 蛋炒饭变熟) - self.replaceBlock(pos, dim, recipe["target"], playerId) + # giveItem: 新成品菜体系 —— 被点方块消失, 改为给玩家"成品菜物品"(可再放置出对应方块) + giveItem = recipe.get("giveItem") + if giveItem: + self.replaceBlock(pos, dim, "minecraft:air", playerId) + self.giveItemToPlayer(playerId, giveItem, 1, pos, dim) + else: + self.replaceBlock(pos, dim, recipe["target"], playerId) self._clearWokData(dim, pos) return True diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/__init__.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/service/PlaceBlockService.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/service/PlaceBlockService.py new file mode 100644 index 0000000..efaab15 --- /dev/null +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/service/PlaceBlockService.py @@ -0,0 +1,165 @@ +# -*- coding: utf-8 -*- +""" +================================================================================ +【物品放置方块】(placeblock) 服务 —— 创造栏显示 2D 物品图标, 放置出指定方块模型 +================================================================================ +背景: 网易 1.10 自定义物品不支持 minecraft:block_placer(实测"放不下去"); + 原版 1.21.60 物品虽能 block_placer, 但其 menu_category 只能进原版分页, + 进不了网易自定义分页(如 xy_finished)。两者无法兼得。 +方案A(脚本补位): 方块本体 register_to_creative_menu:false 不出现在创造栏; + 另建带 2D 图标、category 指向自定义分页的网易 1.10 物品(分页正确); + 手持该物品右键任意方块 -> 在被点面的相邻格放置对应方块, 消耗 1 个 + (创造模式不消耗)。 + +路由: 走 FeatureDispatcher 的 itemUseOn(itemName -> 服务), 与其它转换服务同机制。 +================================================================================ +""" +import time +import mod.server.extraServerApi as serverApi + +ServerSystem = serverApi.GetServerSystemCls() # 服务端系统基类 +comp = serverApi.GetEngineCompFactory() # 组件工厂 + +from ....BlueFoxTools.SpecialFunciton.BlueFoxSystem import BlueFoxServerSystem +from ....BlueFoxTools.ToolsConfig import LevelId +from ...service.FeatureDispatcher import FeatureDispatcher, FACE_OFFSET + +# ---- 物品 -> 放置出的方块(要新增的成品菜在这里登记) ---- +PLACE_ITEMS = { + "rtdd:plate_48": "rtdd:plate_48_block", +} + +# ---- 视为"可放置"的目标方块(空气/水) ---- +AIR_LIKE = ("minecraft:air", "minecraft:water", "minecraft:flowing_water") + +# ---- 同一玩家两次放置的最小间隔(秒, 防连点重复放置) ---- +PLACE_COOLDOWN = 0.2 + +# ---- 朝向微调: 0=方块正面朝玩家视线方向; 2=方块正面朝玩家(视线反方向, 与正常摆放一致) ---- +FACING_FLIP = 0 + + +class PlaceBlockService(BlueFoxServerSystem): + """物品放置方块服务(创造栏 2D 图标 -> 放置 3D 方块)""" + + def __init__(self, namespace, systemName): + BlueFoxServerSystem.__init__(self, namespace, systemName) + self.itemBlocks = dict(PLACE_ITEMS) + self.cooldown = {} + FeatureDispatcher.register(self) + + # ------------------------------------------------------------------ + # 分发器路由表(FeatureDispatcher 调用) + # ------------------------------------------------------------------ + def getFeatureBlocks(self): + """本服务不接管任何"右键方块", 只处理 itemUseOn""" + return [] + + def getItemUseOnRules(self): + """手持放置物品右键方块表面 -> 由本服务处理""" + return {item: True for item in self.itemBlocks} + + def ownsItemUseOn(self, itemName, clickedName): + """声明本服务明确处理这些物品的 itemUseOn(不受被点方块归属影响)""" + return itemName in self.itemBlocks + + # ------------------------------------------------------------------ + # 入口: 手持放置物品右键方块 -> 在相邻格放置方块 + 消耗1 + # ------------------------------------------------------------------ + def handleItemUseOn(self, args): + itemName = args.get("itemName") + blockName = self.itemBlocks.get(itemName) + if not blockName: + return False + playerId = args.get("playerId") or args.get("entityId") + if not playerId: + return False + # 冷却: 防连点重复放置 + now = time.time() + if now - self.cooldown.get(playerId, 0) < PLACE_COOLDOWN: + return True + self.cooldown[playerId] = now + + x, y, z = args.get("x"), args.get("y"), args.get("z") + face = args.get("face", 1) + if x is None or y is None or z is None: + return False + dim = args.get("dimensionId") + if dim is None: + try: + dim = comp.CreateDimension(playerId).GetEntityDimensionId() + except Exception: + return False + + # 落点 = 被点方块相邻的那一格(0下 1上 2北 3南 4西 5东) + off = FACE_OFFSET.get(face, (0, 1, 0)) + target = (x + off[0], y + off[1], z + off[2]) + + # 目标位置必须是空气/水, 否则不放置(交还原版) + try: + b = comp.CreateBlockInfo(LevelId).GetBlockNew(target, dim) + name = b.get("name") if b else None + if name not in AIR_LIKE: + return False + except Exception: + return False + + # 放置方块(朝向按玩家水平朝向, 与正常摆放一致) + try: + aux = self._facingAux(playerId) + ok = comp.CreateBlockInfo(LevelId).SetBlockNew( + target, blockDict={"name": blockName, "aux": aux}, + oldBlockHandling=0, dimensionId=dim) + except Exception: + ok = False + if not ok: + return False + + # 消耗 1 个(创造模式不消耗) + if not self._isCreative(playerId): + self._consumeOne(playerId, itemName) + return True + + # ------------------------------------------------------------------ + # 工具 + # ------------------------------------------------------------------ + def _facingAux(self, playerId): + """ + netease:face_directional(type=direction) 的朝向值: + 0=南(+Z) 1=西(-X) 2=北(-Z) 3=东(+X) + 按玩家水平朝向(视线方向)取值; 若方向相反/偏移, 调 FACING_FLIP。 + """ + try: + rot = comp.CreateRot(playerId).GetRot() + dx, _dy, dz = serverApi.GetDirFromRot(rot) + if abs(dx) >= abs(dz): + face = 3 if dx > 0 else 1 # +X 东 / -X 西 + else: + face = 0 if dz > 0 else 2 # +Z 南 / -Z 北 + except Exception: + face = 0 + # 与正常摆放一致的微调: 方块"正面"朝向玩家(视线反方向)时改为 face+2 + return (face + FACING_FLIP) % 4 + + def _isCreative(self, playerId): + try: + return comp.CreateGame(LevelId).GetPlayerGameType(playerId) == 1 + except Exception: + return False + + def _consumeOne(self, playerId, itemName): + try: + itemComp = comp.CreateItem(playerId) + carried = itemComp.GetPlayerItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, 0, True) + if not carried or carried.get("newItemName") != itemName: + return + count = carried.get("count", 1) + itemComp.SetEntityItem( + serverApi.GetMinecraftEnum().ItemPosType.CARRIED, + {"itemName": itemName, + "count": max(count - 1, 0), + "auxValue": carried.get("newAuxValue", 0), + "userData": carried.get("userData", {})}) + except Exception: + pass diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/service/__init__.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/service/__init__.py new file mode 100644 index 0000000..40a96af --- /dev/null +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/placeblock/service/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/InterceptData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/InterceptData.py index 50b640d..8a7c25a 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/InterceptData.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/InterceptData.py @@ -451,7 +451,16 @@ EAT_ITEMS = { "rtdd:beancurd", # 豆腐 } -ITEM_USE_ON_CANCEL_BY_ITEM = PLACE_ITEMS | EAT_ITEMS +# ---- 方案A: 物品放置方块 (placeblock) ---- +# 手持该物品右键任意方块表面 -> 客户端 ret 掉默认行为并显式 ItemUseOnRequest, +# 服务端 PlaceBlockService.handleItemUseOn 负责在被点面相邻格放置对应方块。 +# (原版 1.21 物品的 block_placer 可用但只能进原版分页; 网易 1.10 物品能进自定义 +# 分页但不支持 block_placer, 故用脚本放置, 两者兼得。) +PLACE_BLOCK_ITEMS = { + "rtdd:plate_48", +} + +ITEM_USE_ON_CANCEL_BY_ITEM = PLACE_ITEMS | EAT_ITEMS | PLACE_BLOCK_ITEMS # ============================================================================ diff --git a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shiyongfood/ShiyongfoodData.py b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shiyongfood/ShiyongfoodData.py index 40c8b80..c4df351 100644 --- a/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shiyongfood/ShiyongfoodData.py +++ b/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/shiyongfood/ShiyongfoodData.py @@ -206,7 +206,7 @@ EAT_RULES = [ {"block": "rtdd:cookedpancake", "hunger": 9, "effects": [("saturation", 30, 1), ("resistance", 30, 1)]}, # 盖饭 - {"block": "rtdd:plate_48", "target": "rtdd:plate_48a", "hunger": 9, + {"block": "rtdd:plate_48_block", "target": "rtdd:plate_48a", "hunger": 9, "effects": [("regeneration", 20, 2), ("health_boost", 60, 4)]}, {"block": "rtdd:plate_48a", "hunger": 8, "drop": PLATE_DIRTY}, {"block": "rtdd:plate_55", "target": "rtdd:plate_55a", "hunger": 9,