Architecture
Retromod turns an old mod jar into one that targets the host Minecraft and loader.
Pipeline
- Detect the source Minecraft version and loader from mod metadata.
- Find a chain of version shims.
- Register class, method, field, constructor, and signature redirects.
- Remap Fabric intermediary or Forge SRG names when needed.
- Rewrite classes, mixin annotations, refmaps, access wideners, and metadata, including supported nested jars.
- Embed selected replacement APIs.
- Verify references and cache the result.
The transform is iterative because one rewrite can expose another old reference.
Loader Entry Points
- Fabric:
RetromodPreLaunchprocessesretromod-input/before Fabric scans normal mods. - NeoForge:
RetromodNeoForgetransforms input and supported jars inmods/. - Forge:
RetromodForgefollows the Forge path and registers Forge-specific bridges. - CLI:
RetromodCliruns the same core without a live loader.
Quilt mods use the Fabric bytecode family. QuiltModTransformer handles jars whose authoritative metadata is quilt.mod.json, while the shared host artifact declares Fabric-compatible entrypoint keys for Quilt Loader. The artifact carries both loader metadata files. Retromod does not publish a separate Quilt artifact.
Loader entry points must not reference another loader’s classes. Shared work belongs in loader-neutral helpers.
Core Components
| Component | Role |
|---|---|
RetromodTransformer | ASM visitors and redirect registries |
ShimRegistry | Finds version paths |
IntermediaryToMojangMapper | Fabric names on unobfuscated hosts |
SrgToMojangMapper | Forge SRG names on Mojang-named hosts |
MixinCompatibilityTransformer | Mixin annotations and selected handler repairs |
FabricModTransformer | Fabric metadata, jars, and access wideners |
QuiltModTransformer | Fabric-compatible bytecode repairs and quilt.mod.json updates |
ForgeModTransformer | Forge and NeoForge metadata and jars |
SyntheticEmbedder | Per-mod replacement classes |
AotCompiler | Cached offline transforms |
ResourceManager | Transactional staged resource and data pack processing |
Shims and Polyfills
A version shim describes a transition between releases. Shims compose through a breadth-first search, so old support must remain registered.
A polyfill replaces an API that no longer exists. Polyfills should preserve useful behavior through a modern equivalent. A no-op is acceptable only when the limitation is explicit.
Both use ServiceLoader registrations under src/main/resources/META-INF/services/.
Safety
Redirects should be owner- and descriptor-specific. Frame recomputation falls back conservatively when a class hierarchy cannot be proven. Fabric runtime nested transforms stop after four levels. Original jars are backed up, and cache stamps prevent packaged builds from reusing stale transforms.
See Technical Details for lower-level notes.