Skip to content

Commit

Permalink
Merge branch 'refactor-recipe-map-backend-modification-callbacks' int…
Browse files Browse the repository at this point in the history
…o dev
  • Loading branch information
serenibyss committed Feb 15, 2025
2 parents 18dcc7a + 4160532 commit a03dd26
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 152 deletions.
27 changes: 0 additions & 27 deletions src/main/java/gregtech/api/interfaces/IRecipeMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,6 @@
*/
public interface IRecipeMap {

/**
* Add a downstream recipe map that will get to handle the original builder.
* <p>
* 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.
* <p>
* 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!!!
*/
Expand All @@ -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.
* <p>
* The returned recipe map will not have any downstreams, but can accept new downstreams.
*/
default IRecipeMap deepCopyInput() {
return newRecipeMap(b -> doAdd(b.copy()));
Expand All @@ -48,25 +33,13 @@ default IRecipeMap deepCopyInput() {
static IRecipeMap newRecipeMap(Function<? super GTRecipeBuilder, Collection<GTRecipe>> func) {
return new IRecipeMap() {

private final Collection<IRecipeMap> downstreams = new ArrayList<>();

@Override
public void addDownstream(IRecipeMap downstream) {
downstreams.add(downstream);
}

@Nonnull
@Override
public Collection<GTRecipe> doAdd(GTRecipeBuilder builder) {
List<Collection<GTRecipe>> ret = new ArrayList<>();
Collection<GTRecipe> 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);
}
};
Expand Down
18 changes: 15 additions & 3 deletions src/main/java/gregtech/api/recipe/RecipeMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<? super GTRecipeBuilder> 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<? super GTRecipe> recipeTransformer) {
backend.properties.appendRecipeTransformer(recipeTransformer);
}

// region add recipe
Expand Down
26 changes: 2 additions & 24 deletions src/main/java/gregtech/api/recipe/RecipeMapBackend.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -65,11 +63,6 @@ public class RecipeMapBackend {
*/
private final Map<RecipeCategory, Collection<GTRecipe>> recipesByCategory = new HashMap<>();

/**
* List of recipemaps that also receive recipe addition from this backend.
*/
private final List<IRecipeMap> downstreams = new ArrayList<>(0);

/**
* All the properties specific to this backend.
*/
Expand Down Expand Up @@ -171,6 +164,7 @@ protected GTRecipe addToItemMap(GTRecipe recipe) {
* Builds recipe from supplied recipe builder and adds it.
*/
protected Collection<GTRecipe> doAdd(GTRecipeBuilder builder) {
properties.transformBuilder(builder);
Iterable<? extends GTRecipe> recipes = properties.recipeEmitter.apply(builder);
Collection<GTRecipe> ret = new ArrayList<>();
for (GTRecipe recipe : recipes) {
Expand All @@ -182,13 +176,7 @@ protected Collection<GTRecipe> 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;
Expand All @@ -199,12 +187,6 @@ protected Collection<GTRecipe> doAdd(GTRecipeBuilder builder) {
}
ret.add(compileRecipe(recipe));
}
if (!ret.isEmpty()) {
builder.clearInvalid();
for (IRecipeMap downstream : downstreams) {
downstream.doAdd(builder);
}
}
return ret;
}

Expand Down Expand Up @@ -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!
*/
Expand Down
48 changes: 43 additions & 5 deletions src/main/java/gregtech/api/recipe/RecipeMapBackendProperties.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package gregtech.api.recipe;

import java.util.function.Consumer;
import java.util.function.Function;

import javax.annotation.Nullable;
Expand Down Expand Up @@ -46,16 +47,16 @@ static RecipeMapBackendPropertiesBuilder builder() {
*/
public final Function<? super GTRecipeBuilder, ? extends Iterable<? extends GTRecipe>> recipeEmitter;

/**
* Runs a custom hook on all recipes added <b>via builder</b>.
*/
@Nullable
public final Function<? super GTRecipe, ? extends GTRecipe> recipeTransformer;
private Consumer<? super GTRecipeBuilder> builderTransformer;
@Nullable
private Consumer<? super GTRecipe> recipeTransformer;

RecipeMapBackendProperties(int minItemInputs, int minFluidInputs, boolean specialSlotSensitive,
boolean disableOptimize,
Function<? super GTRecipeBuilder, ? extends Iterable<? extends GTRecipe>> recipeEmitter,
@Nullable Function<? super GTRecipe, ? extends GTRecipe> recipeTransformer) {
@Nullable Consumer<? super GTRecipeBuilder> builderTransformer,
@Nullable Consumer<? super GTRecipe> recipeTransformer) {
if (minItemInputs < 0 || minFluidInputs < 0) {
throw new IllegalArgumentException("minItemInputs and minFluidInputs cannot be negative");
}
Expand All @@ -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<? super GTRecipeBuilder> builderTransformer) {
if (this.builderTransformer == null) {
this.builderTransformer = builderTransformer;
} else {
Consumer<? super GTRecipeBuilder> t = this.builderTransformer;
this.builderTransformer = b -> {
t.accept(b);
builderTransformer.accept(b);
};
}
}

public void appendRecipeTransformer(Consumer<? super GTRecipe> recipeTransformer) {
if (this.recipeTransformer == null) {
this.recipeTransformer = recipeTransformer;
} else {
Consumer<? super GTRecipe> 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -28,10 +28,9 @@ public final class RecipeMapBackendPropertiesBuilder {

private boolean disableOptimize;

private Consumer<? super GTRecipeBuilder> builderTransformer;
private Function<? super GTRecipeBuilder, ? extends Iterable<? extends GTRecipe>> recipeEmitter = this::defaultBuildRecipe;

@Nullable
private Function<? super GTRecipe, ? extends GTRecipe> recipeTransformer;
private Consumer<? super GTRecipe> recipeTransformer;

RecipeMapBackendPropertiesBuilder() {}

Expand All @@ -42,6 +41,7 @@ RecipeMapBackendProperties build() {
specialSlotSensitive,
disableOptimize,
recipeEmitter,
builderTransformer,
recipeTransformer);
}

Expand Down Expand Up @@ -78,15 +78,16 @@ public RecipeMapBackendPropertiesBuilder combineRecipeEmitter(
return recipeEmitter(b -> Iterables.concat(cur.apply(b), func.apply(b)));
}

public RecipeMapBackendPropertiesBuilder recipeTransformer(
Function<? super GTRecipe, ? extends GTRecipe> recipeTransformer) {
this.recipeTransformer = recipeTransformer;
return this;
}

public RecipeMapBackendPropertiesBuilder chainRecipeTransformer(
Function<? super GTRecipe, ? extends GTRecipe> func) {
this.recipeTransformer = this.recipeTransformer == null ? func : this.recipeTransformer.andThen(func);
public RecipeMapBackendPropertiesBuilder builderTransformer(Consumer<? super GTRecipeBuilder> builderTransformer) {
if (this.builderTransformer == null) {
this.builderTransformer = builderTransformer;
} else {
Consumer<? super GTRecipeBuilder> t = this.builderTransformer;
this.builderTransformer = b -> {
t.accept(b);
builderTransformer.accept(b);
};
}
return this;
}

Expand All @@ -102,4 +103,17 @@ private Iterable<? extends GTRecipe> defaultBuildRecipe(GTRecipeBuilder builder)
private static GTRecipeBuilder copy(GTRecipeBuilder original, GTRecipeBuilder b) {
return b == original ? b.copy() : b;
}

public RecipeMapBackendPropertiesBuilder recipeTransformer(Consumer<? super GTRecipe> recipeTransformer) {
if (this.recipeTransformer == null) {
this.recipeTransformer = recipeTransformer;
} else {
Consumer<? super GTRecipe> t = this.recipeTransformer;
this.recipeTransformer = r -> {
t.accept(r);
recipeTransformer.accept(r);
};
}
return this;
}
}
57 changes: 14 additions & 43 deletions src/main/java/gregtech/api/recipe/RecipeMapBuilder.java
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,16 @@ public RecipeMapBuilder<B> disableOptimize() {
return this;
}

/**
* Transformer which allows you to modify the recipe builder before it emits recipes.
* <br>
* Allows modification of the builder to modify this recipe, or adding recipes to other places based on the builder.
*/
public RecipeMapBuilder<B> builderTransformer(Consumer<? super GTRecipeBuilder> builderTransformer) {
backendPropertiesBuilder.builderTransformer(builderTransformer);
return this;
}

/**
* Changes how recipes are emitted by a particular recipe builder. Can emit multiple recipe per builder.
*/
Expand Down Expand Up @@ -164,54 +174,15 @@ public RecipeMapBuilder<B> combineRecipeEmitterSingle(
}

/**
* Runs a custom hook on all recipes added <b>via builder</b>. For more complicated behavior,
* use {@link #recipeEmitter}.
* <p>
* 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.
* <br>
* Allows modification of the recipe to change this map's recipe, or add this recipe copied and/or edited elsewhere.
*/
public RecipeMapBuilder<B> recipeTransformer(Function<? super GTRecipe, ? extends GTRecipe> recipeTransformer) {
public RecipeMapBuilder<B> recipeTransformer(Consumer<? super GTRecipe> recipeTransformer) {
backendPropertiesBuilder.recipeTransformer(recipeTransformer);
return this;
}

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

/**
* Runs a custom hook on all recipes added <b>via builder</b>. For more complicated behavior,
* use {@link #recipeEmitter}.
* <p>
* Recipes added via one of the overloads of addRecipe will NOT be affected by this function.
* <p>
* 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<B> chainRecipeTransformer(
Function<? super GTRecipe, ? extends GTRecipe> recipeTransformer) {
backendPropertiesBuilder.chainRecipeTransformer(recipeTransformer);
return this;
}

/**
* Runs a custom hook on all recipes added <b>via builder</b>. For more complicated behavior,
* use {@link #recipeEmitter}.
* <p>
* Recipes added via one of the overloads of addRecipe will NOT be affected by this function.
* <p>
* 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<B> chainRecipeTransformer(Consumer<GTRecipe> recipeTransformer) {
return chainRecipeTransformer(withIdentityReturn(recipeTransformer));
}

// endregion

// region frontend UI properties
Expand Down
Loading

0 comments on commit a03dd26

Please sign in to comment.