9.6 KiB
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)
- stage A (not re-run by default):
run_indy.sh->pipeline_a.sh=>work/strip1.jar(obfuscated names, ZKM refs resolved/stripped). rename.sh:docs/mapping.tsv-> tiny-remapper (+Widen: package-private -> public, needed because module classes move intomodule/<category>/) =>work/strip.renamed.jar. Same step is used by the jar route (build_runtime.sh) and regeneratessrc/main/resources/prestige_ui/manifest_live.json(rename_manifest.py).NoTry(tools/notry.txt): clears the exception table ofPrestige.initandaw.a(Object[])JsonObject(Vineflower crashes on them).pipeline_b.sh: remap to Yarn (+ keyword/case-collision/dedup renames), Vineflower,extract_src.py,fix_sources.py. (Fixed: it now deleteswork/remapped.jar/decompiled.jarfirst - tiny-remapper/Vineflower merge into an existing output file.)- 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 beforesuper()hoisted: constant key arithmetic evaluated and inlined, 58 ctors),fix_typed_values.py(covariantSetting.getValue()),fix_reflect.py(rebuilds the lostMethod.invokechains 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 bytecodePatchBootstrap:Bootstrap.pre(this)in all 122 module constructors, adds a constructor to modules that had none). compile.sh= javac againstwork/mc-yarn-aw.jar+ libs;errsummary.pysummarises 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/fare stubs that throwUnsupportedOperationException. Fixing this means making IndyResolve resolve the remaining 1591REMAIN UNFOLDEDsites (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 referencebodies: reconstructedge.<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 withtools/java/ClinitDump.java+bridge/DumpHook(instrument<clinit>array loads in the runtime jar, run the dev client with-PclientJar=... -PdumpClasses=..., logclient/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 (ClassTransformTransformerManagerremapper is null at that point) - check them in game. - Decompiler guesses:
Entity/PlayerEntitycommon types of?:expressions (aG, cg_, fx_),Optional<Vec3d>(eu_), enumvalueOf(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 getsentrypoints.main+accessWidenerinjected byprocessResources.
Next steps
- Make IndyResolve (stage A) resolve all sites so Strip stops dead-removing methods; re-run
build_client.sh --full; re-diff the tree. - 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).
- Behaviour checks module by module (jar route first), then flip the default to the source route and drop
client/work/client-runtime.jar. - 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 HUDq()+ 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 ofg2.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 inwork/boot_yarn.jar(tiny-remapper MERGES into an existing output; old-namedfT/fS/..were loaded by name) ->rmbefore remap;Widennow 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.javaredirects everyClass.forNameof the client jar todev.prestige.ui.bridge.OldNames(mapsrc/main/resources/prestige_ui/old_names.tsv, written bytools/old_names.pyfrom rename.sh). No mixin json / fabric.mod.json / Bridge FQN change was needed (the client's mixins are ClassTransform@CTransformerclasses 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) withtools/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 widensRenderer2D.i/m,CobwebPlacer.E/F/d/o); jar:RecoverBodies. Regeneration (build_source.sh) verified: 0 javac errors, tree identical toclient/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.