自定义建世界界面(GuiCreateCustomWorld)
基本信息
| 属性 | 值 |
|---|---|
| 所属 | Default World Generator(modid defaultworldgenerator) |
| 入口类 | GuiCreateCustomWorld(继承原版 GuiCreateWorld) |
| 源码 | gui/GuiCreateCustomWorld.java:13 |
| 触发类 | events/GuiEvents.java |
| 注册时机 | preInit,MinecraftForge.EVENT_BUS(DefaultWorldGenerator.java:28) |
两处 GUI 拦截
GuiEvents 以 EventPriority.HIGHEST 监听
GuiScreenEvent.ActionPerformedEvent.Pre,做两件事:
| # | 界面 | 按钮 id | 行为 | 行号 |
|---|---|---|---|---|
| 1 | GuiSelectWorld(世界列表) |
3 | 不走原版建世界流程,改为 new GuiCreateCustomWorld(currentScreen) 并 displayGuiScreen |
GuiEvents.java:20-27 |
| 2 | GuiCreateWorld(建世界) |
5 | 受 Lock World Generator 控制,可被吞掉 | GuiEvents.java:29-36 |
拦截 #1 会先播按钮音效(行 24)再 setCanceled(true)(行 25),
因此与 #2 不同,锁定时没有音效。
构造函数做了什么
GuiCreateCustomWorld 继承原版 GuiCreateWorld,在构造阶段就把
默认世界生成器写死(GuiCreateCustomWorld.java:15-78):
- 反射取出父类的私有整型字段
field_146331_K并setAccessible(true)(行 19-20)。这是当前选中的世界类型索引。 - 先把 superflat 预设字段
field_146334_a清空为""(行 22)。 worldGenType初值 0(行 24),遍历WorldType.worldTypes:- 名字与 World Generator 配置匹配(忽略大小写)
→ 取
getWorldTypeID()(行 29-31) - 名字为
flat→ 解析 Flat World Config 写入field_146334_a(行 34-68)
- 名字与 World Generator 配置匹配(忽略大小写)
→ 取
- 用
field_146331_K.setInt(this, worldGenType)回写,让 GUI 显示为已选中 (行 72)。
遍历对每个生成器都要求 getCanBeCreated() 为真(行 27)。
为什么必须用反射
field_146331_K 是原版 GuiCreateWorld 的私有字段,
@SideOnly 且非 protected,子类无法直接访问。
mcmod.info 的 credits 写明 “Special thanks to amadornes for reflection help”
——反射方案即由此而来。field_146334_a 则是 protected,
子类可直接赋值,无需反射(行 22、67)。
已知源码问题
- 字段名硬编码,映射变更即失效:
"field_146331_K"以字符串写死 (行 19)。1.7.10 的 MCP 映射一旦变化,getDeclaredField抛NoSuchFieldException,被最外层catch (Exception ex)吞掉(行 74-77), 只打两条Log.fatal,整个默认生成器设置静默失效。 这是本 mod 最脆弱的耦合点。 - 异常被完全吞掉:行 74-77 只
Log.fatal("Fatal Error:")+Log.fatal(ex),不重抛、不弹窗。玩家侧表现为「设置没生效」,无任何线索。 worldGenType不 break:同名的多个WorldType会后者覆盖前者(行 29-32)。GuiCreateCustomWorld继承原版类,因此没有新增任何按钮; 本 mod 唯一的 UI 变化是世界列表里 id 3 的按钮被改道。 ⚠️ 该 id 在原版GuiSelectWorld中对应的按钮名无法从本仓库核实。GuiEvents.java:38有一行// Log.error(event.button.id + ...)处于注释状态,不参与运行;不能据此认为本 mod 会上报按钮 id。
相关条目
- World Generator - 决定默认选中项
- Flat World Config - 决定超平坦预设
- Lock World Generator - 同一事件类中的另一个拦截