commit
d3d4a988eb
774 files changed
+120915
No files matched your search
@@ -0,0 +1,78 @@
|
||||
# BOOT_NOTES (agent "boot", 2026-10-19)
|
||||
|
||||
Goal: the deobfuscated Prestige client boots under Fabric (dev client, `./gradlew runClient`), `Prestige.init()` completes
|
||||
and the UI bridge binds to the live modules.
|
||||
|
||||
## Findings (root causes, in order of discovery)
|
||||
1. **Two copies of the client were loaded.** `build.gradle` has `implementation files("client/work/client-runtime.jar")`
|
||||
(a Yarn-named jar on the dev classpath). A jar in `run/mods` is a *second* copy (loaded as a mod and remapped
|
||||
intermediary->named by Fabric Loader at runtime). Whichever won the race was used, so every earlier "fix" that only
|
||||
went into `run/mods` seemed flaky (the log showed classes loaded from `client/work/client-runtime.jar`, static keys = 0).
|
||||
Decision: **the classpath jar `client/work/client-runtime.jar` is the one used by the dev client; `run/mods` stays empty.**
|
||||
(If you want to use `run/mods` instead, the jar must be INTERMEDIARY-named incl. intermediary AW: `work/client-boot.jar`,
|
||||
and `build.gradle`'s `implementation files(...)` line must be removed. Loom's loader remaps mods-folder jars itself.)
|
||||
2. **ZKM-like key generator is stateful.** Every class (358 of them) computes its decryption key in `<clinit>` through
|
||||
`hc.a(seed1, seed2, lookupClass).a(const)` (`hb`/`hc` = an interpreter with shared, mutable cached objects:
|
||||
`this.a = a ^ arg ^ d`, instance cache sorted by `identityHashCode`...). The result depends on **how often / in which order the
|
||||
generator was called before**, so the values obtained under Fabric (different class-init order) differ from the values
|
||||
the isolated child JVMs of `IndyResolve` see (e.g. `cJ.g` = 0 / 182876734801923 instead of 22310984220293).
|
||||
Wrong key -> wrong table index -> `Index 184919 out of bounds for length 81` in `bO.a`.
|
||||
3. The old `IndyResolve` "clinit cut" (a `goto` over the table initialisation) was *not* the real problem for these classes
|
||||
(only for the tables' decoded content); but it also removed the table init, so it is now disabled for the runtime jar.
|
||||
4. `FixFlow` recomputed frames with `getCommonSuperClass -> Object` fallback => `VerifyError` (`Object` not assignable to `PlayerEntity`).
|
||||
Now it resolves common super classes through a URLClassLoader over MC + libs + the jar.
|
||||
|
||||
## Fix (pipeline `client/tools/build_runtime.sh`, replaces the previous ad-hoc jars)
|
||||
* `IndyResolve -Dno.clinitcut=true`: no clinit cut. Instead `keyFix()` replaces, in every `<clinit>`,
|
||||
`ldc s1; ldc s2; MethodHandles.lookup().lookupClass(); hc.a(JJObject); ldc c; ha.a(J)J` by `ldc <value recorded by the isolated child run>`
|
||||
(`IndyRec.recH` -> `info.rec["H"+ordinal]`). Result: 357 of 358 classes get the constant; the whole table init (`h`/`i` arrays,
|
||||
`a()V`, DES decrypt, `ldc` tables) stays intact and runs at run time. The 1 remaining class is `gf` (no child value; see below).
|
||||
* Module constructors are hooked: `PatchBootstrap` inserts `dev.prestige.ui.bridge.Bootstrap.pre(this)` after `super()` in all 122
|
||||
subclasses of `dV` (the native module normally injects the settings before the ctor body runs).
|
||||
* `FixFlow` (frames, `getCommonSuperClass` via real classes) -> `work/client-boot.jar` (intermediary-named, usable in a mods folder
|
||||
for Prism, with the Bootstrap hook; the hook class lives in `prestige-ui`).
|
||||
* tiny-remapper intermediary->named + `fix_aw.py` -> `work/client-runtime.jar` (Yarn-named; this is what Gradle uses).
|
||||
* `-Xverify:all` check of all 708 classes standalone: `client/work/t2/V.java` (ok=708 bad=0).
|
||||
|
||||
## Bridge
|
||||
* `Bridge.bind()` is called from the first client tick (`Entry`). The manager (`Prestige.d`, class `cJ`) list is empty after
|
||||
`Prestige.init()` (modules are registered by the native module), so `Bridge.buildModules` constructs every class of
|
||||
`src/main/resources/prestige_ui/manifest_live.json` (copied from `liberate/work/deobf/manifest_live.json`), calls `Bootstrap.post(m)`
|
||||
and registers the list with the manager's `a(List)` setter. Bootstrap = port of `work/deobf/gui/zkminit/Bootstrap.java`
|
||||
(package `dev.prestige.ui.bridge`).
|
||||
|
||||
## Run
|
||||
```
|
||||
bash client/tools/build_runtime.sh # ~2 min; writes work/client-boot.jar (intermediary) + work/client-runtime.jar (yarn)
|
||||
bash client/tools/boot_test.sh 200 # kills stale dev clients, runs ./gradlew runClient (timeout), copies the log to run/logs/boot_*.log
|
||||
```
|
||||
Log lines to look for: `[prestige-ui] bridge bound: 121 modules`.
|
||||
|
||||
## Result (verified 15:20)
|
||||
* `Prestige.init()` completes (no STDERR in the log), `Prestige.d` manager exists; its module list is empty (native registers it).
|
||||
* `[prestige-ui] bridge: built 121 modules from manifest, failed 0` / `[prestige-ui] bridge bound: 121 modules`
|
||||
(log: `client/work/boot_success_latest.log`).
|
||||
* UI click test (`run/cmd/ui.txt` command file, `-PuiCmd=`; new dev commands `pointmod <module>` / `state <module>`, `ui/DevCmd.java`):
|
||||
`Aim Assist ui=false live=false` -> click on its toggle -> `ui=true live.a()=true enabledSetting.value=true` -> click -> false -> click -> true.
|
||||
Screenshot `client/work/boot_toggle_on.png` (header "1 enabled", Aim Assist switch on). Note: the very first click after opening
|
||||
is sometimes ignored (earlier run); a 40-frame wait after `open` makes it reliable.
|
||||
|
||||
## Not done / caveats
|
||||
* Class `gf` has no recorded key value (child run produced no value) -> its `<clinit>` still calls the stateful `hc` generator
|
||||
(`KEYFIX-NOVALUE dev/zprestige/prestige/gf 0` in `work/boot_indy.report.txt`). Not hit during boot; check when it is used.
|
||||
* Module *behaviour* (onEnable hooks, event bus dispatch, rendering) is not verified; only construction + enable flag round trip.
|
||||
* The enable flag round trip goes through the module's `dM` setting (`Bridge.LiveModule.setEnabled`); `onEnable`/`onDisable` side
|
||||
effects depend on how the original dM listener fires (not checked).
|
||||
* `run/mods` is empty on purpose (see Finding 1). `work/client-runtime.pre-boot.jar` is the previous classpath jar (backup).
|
||||
* Source tree compile (client/src) was not touched.
|
||||
|
||||
## Update (agent "rename", 2026-10-19 16:45)
|
||||
* API surface renamed by bytecode: `docs/mapping.tsv` (applied by `tools/rename.sh` = tiny-remapper + `Widen`, called from `build_runtime.sh` and
|
||||
`build_source.sh`). dV->Module, i->Category, dK->Setting, dU->SettingHolder, dM/dN/dO/dP/dQ/dR/dS/dL/dT -> Bool/Color/Float/Int/Range/Enum/Multi/
|
||||
Keybind/TextSetting, bO->EventBus, cJ->ModuleManager, e_->MenuModule, q->Gamemode, bP->Subscribe, Prestige.b/d -> eventBus/moduleManager,
|
||||
plus the fields/methods the UI uses (name/description/value/min/max/low/high/options/selected/toggleMode, getModules/setModules, isEnabled ...).
|
||||
The 121 module classes are mapped to `dev.zprestige.prestige.module.<category>.<PascalCaseName>` (section generated by `tools/gen_module_mapping.py`).
|
||||
* Bridge/Bootstrap use the new names; manifest class/prop names are rewritten from `docs/manifest_live.obf.json` by `tools/rename_manifest.py`.
|
||||
* Evidence: `work/boot_rename_success.log` (API rename, jar route), `work/boot_jar_modules_renamed.log` (+ module classes renamed),
|
||||
`work/boot_source_modules_renamed.log` (source route, `-PwithClient=true`); all show `bridge bound: 121 modules` and the Aim Assist toggle round trip.
|
||||
* Source route: see `TODO_COMPILE.md`.
|
||||
@@ -0,0 +1,156 @@
|
||||
# Handoff: client source refactor (packages + class names)
|
||||
|
||||
## Current state
|
||||
|
||||
The catastrophic part is done. All 400 obfuscated helper classes have been moved out of the root package into
|
||||
18 meaningful sub-packages, and the source tree compiles and builds.
|
||||
|
||||
- Source tree: `project/client/src/main/java/dev/zprestige/prestige`
|
||||
- 543 Java classes total:
|
||||
- 21 already-named API classes intentionally left at the root (`Module`, `Setting`, `SettingHolder`, the 9
|
||||
setting types, `EventBus`, `Category`, `ModuleManager`, `MenuModule`, `Gamemode`, `Native`, `Constants`,
|
||||
`Subscribe`, `ListenerEntry`)
|
||||
- `client/Prestige`
|
||||
- 121 modules under `module/<category>/`
|
||||
- 400 renamed helpers under `event/ hud/ render/ data/ type/ mixin/ world/ math/ combat/ inventory/ network/
|
||||
reflect/ gui/ config/ util/ social/ annotation/ input/`
|
||||
- Zero obfuscated class names remain at the root. Verified by listing the renamed jar: the root contains only the
|
||||
21 API classes.
|
||||
- `./gradlew.bat build -PwithClient=true` succeeds (`BUILD SUCCESSFUL`, one deprecation warning about
|
||||
`ThreadDeath`). Artifacts: `project/build/libs/prestige-0.1.0.jar`,
|
||||
`prestige-0.1.0-sources.jar`.
|
||||
- **Boot has not been tested yet.** That is the first remaining step.
|
||||
|
||||
## What was changed
|
||||
|
||||
### New files (`project/client/tools/`)
|
||||
|
||||
- `gen_class_mapping.py` — generates `docs/classmap.tsv` (400 `C old new` rows) from the decompiled source by
|
||||
classifying superclass/interface/mixin target/HUD description/shader path/record components/enum constants/
|
||||
module references.
|
||||
- `merge_mapping.py` — merges `docs/mapping.tsv` + `docs/classmap.tsv` into `work/rename.map.tsv`, refusing
|
||||
duplicate owners.
|
||||
- `clsmapping.py` — shared lookup used by the fixers:
|
||||
- `Mapping(srcdir).path(old_source_name)` -> real path after renames
|
||||
- `Mapping.source_to_new` -> class-token map for source snippets
|
||||
- `rewrite_tokens()` — token rewrite that skips string literals and fully-qualified package paths
|
||||
|
||||
### Changed files
|
||||
|
||||
- `client/tools/rename.sh`
|
||||
- now merges `docs/classmap.tsv` into the mapping before running tiny-remapper and `rename_manifest.py`.
|
||||
- The class map therefore applies to both routes (source regeneration and runtime jar).
|
||||
- `client/tools/fix_reflect.py`
|
||||
- resolves `cU`/`cW`/`EventBus` through `clsmapping` instead of hardcoded root paths
|
||||
- uses the renamed `Event.class` instead of `aH.class`
|
||||
- `client/tools/fix_ctor.py`
|
||||
- constructor-noise regex accepts both `aH.b();` and `Event.b();`
|
||||
- `client/tools/manual_edits.py`
|
||||
- uses `clsmapping.Mapping`; snippets are token-rewritten outside string literals
|
||||
- removed one obsolete `PostShader` edit (the `i_cF` bridge no longer exists)
|
||||
- the restored `TextRenderer` bridge now implements `a_WorldContract` (the method name generated after the
|
||||
class rename)
|
||||
- `client/tools/notry.txt`
|
||||
- `ConfigManager.a(...)Lcom/google/gson/JsonObject;` updated to the new FQN. Without this the config loader
|
||||
fails to decompile again.
|
||||
- `docs/classmap.tsv` — 400 generated class rows (frozen; treat as source of truth).
|
||||
- `docs/classmap_src.tsv` — source-tree name -> new internal name, used by `clsmapping.py` to survive the
|
||||
`_`-suffixed case-collision twins (`cg_` is jar `cg`, `d_` is jar `d`). Also frozen.
|
||||
|
||||
### Naming decisions
|
||||
|
||||
- Events: `event/Event` (base `aH`), 70 `*Event` subclasses. Fieldless events are `TickEvent`, `TickEvent2`, ...
|
||||
- HUD: `hud/HudElement` (base `b4`), names derived from the `super("Name", ...)` string, e.g.
|
||||
`ModuleListElement`, `WatermarkElement`.
|
||||
- Mixins: `mixin/<Target>Mixin` from `@CTransformer`, e.g. `MinecraftClientMixin`, `EntityMixin`,
|
||||
`InGameHudMixin`. Duplicate targets get `2`, `3`, `4`.
|
||||
- Shaders: `render/<Name>Shader` from the `.frag` path (`AuraOutlineShader`, `ChamsOutlineShader`, ...).
|
||||
- Enums: `type/*` with semantic overrides (`BowMode`, `AnchorState`, `CartState`, `GlPrimitive`, `Easing`, ...).
|
||||
- Records/data: `data/*` (`IntData`, `LongData`, `VecIntData`, ...).
|
||||
- API classes stay at root on purpose. Moving them would require editing hardcoded FQNs in
|
||||
`src/main/java/dev/prestige/ui/bridge/Bootstrap.java` and `Bridge.java`, and gains nothing for this task.
|
||||
|
||||
## Important caveats
|
||||
|
||||
- **Do not blindly re-run `gen_class_mapping.py` on the new tree.** It was written for the pre-refactor tree and
|
||||
reads `client/work/renames.tsv`, which is overwritten by every `build_source.sh` run. The new live tree already
|
||||
has the final names. `docs/classmap.tsv` + `docs/classmap_src.tsv` are the frozen mapping.
|
||||
- `work/renames.tsv` now reflects the *renamed* jar, so its `old -> new` pairs are for collision handling of the
|
||||
post-classmap jar, not the original obfuscated names.
|
||||
- `manual_edits.py` token rewriting deliberately ignores single-letter class tokens (`C`, `I`, `M`, `q`, ...)
|
||||
because method names are also single letters. Do not weaken that filter.
|
||||
- `docs/mapping.tsv` still maps old jar names (`dV`, `d_`, ...) to API/module names. `d_` there is the module
|
||||
`AutoCart`; the enum that the tree calls `d_` is jar class `d` (`type/BowMode`). This collision is handled by
|
||||
`classmap_src.tsv`; do not "fix" it by hand.
|
||||
- Some generated names are functionally consistent but semantically imperfect: `RenderHelperN`, `WorldContract`
|
||||
(this is the text-renderer interface implemented by `TextRenderer`), `RenderContract*`. Renaming them is
|
||||
cosmetic and requires regenerating the decompiled source (method names in these contracts are derived from the
|
||||
class name).
|
||||
- 5 method bodies are still TODO no-ops from the stripping stage. Search for `body lost` /
|
||||
`unresolved ZKM reference` in the tree.
|
||||
- Strings are not restored, and helper **member** names are still obfuscated. Only class/package names changed.
|
||||
|
||||
## Next steps (in order)
|
||||
|
||||
1. **Boot the source route.**
|
||||
```powershell
|
||||
cd project
|
||||
.\gradlew.bat runClient -PwithClient=true --console=plain
|
||||
```
|
||||
or, for a timed logged run:
|
||||
```bash
|
||||
cd project/client
|
||||
"C:/Program Files/Git/bin/bash.exe" -lc "bash tools/boot_test.sh 200 -PwithClient=true"
|
||||
```
|
||||
Use Git Bash, not the WSL `bash` in PATH (WSL has no `cygpath`/Windows Python).
|
||||
Check `project/run/logs/latest.log` for `[prestige-ui] bridge bound: N modules` (expect 121) and for
|
||||
`ClassNotFoundException` / `NoClassDefFoundError`. The manifest was rewritten (903 setting prop keys), so this
|
||||
primarily validates module + setting binding after the package moves.
|
||||
|
||||
2. **Test the runtime jar route.** The class map is applied by `rename.sh`, so the boot jar should contain the same
|
||||
renamed classes:
|
||||
```bash
|
||||
cd project/client
|
||||
"C:/Program Files/Git/bin/bash.exe" -lc "bash tools/build_runtime.sh"
|
||||
```
|
||||
Then boot through the normal launcher path and compare the bridge line with step 1.
|
||||
|
||||
3. **Real input test.** Open the ClickGUI, HUD editor, toggle modules, change settings, move HUD elements. This was
|
||||
never tested in this refactor; package moves can expose package-private access that `Widen` masked at bytecode
|
||||
level but that no longer matches after decompilation.
|
||||
|
||||
4. **Restore the 5 lost bodies** (currently comments with `TODO(compile)`): `dE.run`, `av.run`, `ca.q`, `cb.q`,
|
||||
`b4.q` in the old names. After renaming, locate with:
|
||||
```powershell
|
||||
Get-ChildItem client/src/main/java -Recurse -Filter *.java |
|
||||
Select-String -Pattern 'body lost|unresolved ZKM reference'
|
||||
```
|
||||
`client/TODO_COMPILE.md` has the original phase notes.
|
||||
|
||||
5. **Restore strings / member names** if desired. `gen_mapping.py` is provenance only; add `F`/`M` rows to
|
||||
`docs/mapping.tsv` and regenerate. Do not touch `docs/classmap.tsv` for member work.
|
||||
|
||||
6. **Update docs.** `client/TODO_COMPILE.md` and `liberate/HANDOFF_2.md` still describe the pre-refactor tree.
|
||||
Record the new package layout, the classmap files, and the boot result.
|
||||
|
||||
## Useful commands / paths
|
||||
|
||||
- Root: `C:\Users\Tyler\Documents\Shared\prestige\liberate\project`
|
||||
- Regenerate source into `client/work/src_gen` (does not touch live tree):
|
||||
```bash
|
||||
cd client
|
||||
"C:/Program Files/Git/bin/bash.exe" -lc "bash tools/build_source.sh"
|
||||
```
|
||||
- Compile generated tree only:
|
||||
```bash
|
||||
"C:/Program Files/Git/bin/bash.exe" -lc "cd project/client && bash tools/compile.sh work/src_gen work/javac_final.log"
|
||||
```
|
||||
- Rename a jar manually:
|
||||
```bash
|
||||
"C:/Program Files/Git/bin/bash.exe" -lc "cd project/client && bash tools/rename.sh work/strip1.jar work/test.renamed.jar"
|
||||
```
|
||||
- Build from source: `.\gradlew.bat build -PwithClient=true`
|
||||
- Manifest: `project/src/main/resources/prestige_ui/manifest_live.json`
|
||||
- Bridge FQNs (unchanged): `project/src/main/java/dev/prestige/ui/bridge/{Bridge,Bootstrap}.java`
|
||||
- Class map: `project/docs/classmap.tsv`, `project/docs/classmap_src.tsv`
|
||||
- Merge check: `python client/tools/merge_mapping.py docs/mapping.tsv docs/classmap.tsv <out>`
|
||||
@@ -0,0 +1,92 @@
|
||||
# TODO_COMPILE - decompiled client source tree (client/src/main/java)
|
||||
|
||||
State (2026-10-19 16:45): the regenerated tree compiles with **0 javac errors** (543 files, `client/work/javac_s3.log`), builds with
|
||||
`./gradlew build -PwithClient=true` (jar 10.5 MB) and **boots under Fabric** (`client/work/boot_source_modules_renamed.log`:
|
||||
`bridge: built 121 modules from manifest, failed 0` / `bridge bound: 121 modules`, toggle test passes, screenshot
|
||||
`client/work/boot_source_modules_renamed_on.png`). The classpath-jar route (`client/work/client-runtime.jar`) stays the default
|
||||
(`./gradlew build` / `runClient`); the source route is opt-in with `-PwithClient=true` because it is a *lossy* reconstruction (see
|
||||
"Known gaps").
|
||||
|
||||
## How to build
|
||||
|
||||
```
|
||||
bash client/build_client.sh # regenerate tree -> client/src/main/{java,resources} -> ./gradlew build -PwithClient=true (~1.5 min)
|
||||
bash client/build_client.sh --no-gradle # stop after installing the tree
|
||||
bash client/build_client.sh --jar # only the jar route: tools/build_runtime.sh (indy-fixed, renamed, Yarn) ~1.5 min
|
||||
bash client/build_client.sh --full # stage A too (IndyResolve -> FlowClean -> Strip = work/strip1.jar) + both routes (~10+ min)
|
||||
bash client/tools/boot_test.sh 200 [-PwithClient=true] [-PuiCmd=<cmdfile>] # dev client, log copied to run/logs/boot_*.log
|
||||
```
|
||||
Dev tool flags: `-PclientJar=<yarn jar>` (swap the classpath jar), `-PdumpClasses=a,b` (force class init, see ClinitDump).
|
||||
|
||||
## Pipeline (all scripts in client/tools, driven by tools/build_source.sh)
|
||||
|
||||
1. stage A (not re-run by default): `run_indy.sh` -> `pipeline_a.sh` => `work/strip1.jar` (obfuscated names, ZKM refs resolved/stripped).
|
||||
2. `rename.sh`: `docs/mapping.tsv` -> tiny-remapper (+ `Widen`: package-private -> public, needed because module classes move into
|
||||
`module/<category>/`) => `work/strip.renamed.jar`. Same step is used by the jar route (`build_runtime.sh`) and regenerates
|
||||
`src/main/resources/prestige_ui/manifest_live.json` (`rename_manifest.py`).
|
||||
3. `NoTry` (tools/notry.txt): clears the exception table of `Prestige.init` and `aw.a(Object[])JsonObject` (Vineflower crashes on them).
|
||||
4. `pipeline_b.sh`: remap to Yarn (+ keyword/case-collision/dedup renames), Vineflower, `extract_src.py`, `fix_sources.py`.
|
||||
(Fixed: it now deletes `work/remapped.jar`/`decompiled.jar` first - tiny-remapper/Vineflower *merge* into an existing output file.)
|
||||
5. javac-driven fixers (errors 406 -> 98 -> 0): `fix_diag.py` (raw for-each, record accessors), `fix_rethrow.py` (ZKM identity
|
||||
rethrow handlers), `fix_ctor.py` (code before `super()` hoisted: constant key arithmetic evaluated and inlined, 58 ctors),
|
||||
`fix_typed_values.py` (covariant `Setting.getValue()`), `fix_reflect.py` (rebuilds the lost `Method.invoke` chains in cU/cW/EventBus:
|
||||
MethodHandles.lookup/privateLookupIn/findVarHandle/unreflect/asSpreader), `fix_diag2.py` (raw generics casts),
|
||||
`manual_edits.py` (exact-text repairs, idempotent, fails loudly if upstream changes; resolves module classes through the mapping),
|
||||
`fix_bootstrap.py` (source equivalent of the bytecode `PatchBootstrap`: `Bootstrap.pre(this)` in all 122 module constructors,
|
||||
adds a constructor to modules that had none).
|
||||
6. `compile.sh` = javac against `work/mc-yarn-aw.jar` + libs; `errsummary.py` summarises a log.
|
||||
|
||||
## Naming
|
||||
`docs/mapping.tsv`: API surface (Module, Category, Setting + 9 setting types, SettingHolder, ModuleManager, EventBus, MenuModule, Gamemode,
|
||||
Subscribe, ListenerEntry and their key fields/methods) and the 121 module classes (`module/<category>/<PascalCaseName>`, generated by
|
||||
`gen_module_mapping.py` from `docs/manifest_live.obf.json`). Remaining classes keep obfuscated names; case-colliding twins carry a `_`
|
||||
suffix (`ea` vs `eA` -> `ea_`) only in the *source* (Windows file system), the bridge accepts both.
|
||||
|
||||
## Known gaps (the source route is NOT behaviourally verified; the jar route is the reference)
|
||||
* **Strip removed 275 "dead unresolved" methods** (`work/strip1.report.txt`, `DEADREMOVED`: dl 26, cA 18, dB 17, dA 13, H 10, G 10, ...,
|
||||
dU 5 (SettingHolder: addFloat/addInt/addRange/addText/addMulti), bT 5, ...). Their callers were rewritten to throws or no-ops by Strip;
|
||||
`bT.a_cF/f` are stubs that throw `UnsupportedOperationException`. Fixing this means making IndyResolve resolve the remaining
|
||||
1591 `REMAIN UNFOLDED` sites (`work/boot_indy.report.txt`) instead of cutting.
|
||||
* (2026-10-21: the 5 HUD/runnable bodies below are RECOVERED, see the 2026-10-21 section; only the 5 reconstructed ones remain approximations.)
|
||||
* **10 `unresolved ZKM reference` bodies**: reconstructed `ge.<init>` (vertex offsets/stride = sum(count*bytes)), `dc.<init>`
|
||||
(`fS.a(args)`), `de.<init>` (`g = bU.a(key)`, `j = new HashMap`), `g2.removeEldestEntry` (`size() > cap`), `dv.a`
|
||||
(`glUniform4f(du.g, radii)`); **no-op with TODO**: `dE.run`, `av.run`, `ca.q`, `cb.q`, `b4.q` (HUD widget render bodies).
|
||||
* **Constants lost by Strip** (`Object var0 = null` + `((Object[])var0)[k]`): recovered at runtime with `tools/java/ClinitDump.java` +
|
||||
`bridge/DumpHook` (instrument `<clinit>` array loads in the runtime jar, run the dev client with `-PclientJar=... -PdumpClasses=...`,
|
||||
log `client/work/clinit_dump.log`): cp (10 shader paths), ap/gB (uniform names), gf (GL types 5126/5121), fQ (49-entry XRay block
|
||||
index table, `tools/clinit_tables.json`), c9 (quad buffer sizes 4/24 - dumped = guessed). **Inferred, not dumped**: `C` ("setRotation",
|
||||
the table is [setPos, setRotation]), `W` ("getMatrix"), `I` ("guiProjectionMatrix" vs "itemsProjectionMatrix"), `du.g` ("roundness").
|
||||
C and W cannot be initialised in a dump run (ClassTransform `TransformerManager` remapper is null at that point) - check them in game.
|
||||
* Decompiler guesses: `Entity`/`PlayerEntity` common types of `?:` expressions (aG, cg_, fx_), `Optional<Vec3d>` (eu_), enum `valueOf(String,long)`
|
||||
removed (callers pass only the string), `da_` ZKM string tables + bootstrap helpers deleted.
|
||||
* Not exercised at all: module behaviour (onEnable hooks, event dispatch, rendering), HUD widgets, config download.
|
||||
* ClassTransform (net.lenni0451, `client/libs/classtransform-bundled.jar`) is shaded into the mod jar in the source route.
|
||||
The client's own fabric.mod.json is not copied; the project's one gets `entrypoints.main` + `accessWidener` injected by `processResources`.
|
||||
|
||||
## Next steps
|
||||
1. Make IndyResolve (stage A) resolve all sites so Strip stops dead-removing methods; re-run `build_client.sh --full`; re-diff the tree.
|
||||
2. Verify the inferred constants (C, W, I, du.g) and the 5 no-op HUD bodies against the runtime jar (indy sites there resolve at run time).
|
||||
3. Behaviour checks module by module (jar route first), then flip the default to the source route and drop `client/work/client-runtime.jar`.
|
||||
4. Rename the remaining ~420 helper classes / packages with `docs/mapping.tsv` (same mechanism, re-run both routes + boot test).
|
||||
|
||||
## 2026-10-21 update (agent "verify")
|
||||
Layout: 543 classes = 21 API classes at the root + `client/Prestige` + 121 `module/<category>/*` + 400 helpers in 18 packages (event hud render data type mixin
|
||||
world math combat inventory network reflect gui config util social annotation input). Frozen mapping files: `docs/classmap.tsv` (400 rows, jar names),
|
||||
`docs/classmap_src.tsv` (source-tree names, `_` case twins); `docs/mapping.tsv` = API surface; merged by `tools/merge_mapping.py` -> `work/rename.map.tsv`.
|
||||
Boot results (logs in `client/work/`):
|
||||
* source route (`-PwithClient=true`): `boot_verify_source_final.log` - `bridge: built 121 modules, failed 0` / `bridge bound: 121 modules`, 0 ClassNotFound/NoClassDef/IllegalAccess,
|
||||
Aim Assist toggle ui=true live.a()=true enabledSetting.value=true; HUD smoke (`state hudsmoke`, DevCmd): all 16 HUD `q()` + RenderHelper24.run + CobwebPlacerHelper.run ok
|
||||
(`boot_verify_source_hudsmoke.png`).
|
||||
* jar route (`tools/build_runtime.sh`): `boot_verify_jar_final.log` - 121 modules bound, toggle on/off round trips; HUD smoke: 15/16 q() ok, the first one fails with the
|
||||
known stateful-key BADREF of `g2.removeEldestEntry` (AIOOBE index 188911/9; g2 = LRU map used by the shader/text cache) - jar-route-only, source route has the reconstruction.
|
||||
Note the toggle test needs a few attempts: real mouse movement over the game window overrides the simulated cursor (Overlay.pollCursor).
|
||||
Fixes: stale classes in `work/boot_yarn.jar` (tiny-remapper MERGES into an existing output; old-named `fT/fS/..` were loaded by name) -> `rm` before remap;
|
||||
`Widen` now also widens private members (nest host/member links are lost by the moves; IllegalAccessError); unresolved reference tables still contain OLD class names ->
|
||||
`tools/java/RecoverBodies.java` redirects every `Class.forName` of the client jar to `dev.prestige.ui.bridge.OldNames` (map `src/main/resources/prestige_ui/old_names.tsv`, written by
|
||||
`tools/old_names.py` from rename.sh). No mixin json / fabric.mod.json / Bridge FQN change was needed (the client's mixins are ClassTransform `@CTransformer` classes applied
|
||||
by the native module, not Fabric mixins; shader/resource paths are string literals and unchanged).
|
||||
Recovered bodies (dE.run=RenderHelper24, av.run=CobwebPlacerHelper, ca.q=ModuleListElement, cb.q=ModuleNotificationsElement, b4.q=HudElement): decoded from the pre-strip jar
|
||||
(`out/prestige-deobf-fixed.jar`) with `tools/recover_refs/` (brute-forces the per-method reference-table key; b4.q found by matching entries of another method:
|
||||
`dB.l`=MatrixStack.l + `Color.WHITE`). Source: `tools/manual_edits.py` (also widens `Renderer2D.i/m`, `CobwebPlacer.E/F/d/o`); jar: `RecoverBodies`. Regeneration
|
||||
(`build_source.sh`) verified: 0 javac errors, tree identical to `client/src/main/java`.
|
||||
Remaining: dv.a / g2 / dc / de reconstructions are still inferred; g2 wrong key in the jar route; strings and member names still obfuscated.
|
||||
Reference in new issue
Block a user