默认键位下发
基本信息
| 属性 | 值 |
|---|---|
| 下发源文件 | config/defaultkeys.txt(打包作者编写) |
| 记录文件 | knownkeys.txt(游戏根目录,自动生成) |
| 加载函数 | EventHandler.reloadDefaultMappings()(EventHandler.java:316-381) |
| 触发时机 | 主菜单首次打开时(GuiOpenEvent + initialized 标志) |
| 依赖 | Access Transformer 把 KeyBinding.keyCodeDefault 提升为 public |
文件格式
config/defaultkeys.txt 每行一条:
key_<KeyBinding.getKeyDescription()>:<keyCode>
由 saveDefaultMappings 生成(:303-314):
for (KeyBinding keyBinding : gameSettings.keyBindings) {
writer.println("key_" + keyBinding.getKeyDescription() + ":" + keyBinding.getKeyCode());
}
键位描述即 lang key(如 key.forward),因此该文件是全语言无关的。
加载流程
reloadDefaultMappings()
├─ clear defaultKeys / knownKeys
├─ 读 config/defaultkeys.txt → Map<描述(去掉 "key_" 前缀), keyCode>
│ 跳过空行;split(":") 后长度必须为 2 且 s[0] 以 "key_" 开头,否则跳过
│ 解析失败只 printStackTrace
├─ 读 knownkeys.txt → List<String>
└─ 遍历 gameSettings.keyBindings:
若 defaultKeys 含该描述 →
keyBinding.keyCodeDefault = 默认值 ← 依赖 AT
若 knownKeys 不含该描述 →
keyBinding.setKeyCode(keyCodeDefault)
knownKeys.add(描述)
然后 KeyBinding.resetKeyBindingArrayAndHash()
最后重写 knownkeys.txt
设计意图
knownkeys.txt 记录"本模组已经为哪些键位下发过默认值":
- 键位第一次出现时(模组包刚加了这个绑定)→ 套用默认值;
- 之后玩家自行改键 → 该描述已在
knownKeys中 → 绝不覆盖。
这使得打包作者新增键位绑定时能自动下发默认值,同时不破坏玩家已有习惯。若删掉 knownkeys.txt,下次启动会把所有 defaultkeys.txt 里的键位重置一遍。
触发点
@SubscribeEvent
public void finishMinecraftLoading(GuiOpenEvent event) {
if (!initialized && event.gui instanceof GuiMainMenu) {
reloadDefaultMappings();
initialized = true;
}
}
initialized 是 static 布尔,保证整个进程只执行一次。事件注册在 MinecraftForge.EVENT_BUS 上,且仅客户端(DefaultKeys.java:28-32)。
限制
keyCodeDefault的写入依赖 AT;若 AT 失效,IllegalAccessError会直接抛出(无 try/catch)。- 键位描述硬绑定 lang key。若某个 mod 改名其键位描述,条目会静默失效(
defaultKeys.containsKey为 false,无任何日志)。 knownkeys.txt按描述记录,不区分 mod。同名描述的键位会被当作同一个处理。- 本模组不注册任何
KeyBinding(new KeyBinding全仓 0 处),只改写别人的。 - 无配置开关,无法禁用这套键位下发。
相关条目
- Access Transformer -
keyCodeDefault可写的前提 - /defaultconfigs 指令 -
saveKeys生成该文件 - 启动前文件铺设 -
knownkeys.txt所在目录的由来