Repository navigation
Machine recipe types: datapack loading, lookup, datagen and JEI - #83
Conversation
…tagen and JEI Phase 2 of the machine module. Mods register a MachineRecipeType through their own DeferredRegisters (MachineRecipeTypes.register); its recipe files load, reload and sync like any recipe. - STREAM_CODECs for MachineRecipe, MachineIngredient, MachineProduct and FluidAmount; the type's serializer is built from CODEC and STREAM_CODEC. - MachineRecipeEntry wraps a MachineRecipe as a vanilla Recipe; it matches through RecipeMatcher.check and stays out of the recipe book. - MachineRecipeInput exposes a MachineInventory to vanilla and is never empty, so fluid- or energy-only recipes are still asked. - MachineRecipeLookup finds the runnable recipe, trying the last one by ID so /reload is picked up. - MachineRecipeBuilder writes recipes from datagen. - JEI: a generic MachineRecipeCategory for every registered machine recipe type, sized for its largest recipe. mmdlib:crushing is unchanged; moving it is left for a separate decision. Tests: five game tests over mmdlib_smoke:grinding and its recipe files (registration, loading with a broken file skipped, lookup, network round trip, builder output equal to the file); the GUI smoke test checks the JEI category and saves a screenshot, which CI now uploads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018zpP6ZrFjaGe477FvWAZKo
Review notes from #82. - blocksPlace, bucketsPlaceAndRecover and MachineSmoke.check used absolute world coordinates. They now take a position from helper.absolutePos, so they stay inside their own structure. The first two used a spaced grid, which doesn't fit in the 5x5x5 structure, so they place one block or fluid at a time on the same spot. - verifyReleaseClasses refused everything under data/mmdlib/structure/, which would fail the build if MMDLib ever ships a structure. It now refuses only the test structure, empty.nbt. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018zpP6ZrFjaGe477FvWAZKo
|
Single fix needed: output room ignores what the recipe consumes from the same group Comments:
|
RecipeMatcher.check tested output room against the inventory as it stood, before the recipe's own inputs were gone. A recipe whose input and output share a group couldn't start: 1 iron in a one-slot group returned NO_ROOM for its gold, and a full tank refused a recipe that drains it first. check now keeps what each group's inputs claim and passes it to a new fits(list, taken) on ItemGroup and FluidGroup, which subtracts it from its copies. The claims are built the same way as in consume, so the check matches the slots consume really takes from. Nothing is extracted or rolled back, because that would run the storage's onChange on every recipe check. machineRecipeLookup expected a full tank to block a recipe that drains that tank, so it now blocks the item output instead. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018zpP6ZrFjaGe477FvWAZKo
Review notes from #83. - MachineRecipeLookup.explain returns the recipe closest to running and its MatchResult, for screens and debugging: one that can run, then NO_ROOM, then MISSING_INPUT, then a recipe the machine doesn't suit. It checks every recipe, so it's for when the answer will be shown, and doesn't add to the cost of find. - JEI: fluid inputs from a tag show source fluids, so #minecraft:water no longer cycles through flowing_water. Recipes that can never run, such as one whose input is an empty tag from an optional mod, are left out. - JEI: the energy, time and chance text all format with Locale.ROOT. - MachineRecipeBuilder.build refuses a time below 1, not just 0, instead of failing when the recipe is encoded. - MachineRecipeBuilder.outputFluid has a chance overload, like outputItem. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018zpP6ZrFjaGe477FvWAZKo
|
Checked each of these against the code. The fixes are pushed and CI is green. Output room ignoring consumed inputs: fixed in Lookup can't say why nothing ran: added in
Recipe types in Java only: agreed, deferred. Registries freeze before datapacks load, so this would take a mod-root definition file like Nits: all fixed in
Heads-up: reservations in the processorFixing the room check opens a new problem, so here's the plan before it gets built. A one-slot machine can now start iron to gold, but its slot is empty mid-cycle. A hopper can refill it, the gold then has nowhere to go, and the machine stays stuck if nothing ever empties that slot. The plan for the processor PR is that a running recipe reserves what it needs:
Three routes get past If you see a problem with any of this, I'd like to hear it before the processor gets written. |
explain reported the first recipe's missing input whatever the machine held, so an empty machine could say "missing raw aluminum". Reported on #83. A missing input now only counts when the machine holds some other item or fluid input of that recipe. Energy doesn't count, as a powered machine with nothing in it hasn't begun on any recipe. When nothing qualifies, explain is empty, so a screen can say so. A recipe with NO_GROUP or WRONG_KIND is only returned when the machine suits none of them, as a setup problem. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018zpP6ZrFjaGe477FvWAZKo
What this is
Phase 2 of the machine module, after #81 and #82. Mods can now register machine recipe types, and their recipe files load, reload and sync like any other recipe. There's still no processor, and
mmdlib:crushingis unchanged. MMDLib registers no machine recipe type of its own.Recipe types.
MachineRecipeTypes.registeradds aMachineRecipeTypethrough the mod's ownDeferredRegisters. This is the only new class that imports NeoForge.MachineRecipe,MachineIngredient,MachineProductandFluidAmountgetSTREAM_CODECs, and the type's serializer is built fromCODECandSTREAM_CODEC.MachineRecipeEntrywraps aMachineRecipeas a vanillaRecipe. It matches throughRecipeMatcher.checkand stays out of the recipe book.MachineRecipeInputexposes aMachineInventoryto vanilla. It's never empty, so fluid-only and energy-only recipes still get asked.Lookup and datagen.
MachineRecipeLookup.findfinds the runnable recipe. It tries the last recipe by ID first, so/reloadis picked up.MachineRecipeLookup.explainreports the recipe closest to running and why it can't, for screens and debugging. It's empty when the machine holds nothing any recipe uses.MachineRecipeBuilderwrites recipes from datagen.JEI. A generic
MachineRecipeCategorycovers every registered machine recipe type, sized for its largest recipe. Tags show source fluids only, and recipes that can never run are left out.Review fixes
Notes from #82 (
045844a):buildalready skipscheck; the end ofgradle/verification.gradledetaches it../gradlew build --dry-runlists onlyjar,assembleandbuildfrom the build and verification tasks, with notest,runGameTestServerorverify*. Those run on./gradlew check, which is what CI calls.data/mmdlib/structure/. It now refuses onlydata/mmdlib/structure/empty.nbt, so MMDLib can ship structures.blocksPlaceandbucketsPlaceAndRecovernow usehelper.absolutePos.MachineSmoke.checkhad the same problem, so it changed too. The old grid wouldn't fit in the 5×5×5 structure, so the first two place one block or fluid at a time on the same spot.actions/checkout@v7,actions/setup-java@v6,gradle/actions/setup-gradle@v6andactions/upload-artifact@v7all exist in those repos (gradle/actionsholdssetup-gradle), and the CI run on Test infrastructure: JUnit 5, game tests and CI #82 used them.Notes from this PR:
checknow counts what the recipe's inputs take from a group, using the same claims asconsume. It works on copies, because a rolled-back transaction would runonChangeon every check.explain: in the commit after that. See my comment below for what was deferred, and why.explainfalse positive: fixed in its own commit. An empty machine no longer reports a missing input of a recipe nobody started.Review notes
explainand the nits, then theexplainfix.junit-builder-checksstill gets its own PR after this.Testing
./gradlew checkpasses locally: 52 unit tests and all 18 game tests. Six game tests are new, covering registration, loading with a broken file skipped, lookup,explain, a network round trip, and builder output matching the file.gold fits where the iron was.🤖 Generated with Claude Code
https://claude.ai/code/session_018zpP6ZrFjaGe477FvWAZKo