Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import static gregtech.api.GTValues.ULV;
Expand Down Expand Up @@ -261,7 +262,7 @@ public Recipe getPreviousRecipe() {
* @return true if recipes should be searched for
*/
protected boolean shouldSearchForRecipes() {
return canWorkWithInputs() && canFitNewOutputs();
return canWorkWithInputs() || canFitNewOutputs();
}

/**
Expand Down Expand Up @@ -398,27 +399,56 @@ public void forceRecipeRecheck() {
*/
protected void trySearchNewRecipe() {
long maxVoltage = getMaxVoltage();
Recipe currentRecipe;
Recipe currentRecipe = null;
Iterator<Recipe> recipeIterator;
IItemHandlerModifiable importInventory = getInputInventory();
IMultipleTankHandler importFluids = getInputTank();

// see if the last recipe we used still works
if (checkPreviousRecipe()) {
currentRecipe = this.previousRecipe;
// If there is no active recipe, then we need to find one.
} else {
currentRecipe = findRecipe(maxVoltage, importInventory, importFluids);
}
// If a recipe was found, then inputs were valid. Cache found recipe.
if (currentRecipe != null) {

// proceed if previous recipe still works.
if (currentRecipe != null && checkRecipe(currentRecipe) && prepareRecipe(currentRecipe)) {
this.previousRecipe = currentRecipe;
return;
}
this.invalidInputsForRecipes = (currentRecipe == null);

// proceed if we have a usable recipe.
if (currentRecipe != null && checkRecipe(currentRecipe)) {
prepareRecipe(currentRecipe);
recipeIterator = getRecipeIterator(maxVoltage, importInventory, importFluids);

boolean invalidOutputs = false;
boolean invalidInputs = false;

// not any recipe was found
if (recipeIterator == null || !recipeIterator.hasNext()) {
this.invalidInputsForRecipes = true;
return;
}

// Search for a new recipe if the previous one is no longer valid
while (recipeIterator.hasNext()) {
Recipe next = recipeIterator.next();
if (next == null) continue;

if (checkRecipe(next) && prepareRecipe(next)) {
// If a new recipe was found, cache found recipe.
this.previousRecipe = next;
break;
} else {
// store if recipe has bad IO, then reset for next recipe checks
invalidOutputs = this.isOutputsFull;
invalidInputs = this.invalidInputsForRecipes;
this.isOutputsFull = false;
this.invalidInputsForRecipes = false;
}
}

// if no valid recipes are found mark the inputs and outputs as invalid so any changes
// will re-trigger a recipe search
this.isOutputsFull = invalidOutputs;
this.invalidInputsForRecipes = invalidInputs;
}

/**
Expand Down Expand Up @@ -650,6 +680,25 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul
return map.findRecipe(maxVoltage, inputs, fluidInputs);
}

/**
* Creates a Recipe Iterator using inputs
*
* @param maxVoltage the maximum voltage the recipe can have
* @param inputs the item inputs used to search for the recipe
* @param fluidInputs the fluid inputs used to search for the recipe
* @return the recipe iterator if this.recipeMap is valid, otherwise null
*/
@Nullable
protected Iterator<Recipe> getRecipeIterator(long maxVoltage, IItemHandlerModifiable inputs,
IMultipleTankHandler fluidInputs) {
RecipeMap<?> map = getRecipeMap();
if (map == null || !isRecipeMapValid(map)) {
return null;
}

return map.getRecipeIterator(maxVoltage, inputs, fluidInputs);
}

/**
* @param recipeMap the recipemap to check
* @return true if the recipemap is valid for recipe search
Expand Down
65 changes: 65 additions & 0 deletions src/main/java/gregtech/api/recipes/RecipeIterator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package gregtech.api.recipes;

import gregtech.api.recipes.map.AbstractMapIngredient;

import org.jetbrains.annotations.NotNull;

import java.util.Iterator;
import java.util.List;
import java.util.function.Predicate;

public class RecipeIterator implements Iterator<Recipe> {

int index;
List<List<AbstractMapIngredient>> ingredients;
@NotNull
RecipeMap<?> recipeMap;
@NotNull
Predicate<Recipe> canHandle;
Recipe cachedNext;

RecipeIterator(@NotNull RecipeMap<?> recipeMap, List<List<AbstractMapIngredient>> ingredients,
@NotNull Predicate<Recipe> canHandle) {
this.ingredients = ingredients;
this.recipeMap = recipeMap;
this.canHandle = canHandle;
}

@Override
public boolean hasNext() {
if (cachedNext != null) return true;
if (ingredients == null || this.index > this.ingredients.size()) return false;

while (index < ingredients.size()) {
Recipe r = recipeMap.recurseIngredientTreeFindRecipe(ingredients, recipeMap.getLookup(), canHandle, index,
0,
(1L << index));
++index;
if (r != null) {
cachedNext = r;
return true;
}
}
return false;
}

@Override
public Recipe next() {
if (cachedNext != null) {
Recipe r = cachedNext.copy();
cachedNext = null;
return r;
}
// couldn't build any inputs to use for search, so no recipe could be found
if (ingredients == null) return null;
// Try each ingredient as a starting point, save current index
Recipe r = null;
while (index < ingredients.size()) {
r = recipeMap.recurseIngredientTreeFindRecipe(ingredients, recipeMap.getLookup(), canHandle, index, 0,
(1L << index));
++index;
if (r != null) break;
}
return r;
}
}
77 changes: 74 additions & 3 deletions src/main/java/gregtech/api/recipes/RecipeMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -365,6 +366,10 @@ public RecipeMap<? extends RecipeBuilder<?>> getSmallRecipeMap() {
return smallRecipeMap;
}

public Branch getLookup() {
return lookup;
}

/**
* Internal usage <strong>only</strong>, use {@link RecipeBuilder#buildAndRegister()}
*
Expand Down Expand Up @@ -624,6 +629,72 @@ public Recipe find(@NotNull Collection<ItemStack> items, @NotNull Collection<Flu
return recurseIngredientTreeFindRecipe(list, lookup, canHandle);
}

@NotNull
public Iterator<Recipe> getRecipeIterator(long voltage, IItemHandlerModifiable inputs,
IMultipleTankHandler fluidInputs) {
return this.getRecipeIterator(voltage, GTUtility.itemHandlerToList(inputs),
GTUtility.fluidHandlerToList(fluidInputs));
}

/**
* Creates an Iterator of Recipes matching the Fluid and/or ItemStack Inputs.
*
* @param voltage Voltage of the Machine or Long.MAX_VALUE if it has no Voltage
* @param inputs the Item Inputs
* @param fluidInputs the Fluid Inputs
* @return the Recipe Iterator
*/
@NotNull
public Iterator<Recipe> getRecipeIterator(long voltage, List<ItemStack> inputs, List<FluidStack> fluidInputs) {
return getRecipeIterator(voltage, inputs, fluidInputs, false);
}

/**
* Creates an Iterator of Recipes matching the Fluid and/or ItemStack Inputs.
*
* @param voltage Voltage of the Machine or Long.MAX_VALUE if it has no Voltage
* @param inputs the Item Inputs
* @param fluidInputs the Fluid Inputs
* @param exactVoltage should require exact voltage matching on recipe. used by craftweaker
* @return the Recipe Iterator
*/
@NotNull
public Iterator<Recipe> getRecipeIterator(long voltage, final List<ItemStack> inputs,
final List<FluidStack> fluidInputs,
boolean exactVoltage) {
final List<ItemStack> items = inputs.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList());
final List<FluidStack> fluids = fluidInputs.stream().filter(f -> f != null && f.amount != 0)
.collect(Collectors.toList());

return getRecipeIterator(items, fluids, recipe -> {
if (exactVoltage && recipe.getEUt() != voltage) {
// if exact voltage is required, the recipe is not considered valid
return false;
}
if (recipe.getEUt() > voltage) {
// there is not enough voltage to consider the recipe valid
return false;
}
return recipe.matches(false, inputs, fluidInputs);
});
}

/**
* Creates an Iterator of Recipes using Items and Fluids.
*
* @param items a collection of items
* @param fluids a collection of fluids
* @param canHandle a predicate for determining if a recipe is valid
* @return the Recipe Iterator
*/
@NotNull
public Iterator<Recipe> getRecipeIterator(@NotNull Collection<ItemStack> items,
@NotNull Collection<FluidStack> fluids,
@NotNull Predicate<Recipe> canHandle) {
List<List<AbstractMapIngredient>> list = prepareRecipeFind(items, fluids);
return new RecipeIterator(this, list, canHandle);
}

/**
* Builds a list of unique ItemStacks from the given Collection of ItemStacks.
* Used to reduce the number inputs, if for example there is more than one of the same input,
Expand Down Expand Up @@ -723,9 +794,9 @@ private Recipe recurseIngredientTreeFindRecipe(@NotNull List<List<AbstractMapIng
* @return a recipe
*/
@Nullable
private Recipe recurseIngredientTreeFindRecipe(@NotNull List<List<AbstractMapIngredient>> ingredients,
@NotNull Branch branchMap, @NotNull Predicate<Recipe> canHandle,
int index, int count, long skip) {
protected Recipe recurseIngredientTreeFindRecipe(@NotNull List<List<AbstractMapIngredient>> ingredients,
@NotNull Branch branchMap, @NotNull Predicate<Recipe> canHandle,
int index, int count, long skip) {
// exhausted all the ingredients, and didn't find anything
if (count == ingredients.size()) return null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

@ApiStatus.Internal
Expand Down Expand Up @@ -83,4 +85,11 @@ public Recipe findRecipe(long voltage, List<ItemStack> inputs, List<FluidStack>
}
return null;
}

@Override
@NotNull
public Iterator<Recipe> getRecipeIterator(long voltage, List<ItemStack> inputs, List<FluidStack> fluidInputs,
boolean exactVoltage) {
return Collections.singleton(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)).iterator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

@ApiStatus.Internal
Expand Down Expand Up @@ -77,4 +79,11 @@ public Recipe findRecipe(long voltage, List<ItemStack> inputs, List<FluidStack>
}
return recipe;
}

@Override
@NotNull
public Iterator<Recipe> getRecipeIterator(long voltage, List<ItemStack> inputs, List<FluidStack> fluidInputs,
boolean exactVoltage) {
return Collections.singleton(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)).iterator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Collections;
import java.util.Iterator;
import java.util.List;

@ApiStatus.Internal
Expand Down Expand Up @@ -50,4 +52,11 @@ public Recipe findRecipe(long voltage, List<ItemStack> inputs, List<FluidStack>

return null;
}

@Override
@NotNull
public Iterator<Recipe> getRecipeIterator(long voltage, List<ItemStack> inputs, List<FluidStack> fluidInputs,
boolean exactVoltage) {
return Collections.singleton(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)).iterator();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

@ApiStatus.Internal
Expand Down Expand Up @@ -60,4 +62,11 @@ public Recipe findRecipe(long voltage, List<ItemStack> inputs, List<FluidStack>
}
return null;
}

@Override
@NotNull
public Iterator<Recipe> getRecipeIterator(long voltage, List<ItemStack> inputs, List<FluidStack> fluidInputs,
boolean exactVoltage) {
return Collections.singleton(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)).iterator();
}
}