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 靠手工对齐,无容错。

相关条目