diff --git a/src/main/groovy-tests/recipeMapTests.groovy b/src/main/groovy-tests/recipeMapTests.groovy index b72663c6..46bf8560 100644 --- a/src/main/groovy-tests/recipeMapTests.groovy +++ b/src/main/groovy-tests/recipeMapTests.groovy @@ -3,6 +3,7 @@ import com.nomiceu.nomilabs.groovy.ChangeRecipeBuilder import gregtech.api.recipes.RecipeBuilder +import gregtech.api.recipes.RecipeMaps import gregtech.api.recipes.chance.output.impl.ChancedItemOutput import gregtech.api.recipes.ingredients.nbtmatch.NBTCondition import gregtech.api.recipes.ingredients.nbtmatch.NBTMatcher @@ -77,7 +78,25 @@ mods.gregtech.assembler.recipeBuilder() .inputNBT(ore('dyeBlue'), NBTMatcher.ANY, NBTCondition.ANY) .inputWildNBT(ore('dyeRed')) // Same as above (Except the OreDict of course) .outputs(item('minecraft:apple') * 64) - .EUt(30).duration(VA[LV]) + .EUt(VA[LV]).duration(30) + .buildAndRegister() + +// Replace Recipes +// A ReplaceByOutput on the recipe builder's recipe map, with the outputs (and other info) specified up to that point, will be conducted. +// Remember that ReplaceByOutput ignores amount! + +// Variations: `replace(RecipeMap... otherMaps), `replace(Predicate condition, RecipeMap... otherMaps)`, +// `replaceInCategory(RecipeMap... otherMaps)`, `replaceWithVoltage(RecipeMap... otherMaps)`, +// `replaceWithExactVoltage(RecipeMap... otherMaps)` + +// Other Maps also have the recipe removed from them. Useful when a recipe is auto-registered to multiple recipe maps (e.g. Chemical Reactor) +// Example: Changing the Recipe for Multi-Layer Fiber Reinforced Circuit Board (with Recycling) +mods.gregtech.chemical_reactor.recipeBuilder() + .inputs(metaitem('board.wetware') * 6, metaitem('circuit_assembler.iv') * 5) + .fluidInputs(fluid('rhodium') * 144) + .outputs(metaitem('board.multilayer.fiber_reinforced') * 12) + .EUt(VA[OpV]).duration(1_000_000) + .replace(RecipeMaps.LARGE_CHEMICAL_RECIPES) // Chem Reactor recipes are also registered to Large Chemical Reactor's Recipe Map .buildAndRegister() // Change Recipes diff --git a/src/main/java/com/nomiceu/nomilabs/mixin/gregtech/RecipeBuilderMixin.java b/src/main/java/com/nomiceu/nomilabs/mixin/gregtech/RecipeBuilderMixin.java index 3ae8dad1..1db9dc79 100644 --- a/src/main/java/com/nomiceu/nomilabs/mixin/gregtech/RecipeBuilderMixin.java +++ b/src/main/java/com/nomiceu/nomilabs/mixin/gregtech/RecipeBuilderMixin.java @@ -1,18 +1,32 @@ package com.nomiceu.nomilabs.mixin.gregtech; +import java.util.Arrays; import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Predicate; import net.minecraft.item.ItemStack; +import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; +import com.cleanroommc.groovyscript.api.GroovyLog; import com.cleanroommc.groovyscript.api.IIngredient; +import com.nomiceu.nomilabs.gregtech.mixinhelper.AccessibleRecipeMap; import com.nomiceu.nomilabs.groovy.RecyclingHelper; +import com.nomiceu.nomilabs.util.LabsGroovyHelper; +import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeBuilder; +import gregtech.api.recipes.RecipeMap; +import gregtech.api.recipes.category.GTRecipeCategory; +import gregtech.api.recipes.chance.output.impl.ChancedFluidOutput; +import gregtech.api.recipes.chance.output.impl.ChancedItemOutput; import gregtech.api.recipes.ingredients.GTRecipeInput; import gregtech.api.recipes.ingredients.nbtmatch.NBTCondition; import gregtech.api.recipes.ingredients.nbtmatch.NBTMatcher; @@ -41,6 +55,27 @@ private static GTRecipeInput ofGroovyIngredient(IIngredient ingredient) { return null; } + @Shadow + protected RecipeMap recipeMap; + + @Shadow + @Final + protected List fluidOutputs; + + @Shadow + @Final + protected List chancedOutputs; + + @Shadow + @Final + protected List chancedFluidOutputs; + + @Shadow + protected int EUt; + + @Shadow + protected GTRecipeCategory category; + @Unique @SuppressWarnings("unused") public R changeRecycling() { @@ -60,4 +95,84 @@ public R inputNBT(IIngredient ingredient, NBTMatcher matcher, NBTCondition condi public R inputWildNBT(IIngredient ingredient) { return inputNBT(ingredient, NBTMatcher.ANY, NBTCondition.ANY); } + + @Unique + @SuppressWarnings("unused") + public R replace(RecipeMap... otherMaps) { + return replaceForMaps(otherMaps, (map) -> removeOrWarn(map, + ((AccessibleRecipeMap) map).findByOutput(outputs, fluidOutputs, chancedOutputs, + chancedFluidOutputs, + (r) -> true), + String.format("items: %s, fluids: %s, chanced items: %s, chanced fluids: %s", outputs, fluidOutputs, + chancedOutputs, chancedFluidOutputs))); + } + + @Unique + @SuppressWarnings("unused") + public R replaceInCategory(RecipeMap... otherMaps) { + return replaceForMaps(otherMaps, (map) -> removeOrWarn(map, + ((AccessibleRecipeMap) map).findByOutput(outputs, fluidOutputs, chancedOutputs, + chancedFluidOutputs, + (r) -> Objects.equals(category, r.getRecipeCategory())), + String.format("category: %s, items: %s, fluids: %s, chanced items: %s, chanced fluids: %s", category, + outputs, fluidOutputs, + chancedOutputs, chancedFluidOutputs))); + } + + @Unique + @SuppressWarnings("unused") + public R replaceWithVoltage(RecipeMap... otherMaps) { + return replaceForMaps(otherMaps, (map) -> removeOrWarn(map, + ((AccessibleRecipeMap) map).findRecipeByOutput(EUt, outputs, fluidOutputs, chancedOutputs, + chancedFluidOutputs), + String.format("voltage: %s, items: %s, fluids: %s, chanced items: %s, chanced fluids: %s", EUt, outputs, + fluidOutputs, + chancedOutputs, chancedFluidOutputs))); + } + + @Unique + @SuppressWarnings("unused") + public R replaceWithExactVoltage(RecipeMap... otherMaps) { + return replaceForMaps(otherMaps, (map) -> removeOrWarn(map, + ((AccessibleRecipeMap) map).findRecipeByOutput(EUt, outputs, fluidOutputs, chancedOutputs, + chancedFluidOutputs), + String.format("exact voltage: %s, items: %s, fluids: %s, chanced items: %s, chanced fluids: %s", EUt, + outputs, fluidOutputs, + chancedOutputs, chancedFluidOutputs))); + } + + @Unique + @SuppressWarnings("unused") + public R replace(Predicate canHandle, RecipeMap... otherMaps) { + return replaceForMaps(otherMaps, (map) -> removeOrWarn(map, + ((AccessibleRecipeMap) map).findByOutput(outputs, fluidOutputs, chancedOutputs, + chancedFluidOutputs, + canHandle), + String.format("items: %s, fluids: %s, chanced items: %s, chanced fluids: %s", outputs, fluidOutputs, + chancedOutputs, chancedFluidOutputs))); + } + + @Unique + private R replaceForMaps(RecipeMap[] otherMaps, Consumer> remover) { + remover.accept(recipeMap); + Arrays.stream(otherMaps).forEach(remover); + return (R) (Object) this; + } + + @Unique + private void removeOrWarn(RecipeMap currMap, @Nullable List foundRecipes, String components) { + if (foundRecipes == null) { + if (LabsGroovyHelper.isRunningGroovyScripts()) { + GroovyLog.msg("Error removing GregTech " + currMap.unlocalizedName + " recipe") + .add("could not find recipe for: " + components) + .error() + .post(); + } + return; + } + + for (var recipe : foundRecipes) { + currMap.removeRecipe(recipe); + } + } }