面板(viewpanel/src/com/spineview/) - ObjectPanel:Refresh / New Bone / New Slot / New BBox / New Path / Delete / Rename / Inspect + 名字输入框 + 对象列表(点行=选中)+ 状态行,全英文。 - SceneObjects:查(Tree 控件按层级/扁平列全部对象)、选中(VZ.D(Tree.Node,boolean) —— VZ.D(Object) 内部只是 Selection.L(),不真选中)、读当前选择(VZ.B())。 - SceneActions:增/删/改 + 撤销包装(un.D()/un.B())+ 树节点重建(VZ.D(GP,true,true)); 统一在编辑器渲染线程执行(OG.B(Runnable);OG.I() 有线程断言,非渲染线程会抛 RuntimeException); 输入名字对话框自动化:找到『有 TextField 字段 + L(Object)V 回调』的对话框对象 → 填名字 → 调 L(true)。 - 实测:骨骼新建自动编号(bone7/bone8);模型层允许重名、按名字查只返回第一个;删父骨骼连子节点一起删; 不能在渲染线程里 sleep(有些创建是下一帧做的)。 - 探针:-Dspine.probe=objects|panels|select|crud|matrix|panel。 可识别源码版(工具) - tools/deobf/Renamer.java:ASM Remapper 只改成员名不改类名(indy 运行时要用加密串里的类名反射查)。 - tools/deobf/anchors.tsv(手动 14 条有证据的锚点)+ anchors-libgdx.tsv(MapMethods 对 gdx-1.11.0 指纹自动生成 178 条)→ names.tsv 192 条。 - 产物 ~/Desktop/spine398/src-named(4176 类全量,原 src-readable 不动);已验证 Table.add/clearChildren、SelectBox.getSelected/setSelected/setSelectedIndex、Gp.name。 - 文档:混淆名对照表.md 新增第六节(工具链 + 已验证 + 已知限制)。
129 lines
6.1 KiB
Java
129 lines
6.1 KiB
Java
package com.spineview;
|
||
|
||
/**
|
||
* Spine 3.8.99 载荷里**被混淆成员的对照表**(推导过程见仓库根目录 `混淆名对照表.md`)。
|
||
*
|
||
* 推导办法(可复现,不是猜的):
|
||
* 1) `tools/obfmap/MapMethods.java`:把载荷类与上游 libGDX 同签名方法做
|
||
* "忽略名字的字节码指纹"比对(操作码序列 + 常量 + 成员的描述符);
|
||
* 2) 拿上游 libGDX 1.11.0 的源码逐条核对方法体语义。
|
||
*
|
||
* ⚠️ 这套载荷用了"**同名不同描述符**"的混淆手法:类里同时存在
|
||
* `D(Ldl;)LdR;`、`D()LdR;`、`D(F)LdR;`… 全部叫 `D`。所以任何一处都必须
|
||
* **名字 + 描述符一起判断**,只看名字一定会读错。
|
||
*/
|
||
public final class Obf {
|
||
|
||
// ======================= 类 =======================
|
||
/** com.badlogic.gdx.scenes.scene2d.Actor */
|
||
public static final String ACTOR = "dl";
|
||
/** com.badlogic.gdx.scenes.scene2d.Group(do extends dl) */
|
||
public static final String GROUP = "do";
|
||
/** com.badlogic.gdx.scenes.scene2d.ui.WidgetGroup(eX extends do) */
|
||
public static final String WIDGET_GROUP = "eX";
|
||
/** com.badlogic.gdx.scenes.scene2d.ui.Table(et extends eX) */
|
||
public static final String TABLE = "et";
|
||
/** com.badlogic.gdx.scenes.scene2d.ui.Cell(implements Poolable) */
|
||
public static final String CELL = "dR";
|
||
/** com.badlogic.gdx.scenes.scene2d.Stage 的实现(uk extends dt) */
|
||
public static final String STAGE = "dt";
|
||
/** com.badlogic.gdx.scenes.scene2d.ui.Value */
|
||
public static final String VALUE = "eN";
|
||
/** com.badlogic.gdx.utils.Array */
|
||
public static final String ARRAY = "fI";
|
||
|
||
// ======================= Button =======================
|
||
// 类名保留(TextButton 继承它),但方法名被混淆了。
|
||
/** com.badlogic.gdx.scenes.scene2d.ui.Button */
|
||
public static final String BUTTON = "com.badlogic.gdx.scenes.scene2d.ui.Button";
|
||
/** `isChecked() -> boolean`(体是 `return isChecked;`,读第 1 个 boolean 字段) */
|
||
public static final String BUTTON_IS_CHECKED = "String";
|
||
/** `setChecked(boolean)` */
|
||
public static final String BUTTON_SET_CHECKED = "I";
|
||
/** `setChecked(boolean, boolean)`(第二个参数是否派发事件) */
|
||
public static final String BUTTON_SET_CHECKED_FIRE = "B";
|
||
/** `setDisabled(boolean)` */
|
||
public static final String BUTTON_SET_DISABLED = "a_";
|
||
|
||
// ======================= Label =======================
|
||
/** com.badlogic.gdx.scenes.scene2d.ui.Label */
|
||
public static final String LABEL = "com.badlogic.gdx.scenes.scene2d.ui.Label";
|
||
/**
|
||
* `setText(CharSequence) -> void`。
|
||
* ⚠️ Label 上还有一个 `D(CharSequence) -> boolean`,那是 `textEquals(CharSequence)`
|
||
* —— 只按"一个 CharSequence 参数"去找方法会挑中它,现象是**日志说读取成功、面板文字却不变**。
|
||
*/
|
||
public static final String LABEL_SET_TEXT = "D";
|
||
/** `getText() -> StringBuilder` */
|
||
public static final String LABEL_GET_TEXT = "D";
|
||
|
||
// ======================= Table =======================
|
||
/** `add(Actor) -> Cell` */
|
||
public static final String TABLE_ADD = "D";
|
||
/** `add(Actor...) -> Table`(varargs 版,谨慎别选错) */
|
||
public static final String TABLE_ADD_VARARGS = "D";
|
||
/** `row() -> Cell` —— 换行的关键,不调用的话所有控件都挤在第一行 */
|
||
public static final String TABLE_ROW = "I";
|
||
/**
|
||
* `clearChildren() -> void`(体 = 逐个 actor.remove() + cells.clear() + rows/columns 归零)。
|
||
* 重建列表时用它把旧行清掉。
|
||
*/
|
||
public static final String TABLE_CLEAR_CHILDREN = "SourceFile";
|
||
/** `setFillParent(boolean)`(WidgetGroup 的,让面板铺满停靠框) */
|
||
public static final String TABLE_SET_FILL_PARENT = "Z";
|
||
/** `setClip(boolean)` */
|
||
public static final String TABLE_SET_CLIP = "C";
|
||
/** `setDebug(boolean)` —— 会把单元格描出彩色边框,别误当成 setFillParent */
|
||
public static final String TABLE_SET_DEBUG = "B";
|
||
/** `top() -> Table`(表格内容整体对齐) */
|
||
public static final String TABLE_TOP = "I";
|
||
/** `left() -> Table` */
|
||
public static final String TABLE_LEFT = "S";
|
||
/** `center() / bottom() / right() -> Table` */
|
||
public static final String TABLE_CENTER = "L";
|
||
public static final String TABLE_BOTTOM = "C";
|
||
public static final String TABLE_RIGHT = "Z";
|
||
/** `align(int) -> Table` */
|
||
public static final String TABLE_ALIGN = "D";
|
||
/** `pad(float) / pad(float×4) -> Table` */
|
||
public static final String TABLE_PAD = "D";
|
||
/** `padTop/padLeft/padBottom/padRight(float) -> Table` */
|
||
public static final String TABLE_PAD_TOP = "B";
|
||
public static final String TABLE_PAD_LEFT = "L";
|
||
public static final String TABLE_PAD_BOTTOM = "I";
|
||
public static final String TABLE_PAD_RIGHT = "S";
|
||
|
||
// ======================= Cell =======================
|
||
/** `fill() -> Cell`(fillX = fillY = 1,撑满单元格) */
|
||
public static final String CELL_FILL = "D";
|
||
/** `fill(boolean)` */
|
||
public static final String CELL_FILL_BOOL = "D";
|
||
/** `expand() -> Cell`(expandX = expandY = 1,占掉剩余空间) */
|
||
public static final String CELL_EXPAND = "StackMapTable";
|
||
/** `expandX() / expandY() -> Cell` */
|
||
public static final String CELL_EXPAND_X = "init";
|
||
public static final String CELL_EXPAND_Y = "LineNumberTable";
|
||
/** `fillX() / fillY() -> Cell` */
|
||
public static final String CELL_FILL_X = "B";
|
||
public static final String CELL_FILL_Y = "L";
|
||
/** `grow() / growX() / growY() -> Cell` */
|
||
public static final String CELL_GROW = "F";
|
||
public static final String CELL_GROW_X = "Code";
|
||
public static final String CELL_GROW_Y = "SourceFile";
|
||
/**
|
||
* 对齐:`top() / left() / bottom() / right() / center()`。
|
||
* 载体是 `align |= X & ~Y` 的形式,位掩码取自 libGDX 的 Align:
|
||
* center=1、top=2、bottom=4、left=8、right=16。
|
||
*/
|
||
public static final String CELL_TOP = "S";
|
||
public static final String CELL_LEFT = "C";
|
||
public static final String CELL_BOTTOM = "Z";
|
||
public static final String CELL_RIGHT = "V";
|
||
public static final String CELL_CENTER = "I";
|
||
/** `align(int) -> Cell` */
|
||
public static final String CELL_ALIGN = "D";
|
||
|
||
private Obf() {
|
||
}
|
||
}
|