Files
rtdd/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/InterceptData.py
T
2026-10-06 21:55:32 +08:00

486 lines
23 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
================================================================================
右键拦截白名单数据(共享,客户端/服务端共用)—— 自动派生版
================================================================================
【作用】
统一管理"手持物品右键功能方块"时, 需要【提前取消该物品默认行为
(右键吃/放置)】的精确组合。客户端 ClientFeatureDispatcher 用它提前
cancel/ret 消除闪烁; 服务端 FeatureDispatcher 读同一份, 保持一致。
【为什么需要】
不精确拦截会造成两种问题:
1. 宽泛拦截(以前): 手持任意方块右键"任何功能方块"就取消放置 -> 正常放置失效
2. 不拦截: 手持南瓜派右键盘子时, 原版先触发"吃/放"前摇, 由服务端取消就"闪一下"
因此只对"手持的方块物品 与 被点的功能方块 存在右键转换关系"的组合拦截,
其余一律放行 (一一对应)。
【自动派生(核心)】
各功能分类的"右键转换"规则都写在各自的 *Data.py 里 (如 ChaoguoData 的
SWITCH_RULES / ITEM_USE_ON_RULES)。本模块在 import 时【直接读取这些
Data 模块的规则表】, 自动抽出所有 (手持方块物品, 被点功能方块) 的转换对。
—— 这样未来新增/修改任一菜谱, 白名单自动同步, 永不会漏、永不过时。
【集合】
ITEM_USE_ON_CANCEL : set of (手持item, 被点block) 仅这两者匹配才取消
ITEM_USE_ON_CANCEL_BY_ITEM : set of 手持item 只看手持item即可取消
SUSHI_BLOCKS : 寿司方块物品集合(用于交叉取消, 见说明)
COATING_ITEMS : 裹粉生食材集合(右键面粉块时取消)
================================================================================
"""
# ============================================================================
# 一、导入各功能分类"手持物品右键方块表面"的规则数据符号
# 只扫【ITEM_USE_ON_RULES】(surface 字段) —— 这些才走 ServerItemUseOnEvent
# -> handleItemUseOn, 是客户端 ClientItemUseOnEvent 应拦截的组合。
# 注意: 绝对不要扫 SWITCH_RULES / *_SWITCHES 等(本体现在, 走 ServerBlockUseEvent
# -> handleBlockUse), 若扫进来客户端拦截会吃掉整个右键, 导致"右键什么都不发生"。
# 注: 本项目无 __init__.py, 用与各 Service 相同的 `from ..XxxData import ...`
# 直接导入符号, 而非 import 模块对象。
# ============================================================================
# 每个条目: (规则表内容) —— 规则表 list[dict], 字段含 "item" + "surface"/"source"
_ALL_RULE_TABLES = []
def _collect_all():
"""遍历 _ALL_RULE_TABLES, 汇总全部 (手持item, 被点surface方块) 组合。
只取 "surface"(手持物品右键方块表面) 与 "source"(盘子转换的被点方块),
不取 "block"(本体现在右键, 由服务端 handleBlockUse 处理)。"""
pairs = set()
for value in _ALL_RULE_TABLES:
for rule in _as_list(value):
if not isinstance(rule, dict):
continue
item = rule.get("item")
if not item or not isinstance(item, basestring):
continue
if item.startswith("*"):
continue
for blkf in ("surface", "source"):
blk = rule.get(blkf)
if isinstance(blk, basestring) and blk:
pairs.add((item, blk))
return pairs
# ---- 面食.甜食: 手持生食/面饼/面粉 右键 烤炉/木碗/蒸笼 (itemUseOn) ----
try:
from ..mianshi.MianshiData import ITEM_USE_ON_RULES as MIANSHI_USON
_ALL_RULE_TABLES.append(MIANSHI_USON)
except Exception:
pass
# ---- 炒锅: 盖饭双向 + 蛋炒饭 (itemUseOn, surface=米饭/成品菜) ----
try:
from ..chaoguo.ChaoguoData import (
ITEM_USE_ON_RULES as CHAOGUO_USON,
SWITCH_RULES as CHAOGUO_SWITCH,
PLATE as CHAOGUO_PLATE,
)
_ALL_RULE_TABLES.append(CHAOGUO_USON)
except Exception:
CHAOGUO_SWITCH, CHAOGUO_PLATE = None, None
# ---- 汤锅: 手持锅态汤右键 熟面条 (itemUseOn) ----
try:
from ..tangguo.TangguoData import (
ITEM_USE_ON_RULES as TANGGUO_USON,
SWITCH_RULES as TANGGUO_SWITCH,
BOWL as TANGGUO_BOWL,
PLATE as TANGGUO_PLATE,
)
_ALL_RULE_TABLES.append(TANGGUO_USON)
except Exception:
TANGGUO_SWITCH, TANGGUO_BOWL, TANGGUO_PLATE = None, None, None
# ---- 油锅: 手持盘子 出锅 (take_out) ----
try:
from ..youguo.YouguoData import (
SWITCH_RULES as YOUGUO_SWITCH,
PLATE as YOUGUO_PLATE,
)
except Exception:
YOUGUO_SWITCH, YOUGUO_PLATE = None, None
# ---- 根因B: 各"手持可放置/可投掷物品右键功能方块"走 ServerBlockUseEvent 的转换规则表.
# 字段用 source/block + item(块字段统一为 source; 不同服务可能用 source 或 block, 取兼容). ----
_BLOCK_USE_TABLES = []
# 动物养殖(鸡窝放蛋/饲料槽/水槽 等): AnimalData.ANIMAL_SWITCHES
try:
from ..dongwuyangzhi.AnimalData import ANIMAL_SWITCHES as ANIMAL_RS
_BLOCK_USE_TABLES.append(ANIMAL_RS)
except Exception:
pass
# 烧烤(上杆: 支杆+生肉/鱼): BarbecueData.BARBECUE_SWITCHES
try:
from ..shaokao.BarbecueData import BARBECUE_SWITCHES as BBQ_RS
_BLOCK_USE_TABLES.append(BBQ_RS)
except Exception:
pass
# 死亡生物(挂肉钩: 死鱼+钩/尸体挂放): DeadmobData.DEADMOB_SWITCHES
try:
from ..siwangshengwu.DeadmobData import DEADMOB_SWITCHES as DEADMOB_RS
_BLOCK_USE_TABLES.append(DEADMOB_RS)
except Exception:
pass
# 厨具(炉灶/丸子机/石磨: 木条+炉灶 等): ChujuData.STOVE_RULES / MEATBALLMAKER_RULES
# / STEAMER_RULES / STONEMILL_BLOCKUSE
try:
from ..chuju.ChujuData import (STOVE_RULES as CHUJU_STOVE,
MEATBALLMAKER_RULES as CHUJU_MEAT,
STEAMER_RULES as CHUJU_STEAM,
STONEMILL_BLOCKUSE as CHUJU_MILL)
_BLOCK_USE_TABLES.extend([CHUJU_STOVE, CHUJU_MEAT, CHUJU_STEAM, CHUJU_MILL])
except Exception:
pass
# 面食(面粉加水/揉面 等): MianshiData.SWITCH_RULES
try:
from ..mianshi.MianshiData import SWITCH_RULES as MIANSHI_SWITCH
_BLOCK_USE_TABLES.append(MIANSHI_SWITCH)
except Exception:
pass
# 炒锅(放料: 手持食材右键炒锅等): ChaoguoData.SWITCH_RULES
# (放料/翻炒走 handleBlockUse; 其中 action==take_out 的"盘子出锅"已由 TAKEOUT_CANCEL
# 专用通道处理, 派生时过滤掉, 避免与盛出走 TakeoutRequest 冲突)
try:
from ..chaoguo.ChaoguoData import SWITCH_RULES as CHAOGUO_BLOCKUSE
_BLOCK_USE_TABLES.append(CHAOGUO_BLOCKUSE)
except Exception:
pass
# 汤锅(放料: 手持食材/锅态汤右键汤锅等): TangguoData.SWITCH_RULES
# 同样过滤 action==take_out(盛出走 TakeoutRequest)
try:
from ..tangguo.TangguoData import SWITCH_RULES as TANGGUO_BLOCKUSE
_BLOCK_USE_TABLES.append(TANGGUO_BLOCKUSE)
except Exception:
pass
# 油锅(放料: 手持食材右键油锅等): YouguoData.SWITCH_RULES
# 同样过滤 action==take_out(出锅走 TakeoutRequest)
try:
from ..youguo.YouguoData import SWITCH_RULES as YOUGUO_BLOCKUSE
_BLOCK_USE_TABLES.append(YOUGUO_BLOCKUSE)
except Exception:
pass
# 饮料·榨汁机(手持 玻璃杯/各水果 右键榨汁机任意状态 放水果/逐级榨汁/取汁):
# YinliaoData.JUICER_BLOCKUSE。与汤锅等不同, 榨汁机取汁走 BlockUse(右击方块),
# 不标 take_out, 直接进 BlockUseRequest 通道消闪。
try:
from ..yinliao.YinliaoData import JUICER_BLOCKUSE as JUICER_BLOCKUSE
_BLOCK_USE_TABLES.append(JUICER_BLOCKUSE)
except Exception:
pass
# 饮料·冰棍盒/炒冰盒 整条"放料"链(放冰 + 放水果): YinliaoData.LOLLY_FRYICE_BLOCKUSE。
# 冰块是可放置方块物品 -> 原版先播"放置"前摇(闪一下);
# 水果多为可食用(苹果/西瓜片/葡萄/桃子/橙子) -> 原版当"吃"吞掉(一边吃一边放)。
# 两处均为内联转换, 故需在此罗列组合 -> 纳入 BLOCKUSE_CANCEL, 客户端提前 ret 并走
# BlockUseRequest 到 YinliaoService.handleBlockUse(放冰/放水果换态)。
try:
from ..yinliao.YinliaoData import LOLLY_FRYICE_BLOCKUSE as YINLIAO_LOLLY_BLOCKUSE
_BLOCK_USE_TABLES.append(YINLIAO_LOLLY_BLOCKUSE)
except Exception:
pass
# ---- 乡野自然(种葡萄: 手持葡萄右键支杆): NaturalData.GRAPE_PLANT ----
# 葡萄是食物(eat 动画), 右键支杆会被原版当"吃/使用"前摇, 需纳入 BLOCKUse 取消消闪,
# 机制与烧烤上杆(cod/salmon 同为食物右键支杆)完全一致。
try:
from ..ziran.NaturalData import GRAPE_PLANT as NATURAL_GRAPE_PLANT
_BLOCK_USE_TABLES.append(NATURAL_GRAPE_PLANT)
except Exception:
pass
# ---- 乡野自然(柴火堆叠: 手持半捆柴火右键半捆柴火): NaturalData.FIREWOOD_RULES ----
# 半捆柴火(rtdd:firewood_2) 是可放置方块物品, 手持它右键同种方块会被原版当"放置"前摇
# -> "闪一下"。纳入 BLOCKUSE_CANCEL 后由客户端提前 ret 并走 BlockUseRequest 到
# NaturalService.handleBlockUse, 消闪并执行消耗1个堆叠成柴火。
# (规则表里 item=None 的"空手取用柴火"会被派生自动过滤, 仍走正常 ServerBlockUseEvent。)
try:
from ..ziran.NaturalData import FIREWOOD_RULES as NATURAL_FIREWOOD
_BLOCK_USE_TABLES.append(NATURAL_FIREWOOD)
except Exception:
pass
# 市场贸易(条箱/货桶/售卖盒 放入: 手持 苹果/胡萝卜/土豆/桃/橘/鳕鱼/鲑鱼/面包/南瓜/西瓜
# 右键空容器): MarketData.MARKET_SWITCHES。
# 手持这些"可放置/可食用"物品右键容器时, 原版会先播放放置/使用预览, 需纳入 BLOCKUSE_CANCEL
# 由客户端 cancel 后走 BlockUseRequest 到 MarketService.handleBlockUse, 实现"手中物品消失进容器"。
# 注意: 派生会自动过滤 item=None 的取出规则(空手取出走 ServerBlockUseEvent, 本就不受 itemUseOn 影响)。
try:
from ..shichangmaoyi.MarketData import MARKET_SWITCHES as MARKET_RS
_BLOCK_USE_TABLES.append(MARKET_RS)
except Exception:
pass
# 家具家私(碗柜放碗/水槽/盘子架/唱片机/垃圾桶/壁炉加柴 等): FurnitureData.FURNITURE_SWITCHES。
# 手持 木碗/唱片/木条/打火石 等右键这些家具方块时, 原版会先播放放置/使用预览再被服务端取消
# -> "闪一下"。纳入 BLOCKUSE_CANCEL 后由客户端提前 ret 并走 BlockUseRequest 到
# FurnitureService.handleBlockUse, 消除闪动。item=None(取回) 会被派生自动过滤。
try:
from ..jiaju.FurnitureData import FURNITURE_SWITCHES as FURNITURE_RS
_BLOCK_USE_TABLES.append(FURNITURE_RS)
except Exception:
pass
# ---- 寿司(手持 饭团/鱼/卷寿司/手握 右键 寿司方块 走 handleBlockUse):
# ShousiData.SHOUSI_SWITCHES。
# 寿司规则内联在 ShousiService, 未随 *Data.SWITCH_RULES 派生; 若不在此汇入,
# 客户端会把"手持饭团/鱼右键寿司方块"当成吃/放置(饭团被吃、鱼放成死鱼),
# 转换不触发。加入后命中 BLOCKUSE_CANCEL -> 客户端显式发 BlockUseRequest。
try:
from ..shousi.ShousiData import SHOUSI_SWITCHES as SHOUSI_RS_BLOCKUSE
_BLOCK_USE_TABLES.append(SHOUSI_RS_BLOCKUSE)
except Exception:
pass
# ---- 原版放置/盘子转换 (itemUseOn, surface=相邻放置 / source=盘子) ----
try:
from ..yuanbanfangzhi.YuanbanData import (
ITEM_USE_ON_RULES as YUANBAN_USON,
PLATE_RULES,
)
_ALL_RULE_TABLES.append(YUANBAN_USON)
_ALL_RULE_TABLES.append(PLATE_RULES)
except Exception:
pass
# ============================================================================
# 二、从规则表派生 (手持方块物品, 被点功能方块) 转换对
# ============================================================================
def _as_list(value):
"""RICE_PLANT 这类是单个 dict, 规则表是 list[dict], 统一转成 list。"""
if isinstance(value, list):
return value
if isinstance(value, dict):
return [value]
return []
# ============================================================================
# 三、自动派生 + 少量"非规则表内联转换"的手工补充
# ============================================================================
# ---- 由各 Data 规则表自动派生 ----
AUTO_CANCEL = _collect_all()
# ============================================================================
# 三之A、"盛出/出锅"专用: 手持容器(木碗/盘子) 右键 成品方块 -> 客户端拦截
# 放置预览(消闪) + 显式通知服务端执行盛出(见 ClientFeatureDispatcher /
# FeatureDispatcher TakeoutRequest). 从 汤锅/炒锅/油锅 的 SWITCH_RULES 里
# action=="take_out" 且 item 是容器(木碗/盘子) 的规则自动派生.
# 空手(item=None)取饭团/水煮蛋/煎饼、菜刀切豆腐 不在此列, 走旧路径.
# ============================================================================
TAKEOUT_CANCEL = set()
def _derive_takeout(switch_rules, *container_items):
"""从一段 SWITCH_RULES 派生 take_out 且 item 是容器的 (item, block) 组合"""
if not switch_rules:
return set()
out = set()
for _r in switch_rules:
if not isinstance(_r, dict):
continue
if _r.get("action") != "take_out":
continue
_it = _r.get("item")
_bk = _r.get("block")
if _it in container_items and isinstance(_bk, basestring) and _bk:
out.add((_it, _bk))
return out
# 汤锅: 木碗/盘子 盛出碗装成品
TAKEOUT_CANCEL |= _derive_takeout(TANGGUO_SWITCH, TANGGUO_BOWL, TANGGUO_PLATE)
# 炒锅: 手持盘子 出锅盘装成品(空手出锅的煎饼/馍不在此列)
TAKEOUT_CANCEL |= _derive_takeout(CHAOGUO_SWITCH, CHAOGUO_PLATE)
# 油锅: 手持盘子 出锅炸物
TAKEOUT_CANCEL |= _derive_takeout(YOUGUO_SWITCH, YOUGUO_PLATE)
# ============================================================================
# 三之B、"盖饭/蛋炒饭"(itemUseOn) 专用: 手持 成品菜/米饭 右键 米饭/成品菜/炒锅蛋炒饭
# -> 客户端拦截放置预览(消闪) + 显式通知服务端执行转换(同 TakeoutRequest 机制).
# 从炒锅 ITEM_USE_ON_RULES(surface 字段) 自动派生: 盖饭双向 + 蛋炒饭.
# 若不单独抽出, 这些组合会被 ITEM_USE_ON_CANCEL 以纯 ret=True 吞掉,
# 导致服务端 ServerItemUseOnEvent 不触发 -> 盖饭"点无反应"(服务端 owners 修复无效).
# ============================================================================
GAI_FAN_CANCEL = set()
if CHAOGUO_USON:
for _r in CHAOGUO_USON:
if not isinstance(_r, dict):
continue
_it = _r.get("item")
_bk = _r.get("surface")
if isinstance(_it, basestring) and _it and isinstance(_bk, basestring) and _bk:
GAI_FAN_CANCEL.add((_it, _bk))
# ============================================================================
# 三之C、根因B "手持可放置/可投掷物品右键功能方块" -> BlockUse 显式事件拦截
# 客户端拦(手持物品, 功能方块)的放置/投掷预览后, NotifyToServer(BLOCK_USE_REQUEST),
# 服务端 OnBlockUseRequest 按被点方块路由到对应服务的 handleBlockUse。
# 仅取"手持物品非空"(item != None 且非 * 通配) 的转换对 —— 空手右键(item=None)
# 不涉及放置预览, 不需要拦截, 仍走正常 ServerBlockUseEvent。
# ============================================================================
BLOCKUSE_CANCEL = set()
for _tbl in _BLOCK_USE_TABLES:
for _r in _as_list(_tbl):
if not isinstance(_r, dict):
continue
_it = _r.get("item")
if not _it or not isinstance(_it, basestring) or _it.startswith("*"):
continue # 只看"手持具体物品"的转换; 空手/通配不拦
# 炒锅 SWITCH_RULES 的 action==take_out(盘子出锅) 已由 TAKEOUT_CANCEL 专用通道处理,
# 这里跳过, 避免与盛出走 TakeoutRequest 冲突; 其余(放料/翻炒)走 BlockUse。
if _r.get("action") == "take_out":
continue
# 被点方块: 兼容 source(主流) 与 block(个别)
_bk = _r.get("source") or _r.get("block")
if isinstance(_bk, basestring) and _bk:
BLOCKUSE_CANCEL.add((_it, _bk))
# BlockUse 转换涉及的全部手持物品集合(客户端 OnItemTryUse 也需取消默认"吃/使用/投掷/倒水",
# 否则手持 原版生肉/鱼/蛋 或 可食用的 rtdd 食材(brownrice/beancurd/crab/ham/beef_tenderloin
# 等) 右键炒锅/汤锅/油锅放料时, 会被原版当"吃"前摇吞掉食材)。
# 不限制前缀: 只要出现在放料/转换组合里都纳入, 取消仅在"放料后 0.2s 窗口"内生效,
# 工具类(锅铲/盘子/支杆)不触发 TryUse 吃, 加宽无副作用, 能覆盖全部可食 rtdd 食材。
BLOCKUSE_CANCEL_ITEMS = set(
_it for (_it, _bk) in BLOCKUSE_CANCEL
)
# ---- 通配"任意物品"转换(垃圾桶)的【整块】拦截集合 ----
# 垃圾桶规则的 item="*any"(任意非空物品), 无法枚举成 (item, block) 对, 上面的精确派生
# 会整条跳过 -> 手持 葡萄(吃)/胡萝卜(放置) 右键垃圾桶时客户端不拦, 原版先吃/先放,
# 服务端再取消已经太晚("一边吃葡萄一边清空"/"直接放置")。故改为按"被点方块"整块拦截。
# 派生条件: 规则表里 item == "*any" 且【无 below 前置条件】。
# (带 below 的如丸子机 meatballmaker_2 需下方有炉灶, 客户端无法判断, 不能无条件拦,
# 否则条件不满足时会吞掉玩家正常对着它吃东西/放东西。)
BLOCKUSE_CANCEL_ANY_BLOCKS = set()
for _tbl in _BLOCK_USE_TABLES:
for _r in _as_list(_tbl):
if not isinstance(_r, dict):
continue
if _r.get("item") != "*any":
continue
if _r.get("below"):
continue # 有前置条件(如炉灶)的客户端无法判断, 不拦
_bk = _r.get("source") or _r.get("block")
if isinstance(_bk, basestring) and _bk:
BLOCKUSE_CANCEL_ANY_BLOCKS.add(_bk)
# ---- Chuju 锅铲/油罐 inline 转换(在 ChujuService.handleItemUseOn 内联, 不在数据表) ----
# 手持 锅铲/带油锅铲 右键 油罐(oilcan)/炒锅(wok) 蘸油/还油/上油 -> 取消默认
CHUJU_INLINE_CANCEL = {
("rtdd:spatula", "rtdd:oilcan"), # 锅铲蘸油罐
("rtdd:spatula_oil", "rtdd:oilcan"), # 带油锅铲还油罐
("rtdd:spatula_oil", "rtdd:wok"), # 带油锅铲给炒锅上油
}
AUTO_CANCEL |= CHUJU_INLINE_CANCEL
# ============================================================================
# 四、寿司: 手持任何寿司方块物品 右键自家寿司方块 取消默认放置
# (寿司的堆叠/取走/转换规则在 ShousiService 内联构建, 不在 Data 表,
# 故此处手工列出寿司方块物品集合, 交叉生成 (块, 块) 组合)
# ============================================================================
SUSHI_BLOCKS = {
"rtdd:sushi_0", "rtdd:sushi_1",
"rtdd:codsushi_1", "rtdd:codsushi_2", "rtdd:codsushi_3",
"rtdd:codsushi_4", "rtdd:codsushi_5", "rtdd:codsushi_6",
"rtdd:salmonsushi_1", "rtdd:salmonsushi_2", "rtdd:salmonsushi_3",
"rtdd:salmonsushi_4", "rtdd:salmonsushi_5", "rtdd:salmonsushi_6",
"rtdd:fishsushi_1", "rtdd:fishsushi_2", "rtdd:fishsushi_3",
"rtdd:fishsushi_4", "rtdd:fishsushi_5", "rtdd:fishmonsushi_6",
"rtdd:nigirisushi",
"rtdd:sushipile_0", "rtdd:sushipile_1", "rtdd:sushipile_2",
"rtdd:sushipile_3", "rtdd:sushipile_4", "rtdd:sushipile_5",
"rtdd:nigirisushifishcod", "rtdd:nigirisushicod_2", "rtdd:nigirisushicod_3",
"rtdd:nigirisushifishsalmon_1", "rtdd:nigirisushisalnom_2", "rtdd:nigirisushisalnom_3",
"rtdd:nigirisushifish_1", "rtdd:nigirisushifish_2", "rtdd:nigirisushifish_3",
"rtdd:squid_sushi", "rtdd:squidsushi_2", "rtdd:squidsushi_3",
}
SUSHI_CANCEL = set(
(held, block) for held in SUSHI_BLOCKS for block in SUSHI_BLOCKS
)
# ============================================================================
# 五、裹粉(Shicai COATING_RULES 是 item->drop 结构, 无 floor 字段, 需手工指定被点面块)
# ============================================================================
COATING_ITEMS = {
"rtdd:sashimi", # 生鱼片
"rtdd:lobster", # 龙虾
"minecraft:porkchop", # 生猪肉
"minecraft:chicken", # 生鸡肉
"minecraft:potato", # 生土豆
}
COATING_CANCEL = set(
(item, "rtdd:farineblock_3") for item in COATING_ITEMS
)
# ============================================================================
# 六、汇总: 精确组合 ITEM_USE_ON_CANCEL = 自动派生 ∪ 寿司交叉 ∪ 裹粉
# ============================================================================
ITEM_USE_ON_CANCEL = AUTO_CANCEL | SUSHI_CANCEL | COATING_CANCEL
# ============================================================================
# 七、纯手持物品取消: 只看手持item (不做方块匹配)
# ============================================================================
# ---- 原版相邻放置(YuanbanService ITEM_USE_ON_RULES) ----
# 手持这些"非方块食品"右键任意方块表面, 都在相邻空位摆放对应切配方块。
# 他们本身不是可放置方块物品(放的是另一块), 但右键时会默认"吃/用", 需取消。
# 注: 稻谷(rtdd:rice_seeds)不在此列 —— 它已改用物品 JSON 的 minecraft:seed 组件
# 由引擎原生种植(plant_at=farmland, crop_result=riceseedlingsb), 客户端不拦截,
# 否则会吞掉引擎的原生种植行为。
PLACE_ITEMS = {
"minecraft:chicken",
"minecraft:salmon",
"minecraft:cod",
"minecraft:fish",
"minecraft:carrot",
"minecraft:potato",
"rtdd:qingcai",
"rtdd:scallions",
"minecraft:dried_kelp", # 原版干海带 → 干海带(放置后 sushi_0), 右键屏蔽吃前摇
}
# ---- 总食用 手持直接吃 (Shiyongfood TRY_USE_RULES) ----
EAT_ITEMS = {
"rtdd:rice_balls", # 饭团
"rtdd:boiled_egg", # 水煮蛋
"rtdd:beancurd", # 豆腐
}
# ---- 方案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
# ============================================================================
# 八、自检输出(便于调试/核对派生是否完整)
# ============================================================================
if __name__ == "__main__":
print "=== 自动派生转换对 数量:", len(AUTO_CANCEL), "==="
for _it, _bk in sorted(AUTO_CANCEL):
print " ", _it, "->", _bk
print "=== 汤锅盛出(TAKEOUT_CANCEL) 数量:", len(TAKEOUT_CANCEL), "==="
for _it, _bk in sorted(TAKEOUT_CANCEL):
print " ", _it, "->", _bk