aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/recipe/FindRecipeQuery.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/api/recipe/FindRecipeQuery.java')
-rw-r--r--src/main/java/gregtech/api/recipe/FindRecipeQuery.java178
1 files changed, 178 insertions, 0 deletions
diff --git a/src/main/java/gregtech/api/recipe/FindRecipeQuery.java b/src/main/java/gregtech/api/recipe/FindRecipeQuery.java
new file mode 100644
index 0000000000..77c0648688
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/FindRecipeQuery.java
@@ -0,0 +1,178 @@
+package gregtech.api.recipe;
+
+import java.util.function.Predicate;
+import java.util.stream.Stream;
+
+import javax.annotation.Nullable;
+import javax.annotation.ParametersAreNonnullByDefault;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.MethodsReturnNonnullByDefault;
+
+// spotless:off spotless likes formatting @code to @code
+/**
+ * Helper class for searching recipe. Retrieve instance with {@link RecipeMap#findRecipeQuery}.
+ * <p>
+ * It features fluent API, so you can find recipes like this:
+ *
+ * <pre>
+ * {@code
+ * GT_Recipe recipe = recipeMap.findRecipeQuery()
+ * .items(inputItems)
+ * .fluids(inputFluids)
+ * .find();
+ * }
+ * </pre>
+ */
+// spotless:on
+@SuppressWarnings("unused")
+@ParametersAreNonnullByDefault
+@MethodsReturnNonnullByDefault
+public final class FindRecipeQuery {
+
+ private static final Predicate<GT_Recipe> ALWAYS = r -> true;
+
+ private final RecipeMap<?> recipeMap;
+
+ @Nullable
+ private ItemStack[] items;
+ @Nullable
+ private FluidStack[] fluids;
+ @Nullable
+ private ItemStack specialSlot;
+ private Predicate<GT_Recipe> filter = ALWAYS;
+ private long voltage = Integer.MAX_VALUE;
+ @Nullable
+ private GT_Recipe cachedRecipe;
+ private boolean notUnificated;
+ private boolean dontCheckStackSizes;
+ private boolean forCollisionCheck;
+
+ FindRecipeQuery(RecipeMap<?> recipeMap) {
+ this.recipeMap = recipeMap;
+ }
+
+ // region executors
+
+ /**
+ * @return The first matched recipe, or null if not found.
+ */
+ @Nullable
+ public GT_Recipe find() {
+ return findAll().findFirst()
+ .orElse(null);
+ }
+
+ /**
+ * @return All the matched recipes in the form of Stream.
+ */
+ public Stream<GT_Recipe> findAll() {
+ if (items == null) {
+ items = new ItemStack[0];
+ }
+ if (fluids == null) {
+ fluids = new FluidStack[0];
+ }
+
+ return recipeMap.getBackend()
+ .matchRecipeStream(
+ items,
+ fluids,
+ specialSlot,
+ cachedRecipe,
+ notUnificated,
+ dontCheckStackSizes,
+ forCollisionCheck)
+ .filter(recipe -> voltage * recipeMap.getAmperage() >= recipe.mEUt && filter.test(recipe));
+ }
+
+ /**
+ * Checks if given inputs conflict with already registered recipes.
+ *
+ * @return True if collision is found.
+ */
+ public boolean checkCollision() {
+ dontCheckStackSizes = true;
+ forCollisionCheck = true;
+ return findAll().findAny()
+ .isPresent();
+ }
+
+ // endregion
+
+ // region setters
+
+ /**
+ * @param items Item inputs.
+ */
+ public FindRecipeQuery items(@Nullable ItemStack... items) {
+ this.items = items;
+ return this;
+ }
+
+ /**
+ * @param fluids Fluid inputs.
+ */
+ public FindRecipeQuery fluids(@Nullable FluidStack... fluids) {
+ this.fluids = fluids;
+ return this;
+ }
+
+ /**
+ * @param specialSlot Content of the special slot. Normal recipemaps don't need this, but some do.
+ * Set {@link RecipeMapBuilder#specialSlotSensitive} to make it actually functional.
+ * Alternatively overriding {@link RecipeMapBackend#filterFindRecipe} will also work.
+ */
+ public FindRecipeQuery specialSlot(@Nullable ItemStack specialSlot) {
+ this.specialSlot = specialSlot;
+ return this;
+ }
+
+ /**
+ * @param filter Matched recipe will be tested by this function. If it returns false, the query will attempt to
+ * find next recipe.
+ */
+ public FindRecipeQuery filter(Predicate<GT_Recipe> filter) {
+ this.filter = filter;
+ return this;
+ }
+
+ /**
+ * @param voltage Recipes that exceed this voltage won't match. It will be automatically multiplied by amperage
+ * of the recipemap.
+ */
+ public FindRecipeQuery voltage(long voltage) {
+ this.voltage = voltage;
+ return this;
+ }
+
+ /**
+ * @param cachedRecipe If this is not null, the query tests it before all other recipes.
+ */
+ public FindRecipeQuery cachedRecipe(@Nullable GT_Recipe cachedRecipe) {
+ this.cachedRecipe = cachedRecipe;
+ return this;
+ }
+
+ /**
+ * @param notUnificated If this is set to true, item inputs will be unificated.
+ */
+ public FindRecipeQuery notUnificated(boolean notUnificated) {
+ this.notUnificated = notUnificated;
+ return this;
+ }
+
+ /**
+ * @param dontCheckStackSizes If this is set to true, the query won't check item count and fluid amount
+ * for the matched recipe.
+ */
+ public FindRecipeQuery dontCheckStackSizes(boolean dontCheckStackSizes) {
+ this.dontCheckStackSizes = dontCheckStackSizes;
+ return this;
+ }
+
+ // endregion
+}