桥接模组
compat JSON 只能调整「已经存在的东西」—— 已注册的 KeyMapping、已派发的按键、已打开的界面。模组要是自己造了一套输入系统,就得在 Java 侧接进来,这就是桥接模组。这一页先回答「到底该不该写代码」,再给一张手法速查表;接入步骤、接口细节、五个官方实现的源码、生态清单各占一页。
本节: 概览 · 接入与生命周期 · 接口速查 · 官方实现 · 谁在用这套 API
接入与生命周期
gradle 依赖、SPI 注册、六个回调的时序、资源装到哪一层,以及多加载器工程怎么摆。
从零搭一个 →
接口速查
13 个公开类型的方法签名、线程约定、动作 ID 写法与版本变更。
查接口 →
官方实现解剖
Epic Fight / Create / Exposure / EMI / 载具五个桥接逐个拆,附五种手法的代码。
看实现 →
谁在用这套 API
哪些模组真的依赖 control-flex-api、哪些只是被适配,各自的版本要求。
看清单 →
先判断:到底该不该写代码
| compat JSON 能做到 | 只有桥接模组能做到 |
|---|---|
| 把已注册的键位归到 Main / Screen / Overlay | 让没有注册 KeyMapping 的按键出现在绑定列表里 |
| 选择派发通道(含 GLFW 轮询镜像) | 接住直接调 GLFW.glfwGetKey 的模组(GLFW 层不可注入) |
| 按主手物品 + 玩家状态压制动作 | 把模组的运行时状态推给 Control Flex 当条件用 |
| 相位保持、忽略键、提示文案、每页摇杆参数 | 声明「某个叠层 / 相机现在被模组接管了」,切换摇杆与视角行为 |
| 用虚拟键鼠兜底只认物理键的模组 | 读摇杆轴做完全自定义的逻辑(载具转向、镜头),或把动作转发回模组自己的函数 |
一句话判断:目标模组的按键能在「按键映射 → 该模组」里看到,就不需要桥接;看不到,才需要。三种手段是递进的 —— 自动发现 → compat JSON → 桥接,别跳过前两级直接写代码。
五种手法速览
桥接不是一种写法,而是五类问题的五种答案。先认出目标模组属于哪一类,再跳到官方实现看对应的完整代码。
| 目标模组的信号 | 桥接要做什么 | 代表实现 |
|---|---|---|
| 键位存在自己的配置里,从不注册 KeyMapping | 注册一组伪 KeyMapping 让自动发现看见,按下时转发回模组自己的函数 | cfx-compat-emi |
直接读 InputConstants / ControlsUtil 这类键态查询 |
在它的判定方法上注入一次,把模拟移动的脉冲并进结果 | cfx-compat-create |
直接调 GLFW.glfwGetKey,连 InputConstants 都不过 |
mixin 落到它自己的读取入口上,回答「现在按着没有」 | cfx-compat-vehicles |
| 有运行时状态会改变按键语义(战斗模式、载具模式) | 把状态推成 modId:state,让 compat JSON 当条件用 |
cfx-compat-epicfight |
| 自绘叠层抢走镜头与光标,但不是 Screen | 打开 / 关闭时成对通报前台与后台 | cfx-compat-exposure |
还有一种情况是模组接管了渲染相机(TPR 战斗视角、锁定目标):这时要额外实现 ICameraLookConsumer,把视角增量交给接管方,否则手柄转不动画面。Epic Fight 桥接同时用了第 4 与这一类。