promotional bannermobile promotional banner

Polymorphic Refined Storage

Polymorph recipe selection button directly into Refined Storage 2 Crafting Grids and Pattern Grids.

File Details

rspolymorph-neoforge-1.21.1-1.2.0

  • R
  • Jun 6, 2026
  • 74.46 KB
  • 6.0K
  • 1.21.1
  • NeoForge

File Name

rspolymorph-neoforge-1.21.1-1.2.0.jar

Supported Versions

  • 1.21.1

Curse Maven Snippet

NeoForge

implementation "curse.maven:rs-polymorph-1492934:8206119"
Curse Maven does not yet support mods that have disabled 3rd party sharing

Learn more about Curse Maven

## [1.2.0] - 2026-06-05

### Added

- **Standalone — no Polymorph dependency** — RS Polymorph no longer requires the Polymorph mod. The recipe-selection UI (side button + popup) and the per-grid selection persistence are now provided entirely by RS Polymorph itself. The side button is the native Refined Storage `AbstractSideButtonWidget`; the popup is a self-contained `RecipeSelectorPopup` (own item-grid widget + render/click mixin on the grid screen); the per-grid choice is persisted on the grid block entity via loader Data Attachments (NeoForge `AttachmentType` / Fabric persistent attachment) behind a `Services.GRID_STORE` abstraction. The printed-pattern tag stays a vanilla `DataComponentType`. The Polymorph-only classes (`RsGridRecipeData`, `MixinSelectionWidget`, `MixinRecipeManagerSafety`) were removed. Result: a true Refined Storage add-on that works everywhere RS does, with no third-party recipe-selection dependency.
- **Minecraft 26.1.2 / Refined Storage 3.2.0 (NeoForge)** — A parallel build targets the new Minecraft 26.1.2 (year-based versioning, Java 25) against Refined Storage 3.2.0, sharing the 1.21.1 codebase. RS 3.x kept the same `com.refinedmods.refinedstorage.common.*` structure, so the mixins carry over; the few MC 26.x renames (`ResourceLocation`→`Identifier`, `GuiGraphics`→`GuiGraphicsExtractor`) are applied by a build-time source remap, and the handful of files touching the reworked recipe API (`server.getRecipeManager()`/RS3 `RecipeProvider`, single-arg `assemble`, `RecipeHolder.id()` now a `ResourceKey`) and the new two-phase GUI render pipeline (`extractRenderState`/`extractContents`) are forked under `common-261`. `MixinPatternResolver` is re-targeted with `@WrapOperation` onto RS3's `Platform.getClientRecipeProvider().getRecipesFor(...)`. Build with Gradle on JDK 25: `./gradlew :neoforge-261:build -Dorg.gradle.java.home=<jdk25>`.
- **Fabric support — one mod, two loaders** — RS Polymorph now ships for **Fabric** in addition to NeoForge, both for Minecraft 1.21.1. The project was restructured into a MultiLoader layout (`common` + `neoforge` + `fabric`): all gameplay logic and every mixin live in `common` and are shared verbatim by both loaders. Because the mixins target Refined Storage 2 and Polymorph classes (never Minecraft) with `remap=false`, and both RS2 and Polymorph ship their public surface in a shared cross-loader module, the injection logic resolves byte-for-byte identically on NeoForge and Fabric with no per-loader rewrite.
- **Loader-agnostic core** — Introduced a small platform abstraction so `common` never references a loader API: `Services`/`NetworkPlatform` resolve the active loader's networking via `ServiceLoader`, the `selected_recipe` data component is registered by each loader and injected into the shared core, and `SelectRecipePacket` exposes a pure `applyOnServer(ServerPlayer, ResourceLocation)` that each loader drives from its own packet receiver (NeoForge `IPayloadContext`, Fabric `ServerPlayNetworking`).
- **Combined single jar (optional)** — In addition to the two per-loader jars, an optional fused jar (`rspolymorph-<version>.jar`) that loads on both NeoForge and Fabric is produced via ModFusioner (`./gradlew fusejars`). The per-loader jars remain the primary, most robust distribution.
- **First-open tutorial card** — The first time a player opens an RS grid, a one-time, bilingual card explains the recipe-selection feature (button + popup) and is dismissed by a click or by pressing Space/Enter. The "seen" flag is persisted client-side (`config/rspolymorph_tutorial.flag`, written off the render thread, fail-soft) so it never reappears. Screen-reader users get a one-shot narrator announcement.
- **Redesigned recipe selector popup** — The selection popup was reworked to look native: a titled header, inset slot frames, a gold highlight on the recipe the grid is currently producing, on-screen clamping, item-count decorations, and a single readable recipe name on hover. Per-frame allocations in the render path were removed.

### Fixed

- **Recipe selection on NeoForge** — Selecting a recipe threw `UnsupportedOperationException` server-side: the per-grid map decoded from the attachment codec is a Guava `ImmutableMap`, so `put`/`remove` failed. `NeoForgeGridRecipeStore.set` now copies-on-write into a fresh `HashMap` before `setData`. Affected both 1.21.1 and 26.1.2 NeoForge.
- **Overlapping slot tooltip** — Refined Storage's grid screens override `renderTooltip` per subclass (`CraftingGridScreen`/`PatternGridScreen`/`AbstractGridScreen`) and draw the hovered-slot tooltip themselves, so a mixin on vanilla `AbstractContainerScreen.renderTooltip` was bypassed and the underlying "Stick" tooltip drew over the popup. The suppression mixin now targets those RS classes and fires whenever the popup is open. The 26.x render pipeline differs, so its fork is a fail-soft no-op.
- **Per-MC-version recipe parsing** — Crafting-recipe ingredient JSON differs between MC versions (1.21.1 uses object form `{"item":"..."}`, 26.x uses bare strings). The test recipes are split per version and merged by a build task, so the test items now craft on every target.

### Changed

- **Refined Storage 2 baseline bumped to 2.0.8** — The Fabric build pulls Refined Storage 2.0.8 and Polymorph 1.1.0+1.21.1 from the Modrinth maven; the declared `refinedstorage` dependency floor stays `>= 2.0.1`. RS 2.x and RS 3.x share the same internal package structure (`com.refinedmods.refinedstorage.common.*`), so the mixins are forward-compatible across the RS 2.x line with no signature changes.
- **Build toolchain** — Migrated to the MultiLoader-Template build (Gradle 9.5.1, Fabric Loom 1.16.3 for the Fabric module, ModDevGradle 2.0.140 for the common/NeoForge modules). The Gradle wrapper was bumped from 9.2.1 to 9.5.1 to satisfy Loom 1.16.3.

### Known limitations

- **Fabric on Minecraft 26.1.2 not yet enabled** — Minecraft 26.1.x ships un-obfuscated (no Mojang ProGuard mappings), which only `fabric-loom` 1.17.0-alpha+ supports, and that alpha conflicts with the stable Loom 1.16.3 used by the 1.21.1 Fabric module in the same build. The `fabric-261` module (sources, entrypoints, metadata) is implemented but excluded from the default build; enable it on a branch that bumps Loom once a stable Loom with 26.x support lands. NeoForge 26.1.2 ships normally.

### Ajouts

- **Autonome — plus de dépendance à Polymorph** — RS Polymorph ne requiert plus le mod Polymorph. L'UI de sélection de recette (bouton latéral + popup) et la persistance du choix par grille sont désormais fournies entièrement par RS Polymorph. Le bouton latéral est l'`AbstractSideButtonWidget` natif de Refined Storage ; le popup est un `RecipeSelectorPopup` autonome (widget de grille d'items + mixin de rendu/clic sur l'écran de grille) ; le choix par grille est persisté sur le block entity via les Data Attachments du loader (NeoForge `AttachmentType` / attachment persistant Fabric) derrière une abstraction `Services.GRID_STORE`. Le tag du patron imprimé reste un `DataComponentType` vanilla. Les classes spécifiques à Polymorph (`RsGridRecipeData`, `MixinSelectionWidget`, `MixinRecipeManagerSafety`) ont été supprimées. Résultat : un véritable add-on Refined Storage qui fonctionne partout où RS fonctionne, sans dépendance tierce de sélection de recette.
- **Minecraft 26.1.2 / Refined Storage 3.2.0 (NeoForge)** — Un build parallèle cible le nouveau Minecraft 26.1.2 (versioning par année, Java 25) avec Refined Storage 3.2.0, en partageant la base de code 1.21.1. RS 3.x a conservé la même structure `com.refinedmods.refinedstorage.common.*`, donc les mixins sont repris ; les quelques renommages MC 26.x (`ResourceLocation`→`Identifier`, `GuiGraphics`→`GuiGraphicsExtractor`) sont appliqués par un remap de sources au build, et les fichiers touchant l'API de recette remaniée (`server.getRecipeManager()`/`RecipeProvider` RS3, `assemble` à un argument, `RecipeHolder.id()` désormais un `ResourceKey`) et le nouveau pipeline de rendu GUI à deux phases (`extractRenderState`/`extractContents`) sont forkés sous `common-261`. `MixinPatternResolver` est re-ciblé avec `@WrapOperation` sur `Platform.getClientRecipeProvider().getRecipesFor(...)` de RS3. Build avec Gradle sur JDK 25 : `./gradlew :neoforge-261:build -Dorg.gradle.java.home=<jdk25>`.
- **Support Fabric — un seul mod, deux loaders** — RS Polymorph est désormais publié pour **Fabric** en plus de NeoForge, tous deux pour Minecraft 1.21.1. Le projet a été restructuré en architecture MultiLoader (`common` + `neoforge` + `fabric`) : toute la logique de jeu et chaque mixin vivent dans `common` et sont partagés à l'identique par les deux loaders. Comme les mixins ciblent des classes de Refined Storage 2 et de Polymorph (jamais de Minecraft) avec `remap=false`, et que RS2 comme Polymorph exposent leur surface publique dans un module commun cross-loader, la logique d'injection se résout octet pour octet de façon identique sur NeoForge et Fabric, sans réécriture par loader.
- **Noyau agnostique du loader** — Ajout d'une petite abstraction de plateforme pour que `common` ne référence jamais une API de loader : `Services`/`NetworkPlatform` résolvent le réseau du loader actif via `ServiceLoader`, le data component `selected_recipe` est enregistré par chaque loader puis injecté dans le noyau partagé, et `SelectRecipePacket` expose un `applyOnServer(ServerPlayer, ResourceLocation)` pur que chaque loader pilote depuis son propre récepteur de paquet (NeoForge `IPayloadContext`, Fabric `ServerPlayNetworking`).
- **Jar unique combiné (optionnel)** — En plus des deux jars par loader, un jar fusionné optionnel (`rspolymorph-<version>.jar`) chargeable sur NeoForge ET Fabric est produit via ModFusioner (`./gradlew fusejars`). Les jars par loader restent la distribution principale, la plus robuste.
- **Carte tuto au premier lancement** — La première fois qu'un joueur ouvre une grille RS, une carte unique et bilingue explique la sélection de recette (bouton + popup) ; elle se ferme d'un clic ou en appuyant sur Espace/Entrée. Le drapeau « vu » est persisté côté client (`config/rspolymorph_tutorial.flag`, écrit hors du thread de rendu, fail-soft) pour ne jamais réapparaître. Les utilisateurs de lecteur d'écran reçoivent une annonce narrateur unique.
- **Popup de sélection redesigné** — Le popup a été retravaillé pour un rendu natif : en-tête titré, slots en relief, surbrillance dorée sur la recette actuellement produite, calage à l'écran, décorations de quantité, et un seul nom de recette lisible au survol. Les allocations par frame du rendu ont été supprimées.

### Correctifs

- **Sélection de recette sur NeoForge** — La sélection levait `UnsupportedOperationException` côté serveur : la map par grille décodée du codec d'attachment est une `ImmutableMap` Guava, donc `put`/`remove` échouaient. `NeoForgeGridRecipeStore.set` fait désormais une copie dans un nouveau `HashMap` avant `setData`. Affectait NeoForge 1.21.1 et 26.1.2.
- **Tooltip de slot superposé** — Les écrans de grille de Refined Storage overrident `renderTooltip` par sous-classe (`CraftingGridScreen`/`PatternGridScreen`/`AbstractGridScreen`) et dessinent eux-mêmes le tooltip du slot survolé ; un mixin sur le `AbstractContainerScreen.renderTooltip` vanilla était donc contourné et le tooltip « Stick » s'affichait par-dessus le popup. Le mixin de suppression cible désormais ces classes RS et s'active dès que le popup est ouvert. Le pipeline de rendu 26.x diffère, son fork est un no-op fail-soft.
- **Parsing des recettes par version MC** — Le JSON des ingrédients de craft diffère selon la version MC (1.21.1 en objet `{"item":"..."}`, 26.x en chaîne brute). Les recettes de test sont séparées par version et fusionnées par une tâche de build, donc les items de test se craftent désormais sur chaque cible.

### Modifications

- **Base Refined Storage 2 portée à 2.0.8** — Le build Fabric récupère Refined Storage 2.0.8 et Polymorph 1.1.0+1.21.1 depuis le maven Modrinth ; le plancher de dépendance `refinedstorage` déclaré reste `>= 2.0.1`. RS 2.x et RS 3.x partagent la même structure de packages interne (`com.refinedmods.refinedstorage.common.*`), donc les mixins sont compatibles ascendant sur toute la ligne RS 2.x sans changement de signature.
- **Chaîne de build** — Migration vers le build MultiLoader-Template (Gradle 9.5.1, Fabric Loom 1.16.3 pour le module Fabric, ModDevGradle 2.0.140 pour les modules common/NeoForge). Le wrapper Gradle est passé de 9.2.1 à 9.5.1 pour satisfaire Loom 1.16.3.