From 33276b54ba69032133c769e31286a3e303ff4a61 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Thu, 1 Feb 2024 23:09:45 -0800 Subject: [PATCH 01/17] Implement Iterator for traversing Recipe Tree --- .../gregtech/api/recipes/RecipeIterator.java | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 src/main/java/gregtech/api/recipes/RecipeIterator.java diff --git a/src/main/java/gregtech/api/recipes/RecipeIterator.java b/src/main/java/gregtech/api/recipes/RecipeIterator.java new file mode 100644 index 00000000000..33869a9c203 --- /dev/null +++ b/src/main/java/gregtech/api/recipes/RecipeIterator.java @@ -0,0 +1,47 @@ +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 { + + int index; + List> ingredients; + @NotNull + RecipeMap recipeMap; + @NotNull + Predicate canHandle; + + RecipeIterator(@NotNull RecipeMap recipeMap, List> ingredients, + @NotNull Predicate canHandle) { + this.ingredients = ingredients; + this.recipeMap = recipeMap; + this.canHandle = canHandle; + } + + // does not guarantee a next recipe, just the possibility of one + @Override + public boolean hasNext() { + return ingredients != null && this.index < this.ingredients.size(); + } + + @Override + public Recipe next() { + // 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; + } +} From 334bae6dc6072af6d0eb48f8c647888df40e4416 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Thu, 1 Feb 2024 23:10:37 -0800 Subject: [PATCH 02/17] Use Iterator when searching for new valid Recipes rather than only trying the "first" valid recipe. --- .../capability/impl/AbstractRecipeLogic.java | 50 +++++++++--- .../java/gregtech/api/recipes/RecipeMap.java | 78 ++++++++++++++++++- 2 files changed, 115 insertions(+), 13 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index e00cdc21235..7c8b06a4e33 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -37,6 +37,7 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; import static gregtech.api.GTValues.ULV; @@ -368,7 +369,8 @@ public void forceRecipeRecheck() { */ protected void trySearchNewRecipe() { long maxVoltage = getMaxVoltage(); - Recipe currentRecipe; + Recipe currentRecipe = null; + Iterator recipeIterator = null; IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); @@ -376,19 +378,30 @@ protected void trySearchNewRecipe() { 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) { + recipeIterator = getRecipeIterator(maxVoltage, importInventory, importFluids); + + // 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); + while (recipeIterator != null && recipeIterator.hasNext()) { + Recipe next = recipeIterator.next(); + if (next == null) continue; + this.isOutputsFull = false; + this.invalidInputsForRecipes = false; + + if (checkRecipe(next) && prepareRecipe(next)) { + // If a new recipe was found, cache found recipe. + this.previousRecipe = next; + return; + } } + +// this.isOutputsFull = true; + this.invalidInputsForRecipes = true; } /** @@ -543,6 +556,25 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul return map.findRecipe(maxVoltage, inputs, fluidInputs); } + /** + * Find a recipe Supplier 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 if found, otherwise null + */ + @Nullable + protected Iterator 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 diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index 1103deef462..aa984dc4b0a 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -71,6 +71,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; @@ -330,6 +331,10 @@ public RecipeMap> getSmallRecipeMap() { return smallRecipeMap; } + public Branch getLookup() { + return lookup; + } + /** * Internal usage only, use {@link RecipeBuilder#buildAndRegister()} * @@ -593,11 +598,76 @@ protected List> prepareRecipeFind(@NotNull Collectio public Recipe find(@NotNull Collection items, @NotNull Collection fluids, @NotNull Predicate canHandle) { List> list = prepareRecipeFind(items, fluids); - // couldn't build any inputs to use for search, so no recipe could be found if (list == null) return null; return recurseIngredientTreeFindRecipe(list, lookup, canHandle); } + @NotNull + public Iterator getRecipeIterator(long voltage, IItemHandlerModifiable inputs, + IMultipleTankHandler fluidInputs) { + return this.getRecipeIterator(voltage, GTUtility.itemHandlerToList(inputs), + GTUtility.fluidHandlerToList(fluidInputs)); + } + + /** + * Finds a Supplier 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 Supplier + */ + @NotNull + public Iterator getRecipeIterator(long voltage, List inputs, List fluidInputs) { + return getRecipeIterator(voltage, inputs, fluidInputs, false); + } + + /** + * Finds a Supplier 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 Supplier + */ + @NotNull + public Iterator getRecipeIterator(long voltage, final List inputs, + final List fluidInputs, + boolean exactVoltage) { + final List items = inputs.stream().filter(s -> !s.isEmpty()).collect(Collectors.toList()); + final List 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); + }); + } + + /** + * Finds a Supplier 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 Supplier + */ + @NotNull + public Iterator getRecipeIterator(@NotNull Collection items, + @NotNull Collection fluids, + @NotNull Predicate canHandle) { + List> 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, @@ -697,9 +767,9 @@ private Recipe recurseIngredientTreeFindRecipe(@NotNull List> ingredients, - @NotNull Branch branchMap, @NotNull Predicate canHandle, - int index, int count, long skip) { + public Recipe recurseIngredientTreeFindRecipe(@NotNull List> ingredients, + @NotNull Branch branchMap, @NotNull Predicate canHandle, + int index, int count, long skip) { // exhausted all the ingredients, and didn't find anything if (count == ingredients.size()) return null; From e4b5ed8bcf7efd6d89ce0dd6143c6cc491dd3550 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Thu, 1 Feb 2024 23:12:42 -0800 Subject: [PATCH 03/17] Apply Spotless formatting. --- .../java/gregtech/api/capability/impl/AbstractRecipeLogic.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 7c8b06a4e33..34ec8d76c8a 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -400,7 +400,7 @@ protected void trySearchNewRecipe() { } } -// this.isOutputsFull = true; + // this.isOutputsFull = true; this.invalidInputsForRecipes = true; } From 75767de532f777354973f1e5ced1bdb68aaf0af7 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Thu, 1 Feb 2024 23:19:27 -0800 Subject: [PATCH 04/17] More comments. --- .../api/capability/impl/AbstractRecipeLogic.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 34ec8d76c8a..ea35b776f31 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -370,7 +370,7 @@ public void forceRecipeRecheck() { protected void trySearchNewRecipe() { long maxVoltage = getMaxVoltage(); Recipe currentRecipe = null; - Iterator recipeIterator = null; + Iterator recipeIterator; IItemHandlerModifiable importInventory = getInputInventory(); IMultipleTankHandler importFluids = getInputTank(); @@ -387,9 +387,13 @@ protected void trySearchNewRecipe() { return; } + // Search for a new recipe if the previous one is no longer valid while (recipeIterator != null && recipeIterator.hasNext()) { Recipe next = recipeIterator.next(); if (next == null) continue; + + // since previous attempts to prepare a recipe will have flagged either the input + // or outputs as invalid we must reset the flags before attempting to prepare another recipe this.isOutputsFull = false; this.invalidInputsForRecipes = false; @@ -400,7 +404,9 @@ protected void trySearchNewRecipe() { } } - // this.isOutputsFull = true; + // if no valid recipes are found mark the inputs and outputs as invalid so any changes + // will re-trigger a recipe search + this.isOutputsFull = true; this.invalidInputsForRecipes = true; } From 9b70c9b2d34b0b52d48020e5479e5dfa75d9a2ed Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Thu, 1 Feb 2024 23:45:53 -0800 Subject: [PATCH 05/17] Made multiblocks stop softlocking when outputs change. --- .../java/gregtech/api/capability/impl/AbstractRecipeLogic.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index ea35b776f31..94af923bac5 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -232,7 +232,7 @@ public Recipe getPreviousRecipe() { * @return true if recipes should be searched for */ protected boolean shouldSearchForRecipes() { - return canWorkWithInputs() && canFitNewOutputs(); + return canWorkWithInputs() || canFitNewOutputs(); } /** From 6cbc0b4cfb56ce7c1208309e00c591ab8ad2afee Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Thu, 1 Feb 2024 23:50:48 -0800 Subject: [PATCH 06/17] fixed comments. --- .../api/capability/impl/AbstractRecipeLogic.java | 4 ++-- src/main/java/gregtech/api/recipes/RecipeMap.java | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index 94af923bac5..c60a7b48287 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -563,12 +563,12 @@ protected Recipe findRecipe(long maxVoltage, IItemHandlerModifiable inputs, IMul } /** - * Find a recipe Supplier using inputs + * 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 if found, otherwise null + * @return the recipe iterator if this.recipeMap is valid, otherwise null */ @Nullable protected Iterator getRecipeIterator(long maxVoltage, IItemHandlerModifiable inputs, diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index aa984dc4b0a..544469d71fd 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -610,12 +610,12 @@ public Iterator getRecipeIterator(long voltage, IItemHandlerModifiable i } /** - * Finds a Supplier of Recipes matching the Fluid and/or ItemStack Inputs. + * 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 Supplier + * @return the Recipe Iterator */ @NotNull public Iterator getRecipeIterator(long voltage, List inputs, List fluidInputs) { @@ -623,13 +623,13 @@ public Iterator getRecipeIterator(long voltage, List inputs, } /** - * Finds a Supplier of Recipes matching the Fluid and/or ItemStack Inputs. + * 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 Supplier + * @return the Recipe Iterator */ @NotNull public Iterator getRecipeIterator(long voltage, final List inputs, @@ -653,12 +653,12 @@ public Iterator getRecipeIterator(long voltage, final List in } /** - * Finds a Supplier of Recipes using Items and Fluids. + * 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 Supplier + * @return the Recipe Iterator */ @NotNull public Iterator getRecipeIterator(@NotNull Collection items, From 3eade294a7a43018256bda62215be96351c0dc76 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Thu, 1 Feb 2024 23:53:11 -0800 Subject: [PATCH 07/17] fixed comments. --- src/main/java/gregtech/api/recipes/RecipeMap.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index 544469d71fd..5f690e7425a 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -598,6 +598,7 @@ protected List> prepareRecipeFind(@NotNull Collectio public Recipe find(@NotNull Collection items, @NotNull Collection fluids, @NotNull Predicate canHandle) { List> list = prepareRecipeFind(items, fluids); + // couldn't build any inputs to use for search, so no recipe could be found if (list == null) return null; return recurseIngredientTreeFindRecipe(list, lookup, canHandle); } From 39a5f6daed3b402f6b89fbbd12634fb166f5b71c Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 00:22:56 -0800 Subject: [PATCH 08/17] made hasNext guarantee a next recipe. --- .../java/gregtech/api/recipes/RecipeIterator.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeIterator.java b/src/main/java/gregtech/api/recipes/RecipeIterator.java index 33869a9c203..3167fc50997 100644 --- a/src/main/java/gregtech/api/recipes/RecipeIterator.java +++ b/src/main/java/gregtech/api/recipes/RecipeIterator.java @@ -18,16 +18,24 @@ public class RecipeIterator implements Iterator { Predicate canHandle; RecipeIterator(@NotNull RecipeMap recipeMap, List> ingredients, - @NotNull Predicate canHandle) { + @NotNull Predicate canHandle) { this.ingredients = ingredients; this.recipeMap = recipeMap; this.canHandle = canHandle; } - // does not guarantee a next recipe, just the possibility of one @Override public boolean hasNext() { - return ingredients != null && this.index < this.ingredients.size(); + if (ingredients == null || this.index > this.ingredients.size()) return false; + + int i = index; + while (i < ingredients.size()) { + Recipe r = recipeMap.recurseIngredientTreeFindRecipe(ingredients, recipeMap.getLookup(), canHandle, i, 0, + (1L << i)); + ++i; + if (r != null) return true; + } + return false; } @Override From 95cd4c8479e356bf58a569d103d20757b3f6744f Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 00:23:34 -0800 Subject: [PATCH 09/17] Fixed bug caused by multismelter not having a recipemap for ARL to compare inputs to. --- .../recipes/machines/RecipeMapFurnace.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java b/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java index 2c1b3d442e2..b0aea89b0e9 100644 --- a/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java +++ b/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java @@ -1,7 +1,9 @@ package gregtech.api.recipes.machines; +import gregtech.api.capability.IMultipleTankHandler; import gregtech.api.recipes.ModHandler; import gregtech.api.recipes.Recipe; +import gregtech.api.recipes.RecipeIterator; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.builders.SimpleRecipeBuilder; import gregtech.api.recipes.ui.RecipeMapUIFunction; @@ -11,11 +13,15 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.items.IItemHandlerModifiable; + import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Iterator; import java.util.List; +import java.util.Stack; @ApiStatus.Internal public class RecipeMapFurnace extends RecipeMap { @@ -50,4 +56,26 @@ public Recipe findRecipe(long voltage, List inputs, List return null; } + + // probably can just extend Iterator directly. + static class FurnaceRecipeIterator implements Iterator { + Stack recipe = new Stack<>(); + FurnaceRecipeIterator(Recipe recipe) { + this.recipe.add(recipe); + } + @Override + public boolean hasNext() { return !recipe.isEmpty(); } + @Override + public Recipe next() { + if (recipe.isEmpty()) return null; + return recipe.pop(); + } + } + + @Override + @NotNull + public Iterator getRecipeIterator(long voltage, List inputs, List fluidInputs, + boolean exactVoltage) { + return new FurnaceRecipeIterator(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)); + } } From 714fad2e4006f4365be460dd6598a5e7b0422804 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 00:25:36 -0800 Subject: [PATCH 10/17] spotless moment --- .../java/gregtech/api/recipes/RecipeIterator.java | 2 +- .../api/recipes/machines/RecipeMapFurnace.java | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeIterator.java b/src/main/java/gregtech/api/recipes/RecipeIterator.java index 3167fc50997..415ae99951a 100644 --- a/src/main/java/gregtech/api/recipes/RecipeIterator.java +++ b/src/main/java/gregtech/api/recipes/RecipeIterator.java @@ -18,7 +18,7 @@ public class RecipeIterator implements Iterator { Predicate canHandle; RecipeIterator(@NotNull RecipeMap recipeMap, List> ingredients, - @NotNull Predicate canHandle) { + @NotNull Predicate canHandle) { this.ingredients = ingredients; this.recipeMap = recipeMap; this.canHandle = canHandle; diff --git a/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java b/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java index b0aea89b0e9..43e6b69d928 100644 --- a/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java +++ b/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java @@ -1,9 +1,7 @@ package gregtech.api.recipes.machines; -import gregtech.api.capability.IMultipleTankHandler; import gregtech.api.recipes.ModHandler; import gregtech.api.recipes.Recipe; -import gregtech.api.recipes.RecipeIterator; import gregtech.api.recipes.RecipeMap; import gregtech.api.recipes.builders.SimpleRecipeBuilder; import gregtech.api.recipes.ui.RecipeMapUIFunction; @@ -13,8 +11,6 @@ import net.minecraft.item.ItemStack; import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.items.IItemHandlerModifiable; - import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -59,12 +55,18 @@ public Recipe findRecipe(long voltage, List inputs, List // probably can just extend Iterator directly. static class FurnaceRecipeIterator implements Iterator { + Stack recipe = new Stack<>(); + FurnaceRecipeIterator(Recipe recipe) { this.recipe.add(recipe); } + @Override - public boolean hasNext() { return !recipe.isEmpty(); } + public boolean hasNext() { + return !recipe.isEmpty(); + } + @Override public Recipe next() { if (recipe.isEmpty()) return null; From 89f3b5a20fd5fa38ae3895b78814992627016f8b Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 00:54:44 -0800 Subject: [PATCH 11/17] simplified iterator --- .../recipes/machines/RecipeMapFurnace.java | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java b/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java index 43e6b69d928..6475721e5b0 100644 --- a/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java +++ b/src/main/java/gregtech/api/recipes/machines/RecipeMapFurnace.java @@ -15,9 +15,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Collections; import java.util.Iterator; import java.util.List; -import java.util.Stack; @ApiStatus.Internal public class RecipeMapFurnace extends RecipeMap { @@ -53,31 +53,10 @@ public Recipe findRecipe(long voltage, List inputs, List return null; } - // probably can just extend Iterator directly. - static class FurnaceRecipeIterator implements Iterator { - - Stack recipe = new Stack<>(); - - FurnaceRecipeIterator(Recipe recipe) { - this.recipe.add(recipe); - } - - @Override - public boolean hasNext() { - return !recipe.isEmpty(); - } - - @Override - public Recipe next() { - if (recipe.isEmpty()) return null; - return recipe.pop(); - } - } - @Override @NotNull public Iterator getRecipeIterator(long voltage, List inputs, List fluidInputs, boolean exactVoltage) { - return new FurnaceRecipeIterator(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)); + return Collections.singleton(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)).iterator(); } } From 3e0b96bb2d5a4f881279fbf054f08fbe42743a30 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 00:54:59 -0800 Subject: [PATCH 12/17] added iterator override to support custom recipes. --- .../api/recipes/machines/RecipeMapFluidCanner.java | 9 +++++++++ .../api/recipes/machines/RecipeMapFormingPress.java | 9 +++++++++ .../gregtech/api/recipes/machines/RecipeMapScanner.java | 9 +++++++++ 3 files changed, 27 insertions(+) diff --git a/src/main/java/gregtech/api/recipes/machines/RecipeMapFluidCanner.java b/src/main/java/gregtech/api/recipes/machines/RecipeMapFluidCanner.java index 719cde4c311..466d8bdeda7 100644 --- a/src/main/java/gregtech/api/recipes/machines/RecipeMapFluidCanner.java +++ b/src/main/java/gregtech/api/recipes/machines/RecipeMapFluidCanner.java @@ -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 @@ -83,4 +85,11 @@ public Recipe findRecipe(long voltage, List inputs, List } return null; } + + @Override + @NotNull + public Iterator getRecipeIterator(long voltage, List inputs, List fluidInputs, + boolean exactVoltage) { + return Collections.singleton(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)).iterator(); + } } diff --git a/src/main/java/gregtech/api/recipes/machines/RecipeMapFormingPress.java b/src/main/java/gregtech/api/recipes/machines/RecipeMapFormingPress.java index 492ae4080c1..f6f250c1fbb 100644 --- a/src/main/java/gregtech/api/recipes/machines/RecipeMapFormingPress.java +++ b/src/main/java/gregtech/api/recipes/machines/RecipeMapFormingPress.java @@ -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 @@ -77,4 +79,11 @@ public Recipe findRecipe(long voltage, List inputs, List } return recipe; } + + @Override + @NotNull + public Iterator getRecipeIterator(long voltage, List inputs, List fluidInputs, + boolean exactVoltage) { + return Collections.singleton(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)).iterator(); + } } diff --git a/src/main/java/gregtech/api/recipes/machines/RecipeMapScanner.java b/src/main/java/gregtech/api/recipes/machines/RecipeMapScanner.java index f76c7b10814..249ff7f0233 100644 --- a/src/main/java/gregtech/api/recipes/machines/RecipeMapScanner.java +++ b/src/main/java/gregtech/api/recipes/machines/RecipeMapScanner.java @@ -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 @@ -60,4 +62,11 @@ public Recipe findRecipe(long voltage, List inputs, List } return null; } + + @Override + @NotNull + public Iterator getRecipeIterator(long voltage, List inputs, List fluidInputs, + boolean exactVoltage) { + return Collections.singleton(this.findRecipe(voltage, inputs, fluidInputs, exactVoltage)).iterator(); + } } From cd3a21036f37366ed1418233915b309f1e46df62 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 15:38:22 -0800 Subject: [PATCH 13/17] only mark IO dirty when appropriate. --- .../capability/impl/AbstractRecipeLogic.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index c60a7b48287..bb3934cb127 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -379,7 +379,6 @@ protected void trySearchNewRecipe() { currentRecipe = this.previousRecipe; // If there is no active recipe, then we need to find one. } - recipeIterator = getRecipeIterator(maxVoltage, importInventory, importFluids); // proceed if previous recipe still works. if (currentRecipe != null && checkRecipe(currentRecipe) && prepareRecipe(currentRecipe)) { @@ -387,27 +386,33 @@ protected void trySearchNewRecipe() { return; } + recipeIterator = getRecipeIterator(maxVoltage, importInventory, importFluids); + + boolean invalidOutputs = false; + boolean invalidInputs = false; + // Search for a new recipe if the previous one is no longer valid while (recipeIterator != null && recipeIterator.hasNext()) { Recipe next = recipeIterator.next(); if (next == null) continue; - // since previous attempts to prepare a recipe will have flagged either the input - // or outputs as invalid we must reset the flags before attempting to prepare another recipe - this.isOutputsFull = false; - this.invalidInputsForRecipes = false; - if (checkRecipe(next) && prepareRecipe(next)) { // If a new recipe was found, cache found recipe. this.previousRecipe = next; return; + } 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 = true; - this.invalidInputsForRecipes = true; + this.isOutputsFull = invalidOutputs; + this.invalidInputsForRecipes = invalidInputs; } /** From 1c0da7acc1e33ac3f99c7eda1a458422caf3a22f Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 15:38:32 -0800 Subject: [PATCH 14/17] add caching --- .../gregtech/api/recipes/RecipeIterator.java | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeIterator.java b/src/main/java/gregtech/api/recipes/RecipeIterator.java index 415ae99951a..80f360bc68c 100644 --- a/src/main/java/gregtech/api/recipes/RecipeIterator.java +++ b/src/main/java/gregtech/api/recipes/RecipeIterator.java @@ -16,6 +16,7 @@ public class RecipeIterator implements Iterator { RecipeMap recipeMap; @NotNull Predicate canHandle; + Recipe cachedNext; RecipeIterator(@NotNull RecipeMap recipeMap, List> ingredients, @NotNull Predicate canHandle) { @@ -26,20 +27,28 @@ public class RecipeIterator implements Iterator { @Override public boolean hasNext() { + if (cachedNext != null) return true; if (ingredients == null || this.index > this.ingredients.size()) return false; - int i = index; - while (i < ingredients.size()) { - Recipe r = recipeMap.recurseIngredientTreeFindRecipe(ingredients, recipeMap.getLookup(), canHandle, i, 0, - (1L << i)); - ++i; - if (r != null) return true; + 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 From 69b74130a49f20ebe0788abd1f5e6020187367c8 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 15:38:53 -0800 Subject: [PATCH 15/17] unexpose recurseIngredientTreeFindRecipe --- src/main/java/gregtech/api/recipes/RecipeMap.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index 5f690e7425a..858b5a7bc8e 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -768,7 +768,7 @@ private Recipe recurseIngredientTreeFindRecipe(@NotNull List> ingredients, + protected Recipe recurseIngredientTreeFindRecipe(@NotNull List> ingredients, @NotNull Branch branchMap, @NotNull Predicate canHandle, int index, int count, long skip) { // exhausted all the ingredients, and didn't find anything From 57feb9689192b0cb1bcb7de79d17195ce3948447 Mon Sep 17 00:00:00 2001 From: "Wong, Dylan" Date: Sun, 4 Feb 2024 15:39:51 -0800 Subject: [PATCH 16/17] spotless moment 2: electric boogaloo --- src/main/java/gregtech/api/recipes/RecipeIterator.java | 3 ++- src/main/java/gregtech/api/recipes/RecipeMap.java | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/gregtech/api/recipes/RecipeIterator.java b/src/main/java/gregtech/api/recipes/RecipeIterator.java index 80f360bc68c..fbf91186dac 100644 --- a/src/main/java/gregtech/api/recipes/RecipeIterator.java +++ b/src/main/java/gregtech/api/recipes/RecipeIterator.java @@ -31,7 +31,8 @@ public boolean hasNext() { if (ingredients == null || this.index > this.ingredients.size()) return false; while (index < ingredients.size()) { - Recipe r = recipeMap.recurseIngredientTreeFindRecipe(ingredients, recipeMap.getLookup(), canHandle, index, 0, + Recipe r = recipeMap.recurseIngredientTreeFindRecipe(ingredients, recipeMap.getLookup(), canHandle, index, + 0, (1L << index)); ++index; if (r != null) { diff --git a/src/main/java/gregtech/api/recipes/RecipeMap.java b/src/main/java/gregtech/api/recipes/RecipeMap.java index 858b5a7bc8e..03faad77bc8 100644 --- a/src/main/java/gregtech/api/recipes/RecipeMap.java +++ b/src/main/java/gregtech/api/recipes/RecipeMap.java @@ -769,8 +769,8 @@ private Recipe recurseIngredientTreeFindRecipe(@NotNull List> ingredients, - @NotNull Branch branchMap, @NotNull Predicate canHandle, - int index, int count, long skip) { + @NotNull Branch branchMap, @NotNull Predicate canHandle, + int index, int count, long skip) { // exhausted all the ingredients, and didn't find anything if (count == ingredients.size()) return null; From 02502505ea04b2410f30f2d6054d0b1af2c7aff9 Mon Sep 17 00:00:00 2001 From: Taskeren Date: Wed, 19 Mar 2025 09:08:06 +0800 Subject: [PATCH 17/17] fixed bugs --- .../api/capability/impl/AbstractRecipeLogic.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java index d04183b4413..dacd7e38f81 100644 --- a/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/AbstractRecipeLogic.java @@ -421,15 +421,21 @@ protected void trySearchNewRecipe() { 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 != null && recipeIterator.hasNext()) { + 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; - return; + break; } else { // store if recipe has bad IO, then reset for next recipe checks invalidOutputs = this.isOutputsFull;