CFXControl Flex Wiki
English中文

平台支持

Control Flex 通过 libgamepadjni + SDL3 读取手柄。桌面三平台的原生库与 SDL3 都随 JAR 提供,开箱即用;Android 上 SDL3 必须来自启动器 APK,因此不同启动器的行为并不完全一样。

支持总览

平台 架构 SDL3 来源 状态
Windows x86_64 JAR 内置(SDL3.dll) 支持
macOS x86_64 · Apple Silicon (aarch64) JAR 内置(libSDL3.0.dylib) 支持
Linux x86_64 · aarch64 JAR 内置(libSDL3.so) 支持
Android
启动器里的游戏 JVM
arm64-v8a · armeabi-v7a · x86_64 启动器 APK 提供,JAR 不打包 支持
iOS — — 尚未支持

平台判定只看 os.version:以 Android- 开头即视为 Android,其余按桌面处理。os.name(Android 启动器同样写 Linux)只用于诊断日志,不参与判定。

桌面平台

Android(启动器环境)

Android 版 Minecraft: Java Edition 由启动器提供的 JVM 运行,手柄链路因此分成两段:SDL3 来自启动器 APK(启动器已经在 ART 侧装好 SDL 的 glue),libgamepadjni.so 由模组自带并按 os.arch 解压加载。两者顺序固定 —— 先 SDL3,再 JNI 桥,否则动态链接器绑不到同一份库。

先改两项启动器设置

这两项都在启动器里改,不在模组里;换启动器、或实例目录被重置之后要重新设一次。不改也能进游戏,只是看起来像坏了:屏幕上多出一个乱飘的指针,或者手柄在设置里根本不出现。

1 · 隐藏屏幕上的虚拟鼠标指针

启动器画的指针是它自己的覆盖层,和模组的虚拟光标没有关系,两者不会互相同步 —— 结果就是屏幕上出现两个指针,或者指针停在上一次触屏的位置、和真正的点击热点差一截。

三种做法效果一样,看你用的启动器提供哪一种,任选其一:

  • 把指针显示关掉(隐藏虚拟鼠标光标)
  • 把指针大小设为 0
  • 把指针不透明度设为 0(即全透明)

之后屏幕上只剩模组自己的光标,位置和点击判定一致。样式与缩放在游戏内的「光标样式」里改:System / Bedrock / Hand,缩放 0.1–1.0。

2 · 手柄输入模式改成 SDL 直通(ZL2 / FCL)

ZL2 与 FCL 的「手柄输入模式」默认是「映射(虚拟按键)」:手柄按键与摇杆先被翻译成虚拟键鼠事件,再交给游戏。这样 ControlFlex 拿不到原始设备 —— 设置里看不到手柄,死区、扳机行程、震动也全由启动器说了算。

改成 SDL 直通。ZL2 的路径是 设置 → 手柄设置 → 手柄输入模式。选项自己的说明就写着「手柄输入经 SDL/GLFW gamepad API 原样交给游戏,不经过按键映射」—— 正是要的状态:SDL3 直接打开设备,模组经 libgamepadjni 读到原始轴与按键,多手柄、热插拔、震动全靠这一步才能生效。

  • 先确认同页顶部的手柄控制总开关是开着的 —— 只有在别的手柄或外设被误识别成手柄时才需要关掉它。
  • 校验:进游戏后 设置 → 手柄选择 里能按名字看到设备,按任意键有反应。
  • 代价:切到 SDL 直通后,「映射(虚拟按键)」对这个手柄不再生效。这是预期行为,映射全部交给模组的键位面板。
  • 改完退出游戏重新启动一次,让启动器重新枚举设备。

已验证的启动器

启动器 如何找到启动器的 libSDL3.so
Fold Craft Launcher (FCL) 设置 POJAV_NATIVEDIR 为 APK native 目录,走绝对路径
Zalith Launcher 2 (ZL2) 同上
Mojo Launcher
v3_openjdk
不设 POJAV_NATIVEDIR;APK native 目录在 LD_LIBRARY_PATH 里,通过 System.loadLibrary("SDL3") 命中
Amethyst Android 设置 POJAV_NATIVEDIR,走绝对路径

这是兼容性说明,不是运行时白名单:只要启动器把 os.version 写成 Android-*,未列出的启动器同样会走 Android 路径。

ABI 与原生库

os.arch JAR 内目录
aarch64 / arm64native/android-arm64-v8a/
arm / armv7l / armv8lnative/android-armeabi-v7a/
x86_64 / amd64native/android-x86_64/
i386 及其他 不支持 —— 初始化失败,游戏仍可正常启动(只是没有手柄)

Android 上的注意事项

不要覆盖 os.version。部分启动器的自定义 JVM 参数或版本 JSON 会把它改成普通内核号(例如 5.0)或干脆不写 Android- 前缀,这时模组会把环境当成桌面 Linux,去加载桌面的 SDL3,结果是手柄在设置里始终不可见。确认启动器注入 -Dos.version=Android-<版本> 没有被你的自定义参数覆盖。

平台与依赖对照

平台 需要额外安装 配置文件位置
Windows / macOS / Linux 无(SDL3 内置) config/controlflex/
Android 无(SDL3 由启动器提供;启动器需被本页列出的机制覆盖)—— 另外还要改上文那两项启动器设置 启动器实例目录下的 config/controlflex/

排障速查

现象 先检查什么
设置 → 手柄选择里完全没有设备(桌面) JAR 是否与 MC 版本、加载器匹配(见 MC 版本支持);手柄是否被其他程序(Steam Input、远程串流等)独占
Android 上游戏正常但手柄始终不可见 os.version 是否被覆盖;启动器是否属于已验证的那几种;日志里 POJAV_NATIVEDIR 与 SDL3 路径是否打印出来
屏幕上出现两个指针,或指针位置和实际点击位置对不上 启动器的虚拟鼠标指针还开着 —— 隐藏它,或把大小 / 不透明度设为 0
手柄在启动器自带的按键映射里能用,但「设置 → 手柄选择」里始终没有它 手柄输入模式选的是「映射(虚拟按键)」而不是 SDL 直通 —— 见上文那两项设置
日志出现 UnsatisfiedLinkError Android 上要么是不支持的 ABI(如 32 位 x86),要么启动器 APK 没带 SDL3;桌面上是原生库与系统架构不匹配 —— 注意 Windows 只有 x86_64 版本,ARM64 机器上要换 x64 版 Java。
iOS 设备上找不到入口 iOS 尚未接入(平台层已预留判定位,但没有原生库)