输入管线补丁

基本信息

属性 值
补丁目标 原版 net.minecraft.client.settings.KeyBinding
补丁类 com.blamejared.controlling.mixins.early.MixinKeyBinding
加载阶段 Phase.EARLY(客户端)
Mixin 配置 mixins.controlling.early.json,包 com.blamejared.controlling.mixins.early
枚举项 Mixins.KEYBINDING

功能

组合键要生效,就必须在原版"这个键码按下了吗"的判定里插入修饰键检查。 MixinKeyBinding 对 KeyBinding 的 4 个方法做了注入,其中前两个完全取消原版实现 (ci.cancel()),后两个只是提前返回 false。

被补丁的原版方法 注入位置 是否取消原版 行为
setKeyBindState(int, boolean) HEAD 是 逐个匹配 keyCode 的按键,只有修饰键满足时才置位 pressed
onTick(int) HEAD 是 只有修饰键满足时才累加 pressTime
getIsKeyPressed() HEAD 否(提前返回) 修饰键不满足时直接返回 false
isPressed() HEAD 否(提前返回) 修饰键不满足时把 pressTime 清零并返回 false

被 shadow 的原版字段包括静态的 keybindArray、keyCode、keyCodeDefault、pressed、 pressTime,以及非静态的 keyCode。

按键激活判定

所有静态判定最终都汇到 controlling$isBindingActiveWithModifier(KeyBinding, int inputKeyCode), 按顺序执行 4 步:

步骤 条件 返回
1 该按键不是 ComboKeyBinding true(直接放行,不参与组合键系统)
2 修饰键为 NONE 且 keyCode == inputKeyCode 且该输入键码本身是修饰键 true
3 修饰键为 NONE 且 controlling$hasActiveModifiedSiblingBinding(...) 为真 false(压制)
4 其余情况 combo.controlling$isModifierActive()

第 2 步的含义:当玩家直接按下 Ctrl/Shift/Alt 键本身时放行,这样裸修饰键(如直接绑定 Shift)仍然能被按到,而不会被"必须同时存在另一个修饰键"的条件卡死。

第 3 步是本 mod 最重要的行为修正,见下节。

兄弟按键压制

controlling$hasActiveModifiedSiblingBinding(KeyBinding keyBinding, int inputKeyCode) 遍历 keybindArray,寻找同一键码上另一个正在生效的组合键:

  • 跳过自身;
  • 跳过键码不等于 inputKeyCode 的绑定;
  • 若该绑定是 ComboKeyBinding、其修饰键不为 NONE、且该修饰键此刻 isActive() → 返回 true。

结果就是:当玩家按住 G 时,如果 G 上还绑了一个 Ctrl + G,那么裸的 G 会被临时压制, 只有 Ctrl + G 生效。反过来在没有修饰键按下时,裸 G 照常工作。

源码在 GuiNewKeyBindingList 里的注释把这称为"less severe form of conflict"(较轻度的冲突), 对应 GUI 上用金色而非红色 [ ] 标记的情形。

裸修饰键绑定的额外条件

controlling$isModifierActive() 有一个针对 NONE 的分支:

  • 若 keyModifier != NONE → 直接返回 keyModifier.isActive();
  • 若 keyModifier == NONE 且 键码本身是一个修饰键(KeyModifier.isKeyCodeModifier(keyCode)) → 返回 KeyModifier.fromKeyCode(keyCode).isActive();
  • 否则 → 返回 true(普通按键无修饰键要求)。

即:把裸 Ctrl / Shift / Alt 绑成热键时,只有按住该修饰键时该热键才触发。 而普通按键不绑修饰键时不受任何限制。

其他 Mixin 与加载器

除按键本身外,还有两个 Mixin 加载基础设施:

类 作用
EarlyMixinsLoader 实现 IFMLLoadingPlugin + IEarlyMixinLoader,标注 @IFMLLoadingPlugin.MCVersion("1.7.10"),Mixin 配置 mixins.controlling.early.json。所有 IFMLLoadingPlugin 方法均返回 null 或空实现
LateMixinsLoader 标注 @LateMixin,实现 ILateMixinLoader,Mixin 配置 mixins.controlling.late.json
Mixins 枚举,KEYBINDING → 早期 MixinKeyBinding,GAME_SETTINGS → 早期 MixinGameSettings

Mixins 枚举中没有任何 Phase.LATE 条目,所以 mixins.controlling.late.json 当前不注册任何 mixin(仓库中另有未被引用的 mixins.controlling.json)。

配套资源 META-INF/controlling_at.cfg 开通了两个原版私有字段以支持界面实现: GuiScreen.buttonList(field_146292_n)与 GuiScreen.selectedButton(field_146290_a)。

相关条目