Skip to content

Commit 3bdc1dd

Browse files
committed
fix: TTSCancel 注入体改用反射直调并显式数组,修复 javassist 编译失败导致补丁被跳过
1 parent f9327f7 commit 3bdc1dd

1 file changed

Lines changed: 16 additions & 14 deletions

File tree

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
package com.mio.libpatcher.transformer;
22

3-
import com.mio.libpatcher.util.LogUtil;
43
import javassist.CtClass;
54
import javassist.CtMethod;
65

76
/**
87
* 游戏复述的截停实现:NarratorLinux 的打断只靠 executionBatch 批次号跳过尚未开始的句子,
9-
* 正在播放的句子无法中止。启动器的 flite 桥接将朗读改为异步排队后,
10-
* clear() 需额外经 JNA 调用 flite 库的 flite_cancel 符号,通知桥接立即停止系统 TTS 的当前朗读并清空排队文本。
11-
* 桌面端真实 flite 库没有该符号,注入的调用失败时静默忽略。
8+
* 正在播放的句子无法中止。在 clear() 前置经 JNA 调用 flite 库的 flite_cancel 符号,
9+
* 通知桥接立即停止系统 TTS 的当前朗读;桌面端真实 flite 库没有该符号,调用失败时静默忽略。
10+
*
11+
* <p>注入体只引用 JDK 类型并以反射驱动 JNA:com.sun.jna 是否可见因游戏加载器
12+
* (Knot/ModLauncher)而异,编译期引用会在 javassist 解析时失败,导致整个补丁被跳过。</p>
1213
*/
1314
public class TTSCancelTransformer implements BaseTransformer {
15+
// javassist 编译器不支持 varargs 解析,反射调用的参数表必须用显式数组
16+
private static final String HOOK =
17+
"{ try {"
18+
+ " Object lib = Class.forName(\"com.sun.jna.NativeLibrary\")"
19+
+ " .getMethod(\"getInstance\", new Class[]{String.class}).invoke(null, new Object[]{\"flite\"});"
20+
+ " Object fn = lib.getClass().getMethod(\"getFunction\", new Class[]{String.class}).invoke(lib, new Object[]{\"flite_cancel\"});"
21+
+ " fn.getClass().getMethod(\"invokeVoid\", new Class[]{Object[].class}).invoke(fn, new Object[]{new Object[0]});"
22+
+ " } catch (Throwable t) {} }";
23+
1424
@Override
1525
public String getTargetClassName() {
1626
return "com.mojang.text2speech.NarratorLinux";
@@ -21,15 +31,7 @@ public void transform(CtClass clazz) throws Throwable {
2131
if (!Boolean.parseBoolean(System.getProperty("miolibpatcher.ttsCancel", "true"))) {
2232
return;
2333
}
24-
if (pool.find("com.sun.jna.NativeLibrary") == null) {
25-
LogUtil.error("TTSCancel: JNA is not visible to the ClassPool, narrator cancel patch skipped");
26-
return;
27-
}
28-
CtMethod method = clazz.getDeclaredMethod("clear");
29-
method.setBody(
30-
"{ executionBatch.incrementAndGet();"
31-
+ " try { com.sun.jna.NativeLibrary.getInstance(\"flite\")"
32-
+ " .getFunction(\"flite_cancel\").invokeVoid(new Object[0]); }"
33-
+ " catch (Throwable t) {} }");
34+
// insertBefore 保留原方法体,兼容各代 NarratorLinux(含无 executionBatch 的 1.13.9-)
35+
clazz.getDeclaredMethod("clear").insertBefore(HOOK);
3436
}
3537
}

0 commit comments

Comments
 (0)