找回密码
 初始化身份识别芯片
搜索
查看: 253|回复: 4

中文输入修复

[复制链接]

巡洋大副

发表于 昨天 21:15 | 显示全部楼层 |阅读模式
原创Mod发布
中文输入修复 2.0.0 / ID:ChineseInputFix
ChineseInputFix
游戏内中文输入法支持。通过窗口子类化捕获系统IME输入,自动定位候选框到文本框下方,非侵入式动态加载JNA,无需修改游戏主程序文件。支持战役、主菜单、弹窗等所有文本输入场景。
Mod作者: CHesand
Mod类别: 功能
Mod适用版本: 0.98 0.96 0.95 
Mod更新时间: 2026-08-01
可安全移除:
依赖Mod: 无 
其它依赖Mod:
冲突Mod:
Mod下载地址:
网盘提取码 / 解压密码:
功能简介
本mod为《远行星号》(Starsector) 提供完整的原生中文输入法支持,无需修改游戏任何主程序文件。

原生系统IME :使用Windows系统自带的中文输入法(搜狗、百度、微软拼音等均可)
自动候选框定位 :候选框自动紧贴文本框下方显示,不遮挡输入区域
全场景支持 :主菜单、角色改名、战役界面、数据百科搜索框、弹窗等所有文本输入场景
零侵入安装 :无需修改vmparams、无需复制jar到游戏目录、mod可以安全卸载
零快捷键 :无需切换模式,直接在文本框中打字即可输入中文
线程安全 :彻底解决输入中文时游戏Fatal崩溃问题


技术细节 1. 非侵入式JNA动态注入(核心突破)
游戏自带的安全沙箱(ScriptClassLoader)会拦截以下操作:

- 所有 java.io.File 操作(包括 new File() )
- 所有 java.lang.reflect 反射操作(甚至引用 Method / Field 类都会触发SecurityException)
- JDK 25的模块强封装禁止 setAccessible(true) 访问内部API
为绕过这些限制,设计了双层类加载器架构:

JnaBootstrap.java :
- 由游戏ScriptClassLoader加载, 字节码中完全不包含任何对java.lang.reflect包的符号引用 (包括import、方法参数、局部变量、泛型、字符串常量等)
- 通过System Properties传递参数和结果,使用Class.forName()触发JnaLoader静态初始化
- 创建trampoline URLClassLoader(父=系统类加载器)加载JnaLoader,绕过ScriptClassLoader沙箱
JnaLoader.java :
- 由trampoline类加载器加载,不受ScriptClassLoader安全限制
- 使用 sun.misc.Unsafe 直接读取private字段偏移量, 完全不调用setAccessible() ,绕过JDK 25模块强封装
- 沿类加载器父链深度遍历,在深度1找到标准JDK AppClassLoader(游戏自定义AppClassLoader的父加载器)
- 读取URLClassPath内部的 path (ArrayList) 和 unopenedUrls (ArrayDeque) 集合字段,直接调用public add() 方法注入JNA URL
关键代码片段:
2. 严格线程隔离架构
LWJGL 2的输入类(Mouse/Keyboard)和游戏UI对象 不是线程安全的 ,后台线程直接访问会导致内部状态竞争损坏,触发Fatal崩溃( Cannot invoke "com.fs.starfarer.ui.c.getPosition()" because "<local4>" is null )。

解决方案采用三线程严格隔离:

线程 职责 可访问对象 CIF-IME-Service 后台线程 钩子重试、轮询IME结果、剪贴板+Robot Ctrl+V注入 仅系统API(剪贴板、AWT Robot), 完全不访问游戏UI对象 游戏主线程(渲染线程) 定期UI扫描、文本框坐标缓存更新、IME窗口重定位 游戏UI对象(反射调用) WndProc回调线程(Windows窗口过程) 处理IME消息、记录鼠标点击、定位IME窗口 仅读取主线程预缓存的坐标数据, 禁止在回调中扫描UI组件树

中文注入通路完全不依赖游戏UI:

WndProc捕获IME结果 → 后台线程设置剪贴板 → Robot触发Ctrl+V → 游戏文本框接收粘贴
3. 窗口子类化与IME消息处理
通过JNA调用Windows API实现:
SetWindowLongPtr(GWLP_WNDPROC) 子类化游戏窗口,拦截WM_IME系列消息
ImmGetCompositionString 读取IME确认的汉字结果
ImmSetCompositionWindow / ImmSetCandidateWindow 定位组合窗口和候选窗
处理 WM_IME_SETCONTEXT 时改写lParam为 ISC_SHOWUIALL ,强制系统显示IME窗口
关键防抖处理:
ImmSetCompositionWindow 调用后设置500ms冷却防抖,避免IME回声消息触发无限递归重定位
忽略 IMN_SETCOMPOSITIONWINDOW(wParam=9) IME回声通知消息
WndProc回调中只读取预缓存的文本框坐标,不触发UI组件树扫描(避免僵尸组件null引用) 4. 坐标系统转换
游戏PositionAPI使用OpenGL坐标系( 左下角原点,y轴向上 ),而Windows客户区使用屏幕坐标系( 左上角原点,y轴向下 ),需要正确转换:

候选窗定位策略(5级锚点选择):

1. 优先1秒内获得焦点的文本框
2. 其次1秒内文本发生变化的文本框
3. 再次1秒内鼠标点击命中的文本框
4. 兜底使用鼠标最后点击位置正下方20px
5. 使用 CFS_EXCLUDE 标志排除文本框区域(加2px padding),让系统自动定位候选窗避免遮挡 5. 文本框缓存机制
- 主线程每秒扫描一次UI组件树,缓存所有文本框的Windows坐标到 ConcurrentHashMap
- WndProc/后台线程 只读 缓存,不做任何UI反射调用
- 鼠标点击、IME开始时设置 forceScanRequested 标志,主线程立即强制扫描更新缓存
- 强制扫描完成后立即调用 ImeCapture.repositionFromMainThread() 更新IME窗口位置

已知限制
1. 仅支持Windows系统(依赖Win32 IME API)
2. 需要在战役场景加载完成后注册协调器(主菜单文本框输入需进入战役后再返回主菜单即可正常使用)
3. IME候选框使用系统默认样式,与游戏UI风格可能不完全一致(这是原生IME的正常表现)

感谢使用!如有问题请提供包含 [SysIME] 、 [JnaBootstrap] 标签的日志文件。


本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?初始化身份识别芯片

×

评分

参与人数 3星币 +15 收起 理由
天狼亡者 + 5 鉴定为本年度最佳辅助mod之一👍 ...
AIYHBVDCX + 5 评分: 差不多是势力争霸和swp那种必装的mod ...
人质救星Fuze + 5 惊了!

查看全部评分


Oculus Dei Omnividentis, Ordin Illuminati Trinitatis
Pro Sacrā Devōtiōne, Pro Sublīmī Sacrificiō, Dominus Deī Omnipotentis.

星域军阀

发表于 昨天 21:23 | 显示全部楼层
真神登场

战列舰长

发表于 昨天 21:36 来自手机 | 显示全部楼层
好好好

势力巨擘

英仙领大胖鸡

发表于 昨天 21:50 | 显示全部楼层
我草 牛啊
游历星域, 播撒福恩, 光荣朝圣, 复兴英仙领.

势力巨擘

一个响亮的名字~

发表于 昨天 23:48 | 显示全部楼层
真正的“请输入文本”

本版积分规则

Archiver|手机版|小黑屋|远行星号中文论坛

GMT+8, 2026-8-2 00:15

Powered by Discuz! X3.5

© 2001-2077 Tencent Cloud | Durian Software Studio

快速回复 返回顶部 返回列表