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 逐行画字。

相关条目