Renaming mixin classes and patching mixins.json (90506a4) breaks Fabric
mods at runtime, proven on LoVisual (2026-10-13):
- When obfuscated packages are randomized per class the config patcher
computes an empty common prefix and writes `package: ""`. Fabric/Mixin
then drops every mixin as "orphaned", so `RenderPipelineMixin
implements IRenderPipeline` never applies, the interface is not
injected into `RenderPipeline`, and the entrypoint dies with
`ClassCastException: RenderPipeline cannot be cast to IRenderPipeline`.
- `IMixinConfigPlugin.shouldApplyMixin` compares the runtime mixin class
name against string literals (`Set.of("dev.loki...Mixin")`); renaming
desyncs those sets and optional sodium/iris/xaero mixins get applied
when the target mod is absent.
Re-enable absorb_mixins: mixin entry classes and the config plugin keep
their names, and locking a class freezes its members too (needed for
@Accessor/@Invoker/@Overwrite name lookups). Calls from locked mixin
bytecode are still rewritten consistently, and the family mechanism keeps
interface method names (IRenderPipeline) in sync with the frozen mixin
methods. patch_mixins_json stays but is identity for locked classes.
Verified: LoVisual obf jar loads all 221 mixins (0 orphaned), the main
menu renders, the entrypoint runs.
- Remove absorb_mixins keep rule (mixin classes now renameable)
- Add mixins.rs: patch_mixins_json rewrites package + entries via
common prefix of mapped names; patch_refmap_json rewrites all strings
- Resources pass routes *.mixins.json and *refmap.json to specialized
patchers, falls back to generic text remap
Reference: OBF fabric-obfuscator patchMixinsJson/patchRefmapJson.