铭文输入界面

SignPostLabelGui —— 客户端弹出式输入框,用于给未刻写的 路牌 写名字。界面上只有一个文本框和「完成 / 取消」两个按钮(复用 Atlas 的 I18n 键 gui.done / gui.cancel,标题键为 gui.signposts.marker.label,英文原文 “Inscription”,德文 “Inschrift”)。

打开条件

由 路牌 的 onBlockActivated 触发,全部在客户端:

if (currentItemStack != null && currentItemStack.getItem() instanceof SignPostMarkerItem) {
    if (signPost.getMarkerId() == 0) {
        SignPostsMod.proxy.openSignPostLabelGui(x, y, z, player.posX, Math.floor(player.posY - 1), player.posZ);
    }
    return false;
}
条件 要求
手持物 必须是 魔法路牌标记
路牌状态 markerId == 0(尚未刻写);已刻写的路牌右键无反应
侧 无限制,任意面都可触发
重开保护 ClientProxy.openSignPostLabelGui 内 if (mc.currentScreen == null),已有界面时不覆盖

跳转目标坐标的取法

传入界面的 3 个 double 跳转坐标不是路牌位置,而是玩家当时的位置:

参数 值
jumpX player.posX(浮点)
jumpY Math.floor(player.posY - 1)(向下取整后作为 double 传入)
jumpZ player.posZ(浮点)

而路牌自身的方块坐标 x, y, z 由 Block 参数单独携带,用于在服务端定位要写入哪个 TileEntity。两者在 CreateJumpTargetMessage 中是两组独立的 6 个数字。

界面元素

元素 值
文本框宽度 200 px
文本框高度 20 px
水平位置 (width - 200) / 2(水平居中)
垂直位置 height / 2 - 81
标题 height / 2 - 97,文案 gui.signposts.marker.label
最大字符数 15(textField.setMaxStringLength(15),与原版告示牌一致)
按钮宽度 BUTTON_WIDTH = 100
按钮间距 BUTTON_SPACING = 4
按钮纵向位置 height / 2 + 40
「完成」按钮 width / 2 - 100 - 2,文案 gui.done
「取消」按钮 width / 2 + 2,文案 gui.cancel
初始焦点 textField.setFocused(true),输入框打开即获焦
初始文本 setText("")(不预填已有的路牌名字)
是否暂停游戏 doesGuiPauseGame() 返回 false(多人游戏也不暂停)

提交与取消

protected void actionPerformed(GuiButton button) {
    if (button == btnDone) {
      CreateJumpTargetMessage msg = new CreateJumpTargetMessage(signX, signY, signZ, jumpX, jumpY, jumpZ, textField.getText());
      SignPostsNetworkHelper.sendCreateJumpTargetMessage(msg);
      close();
    } else if (button == btnCancel) {
      close();
    }
}
按钮 行为
完成 发送 判别号 0 的消息 并 close();不校验文本是否为空(可以提交空铭文)
取消 直接 close(),不发任何消息,不扣耐久

界面继承 Atlas 的 GuiComponent,keyTyped 转发给 textField.textboxKeyTyped,mouseClicked 转发给 textField.mouseClicked——因此文本框可正常输入中文/非 ASCII(UTF8 编码上限 15 字符按 Java String.length() 计,不按码点)。

⚠️ 15 字符限制只在客户端界面生效。CreateJumpTargetMessage 用的 ByteBufUtils.writeUTF8String 无长度校验,而服务端 addJumpTarget 也不检查 label 长度。

界面实例复用

ClientProxy.init 只 new 一次(labelGui = new SignPostLabelGui()),openSignPostLabelGui 通过 labelGui.setJumpTargetValues(...) 覆盖字段后复用同一实例;atlasGui 同理。

相关条目