Files
rtdd/behavior_pack_v8jz0zSR/Script_NeteaseModousIY5aSF/xiangyemod/service/InterceptData.py
T
2026-09-23 14:27:13 +08:00

281 lines
13 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
# ---- 原版放置/盘子转换 (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))
# ---- 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) + 水稻种植(Natural RICE_PLANT) ----
# 手持这些"非方块食品/种子"右键任意方块表面, 都在相邻空位摆放对应切配方块。
# 它们本身不是可放置方块物品(放的是另一块), 但右键时会默认"吃/用", 需取消。
PLACE_ITEMS = {
"minecraft:chicken",
"minecraft:salmon",
"minecraft:cod",
"minecraft:fish",
"minecraft:carrot",
"minecraft:potato",
"rtdd:qingcai",
"rtdd:scallions",
"rtdd:rice_seeds", # 稻谷: 右键耕地相邻放置水稻苗(RICE_PLANT)
}
# ---- 总食用 手持直接吃 (Shiyongfood TRY_USE_RULES) ----
EAT_ITEMS = {
"rtdd:rice_balls", # 饭团
"rtdd:boiled_egg", # 水煮蛋
"rtdd:beancurd", # 豆腐
}
ITEM_USE_ON_CANCEL_BY_ITEM = PLACE_ITEMS | EAT_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