GUI 注入
两个客户端界面改动:主菜单上的更新按钮,以及 SloppyDepLoader 下载完依赖后的重启动提示。全部通过 Forge 客户端事件注入,不改动原版类。
基本信息
| 属性 | 值 |
|---|---|
| 类型 | GUI 注入 / 按钮与对话框 |
| 运行端 | 仅客户端(@SideOnly(Side.CLIENT)) |
| 注入事件 | GuiScreenEvent.InitGuiEvent.Post(更新按钮)、GuiOpenEvent(重启动提示) |
| 原版类改动 | 无(不改 GuiMainMenu 源码,全靠事件追加 buttonList / 替换 event.gui) |
GuiButtonGeneric
包路径 makamys.mclib.updatecheck.gui,继承 net.minecraft.client.gui.GuiButton。源码注释写明改编自 TConstruct 的 AbstractTab。
| 成员 | 说明 |
|---|---|
| 构造 | GuiButtonGeneric(int id, int posX, int posY, int width, int height, String text) |
| 点击判定 | 重写 mousePressed(Minecraft, int, int),自己做 enabled/visible/矩形命中判断,命中则调 onClicked() 并返回 true |
onClicked() |
执行 clickListener(可为 null) |
| 提示渲染 | 重写 drawButton,鼠标在按钮矩形内时若 getTooltipStrings() 非 null 则调 Util.drawSimpleTooltip |
getTooltipStrings() |
基类返回 null;子类覆盖 |
setClickListener(Runnable) |
返回 this,支持链式调用 |
GuiButtonUpdates
包路径 makamys.mclib.updatecheck.gui,继承 GuiButtonGeneric。主菜单上的更新按钮,20x20 像素。
| 项 | 值 |
|---|---|
| 按钮 ID | UpdateCheckLib.UPDATES_BUTTON_ID = 1615486202 |
| 默认尺寸 | 宽 20、高 20 |
| 目标 URL | updates.html 的 file: URL(updatesFile.toURI().toURL().toString()) |
updateCount 状态 |
显示文本 | 可见性 | 可点击 |
|---|---|---|---|
-1(检查中) |
循环动画 .. / .. / ..,用深浅灰三段组合,按 (System.nanoTime() / 1000000000) % 3 切换 |
true | false |
0(无更新) |
空 | false | false |
> 0 |
GREEN + "+" + updateCount |
true | true |
setUpdateCount(int newCount) 统一处理上述状态。注意 updateCount == 0 时 displayString 不被更新,保留上一次的值——但因为 visible = false,视觉上无影响。
点击行为
| 操作 | 结果 |
|---|---|
| 普通左键 | Util.openURLInBrowser(url),用 java.awt.Desktop.browse 反射调用打开默认浏览器 |
| 按住左 Shift 左键 | GuiScreen.setClipboardString(url) 把 URL 复制到剪贴板 |
检测方式为 Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)。这是本 mod 唯一的键盘输入,但不是 KeyBinding——它只在鼠标点击按钮的瞬间轮询 Shift 状态,不注册进 Forge 的按键设置界面。
提示文本
getTooltipStrings() 返回两套文案:
| 状态 | 三行内容 |
|---|---|
updateCount >= 0 |
GREEN + <数量> + RESET + " update(s) available."(数量为 1 时无复数 s)、"Click to open list in browser."、GRAY + "(Shift click to copy URL.)" |
updateCount < 0 |
单行 GRAY + "Checking for updates..." |
GuiRestartNotification
包路径 makamys.mclib.sloppydeploader,继承 net.minecraft.client.gui.GuiYesNo,注释写明改编自 GuiConfirmOpenLink。仅客户端。
| 元素 | 值 |
|---|---|
| 标题 / 说明 | 构造时都传空串 super(null, "", "", -1) |
| 确认按钮文本 | I18n.format("Quit game"),ID 0 |
| 取消按钮文本 | I18n.format("Keep playing"),ID 1 |
| 确认按钮行为 | FMLCommonHandler.instance().exitJava(0, false) |
| 取消按钮行为 | Minecraft.getMinecraft().displayGuiScreen(parent),返回原主菜单 |
initGui 不调父类,而是自己往 buttonList 里塞两个 GuiOptionButton,Y 坐标为 this.height - 32(原版 quit 按钮位置),X 分别为 width/2 - 155 与 width/2 + 5。
drawScreen 先调父类,再自上而下居中绘制(this.width / 2):
| 行 | 内容 | 颜色 |
|---|---|---|
| 1 | "The following optional dependencies have been downloaded:" |
0xFFFFFF |
| 2…n | 每个依赖的文件名,每个 12px 一行 | YELLOW |
| n+1 | "A game restart is needed to activate them." |
0xFFFFFF |
| n+2 | "Do you want to restart the game now?" |
0xFFFFFF |
起始 Y 为 30,每行递增 18,依赖列表内部 12,最后两行之间额外加 6。actionPerformed 按按钮 id 分派。
Util
包路径 makamys.mclib.updatecheck,两个客户端工具方法。
| 方法 | 说明 |
|---|---|
openURLInBrowser(String url) |
反射 Class.forName("java.awt.Desktop") 取 getDesktop() 再调 browse(URI);任何异常都 LOGGER.error("Couldn't open link", throwable)。用反射是为了避免编译期依赖 AWT |
drawSimpleTooltip(int mouseX, int mouseY, int z, List<String> lines) |
自绘 tooltip,在 Minecraft.getMinecraft().currentScreen 上叠加绘制。宽度取所有行 fr.getStringWidth 的最大值,高度为 lines.size() * 10;背景半透明黑 setColorRGBA_F(0, 0, 0, 0.7f),四周 margin = 2 |
drawSimpleTooltip 的渲染顺序(Util 里手工写的 OpenGL 调用,用 Tessellator 画四边形):关 GL_TEXTURE_2D → 开 GL_BLEND → 关 GL_ALPHA_TEST → OpenGlHelper.glBlendFunc(770, 771, 1, 0) → glShadeModel(GL_SMOOTH) → 画背景 → glShadeModel(GL_FLAT) → 关 blend → 开 alpha test → 开纹理 → 用 current.drawString 逐行画字。
相关条目
- Forge 事件钩子 - 两个 GUI 事件的订阅位置
- UpdateCheck - 按钮上的数字来源与结果页
- SloppyDepLoader - 重启动提示的触发方
- 配置文件 - 按钮位置与开关