File Details
Retromod 1.2.0-snapshot.8 (Forge 1.21.11)
- R
- Jul 4, 2026
- 3.22 MB
- 3
- 1.21.11
- Forge
File Name
retromod-1.2.0-snapshot.8+1.21.11.jar
Supported Versions
- 1.21.11
Curse Maven Snippet
The three remaining 1.2.0 pillars landed, plus a full in-game acceptance pass for Apollo's Enchantment Rebalance on Fabric 26.2 (#119). §A the pre-26.1 Fabric acceptance pass: real 1.16.5 Serilum mods run clean through full server start on a 1.20.1 host (Text/Entity-field/Material bridges + a rebuilt constructor-to-factory pass). §D the 1.12.2 in-game layers (SRG member namespace, the pre-1.13 FML lifecycle idiom, a 1.20.1-target class-move table). §B the 26.2 render-API stand-ins (MultiBufferSource, Tesselator, VertexFormat$Mode). And #119: the anvil-crash phantom redirect, a systemic phantom-target safety net, and the blank-enchanted-books tooltip rename, all fixed and verified in-game.
Added
- 26.2 render-API stand-ins (SS B): render-referencing mods now LOAD on 26.2. 26.2 deleted
MultiBufferSource/MultiBufferSource$BufferSourceandTesselator, and replaced theVertexFormat$Modeenum withPrimitiveTopology(all verified against the real 26.1.2 and 26.2 client jars), so a 26.1-translated mod referencing any of them diedNoClassDefFoundErrorat class load on 26.2, even when the render path never ran. New per-mod-embedded stand-ins reproduce the exact 26.1 shapes:BufferSource.getBuffer(renderType)returns a REAL 26.2BufferBuilderbuilt from the RenderType's ownformat()/primitiveTopology(), andTesselator.getInstance().begin(...)works the same way, so mod geometry code actually executes; theendBatchfamily is staged (warns once and drops the batch: frame submission through the newSubmitNodeCollector.submitCustomGeometrypipeline is the follow-up).VertexFormat$Modeis class-redirected toPrimitiveTopology(identical constants and public fields). Registered in the 26.1 to 26.2 layer on all loaders. Tested (RenderBufferSyntheticsTest). - 1.12.2 SRG member namespace (SS D, #103/#108/#117). Distributed 1.12.2 Forge mods reference members by the OLD SRG names (
func_NNNNN_x/field_NNNNN_x), a different namespace from the modernm_/f_one, so the SRG remap never fired for them. A new bundled dictionary (srg-1.12.2-to-mojang.tsv, 7,736 entries) maps them to readable names: harvested from the MCPBot 1.12.2 stable CSVs and kept ONLY where the name exists in Mojang's official 1.20.1 mappings (a wrong rename is worse than none). The remapper's SRG branch now matches both eras, and the dictionary loader merges both files. Also fixed a latent core bug the new tests flushed out: an SRG-only registration built no remapper at all (masked before because real runs always carry class redirects). Tested (Srg1122MemberRemapTest). - 1.12.2 class moves for 1.20.x hosts (SS D). The 1.12.2 class-move table only existed with 26.1-target names, but the reported 1.12.2 hosts (#103/#108/#117) all run 1.20.1. A new validated variant (
forge-1.12.2-class-moves-1201.tsv, 125 rows, every target checked against Mojang's official 1.20.1 mappings byscripts/harvest-1.12.2-class-moves-1201.py) loads on 1.20.x hosts instead, and additionally carries the families 26.1 removed but 1.20.x still has (ItemSword -> SwordItem,EnumAction -> UseAnim,CreativeTabs -> CreativeModeTab, tool/armor tiers, ...). The Block/Item Properties constructor bridge and theMaterialstatic-field nuller now apply on 1.20.x hosts too (verified: 1.20 already removedMaterial, andProperties.of()/Item$Properties()are present with the same shapes as 26.1). 1.21.x hosts get no table (none validated against those jars). Tested (Forge1122ClassMovesTest). - 1.12.2 in-game FML lifecycle layer (SS D, #103/#108/#117). A 1.12.2 mod's
@Mod(modid=...)annotation shape is invisible to a modern loader (it reads@Mod(value)), and nothing ever calls its@Mod.EventHandlersetup methods, so even a mod that LOADED did nothing. The upgrade pass rewrites the annotation to the modern shape and injects a constructor-time call into an embedded lifecycle bridge that constructs the legacyFMLPreInitialization/FMLInitialization/FMLPostInitializationevent stand-ins (config-dir surface included:getSuggestedConfigurationFileyieldsconfig/<modid>.cfg) and reflectively invokes the mod's handlers in order. Active only when the 1.12.2 shim chain registered. Tested (Forge1122LifecycleTest, including a functional fire test). - Pre-26.1 Fabric bridge chain from the LIVE acceptance pass (SS A, #55). Real 1.16.5 Fabric content mods (Serilum's Double Doors, Mineral Chance, Stack Refill plus their shared Collective library) were run on an actual 1.20.1 Fabric server and every crash in the chain was fixed at the transform level:
- Pre-1.19 Text bridge. The 1.19 chat rework removed the
TranslatableText/LiteralTextconstructors;new TranslatableText("key")diedNoSuchMethodError. Constructor-to-factory redirects targetText.translatable/Text.literal(plus the with-args overload), registered with the InterfaceMethodref form (Textis an interface on 1.19+: a plain-Methodref INVOKESTATIC diesIncompatibleClassChangeError), and both old classes class-redirect toMutableTextso the mod's downstream fluent calls (formatted,setStyle,append: same intermediary ids onMutableTextsince 1.16, verified on the 1.20.1 jar) type-check against the factory's return value. - Pre-1.17 Entity field bridge.
Entity.onGroundwent non-public in the 1.17 access cleanup; direct access diedIllegalAccessError. GETFIELD/PUTFIELD rewrite toisOnGround()/setOnGround(boolean). - Pre-1.20 Material bridge. MC 1.20 deleted the Material system, and ONE
List<Material>in a<clinit>(Collective'sGlobalVariables) took the whole class down withNoClassDefFoundError.class_3614class-redirects to a shippedMaterialPolyfill(44 distinct constants under their exact 1.16.5 intermediary field ids, harvested from the official intermediary mappings), andBlockState.getMaterial()devirtualizes to a stagedfromState(returns a sentinel matching no constant, so material-membership features quietly no-op instead of crashing). - All three bridges are host-introspecting (probe with
Class.forName(..., false, ...), never initialize): they register only where the host actually lost the API, so 1.16.x-1.18.x hosts are untouched. Tested (Pre1_17EntityFieldBridgeTest,Pre1_20MaterialBridgeTest, plus the real failing Collective class as a gated repro). - Also fixed while here: the fuzzy method resolver never activated on pre-26.1 Fabric hosts (its MC-jar probe only knew the Mojang-named
SharedConstants; intermediary hosts need theclass_310/MinecraftServerprobes), andFabric_1_16_5_to_1_17carried four 26.x-only tick-event renames (*WorldTickto*LevelTick) that broke the very hosts the shim targets; the correct copies live in the 26.1 shim.
- Pre-1.19 Text bridge. The 1.19 chat rework removed the
Fixed
- 1.12.2 Forge mods no longer die "mods.toml missing metadata for modid null" on 1.20.1+ (#120, Betweenlands / Scape and Run Parasites). A 1.12.2
@Modannotation is@Mod(modid="x", name=..., version=..., dependencies=...); modern Forge's@Modhas ONLYvalue()(which IS the modid), so it readvalue()= null from the old shape and aborted mod loading with a null modid. TheForge1122LifecycleSynthetics@Modmodernization (added this cycle) collapses the whole legacy annotation to@Mod(value=modid)so Forge reads a real id. Verified on the realSRPMainclass from Scape and Run Parasites (@Mod(modid="srparasites", ...)->@Mod(value="srparasites")). The runtime Forge path already activated the pass via the 1.12.2 shim chain; the CLI transform now activates it too (at startup, self-gating on the old annotation shape so it never touches modern mods), so pre-transformed jars get the same fix. Tested (Forge1122LifecycleTest, incl. the full 4-element annotation shape). - Custom
ClientTooltipComponentrenderers now draw on 26.1+ (Apollo's Enchantment Rebalance blank enchanted books, #119). 26.1 renamedClientTooltipComponent.renderText/renderImagetoextractText/extractImage(the params takeGuiGraphics, itself renamed toGuiGraphicsExtractor). The intermediary->Mojang table is 1.21.4-based and mapped those two intermediary ids (method_32665/method_32666) to the OLD names, so a distributed 1.21.x Fabric mod's overrides were renamed torenderText/renderImageand no longer overrode the interface: the vanilla empty default methods ran, and the mod's custom tooltip drew nothing (AER's enchanted books showed no enchantment lines, even though the enchantments themselves applied and functioned). Corrected the two id mappings to the 26.1 names; the fix is id-scoped, so the four unrelatedrenderTextmethods are untouched. Tested (ClientTooltipRenderRenameTest, both the mapping and a transformed override). This is one instance of a broader class: the 1.21.4-based intermediary table carries stale names for any method renamed between 1.21.4 and 26.1, which breaks overrides on a 26.1+ host; more such renames may need the same correction as they surface. - Apollo's Enchantment Rebalance no longer crashes the anvil on Fabric 26.2 (#119). The mod's anvil
createResultcallsEnchantment.getMaxLevel(), which Retromod was rewriting to acom/retromod/shim/*/embedded/EnchantmentShimthat was never written (a phantom target): the anvil combined an item + book, the rewritten call resolved, and it diedNoClassDefFoundErroron first use. Three compounding faults, all fixed:- The Fabric transform path had no loader-type filter.
RetromodPreLaunchregistered EVERY version shim regardless ofgetModLoaderType(), unlike the other three entry points. So a NeoForge shim's Mojang-named redirect (NeoForge_1_20_6_to_1_21) fired on a Fabric mod once the intermediary->Mojang harvest made the names match. It now applies the same{fabric, common}filter the NeoForge/Forge/onInitialize paths already use, which closes the entire class of cross-loader phantom bites on Fabric (NeoForge/Forge enchantment, ItemStack-NBT, DamageSource, Material, Tag redirects, etc.). - The redirects were wrong regardless.
Enchantment.getMaxLevel()/getMinLevel()never left the API (present 1.21 through 26.2, backed by the data-driven definition); redirecting them was pointless. Both the NeoForge and the Yarn-keyed Fabric copies (dead code per the intermediary-namespace note) are deleted.getRaritywas genuinely removed but can't be bridged by a call-site redirect alone (itsRarityreturn type is gone too), so it's deleted pending a proper synthetic bridge. - A phantom-target safety net. The transformer now sweeps its redirect tables once, before the first transform, and drops any redirect whose
com/retromod/*target is neither a registered synthetic nor a loadable class, logging one warning instead of letting it detonate at first use. This retroactively neutralizes several other never-written targets found across the shim tree (FlatteningShim,SidedProxyShim, a wrong-packageGameRegistryShim, ...): the affected feature quietly no-ops instead of crashing whatever runs it. This also surfaced and fixed a latent bug where a redirect set containing only super-constructor + class redirects skipped the method-body visitor entirely (the 1.12.2 Block/Itemsuper(Material)->super(Properties)bridge relied on an unrelated method redirect being present to stay active). The reported blank-enchanted-books symptom is a separate client mixin-apply matter still under investigation.
- The Fabric transform path had no loader-type filter.
- Constructor-to-factory rewriting no longer corrupts stack frames when the args contain branches (found live on Collective's
DuskConfig). The old deferral buffered ONE pendingNEWand flushed it as soon as a nested plainnewappeared, i.e. mid-expression: with a ternary in the constructor args the buffered NEW+DUP landed on one branch path only, ASM's frame computation failed (Frame.mergeAIOOBE), and the silent COMPUTE_MAXS fallback then shipped the class with its ORIGINAL StackMapTable whose offsets the rewrite had invalidated:ClassFormatError: StackMapTable format error: bad offset for Uninitializedat load, taking the whole mod down. The machinery is now a proper deferral STACK flushed only at the<init>convergence point (branch-safe by construction, and nested redirect-eligiblenews compose), it moved UPSTREAM of the class remapper into its own pass (CtorRedirectPrePass, so constructor redirects stay keyed on distinct pre-remap owners even when several old classes retype onto ONE new class, as the Text bridge needs), the fallback now logs the primary failure instead of swallowing it, and a fallback pass that made frame-invalidating rewrites refuses to ship the result (degrades to the untransformed class instead of a corrupt one). Regression-tested with synthesized pathological shapes (CtorRedirectBranchedArgsTest) plus the real failing class.