diff options
Diffstat (limited to 'src/main/java/gregtech/api/recipe/FindRecipeQuery.java')
-rw-r--r-- | src/main/java/gregtech/api/recipe/FindRecipeQuery.java | 178 |
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 +} |