MinecraftMixin
基本信息
| 属性 | 值 |
|---|---|
| 文件 | net/sxmaa/headlessnh/mixins/early/MinecraftMixin.java |
| 目标类 | net.minecraft.client.Minecraft |
| 注入点 | runTick @HEAD、startGame @TAIL、displayGuiScreen @TAIL |
| Mixin 集 | JOIN_WORLD_ON_MAINMENU_LOAD(EARLY) |
| 平台 | 纯客户端(addClientMixins) |
这是 HeadlessNH 的主入口:整个「自动点菜单」的行为都挂在一个 displayGuiScreen 的 TAIL 注入上——每当客户端切换界面,mixin 就检查这个新界面是不是下一步该自动操作的目标。
两个注入点
runTick @HEAD — 主线程任务队列
IntegrationTestController 内部所有可能触碰 OpenGL 上下文的操作都通过 runOnMainThread(Runnable) 投递到 MAIN_THREAD_TASKS(ConcurrentLinkedQueue)。本注入在每个 tick 开头把队列排干并逐个 task.run()。
[!NOTE] 这是必要的:菜单点击、字段写入、
displayGuiScreen切换都必须在渲染线程执行,而MinecraftMixin内部的「等待稳定」逻辑跑在自建的new Thread(...)里。
startGame @TAIL — 启动完成
置 headlessNH$finishedLoading = true,调用 logSettings() 打印全部属性,然后 onGameStarted() 写出主菜单 marker(仅在 isActive() 时,且 mc != null)。若主菜单尚未标记为已到达,立刻 changedScreen(this.currentScreen, null) 手动触发一次后续处理。
displayGuiScreen 的 6 个分支
整个入口先做一次守卫:if (!Boolean.getBoolean("headlessnh.active")) return;——即属性未设(自动化开启)才继续。
| 新界面 | 动作 | 硬编码延迟 |
|---|---|---|
GuiMainMenu |
等 delay.mainmenu → 写主菜单 marker → 等 mainmenu gate → 合成 GuiButton(1=单人 / 2=多人) 派发 |
可配(500 ms) |
GuiSelectWorld |
派发 GuiButton(3)(「创建新世界」) |
500 ms |
GuiCreateWorld |
若两个文本框为空则先 Thread.sleep(2500),再派发 GuiButton(0)(「创建」) |
500 ms + 2500 ms |
GuiMultiplayer |
派发 GuiButton(4)(「直接连接」) |
500 ms |
GuiScreenServerList |
把地址框文本设为 127.0.0.1,再设 serverIP 并 confirmClicked(true, 0) |
500 ms |
GuiDisconnected |
等 1000 ms → onConnectionFailed() → 复位多人/直连标志 → 回主菜单 |
1000 ms |
GuiIngameMenu |
若不是自己请求的拆除则警告并关闭;否则派发 GuiButton(1)(返回游戏) |
500 ms |
需要注意的实现细节
- 服务器地址硬编码为
127.0.0.1,没有任何系统属性可以覆盖。多人测试只能连本机。 - 除主菜单分支外,所有延迟都是硬编码字面量(500 / 1000 / 2500 ms),不受
headlessnh.delay.*控制。 GuiCreateWorld分支读createWorld.field_146333_g/field_146335_h(两个文本框)判断世界名是否为空,靠 access transformer 开放。- 按钮 ID 取自原版:
GuiMainMenu单人=1/多人=2、GuiSelectWorld创建=3、GuiCreateWorld创建=0、GuiMultiplayer直连=4、GuiIngameMenu返回游戏=1。这些actionPerformed方法在 1.7.10 是 private,靠 AT 开放。
相关条目
- Mixin 加载与 Access Transformer - coremod 加载与 12 条 AT 规则
- Stage 状态机 - 一次性标志与重试逻辑
- 失焦暂停菜单抑制 - 同一 early 阶段的另一个 Mixin
- Custom Main Menu 适配 - 主菜单分支在 CMM 下的替代实现