Drawbridge GUI
基本信息
| 属性 | 值 |
|---|---|
| GUI ID | 0 = CommonProxy.drawbridgeID |
| GUI ID | 1 = CommonProxy.advDrawbridgeID |
| ID 分派 | RedstoneMachine.getGui(World, x, y, z, EntityPlayer)(blocks/RedstoneMachine.java:114-124) |
| 服务端容器 | CommonProxy.getServerGuiElement → ((InventoryLogic) tile).getGuiContainer(...) |
| 客户端 GUI | ClientProxy.getClientGuiElement(client/proxy/ClientProxy.java:26-33) |
| 普通容器 | DrawbridgeContainer(DrawbridgeLogic.getGuiContainer) |
| 高级容器 | AdvancedDrawbridgeContainer(AdvancedDrawbridgeLogic.getGuiContainer) |
| 方向按钮数 | 5(id 0–4,无 direction 5 / 东) |
| 展开按钮 | 仅 Advanced,id 5 |
| 槽类 | DrawbridgeSlot / SlotOpaqueBlocksOnly / SlotBlocksOnly(均 getSlotStackLimit() == 1) |
| 同步 | 槽位 = vanilla 容器同步;方向按钮 = PacketDrawbridge |
| 适用方块 | redstoneMachine meta 0 / 2 / 3(meta 1 Igniter 无 GUI) |
ID 分派
// blocks/RedstoneMachine.java:114-124
public Integer getGui(World world, int x, int y, int z, EntityPlayer entityplayer) {
int meta = world.getBlockMetadata(x, y, z);
switch (meta) {
case 0: case 3: return TMechworks.proxy.drawbridgeID; // 0
case 2: return TMechworks.proxy.advDrawbridgeID; // 1
}
return null; // meta 1 = Igniter
}
CommonProxy.getClientGuiElement 恒返回 null(common/CommonProxy.java:33-36)—— 客户端 GUI 由 ClientProxy 覆写提供。meta 0 与 meta 3 共用 GUI ID 0,玩家无法从界面区分 15 格与 64 格版本。
DrawbridgeContainer(GUI ID 0)
inventory/DrawbridgeContainer.java:20-37:
| 槽 | 类 | 坐标 | 说明 |
|---|---|---|---|
| 0 | DrawbridgeSlot(logic, 0, 80, 36) |
(80, 36) | 待放置方块 |
| 1 | SlotOpaqueBlocksOnly(logic, 1, 35, 36) |
(35, 36) | 伪装方块(须 isOpaqueCube() && renderAsNormalBlock()) |
| 2–10 | Slot |
(8+18r, 84+18c) | 玩家背包 3×9 |
| 11–19 | Slot |
(8+18c, 142) | 玩家快捷栏 |
AdvancedDrawbridgeContainer(GUI ID 1)
inventory/AdvancedDrawbridgeContainer.java:56-63:
| 槽 | 类 | 坐标 |
|---|---|---|
| 0 | SlotOpaqueBlocksOnly(logic.camoInventory, 0, 35, 36) |
(35, 36) |
| 1–16 | DrawbridgeSlot(logic, i, ...) |
x = 10+20i(i<8)/ 10+20(i-8),y = 35 + floor(i/8)*18 + (i<8 ? 0 : 1) |
| 17–25 | Slot |
(8+18r, 84+18c) |
| 26–34 | Slot |
(8+18c, 142) |
折叠/展开机制:16 个 DrawbridgeSlot 默认被移到 (-1000, -1000) 隐藏(updateContainerSlots(),:120-134),点击 id 5 展开按钮后移到 2×8 网格,同时 camo 槽与 5 个方向按钮被 setExpanded 隐藏(:113-126)。slotClick 在 gui.containerNeglectMouse 为真时直接 return null(:137-144),防止展开状态下误点槽位。
关键限制:伸出时禁止装填
DrawbridgeSlot(inventory/DrawbridgeSlot.java:22-46)的两条核心规则:
public boolean isItemValid(ItemStack par1ItemStack) {
... // 必须是 ItemBlock、不在黑名单、且通过 blockToItemMapping 反查
return !logic.hasExtended(); // ← 伸出时拒绝
}
public boolean canTakeStack(EntityPlayer par1EntityPlayer) {
return !logic.hasExtended(); // ← 伸出时也拒绝取出
}
hasExtended() 即 extension != 0(DrawbridgeLogic.java:553-555)。Drawbridge 伸出期间无法放入也无法取出方块,必须先完全收回。
mergeItemStack(两个容器中逻辑相同)另有一条 logic.hasExtended() 短路,因此 Shift 放入在伸出时同样无效。
5 个方向按钮
DrawbridgeGui.initGui(client/gui/DrawbridgeGui.java:46-67),DrawbridgeButton 继承 GuiButton 自绘 UV:
| id | direction | 屏幕坐标(相对 GUI 角) | UV (u, v) | 尺寸 |
|---|---|---|---|---|
| 0 | 上 | (+131, +18) | (176, 0) | 21×22 |
| 1 | 下 | (+146, +34) | (199, 23) | 22×21 |
| 2 | 北 | (+132, +48) | (199, 0) | 21×22 |
| 3 | 南 | (+117, +34) | (178, 23) | 22×21 |
| 4 | 西 | (+135, +40) | (217, 0) | 10×10 |
| 5 | 东 | — | — | 无按钮 |
DrawbridgeButton.drawButton 的 V 偏移三态:正常 +0、禁用 +46、悬停 +92。当前 direction 对应的按钮 enabled = false(变灰)。点击后 updateServer((byte) button.id) 发 PacketDrawbridge。
数值
| 数值 | 值 |
|---|---|
| GUI ID(普通 / 高级) | 0 / 1 |
| 适用 metadata | 0、2、3(1 = Igniter 无 GUI) |
| 普通容器机器槽 | 2(槽 0 方块 / 槽 1 伪装) |
| 高级容器机器槽 | 17(1 camo + 16 序列槽) |
| 玩家槽位 | 36(3×9 @ y=84 + 快捷栏 @ y=142) |
| 方向按钮 | 5(id 0–4,缺 id 5 / 东) |
| 按钮 V 偏移 | 0 / 46(禁用)/ 92(悬停) |
| 展开按钮 | id 5,26×26,标签 container.inv |
| 展开网格 | 2 行 × 8 列,间距 20px × 18px |
| 隐藏槽位坐标 | (-1000, -1000) |
| GUI 背景 | tmechworks:textures/gui/drawbridge.png / drawbridgeAdvanced.png |
| 槽堆叠上限 | 1(SlotBlocksOnly.getSlotStackLimit()) |
| 容器 lang | container.drawbridge / container.advdrawbridge / container.inventory |
源码缺陷
- 缺 direction 5(东)按钮(
DrawbridgeGui.java:46-67只创建 5 个)。DrawbridgeLogic.direction支持 0–5 六向,但 GUI 只能设到 4。放置时若自动判定为东(yaw 对应 5),玩家无法在界面改回。 AdvancedDrawbridgeLogic.getDefaultName()返回"tinker.drawbridge"(blocks/logic/AdvancedDrawbridgeLogic.java:240-242),而DrawbridgeLogic返回"tmechworks.drawbridge"(:220-222)。Advanced 版本误用 Tinkers’ Construct 的命名空间,该名字用于hasCustomInventoryName()判定与物品名。AdvancedDrawbridgeContainer.transferStackInSlot的反向合并被注释(:85-91):源码留有// TODO: Fix Shift click into the advance drawbridge Logic,else分支直接return null。因此从玩家背包 Shift 点击放入高级 Drawbridge 的槽位无效(普通 Drawbridge 的同一分支是可用的)。DrawbridgeContainer有 3 个死字段(:16-18):progress、fuel、fuelGague(拼写错误)全仓无读写,是从 BuildCraft 模板复制来的残留。AdvDrawbridgeGui构造器重复建容器(:27-30):super(frypan.getGuiContainer(...))之后又this.inventorySlots = new AdvancedDrawbridgeContainer(...)并手动player.openContainer = this.inventorySlots—— 第一个容器被立即丢弃,属明显的浪费。setExpanded置containerNeglectMouse = true但只在updateScreen中复位(:115/:161-163):若在同 tick 内展开后立刻点击,slotClick仍被屏蔽;且若 GUI 异常关闭不复位则该标记残留于容器实例。DrawbridgeGui无AdvDrawbridgeGui的展开功能:普通 Drawbridge 的 2 个槽恒显示,无折叠。- 展开状态下方向按钮全部隐藏(
setExpanded的b.visible = !flag),玩家必须先收起才能改方向。 - 无 GUI 缩放适配:按钮坐标相对
cornerX/cornerY硬编码,GUI 缩放较大时按钮与槽位可能重叠。 DrawbridgeButton复用drawbridge.png作为按钮贴图(:27-29),与 GUI 背景同一张图,UV 偏移 46/92 靠手工对齐,无容错。
相关条目
- Drawbridge - GUI ID 0
- Advanced Drawbridge - GUI ID 1
- Long Drawbridge - 与 meta 0 共用 GUI ID 0
- Igniter - 无 GUI 的第 4 个 meta
- 网络管线 -
PacketDrawbridge的实现 - Drawbridge 放置规则 -
isItemValid里引用的blockToItemMapping