Drawbridge 放置规则
核心结论:137 条白名单是死数据
lib/TMechworksRegistry.java 用 137 次 drawbridgeState.put(...) 建立了一张 ItemStack → PlacementType 的放置白名单。但它在运行时从未被读取。
全仓对 drawbridgeState 的引用只有 3 处:
| 位置 | 状态 |
|---|---|
lib/TMechworksRegistry.java:39 |
public static HashMap<ItemStack, PlacementType> drawbridgeState = ... —— 声明 |
blocks/logic/DrawbridgeLogic.java:478 |
在 validMetadata 内的 /** ... */ 注释块中 |
blocks/logic/AdvancedDrawbridgeLogic.java:502 |
同上 |
两个 validMetadata 实现的真实函数体都是一行:
boolean validMetadata(Block block, int metadata) {
/**
* int type = TMechworksRegistry.drawbridgeState.get(block).getTypeID();
* if (type == 0) { return metadata == bufferStack.getItemDamage(); }
* if (type == 1) { return true; }
* if (type == 2) { return false; } // ← GTFO 会被这里挡住
* if (type == 3) { return true; // TODO: rotational metadata, probably not needed anymore }
* if (type == 4) { return true; }
* if (type == 5) { return metadata == bufferStack.getItemDamage(); }
*/
return true;
}
(blocks/logic/DrawbridgeLogic.java:476-483;Advanced 版同构,:500-508)
因此当前的实际放置规则(DrawbridgeLogic.updateEntity 判定链,:396-400)是:
if (bufferStack != null && validBlock(block) && validMetadata(block, meta) // 恒 true
&& validDrawbridge(xPos, yPos, zPos) && !hasInventory(xPos, yPos, zPos))
外加 isItemValidForSlot(slot, itemstack)(:580-596)的 3 条检查:必须是 ItemBlock、槽 1 额外要求 isOpaqueCube() && renderAsNormalBlock() 且堆叠 1、不在配置黑名单中。
即:Drawbridge 可以放任何非黑名单的方块物品,包括 metadata 5–7 的 137 个 GTFO 方块(bedrock / 下界传送门 / 刷怪笼 / 石门 / 仙人掌 …)。
7 种 PlacementType
lib/blocks/PlacementType.java:
| 常量 | typeID | 语义(源码注释) | 注册条数 |
|---|---|---|---|
metaMatch |
0 | Metadata has to match | 0 |
metaIgnore |
1 | Metadata has no meaning | 86 |
GTFO |
2 | Should not be placed | 17 |
rotationalMeta |
3 | Has rotational metadata | 27 |
rails |
4 | Rails | 4 |
rotationalTE |
5 | Has rotational TileEntity data | 3 |
custom |
6 | Custom placement logic | 0 |
| 合计 | 137 |
metaMatch 与 custom 的 grep 命中各 1 次,但都在文件头的注释块中(lib/TMechworksRegistry.java:67 与 :70),不是真实注册。这两个枚举常量是纯死代码 —— 尤其 custom 意味着没有任何方块走自定义放置路径。
GTFO(17 个)—— 名义上会被烧掉,实际可放
bedrock bed piston_extension mob_spawner wheat
wooden_door iron_door cactus portal cake
pumpkin_stem melon_stem nether_wart end_portal cocoa
carrots skull
注释与原始意图在 lib/TMechworksRegistry.java:130-152(如 // Bedrock, not sure why its in the list to be honestly truthful.)。当前这些方块均可被 Drawbridge 正常放置,包括下界传送门(portal)与末地传送门(end_portal)—— 后两者由游戏自身在 onBlockPlaced 中拒绝,故实际不会真的生成。
rails(4 个)
golden_rail detector_rail rail activator_rail
rotationalTE(3 个)
chest ender_chest trapped_chest
唯一需要「同时旋转方块 metadata 与 TE 内朝向 NBT」的类型。当前该逻辑同样被注释掉,箱子会被按原始朝向放置。
Tinkers’ Construct 方块
仅 2 个进入白名单(lib/TMechworksRegistry.java:226-227):
drawbridgeState.put(new ItemStack(TinkerWorld.slimePad), PlacementType.metaIgnore);
drawbridgeState.put(new ItemStack(TinkerWorld.bloodChannel), PlacementType.metaIgnore);
没有任何 TCon 金属锭、工具部件或矿物进入白名单。TCon 资源在本 mod 的其他用途:Dynamo 的贴图、[过滤网类型](../setting/filter-types) 的 ToolCore/ToolPart 判据、各配方的 ingotAluminumBrass 等材料。
实际生效的映射表
drawbridgeState 之外,以下 3 张表确实在运行时被使用:
| 映射 | 条数 | 运行时调用点 | 用途 |
|---|---|---|---|
blockToItemMapping |
5 | DrawbridgeLogic.java:291 |
HashBiMap,双向「方块 ↔ 物品」:redstone_ore↔redstone、redstone_torch↔unlit_redstone_torch、unpowered_repeater↔repeater、unpowered_comparator↔comparator、grass↔dirt |
interchangableBlockMapping |
9 | DrawbridgeLogic.java:314-318 |
单向替换:redstone_ore→lit_redstone_ore、redstone_torch→lit_redstone_torch、powered_repeater→powered_repeater 等 |
drawbridgeBlackList |
配置驱动 | DrawbridgeLogic.java:591 |
isItemDBBlacklisted(ItemBlock),由 配置文件 的 drawbridge.blacklist 填充 |
drawbridgeBlackList 是 private static List<ItemBlock>,支持 modid:blockname 语法(无冒号则默认 minecraft),并提供 addItemToDBBlackList(Item) / addItemToDBBlackList(Block) 两个运行时 API。
数值
| 数值 | 值 |
|---|---|
drawbridgeState 条数 |
137(全部死数据) |
| metaIgnore / rotationalMeta / GTFO / rails / rotationalTE | 86 / 27 / 17 / 4 / 3 |
| metaMatch / custom | 0 / 0 |
validMetadata 实际逻辑 |
恒 return true(两个实现) |
blockToItemMapping |
5(HashBiMap,双向) |
interchangableBlockMapping |
9(单向为主) |
drawbridgeBlackList |
List<ItemBlock>,配置 + 2 个 API |
isItemValidForSlot 条件 |
instanceof ItemBlock + 非黑名单(槽 1 额外要求 isOpaqueCube && renderAsNormalBlock 且堆叠 1) |
| TCon 方块 | 2(slimePad、bloodChannel) |
| 表键类型 | HashMap<ItemStack, PlacementType>(含 metadata 比较) |
源码缺陷
- 137 条白名单全部是死数据(见上文)—— 本条目最重要的一条。
validMetadata的注释块里保留了完整的 6 分支逻辑与// TODO: rotational metadata, probably not needed anymore的待办,说明这是主动放弃而非忘记,但 GTFO 的 17 个方块因此失去保护。 - 注释掉的代码块被保留在函数体内(
DrawbridgeLogic.java:477-482):两处共 12 行注释代码留在源文件里,读者容易误以为逻辑生效。Advanced 版同样 8 行。 interchangableBlockMapping9 条中 7 组只注册一个方向:只有dirt↔grass双向(:222-223)。redstone_ore、redstone_torch、unpowered_repeater、powered_repeater、unpowered_comparator、powered_comparator均单向。放置时若映射查不到会return(不放置),故「用 lit_redstone_ore 反向放置」不可用。Blocks.tripwire_hook被 put 两次(:191-192),第二次覆盖第一次 —— 复制粘贴残留。- 两张表键类型不一致:
drawbridgeState键是ItemStack(含 metadata),另两张是Block(HashBiMap/HashMap),updateEntity需Item.getIdFromItem桥接(:291),类型转换链冗长。 addItemToDBBlackList(Block)名为 addItem 实收 Block(:289),且抛RuntimeException而非IllegalArgumentException。- 无效方块名只 warn 不 fail(
:256):"Invaild block: " + blockNameCompond—— 源码里Invaild是拼写错误。 TMechworksRegistry的static {}与配置读取的顺序依赖:TMechworks.preInit先ConfigCore.loadConfig()(:52)再首次引用TMechworksRegistry(:54,new TabTools)。顺序恰好正确但无注释保护,重构时极易破坏。drawbridgeState若被重新启用会立即出问题:它以ItemStack为键而所有 put 用new ItemStack(block)(damage 0),只覆盖 meta 0。玩家持有minecraft:logmeta 15 时查不到 → 无法放置。这是恢复该功能前必须先修的坑。
相关条目
- Drawbridge - 使用本规则的方块
- Long Drawbridge - 同一方块 ID 的 meta 3
- Advanced Drawbridge - 同一方块 ID 的 meta 2,另一个
validMetadata桩 - 配置文件 - 唯一的
drawbridge.blacklist配置项 - tinkersconstruct -
slimePad/bloodChannel的来源