# 名字映射锚点(只放**已确定**的;每条都要能说清依据,依据写进 混淆名对照表.md) # 列:owner name desc newName (desc 写 * 表示该 owner 下所有同名成员) # # ---- libGDX:Table(载荷名 et);依据 Obf.java + 直读字节码 ---- et D (Ldl;)LdR; add et D ([Ldl;)Let; addAll et I ()LdR; row et Z (Z)V setFillParent et SourceFile ()V clearChildren et D (Ljava/lang/CharSequence;)LdR; addLabel # ---- libGDX:Cell(载荷名 dR)---- dR StackMapTable ()LdR; expand dR D ()LdR; fill dR C ()LdR; left dR S ()LdR; top # ---- libGDX:Button / Label(保名类)---- com/badlogic/gdx/scenes/scene2d/ui/Button String ()Z isChecked com/badlogic/gdx/scenes/scene2d/ui/Button I (Z)V setChecked com/badlogic/gdx/scenes/scene2d/ui/Button B (ZZ)V setCheckedAndFire com/badlogic/gdx/scenes/scene2d/ui/Button a_ (Z)V setDisabled com/badlogic/gdx/scenes/scene2d/ui/Label D (Ljava/lang/CharSequence;)V setText com/badlogic/gdx/scenes/scene2d/ui/Label D ()Ljava/lang/StringBuilder; getTextBuilder # ---- libGDX:SelectBox(载荷名 KP);依据 DumpSites 解出的 (Ljava/lang/String;)V ---- KP B (Ljava/lang/String;)V setSelected KP B ()Ljava/lang/String; getSelected KP B (I)V setSelectedIndex # ---- 场景模型:Gp = 骨骼;依据 gp_2.java 的 toString()/D(String,boolean)V ---- Gp D Ljava/lang/String; name Gp D (Ljava/lang/String;Z)V setName # ---- 场景模型:Gp = 骨骼的变换字段 ---- # 证据:用户在编辑器里把 root 转到 341.456 / 平移(-168,-116) / 缩放(0.8799,0.572) / 斜切(-52.221,-28.63), # 面板 Inspector 同步显示 Z=-168.00009 V=-116.0 F=33.676704 Code=0.8799178 SourceFile=0.5720396 # StackMapTable=-52.220505 LineNumberTable=-28.629883 —— 一一对应,故确定语义。 Gp Z F x Gp V F y Gp F F rotation Gp Code F scaleX Gp SourceFile F scaleY Gp StackMapTable F shearX Gp LineNumberTable F shearY # 【已作废·未定】静止姿态(rest pose)那一组(D/B/L/I/S/C 的 float)原本只是"值与默认姿态吻合"的推断, # 2026-10-16 被 JSON 导出器证伪:导出器写 length 用的就是 Gp.C:F(见文件末尾"JSON 导出器"一节)。 # C 只能是 length,故整组推断不成立;这些字段的语义**目前未定**,不写进表里(宁可显示混淆名也不写错名)。 # Gp D F setupX # Gp B F setupY # Gp L F setupRotation # Gp I F setupScaleX # Gp S F setupScaleY # 引用类字段:skeleton 由 hd.D(set, bone.D)+GP.D(LGp;) 的用法确定;parent 由创建骨骼时 bone.D=parent 确定 Gp D LGP; skeleton Gp D LGp; parent Gp B Lcom/badlogic/gdx/graphics/Color; color # ---- 2026-10-16 setup pose 实测补充(用户拍照:root/bone/slot/region 四种对象)---- # 【已作废·未定】原写 Gp.Class:F=length / Ljava,java=worldScale*:都是"数值相等"的弱证据, # 其中 length 已被 JSON 导出器改成 Gp.C:F(导出器写 length 时读的就是 C)。 # 剩下 Class/Ljava/java/init/String 这几个 float 导出器一个都没用,语义未定,不写进表。 # GU(插槽):面板 Slot 属性只有 Name/Color;Inspector 里 String D=mega_dg4、Gp D=所属骨骼 GU D Ljava/lang/String; name GU D LGp; bone # GO(region 附件 mega_dg4):面板只有 Image path/Color;Inspector 六个 float 与 # Region 附件的 旋转49.00014 / 缩放(1.997,1.335) / 宽高(157,154) 一一对应 GO S F rotation GO L F scaleX GO I F scaleY GO C F width GO Z F height # ---- ScrollPane(保名类 com/badlogic/gdx/scenes/scene2d/ui/ScrollPane)---- # 依据:MapMethods 对 gdx-1.11.0 指纹比对(tools/deobf/anchors-libgdx.tsv 自动生成), # 并且**踩过一次**:一直以为 B(ZZ)V 是 setForceScroll,传了 (false,true), # 结果纵向滚动被关掉(那其实是 setScrollingDisabled(x,y))—— 现象就是"列表滚不动"。 com/badlogic/gdx/scenes/scene2d/ui/ScrollPane B (ZZ)V setScrollingDisabled com/badlogic/gdx/scenes/scene2d/ui/ScrollPane L (FFFF)V scrollTo com/badlogic/gdx/scenes/scene2d/ui/ScrollPane D (Ldl;)V addActor com/badlogic/gdx/scenes/scene2d/ui/ScrollPane D (Ldl;Z)Z removeActor # ---- ScrollPane / Cell 的滚动与尺寸方法(用于把面板列表改成可滚动;依据:MapMethods 指纹比对)---- # ScrollPane:B(ZZ)V=setScrollingDisabled、I(ZZ)V=setForceScroll、L(ZZ)V=setOverscroll #(候选顺序 size/… 已核对;踩坑:把 B(ZZ) 当 setForceScroll 用,等于关掉纵向滚动) com/badlogic/gdx/scenes/scene2d/ui/ScrollPane I (ZZ)V setForceScroll com/badlogic/gdx/scenes/scene2d/ui/ScrollPane L (ZZ)V setOverscroll # Cell 的 (F)LdR; 成组按声明顺序:B=size L=width I=height S=minWidth C=minHeight Z=prefWidth V=prefHeight dR B (F)LdR; size dR L (F)LdR; width dR I (F)LdR; height dR S (F)LdR; minWidth dR C (F)LdR; minHeight dR Z (F)LdR; prefWidth dR V (F)LdR; prefHeight # ---- Actor 的 Touchable(点击/进入命中相关;用于让 ScrollPane 收到鼠标进入→拿到 scroll focus)---- # 定位方式(不靠名字):`Actor.getTouchable()` = **无参且返回枚举**的那个方法;枚举类 = dv; # libGDX Touchable 声明顺序 enabled/disabled/childrenOnly → 第 0 个常量就是 enabled。 # 现象佐证:ScrollPane 默认 childrenOnly 时自己不是命中目标,收不到 enter → 滚轮事件不会送到它, # 但程序化 scrollY() 是生效的(实测 before=0 after=200)。 dl L (Ldv;)V setTouchable # ---- Cell.height(2026-10-16 实测确认)---- # 依据:对 Cell 的候选 (float) 方法依次调用 900,等一帧后量"根表格高度": # Cell.I(900) -> root 高度 580 -> 1080(其它候选 L/B/Z/V/C/S/F 都没这个效果) # => Cell.I(float) 就是 height(float);现象佐证:设了它之后列表区出现滚动条、可滚。 dR I (F)LdR; height # ---- Stage 宽高(2026-10-16 实测)---- # 依据:编辑器窗口 4K 下读 Stage 的无参 float 只有两个:B=2044、D=3726(高<宽), # 故 B()F = getHeight、D()F = getWidth。 dt B ()F getHeight dt D ()F getWidth # ---- 图片附件 GO 的 7 个 float 字段(2026-10-16 确认,两条独立证据)---- # 证据 1:编辑器自己的 JSON 写入器 sb_0.java:669-675(写 region 时依次读) # x=GO.D y=GO.B scaleX=GO.L scaleY=GO.I rotation=GO.S width=GO.C height=GO.Z # 旁证:width/height 与图片实际像素一致(mega_dg4.png = 157x154,运行时读到的 C=157.0 Z=154.0) # 证据 2:GO 自己的 setTransform 字节码 javap -c GO 的 D(FFFFF)V: # putfield D(第1个参数) -> putfield B(2) -> putfield S(3) -> putfield L(4) -> putfield I(5) # => D(float) = x、B(float) = y(这两个字段名与别的字段重复,必须按类型取 float 那个) GO D F x GO B F y # 图片附件的"设置变换"入口(编辑器自己用的):setTransform(x, y, rotation, scaleX, scaleY) GO D (FFFFF)V setTransform # 图片附件没有 shear 字段:region 只有 x/y/rotation/scaleX/scaleY(+ 只读的 width/height) # ---- 附件删除(编辑器自己的删除流程)---- # 证据:javap -c Gn 的 L()V => this.GU.skeleton.removeAttachment(this, true, true) # GP 的 D(Gn,ZZ)V 字节码里 getfield L:LfI; fI.B(Object,boolean) 把它从附件表移除, # 并同步清掉 GU 上指向它的引用(同一方法里遍历 Z:LfI 即插槽表)。 Gn L ()V delete GP L (LGn;ZZ)V removeAttachment GP L LfI attachments GP Z LfI slots # ---- 附件种类 / 占位附件 ---- # 证据:可读源码 hi_2.java(= 载荷类 Hi)的 I() 直接 return "placeholder"; # 它出现在骨架附件表里但"既不是当前附件也不是静止附件",就是 skin/占位附件。 Gn I ()Ljava/lang/String; type # 附件上指向自己所属占位附件的引用:GP.removeAttachment 的占位分支按它级联删除 Gn D LHi; placeholderRef # ============================================================================ # 【权威来源】编辑器自带的 JSON 导出器(载荷类 sB,2026-10-16) # ---------------------------------------------------------------------------- # 为什么权威:导出 JSON 时**每个 key 后面紧跟被读的那个字段**,key 名就是字段语义。 # 证据链(两处独立,顺序逐条一致): # 1) 可读载荷 ~/Desktop/spine398/spine398.jar(DecAll 产出:ldc 密文已换明文、解密调用已换 nop) # `javap -p -c -cp spine398.jar sB` → `ldc "rotation"` 紧跟 `getfield Gp.F:F`,全部可读; # 2) 未解密载荷 (payload-public.zip) 的 strings.tsv(class sB, method D):同一(类,方法)内 # 密文顺序 = 字节码顺序,281 条与可读副本里的 key 顺序逐条对得上(含三组解密器)。 # 导出器方法:sB.D(GP,boolean,boolean,gy,StringBuilder)=骨架;sB.D(gy,String,Gn,boolean)=附件。 # 字段名重复(D/B/L/I/S…)时**必须按描述符取**,表里已经带描述符。 # ============================================================================ # ---- Gp = 骨骼(导出器写 "bones" 段时读的就是这些)---- Gp C F length # ^ length 是 C(之前写的 Class:F 是错的,已作废) Gp D LiC; transform # ^ iC = 继承模式枚举(normal/onlyTranslation/noScale…) Gp String Z skinOverride # ^ 导出器写 key="skin"(布尔:该骨骼是否覆盖当前 skin) # ---- GU = 插槽(导出器写 "slots" 段)---- GU B Lcom/badlogic/gdx/graphics/Color; color # ^ 写 key="color" 读的是 B(不是 D) GU I Lcom/badlogic/gdx/graphics/Color; darkColor # ^ 写 key="dark" GU I Z hasDarkColor # ^ 写 "dark" 之前先看这个布尔开关 GU B LGn; attachment # ^ 写 key="attachment" 读的是 B(不是 D) GU D Liz; blend # ^ iz = 混合模式枚举 # ---- Gn = 附件基类 ---- Gn D Ljava/lang/String; name # ---- GO = 图片(region)附件 ---- GO D Lcom/badlogic/gdx/graphics/Color; color GO B Ljava/lang/String; path # ^ 导出器写 key="path",值取自静态取值器 GO.B(GO) # ---- GE = 点(point)附件 ---- GE B Lcom/badlogic/gdx/graphics/Color; color GE D F x GE B F y GE L F rotation # ---- Gx = 网格(mesh / linkedmesh)附件 ---- Gx B Lcom/badlogic/gdx/graphics/Color; color Gx B Ljava/lang/String; path Gx D Lga; uvs Gx D Lhp; triangles Gx B LHl; vertices Gx L I hull # ^ 导出器写 hull = Gx.L / 2 Gx D Lgf; edges Gx StackMapTable Z deform Gx D F width # ^ 只在导出器带 extra 标志时写 Gx B F height Gx D LGx; parentMesh # ^ 写 "parent" 时先取它(父网格附件) Gx D LGT; skin # ^ 写 "skin" 时取父网格的 skin Gx D LHi; parentPlaceholder # ^ 父网格的占位附件(Hi) Gx D Ljava/lang/String; parentName # ^ 写 "parent"(非 linkedmesh 分支) # ---- Gr = 包围盒(boundingbox)附件 ---- Gr I Lga; vertexCount Gr B LHl; vertices Gr B Lcom/badlogic/gdx/graphics/Color; color # ---- Gs = 裁剪(clipping)附件 ---- Gs I Lga; vertexCount Gs B LHl; vertices Gs B Lcom/badlogic/gdx/graphics/Color; color Gs B LGU; end # ^ 裁剪结束的那个插槽 # ---- Gw = IK 约束 ---- Gw D Ljava/lang/String; name Gw D LGp; target Gw D F mix Gw L F softness Gw F Z uniform Gw S Z stretch Gw Z Z compress # ---- GX = 变换(transform)约束 ---- GX D Ljava/lang/String; name GX B LGp; target GX SourceFile F rotation GX S Z local GX C Z relative GX L F x GX I F y GX StackMapTable F scaleX GX init F scaleY GX LineNumberTable F shearY GX S F rotateMix GX D F translateMix GX Z F scaleMix GX F F shearMix # ---- GD = 路径(path)约束 ---- GD D Ljava/lang/String; name GD D LGU; target GD D Ljm; positionMode GD D Ljo; spacingMode GD D Ljn; rotateMode GD Z F rotation GD D F position GD V F spacing GD S F rotateMix GD L F translateMix # ============================================================================ # 【面板/新按钮用到的"操作类" API】(2026-10-16 热更实测通过:不重启、纯编辑器自身 API) # 场景:点面板按钮 → 弹名称输入面板 → 按名字匹配附件 → 在当前选中骨骼下建 15 根骨骼, # 每根 1 插槽 1 附件(输入的附件名),位移 xy 0~500 随机、缩放 1、旋转/斜切 0, # 插槽 alpha 0.5~1 随机、blend normal/additive 随机、附件在插槽上变换 0/0/0/1/1。 # 证据:`javap -p -c` 字节码 + attach 到运行进程逐条实测(每个 API 都真跑过并核对过结果)。 # ============================================================================ # ---- 建对象(编辑器自己的"加"API)---- # UH = OG 的模型编辑助手(OG.D:LUH;)。下面两个都实测建出来过: UH D (LGU;LGp;Z;LfI;)LGU; addSlot # ^ 加插槽:参数(插槽模板, 父骨骼, ?, 不重名用列表)。⚠️ 它会把模板插槽**整个复制**,连模板插槽上挂的附件一起复制(实测踩到过) UH D (LGn;LGU;ZZLfI;)LGn; addAttachmentCopy # ^ 加附件:参数(附件模板, 插槽, ?, ?, 列表);内部就是 `Gn.D(LGP;)LGn;` 复制一份模板附件,并挂到该插槽 GP D (LGp;)V addBone # ^ 加骨骼:字节码 `bone.B = array.size; array.add(bone)`(骨架的骨骼表) OG D (Ljava/lang/String;LfI;LGU;)Ljava/lang/String; uniqueName # ^ 编辑器自己的不重名生成器:`OG.D("bone", 骨骼数组, null)` 会给出 bone7 这种名字 GU D (LGn;Z)V setAttachment # ^ 设插槽的当前附件:第二参=是否记撤销;内部按 `Editor.V`(animate/setup)只写 `D:LGn;` 或 `B:LGn;` 其中一个 —— # 所以要"两种模式都覆盖"就直接写两个字段(本次就是这么做的) GU D LGn; attachmentAnimate # ^ 与 `GU.B:LGn;` 成对:`D` 是 animate 模式用的当前附件,`B` 是 setup/非 animate 用的(JSON 导出器读的是 B) VZ D (LGP;ZZ)V refresh # ^ 改完模型重建层级树节点(本次每批建完都调它) un D ()V undoBegin un B ()V undoCommit # ^ 撤销帧的 开始/提交(改模型前 D()、改完 B()) un Z ()V undo # ^ ★ 撤销一步:实测有效(`up.D:` 栈 23→22、redo 栈 0→1,场景对象数同步回退)。 # 本次误删骨骼后就是用连点 un.Z() 一键一键撤回来的。另外 un.S()/un.C()/un.V()/un.I() 不是撤销: # S=跳到历史某下标、C=置标志、V=按当前下标重放、I=up.D()(无效果) # ---- 名称输入面板(编辑器自带的那套对话框)---- xl L (Ljava/lang/Object;)V onOkCancel # ^ 对话框的 OK/Cancel 总回调:收到 Boolean(TRUE=OK、FALSE=Cancel)。 # OK 时它会读名字框、去重校验,然后调下面的抽象方法;Cancel 直接 return xl L (Ljava/lang/String;)V onNameEntered # ^ **抽象方法**:OK 且名字合法时被调用,参数就是输入的名字。想拿名字就子类化它(本次是 ASM 现生成子类) xl D (Ldt;)LvH; show # ^ 显示对话框。⚠️ 实测:**光调它窗口不会挂进 Stage**(parent 一直 null、屏幕上什么都不出现), # 必须再显式 `dt.D(Ldl;)V`(Stage.addActor)挂上去,然后自己 setPosition xl D LKp; nameField # ^ 对话框里的名字输入框(Kp = TextField 子类):构造时会用它填入默认名,OK 时从它读名字 vH B (Ljava/lang/Object;)V okPressed # ^ OK 按钮的回调:唯一会去调 `L(Object)` 的地方(javap -c vH 可见) vH L (Ljava/lang/Object;)V onOkCancelNoop # ^ 空实现(xl 覆盖了它) Kp B ()Ljava/lang/String; getText Kp B (Ljava/lang/String;)V setText # ^ 名字框取/填文字(xl/xp 的构造与 L(Object) 里就是这么用的) # ---- Actor / Stage / WidgetGroup(定位、挂载、删除)---- dt D (Ldl;)V addActor # ^ Stage.addActor:字节码就是 `this.D:Ldo;.addActor(actor)`(root.addActor)。 # ⚠️ 用它把对话框挂上屏幕(配合 xl.D(dt));也踩过坑:它会把 Actor 从原父级摘走(当年把面板列表搬出面板就是它) dl D Ldo; parent dl D Ldt; stage # ^ Actor 上的两个同名字段:`do` 类型的是父控件,`dt` 类型的是所在 Stage。按类型取,别按名字取 dl D ()Ldt; getStage dl b_ ()Z remove # ^ 把 Actor 从父级摘掉。⚠️ `eX.b_()V`(invalidate)与它同名不同描述符 —— `getMethod("b_")` 会取到 void 那个, # 结果就是"调了删除却没删掉"(本次踩到) eX b_ ()V invalidate eX V (Z)V setFillParent dl c_ ()F getX dl d_ ()F getY dl L ()F getWidth dl I ()F getHeight dl S ()F getTop dl C ()F getRight # ^ Actor 的几何读取(都在 dl 上用 `javap -p -c` 对出来的:c_=x、d_=y、L=width、I=height、S=y+h、C=x+w)。 # ⚠️ `et`(Table) 自己还声明了 `int L()`/`int I()`(列数/行数),所以按名字取必须**同时按返回类型 float 过滤** dl D (FFI)V setPosition # ^ setPosition(x, y, alignment):**align=0 时是"以 (x,y) 为中心"**(b1 不是 left/right 就按 center 处理)。 # 本次要把对话框摆屏幕正中就是靠这个:直接传 Stage 中心即可 # ---- 混合模式枚举(插槽 blend)---- iz D Liz; normal iz B Liz; additive iz L Liz; multiply iz I Liz; screen # ^ `iz`(=BlendMode) 的常量顺序取自 `iz.`:依次 new iz("normal",0,770,1,771)、("additive",1,770,1,1)、 # ("multiply",2,774,774,771)、("screen",3,1,1,769) —— 名字是常量池里的明文 # ---- 面板自己那套(本次复用的)---- com.spineview.ObjectPanel wire (Ljava/lang/ClassLoader;Ljava/lang/Object;Ljava/lang/Runnable;)V wireButton # ^ 把按钮接上点击(轮询 isChecked + 路由线程)——新按钮直接复用它,不用自己写监听 com.spineview.SceneObjects listAllNodes (Ljava/lang/ClassLoader;)Ljava/util/List; listAllNodes com.spineview.SceneActions delete (Ljava/lang/ClassLoader;Ljava/lang/Object;)Z delete # ^ 面板自己的"罗列场景对象 / 删除对象"(走编辑器删除流程,自带撤销)——清理误建对象时用它