11package com .mio .libpatcher .transformer ;
22
3- import com .mio .libpatcher .util .LogUtil ;
43import javassist .CtClass ;
54import 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 */
1314public 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