diff --git a/src/main/java/gregtech/api/interfaces/IRecipeMap.java b/src/main/java/gregtech/api/interfaces/IRecipeMap.java index c6184bee342..412778d2ccc 100644 --- a/src/main/java/gregtech/api/interfaces/IRecipeMap.java +++ b/src/main/java/gregtech/api/interfaces/IRecipeMap.java @@ -16,19 +16,6 @@ */ public interface IRecipeMap { - /** - * Add a downstream recipe map that will get to handle the original builder. - *

- * Downstream recipe maps got passed the recipe builder after parent recipe map is done with its business. Notice - * at this time the original recipe builder might be modified by the parent recipe map in some form, but it will - * remain as valid. - *

- * A downstream will only be invoked if parent recipe map added something. - * - * @param downstream the downstream recipe map to add - */ - void addDownstream(IRecipeMap downstream); - /** * Actually add the recipe represented by the builder. CAN modify the builder's internal states!!! */ @@ -38,8 +25,6 @@ public interface IRecipeMap { /** * Return a variant of this recipe map that will perform a deep copy on input recipe builder before doing anything * to it. - *

- * The returned recipe map will not have any downstreams, but can accept new downstreams. */ default IRecipeMap deepCopyInput() { return newRecipeMap(b -> doAdd(b.copy())); @@ -48,13 +33,6 @@ default IRecipeMap deepCopyInput() { static IRecipeMap newRecipeMap(Function> func) { return new IRecipeMap() { - private final Collection downstreams = new ArrayList<>(); - - @Override - public void addDownstream(IRecipeMap downstream) { - downstreams.add(downstream); - } - @Nonnull @Override public Collection doAdd(GTRecipeBuilder builder) { @@ -62,11 +40,6 @@ public Collection doAdd(GTRecipeBuilder builder) { Collection out = func.apply(builder); ret.add(out); builder.clearInvalid(); - if (!out.isEmpty()) { - for (IRecipeMap downstream : downstreams) { - ret.add(downstream.doAdd(builder)); - } - } return GTUtility.concat(ret); } }; diff --git a/src/main/java/gregtech/api/recipe/RecipeMap.java b/src/main/java/gregtech/api/recipe/RecipeMap.java index 9fb504c0a47..2cb839bf739 100644 --- a/src/main/java/gregtech/api/recipe/RecipeMap.java +++ b/src/main/java/gregtech/api/recipe/RecipeMap.java @@ -6,6 +6,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.function.Consumer; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -107,9 +108,20 @@ public int getAmperage() { return frontend.getUIProperties().amperage; } - @Override - public void addDownstream(IRecipeMap downstream) { - backend.addDownstream(downstream); + /** + * Callback called before the recipe builder emits recipes. Can edit this builder to change this recipe, or + * use this information to add recipes elsewhere. + */ + public void appendBuilderTransformer(Consumer builderTransformer) { + backend.properties.appendBuilderTransformer(builderTransformer); + } + + /** + * Callback called after the recipe builder emits recipes, but before it is added to the map. Can edit this recipe + * for this map, or use this information to add recipes elsewhere. + */ + public void appendRecipeTransformer(Consumer recipeTransformer) { + backend.properties.appendRecipeTransformer(recipeTransformer); } // region add recipe diff --git a/src/main/java/gregtech/api/recipe/RecipeMapBackend.java b/src/main/java/gregtech/api/recipe/RecipeMapBackend.java index 8c23e2bfb9a..70d36b933e6 100644 --- a/src/main/java/gregtech/api/recipe/RecipeMapBackend.java +++ b/src/main/java/gregtech/api/recipe/RecipeMapBackend.java @@ -11,7 +11,6 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Objects; import java.util.function.Function; @@ -31,7 +30,6 @@ import com.google.common.collect.SetMultimap; import gregtech.api.GregTechAPI; -import gregtech.api.interfaces.IRecipeMap; import gregtech.api.objects.GTItemStack; import gregtech.api.util.GTOreDictUnificator; import gregtech.api.util.GTRecipe; @@ -65,11 +63,6 @@ public class RecipeMapBackend { */ private final Map> recipesByCategory = new HashMap<>(); - /** - * List of recipemaps that also receive recipe addition from this backend. - */ - private final List downstreams = new ArrayList<>(0); - /** * All the properties specific to this backend. */ @@ -171,6 +164,7 @@ protected GTRecipe addToItemMap(GTRecipe recipe) { * Builds recipe from supplied recipe builder and adds it. */ protected Collection doAdd(GTRecipeBuilder builder) { + properties.transformBuilder(builder); Iterable recipes = properties.recipeEmitter.apply(builder); Collection ret = new ArrayList<>(); for (GTRecipe recipe : recipes) { @@ -182,13 +176,7 @@ protected Collection doAdd(GTRecipeBuilder builder) { handleInvalidRecipeLowFluids(); return Collections.emptyList(); } - if (properties.recipeTransformer != null) { - recipe = properties.recipeTransformer.apply(recipe); - } - if (recipe == null) { - handleInvalidRecipe(); - continue; - } + properties.transformRecipe(recipe); if (builder.isCheckForCollision() && ENABLE_COLLISION_CHECK && checkCollision(recipe)) { handleCollision(recipe); continue; @@ -199,12 +187,6 @@ protected Collection doAdd(GTRecipeBuilder builder) { } ret.add(compileRecipe(recipe)); } - if (!ret.isEmpty()) { - builder.clearInvalid(); - for (IRecipeMap downstream : downstreams) { - downstream.doAdd(builder); - } - } return ret; } @@ -243,10 +225,6 @@ private void handleCollision(GTRecipe recipe) { handleRecipeCollision(errorInfo.toString()); } - void addDownstream(IRecipeMap downstream) { - downstreams.add(downstream); - } - /** * Removes supplied recipes from recipe list. Do not use unless absolute necessity! */ diff --git a/src/main/java/gregtech/api/recipe/RecipeMapBackendProperties.java b/src/main/java/gregtech/api/recipe/RecipeMapBackendProperties.java index 47c400a3dd6..2333db2ae60 100644 --- a/src/main/java/gregtech/api/recipe/RecipeMapBackendProperties.java +++ b/src/main/java/gregtech/api/recipe/RecipeMapBackendProperties.java @@ -1,5 +1,6 @@ package gregtech.api.recipe; +import java.util.function.Consumer; import java.util.function.Function; import javax.annotation.Nullable; @@ -46,16 +47,16 @@ static RecipeMapBackendPropertiesBuilder builder() { */ public final Function> recipeEmitter; - /** - * Runs a custom hook on all recipes added via builder. - */ @Nullable - public final Function recipeTransformer; + private Consumer builderTransformer; + @Nullable + private Consumer recipeTransformer; RecipeMapBackendProperties(int minItemInputs, int minFluidInputs, boolean specialSlotSensitive, boolean disableOptimize, Function> recipeEmitter, - @Nullable Function recipeTransformer) { + @Nullable Consumer builderTransformer, + @Nullable Consumer recipeTransformer) { if (minItemInputs < 0 || minFluidInputs < 0) { throw new IllegalArgumentException("minItemInputs and minFluidInputs cannot be negative"); } @@ -64,6 +65,43 @@ static RecipeMapBackendPropertiesBuilder builder() { this.specialSlotSensitive = specialSlotSensitive; this.disableOptimize = disableOptimize; this.recipeEmitter = recipeEmitter; + this.builderTransformer = builderTransformer; this.recipeTransformer = recipeTransformer; } + + public void appendBuilderTransformer(Consumer builderTransformer) { + if (this.builderTransformer == null) { + this.builderTransformer = builderTransformer; + } else { + Consumer t = this.builderTransformer; + this.builderTransformer = b -> { + t.accept(b); + builderTransformer.accept(b); + }; + } + } + + public void appendRecipeTransformer(Consumer recipeTransformer) { + if (this.recipeTransformer == null) { + this.recipeTransformer = recipeTransformer; + } else { + Consumer t = this.recipeTransformer; + this.recipeTransformer = r -> { + t.accept(r); + recipeTransformer.accept(r); + }; + } + } + + public void transformBuilder(GTRecipeBuilder builder) { + if (builderTransformer != null) { + builderTransformer.accept(builder); + } + } + + public void transformRecipe(GTRecipe recipe) { + if (recipeTransformer != null) { + recipeTransformer.accept(recipe); + } + } } diff --git a/src/main/java/gregtech/api/recipe/RecipeMapBackendPropertiesBuilder.java b/src/main/java/gregtech/api/recipe/RecipeMapBackendPropertiesBuilder.java index aad0748fa91..d77396a09e6 100644 --- a/src/main/java/gregtech/api/recipe/RecipeMapBackendPropertiesBuilder.java +++ b/src/main/java/gregtech/api/recipe/RecipeMapBackendPropertiesBuilder.java @@ -2,9 +2,9 @@ import static gregtech.api.util.GTRecipeMapUtil.buildOrEmpty; +import java.util.function.Consumer; import java.util.function.Function; -import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; import com.google.common.collect.Iterables; @@ -28,10 +28,9 @@ public final class RecipeMapBackendPropertiesBuilder { private boolean disableOptimize; + private Consumer builderTransformer; private Function> recipeEmitter = this::defaultBuildRecipe; - - @Nullable - private Function recipeTransformer; + private Consumer recipeTransformer; RecipeMapBackendPropertiesBuilder() {} @@ -42,6 +41,7 @@ RecipeMapBackendProperties build() { specialSlotSensitive, disableOptimize, recipeEmitter, + builderTransformer, recipeTransformer); } @@ -78,15 +78,16 @@ public RecipeMapBackendPropertiesBuilder combineRecipeEmitter( return recipeEmitter(b -> Iterables.concat(cur.apply(b), func.apply(b))); } - public RecipeMapBackendPropertiesBuilder recipeTransformer( - Function recipeTransformer) { - this.recipeTransformer = recipeTransformer; - return this; - } - - public RecipeMapBackendPropertiesBuilder chainRecipeTransformer( - Function func) { - this.recipeTransformer = this.recipeTransformer == null ? func : this.recipeTransformer.andThen(func); + public RecipeMapBackendPropertiesBuilder builderTransformer(Consumer builderTransformer) { + if (this.builderTransformer == null) { + this.builderTransformer = builderTransformer; + } else { + Consumer t = this.builderTransformer; + this.builderTransformer = b -> { + t.accept(b); + builderTransformer.accept(b); + }; + } return this; } @@ -102,4 +103,17 @@ private Iterable defaultBuildRecipe(GTRecipeBuilder builder) private static GTRecipeBuilder copy(GTRecipeBuilder original, GTRecipeBuilder b) { return b == original ? b.copy() : b; } + + public RecipeMapBackendPropertiesBuilder recipeTransformer(Consumer recipeTransformer) { + if (this.recipeTransformer == null) { + this.recipeTransformer = recipeTransformer; + } else { + Consumer t = this.recipeTransformer; + this.recipeTransformer = r -> { + t.accept(r); + recipeTransformer.accept(r); + }; + } + return this; + } } diff --git a/src/main/java/gregtech/api/recipe/RecipeMapBuilder.java b/src/main/java/gregtech/api/recipe/RecipeMapBuilder.java index ee8953570a8..1c6b49164bd 100644 --- a/src/main/java/gregtech/api/recipe/RecipeMapBuilder.java +++ b/src/main/java/gregtech/api/recipe/RecipeMapBuilder.java @@ -118,6 +118,16 @@ public RecipeMapBuilder disableOptimize() { return this; } + /** + * Transformer which allows you to modify the recipe builder before it emits recipes. + *
+ * Allows modification of the builder to modify this recipe, or adding recipes to other places based on the builder. + */ + public RecipeMapBuilder builderTransformer(Consumer builderTransformer) { + backendPropertiesBuilder.builderTransformer(builderTransformer); + return this; + } + /** * Changes how recipes are emitted by a particular recipe builder. Can emit multiple recipe per builder. */ @@ -164,54 +174,15 @@ public RecipeMapBuilder combineRecipeEmitterSingle( } /** - * Runs a custom hook on all recipes added via builder. For more complicated behavior, - * use {@link #recipeEmitter}. - *

- * Recipes added via one of the overloads of addRecipe will NOT be affected by this function. + * Transformer which allows for modification of a recipe after it is "finalized" but before it is added to the map. + *
+ * Allows modification of the recipe to change this map's recipe, or add this recipe copied and/or edited elsewhere. */ - public RecipeMapBuilder recipeTransformer(Function recipeTransformer) { + public RecipeMapBuilder recipeTransformer(Consumer recipeTransformer) { backendPropertiesBuilder.recipeTransformer(recipeTransformer); return this; } - /** - * Runs a custom hook on all recipes added via builder. For more complicated behavior, - * use {@link #recipeEmitter}. - *

- * Recipes added via one of the overloads of addRecipe will NOT be affected by this function. - */ - public RecipeMapBuilder recipeTransformer(Consumer recipeTransformer) { - return recipeTransformer(withIdentityReturn(recipeTransformer)); - } - - /** - * Runs a custom hook on all recipes added via builder. For more complicated behavior, - * use {@link #recipeEmitter}. - *

- * Recipes added via one of the overloads of addRecipe will NOT be affected by this function. - *

- * Unlike {@link #recipeTransformer(Function)}, this one will not replace the existing special handler. - * The supplied function will be given the output of existing handler when a recipe is added. - */ - public RecipeMapBuilder chainRecipeTransformer( - Function recipeTransformer) { - backendPropertiesBuilder.chainRecipeTransformer(recipeTransformer); - return this; - } - - /** - * Runs a custom hook on all recipes added via builder. For more complicated behavior, - * use {@link #recipeEmitter}. - *

- * Recipes added via one of the overloads of addRecipe will NOT be affected by this function. - *

- * Unlike {@link #recipeTransformer(Function)}, this one will not replace the existing special handler. - * The supplied function will be given the output of existing handler when a recipe is added. - */ - public RecipeMapBuilder chainRecipeTransformer(Consumer recipeTransformer) { - return chainRecipeTransformer(withIdentityReturn(recipeTransformer)); - } - // endregion // region frontend UI properties diff --git a/src/main/java/gregtech/api/recipe/RecipeMaps.java b/src/main/java/gregtech/api/recipe/RecipeMaps.java index d6cbe5bdcf1..125f1c45bb0 100644 --- a/src/main/java/gregtech/api/recipe/RecipeMaps.java +++ b/src/main/java/gregtech/api/recipe/RecipeMaps.java @@ -44,7 +44,6 @@ import gregtech.api.enums.OrePrefixes; import gregtech.api.enums.TierEU; import gregtech.api.gui.modularui.GTUITextures; -import gregtech.api.interfaces.IRecipeMap; import gregtech.api.objects.ItemData; import gregtech.api.recipe.maps.AssemblerBackend; import gregtech.api.recipe.maps.AssemblyLineFrontend; @@ -478,6 +477,12 @@ public final class RecipeMaps { .maxIO(0, 0, 1, 1) .minInputs(0, 1) .progressBar(GTUITextures.PROGRESSBAR_ARROW_MULTIPLE) + .builderTransformer( + b -> b.copy() + .special(BioItemList.getPetriDish(BioCultureLoader.generalPurposeFermentingBacteria)) + .metadata(GLASS, 3) + .eut(b.getEUt()) + .addTo(BartWorksRecipeMaps.bacterialVatRecipes)) .build(); public static final RecipeMap fluidSolidifierRecipes = RecipeMapBuilder .of("gt.recipe.fluidsolidifier") @@ -745,6 +750,11 @@ public final class RecipeMaps { .setInputs(input, GTModHandler.getIC2Item("industrialTnt", tITNT, null)); return coll.getAll(); }) + .builderTransformer( + b -> b.copy() + .duration(1 * TICK) + .eut(TierEU.RECIPE_UEV) + .addTo(BartWorksRecipeMaps.electricImplosionCompressorRecipes)) .build(); public static final RecipeMap vacuumFreezerRecipes = RecipeMapBuilder .of("gt.recipe.vacuumfreezer") @@ -1033,6 +1043,17 @@ && isArrayEmptyOrNull(b.getFluidOutputs()) public static final RecipeMap dieselFuels = RecipeMapBuilder .of("gt.recipe.dieselgeneratorfuel", FuelBackend::new) .maxIO(1, 1, 0, 0) + .builderTransformer(b -> { + b.copy() + .build() + .ifPresent( + r -> RecipeMaps.largeBoilerFakeFuels.getBackend() + .addDieselRecipe(r)); + if (b.getMetadataOrDefault(FUEL_VALUE, 0) >= 1500) { + b.copy() + .addTo(RecipeMaps.extremeDieselFuels); + } + }) .neiSpecialInfoFormatter(FuelSpecialValueFormatter.INSTANCE) .build(); public static final RecipeMap extremeDieselFuels = RecipeMapBuilder @@ -1053,6 +1074,12 @@ && isArrayEmptyOrNull(b.getFluidOutputs()) public static final RecipeMap denseLiquidFuels = RecipeMapBuilder .of("gt.recipe.semifluidboilerfuels", FuelBackend::new) .maxIO(1, 1, 0, 0) + .builderTransformer( + b -> b.copy() + .build() + .ifPresent( + r -> RecipeMaps.largeBoilerFakeFuels.getBackend() + .addDenseLiquidRecipe(r))) .disableRegisterNEI() .build(); public static final RecipeMap plasmaFuels = RecipeMapBuilder @@ -1216,40 +1243,4 @@ && isArrayEmptyOrNull(b.getFluidOutputs()) .neiRecipeBackgroundSize(170, 60) .neiHandlerInfo(builder -> builder.setDisplayStack(GTModHandler.getIC2Item("nuclearReactor", 1, null))) .build(); - - static { - RecipeMaps.dieselFuels.addDownstream( - IRecipeMap.newRecipeMap( - b -> b.build() - .map( - r -> RecipeMaps.largeBoilerFakeFuels.getBackend() - .addDieselRecipe(r)) - .map(Collections::singletonList) - .orElse(Collections.emptyList()))); - RecipeMaps.dieselFuels.addDownstream(IRecipeMap.newRecipeMap(b -> { - if (b.getMetadataOrDefault(FUEL_VALUE, 0) < 1500) return Collections.emptyList(); - return b.addTo(RecipeMaps.extremeDieselFuels); - })); - RecipeMaps.denseLiquidFuels.addDownstream( - IRecipeMap.newRecipeMap( - b -> b.build() - .map( - r -> RecipeMaps.largeBoilerFakeFuels.getBackend() - .addDenseLiquidRecipe(r)) - .map(Collections::singletonList) - .orElse(Collections.emptyList()))); - RecipeMaps.fermentingRecipes.addDownstream( - IRecipeMap.newRecipeMap( - b -> BartWorksRecipeMaps.bacterialVatRecipes.doAdd( - b.copy() - .special(BioItemList.getPetriDish(BioCultureLoader.generalPurposeFermentingBacteria)) - .metadata(GLASS, 3) - .eut(b.getEUt())))); - RecipeMaps.implosionRecipes.addDownstream( - IRecipeMap.newRecipeMap( - b -> BartWorksRecipeMaps.electricImplosionCompressorRecipes.doAdd( - b.copy() - .duration(1 * TICK) - .eut(TierEU.RECIPE_UEV)))); - } }