阶段四:Spine 3.8.99 编辑器里挂上自建视图面板

目标:在 Spine 编辑器窗口内部加一个自己的视图面板(按钮 + 文字显示),
点击读取场景对象,并像原生面板一样出现在 Views 菜单、可停靠可折叠。

本轮打通:
1. 编辑器在我们自己的进程里完整启动
   - 类加载器必须是 URLClassLoader 本身(自检要求)
   - Editor.main 必须在 AWT EDT 上调用
   - jvm.cfg 第 21 行要以两个空格结尾 + -DSpineJava
   - Editor.D:I 版本号、fonts/、/tzax 资源、Java8 版 launcher.Launcher 替身
2. 3.8.99 全量解密 → 可读源码
   - 字符串 17251/17461(伪造同名调用帧对齐 key)
   - 混淆动态派发还原 53871 处(调引导方法取 MemberName)
3. 自建视图
   - agent 在内存里给 us 枚举加 spineView 常量(不改磁盘,避开完整性自检)
   - 面板 Actor 由外部反射填进 us.spineView.D
   - 复用已有图标做别名(不新建图片资源)
   最终 "Spine View" 出现在 Views 菜单,可与 Tree 并排停靠、折叠展开

另外:
- ViewPatcher/ViewAgent:视图枚举与面板挂载的字节码插桩
- DecAll/ObMap/rewrite_source:字符串解密、派发还原、可读源码生成
- 阶段四-视图面板挂载.md:完整记录做法与踩过的坑

不纳入版本管理:rea/(独立仓库)、tools 下的 JDK/Ghidra 工具链、
Spine.app 与 spine-lab 副本、从载荷派生的批量产物。
This commit is contained in:
tianmo committed 2026-10-16 13:34:18 +08:00
commit 2e7ab7c33c
113 files changed
+25327

No files matched your search

+46
View File
@@ -0,0 +1,46 @@
#!/bin/zsh
# 编译 ViewPanel:注入器(C,无 UI 依赖)+ 面板(纯 Java / Scene2D 反射)
set -e
HERE="$(cd "$(dirname "$0")" && pwd)"
cd "$HERE"
# 找一个 JDK(编辑器运行时是 OpenJDK;本机现成的是 /tmp 下的 Temurin 17)
if [[ -z "$JAVA_HOME" ]]; then
for candidate in /tmp/jdk-17.0.20.1+1/Contents/Home /tmp/jdk*/Contents/Home; do
[[ -x "$candidate/bin/javac" ]] && JAVA_HOME="$candidate" && break
done
fi
if [[ -z "$JAVA_HOME" || ! -x "$JAVA_HOME/bin/javac" ]]; then
echo "找不到 JDK:请设置 JAVA_HOME" >&2
exit 1
fi
mkdir -p build/classes
echo "== 编译 Java 侧(javac $("$JAVA_HOME/bin/javac" -version 2>&1))"
find src -name '*.class' -delete 2>/dev/null || true
"$JAVA_HOME/bin/javac" --release 8 -encoding UTF-8 -d build/classes $(find src -name '*.java')
# 保名类清单:这套运行时把 libGDX 基类混淆了,但 ui/* 和 editor/* 保名。
# 旧版本的明文载荷里能直接列出这些类名,用它们做静态字段扫描的候选。
UPDATES="$HOME/Library/Application Support/Spine/updates"
if [[ -f "$UPDATES/3.8.99" ]]; then
unzip -l "$UPDATES/3.8.99" 2>/dev/null \
| awk '{print $4}' | grep -E '\.class$' | grep -E '^(com|org)/' \
| sed 's#/#.#g; s#\.class$##' | sort -u > build/kept-classes.txt
echo "保名类清单: $(wc -l < build/kept-classes.txt) 个"
fi
echo "== 编译注入器"
# 编译成通用二进制:3.8.99 的编辑器是 x86_64 的 Spine_x86(Rosetta),
# 只带 arm64 的 dylib 被继承到那个进程会直接 dyld 报错。
clang -dynamiclib -O2 -Wall -Wextra -Wno-unused-parameter \
-arch arm64 -arch x86_64 \
-I"$JAVA_HOME/include" -I"$JAVA_HOME/include/darwin" \
-o build/inject.dylib \
native/inject.c
echo "== 产物"
ls -la build/inject.dylib
find build/classes -name '*.class' | sed 's/^/ /'