Custom Main Menu

[!INFO] Git Commit: fed2e4b(tag 1.14.1,2026-04-27)| MC 1.7.10 / Forge

用 JSON 完全重定义 Minecraft 主菜单的纯客户端 GUI 配置 mod。没有方块、没有物品、没有实体——它的全部"内容"就是一套 GUI 元素类型、8 种按钮动作、一套配置文件机制,外加给其他 mod 用的一个事件接口。

属性 值
modid ⚠️ custommainmenu(CustomMainMenu.java:25,gradle.properties:10)——与本 wiki 分类名 custom-main-menu 不一致
显示名 Custom Main Menu(CustomMainMenu.java:26)
@Mod 类 lumien.custommainmenu.CustomMainMenu(全客户端,无 @SideOnly 注解但只注册客户端事件)
资源命名空间 assets/custommainmenu/
配置文件目录 <.minecraft>/config/CustomMainMenu/*.json
Java 源文件 52 个,全部在 src/main/java/lumien/custommainmenu/
随包资源 3 张贴图 + 1 份默认配置(无 lang 文件、无 mcmod 之外的资源包)

核心设计

<mc>/config/CustomMainMenu/*.json
        ↓ ConfigurationLoader.load()(遍历所有 .json,文件名=界面名)
   GuiConfig.load()   ← 解析 images / buttons / texts / other 四段
        ↓ GuiCustom(每个界面一个实例)
   CMMEventHandler.openGui   ← 反射替换 GuiMainMenu
        ↓
   GuiCustom.drawScreen      ← Panorama → Background → Image → SplashText → Text → Button

三类可扩展点:

层 内容 数量
视觉元素 GUI 元素 7 种
交互动作 按钮动作 8 种
配置机制 配置系统 8 项

GUI 元素

可放在 images / buttons / texts / other 四段里的全部可视元素类型。

按钮动作

action.type 的全部 8 个取值,由 GuiConfig.getWantedAction(GuiConfig.java:389-420)分发。

动作 效果 是否离开游戏进程
打开界面(openGui) 跳转到原版 / FML / 其他 mod / 自定义界面 否
打开链接(openLink) 三按钮确认框后用系统浏览器打开 是
加载世界(loadWorld) 直连指定存档,跳过选关界面 否
连接服务器(connectToServer) 直连指定 IP,跳过服务器列表 否
打开文件夹(openFolder) 资源管理器打开 .minecraft 内的目录 是
退出游戏(quit) Minecraft.shutdown() 是
重载配置(refresh) 重读全部 JSON,可选刷新游戏资源 否
发送 IMC(sendIMC) 在 Forge 事件总线上抛 ActionIMCEvent 否

配置系统

热键

特殊机制

本 mod 没有的内容

以下维度经 grep 确认零命中,因此不建对应目录:

维度 grep 证据(在 src/main/java/ 下)
方块 / 物品 / TileEntity registerBlock 0、registerItem 0、registerTileEntity 0、extends Block 0、extends Item 0
实体 registerEntity 0、extends Entity 0
附魔 / 药水效果 Enchantment 0、PotionEffect 0
维度 / 世界生成 registerDimension 0、WorldProvider 0、WorldGenerator 0
群系 / 结构 BiomeGen / Biome 0、世界生成 0
成就 Achievement 0
指令 addChatCommand 0
合成配方 IRecipe / CraftingRecipe 0
多方块 Multiblock / TileMultiblock 0
本地化 无 assets/*/lang/*.lang(src/main/resources 下仅 3 张贴图 + mainmenu_default.json + mcmod.info)

本 mod 也没有 KeyBinding 注册(grep -rn "KeyBinding" src/ → 0),唯一的键盘交互是 重载配置热键 的裸 LWJGL 键码轮询。

已知源码缺陷与矛盾

# 问题 位置
1 schema 与代码的段名冲突:schema 写 labels,代码只认 texts,且 get("texts") 无判空 → 用 schema 的名字写文件必崩 mainmenu.schema.json:591 vs GuiConfig.java:220
2 主菜单自身 background 写 synced: true 必崩:addGui 在 load() 之后执行,此时 getGUI("mainmenu") 返回 null GuiConfig.java:184-186 + Config.java:29 + ConfigurationLoader.java:64,79
3 四个顶层段(images/buttons/texts/other)全部无判空硬读,缺任一即启动崩溃 GuiConfig.java:210,220,230,115
4 TextURL 对可变 String 值加锁且字段无 volatile,跨线程可见性无保证 TextURL.java:30-36 + LoadStringURL.java:44-47
5 openLink 用 equals(大小写敏感),其余 7 个动作用 equalsIgnoreCase GuiConfig.java:391
6 getStringPlease 对任意数组字段随机取值(不只飘字),且每次调用 new Random() GuiConfig.java:368-379
7 fadeDuration = 0 会在 getAlphaFade 除零 Slideshow.java:44
8 背景 image 字段无判空硬读,与 slideshow 分支不构成真正的二选一 GuiConfig.java:177
9 #mcpversion# 依赖反射 Forge 私有字段 Loader.mcpversion,GTNH 改名即 NPE StringReplacer.java:35-41
10 #mcversion# 硬编码字面量 "1.7.10",不读实际 MC 版本 StringReplacer.java:24
11 schema 的 openGui 枚举漏 4 个代码支持的键(options.ressourcepacks/options.shaderpacks/options.broadcast/mainmenu),且未说明 custom. 前缀 mainmenu.schema.json vs ActionOpenGUI.java
12 schema 把 alignments 画在 other 段,代码从顶层读 mainmenu.schema.json vs GuiConfig.java:98
13 schema 声明的 version 字段代码从不读取 mainmenu.schema.json vs GuiConfig.load
14 快捷键热键无边沿检测,按住即每 tick 全量重载 JSON GuiCustom.java:458-464
15 未识别的原版按钮只打 DEBUG 日志(控制台默认不可见) CMMEventHandler.java:86-89
16 ActionConnectToServer.serverName 声明后从不赋值也从不读取(死字段) ActionConnectToServer.java:11
17 TextureURL.load() 无任何调用点(死代码),实际走 LoadTextureURL 线程 TextureURL.java:35-53
18 Text.setLink() 无任何调用点(死代码) Text.java:54-56
19 options.ressourcepacks 是拼写错误的兼容别名,与正确拼写并存 ActionOpenGUI.java:60-61
20 字段 ichBinEineSlideshow(德语"我是一个轮播")是作者个人命名混入公共配置模型 Background.java:15、Image.java:16