aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/logic
diff options
context:
space:
mode:
authormiozune <miozune@gmail.com>2023-12-04 05:34:27 +0900
committerGitHub <noreply@github.com>2023-12-03 21:34:27 +0100
commitf74c7cc297d1d19d38a19683cd277ad9ce605d3a (patch)
treeb2a5d66ec5a959099240fb1db239ffc0f9531839 /src/main/java/gregtech/api/logic
parentb08cde7de4ec93cba05fb070991ad1dffb800ce1 (diff)
downloadGT5-Unofficial-f74c7cc297d1d19d38a19683cd277ad9ce605d3a.tar.gz
GT5-Unofficial-f74c7cc297d1d19d38a19683cd277ad9ce605d3a.tar.bz2
GT5-Unofficial-f74c7cc297d1d19d38a19683cd277ad9ce605d3a.zip
Refactor RecipeMap (#2345)
* Remove deprecated and unused things * Move recipemap subclasses * Move GT_Recipe_Map to outside and rename to RecipeMap * Move recipemap instances to separated class & remove prepending s * Remove useless GT_Recipe constructors * Always use ModularUI * Rename IGT_RecipeMap -> IRecipeMap * Add RecipeMapBuilder * Remove more deprecated and unused things * Fix RecipeMap type parameters * Use multimap for recipe index * Fix bending recipe error in dev env * Remove mUniqueIdentifier * Update AE2FC * Less edgy texture for NEI recipe background * Add replicator fluid output slot for NEI and machine GUI * Fix fluid fuels not having fuel value in large boilers * Remove GT_RectHandler and NEI_TransferRectHost * Remove RecipeMapHandler * Move NEI energy description from RecipeMapFrontend to Power * Refactor the way to filter fusion recipes * Check restriction for some properties * Remove showVoltageAmperage * Make Power accept GT_Recipe * Fix NPE * Move NEI duration description to Power from Frontend * Directly implement IRecipeProcessingAwareHatch for GT_MetaTileEntity_Hatch_InputBus_ME * Make Power integrated with GT_OverclockCalculator * Rename Power -> OverclockDescriber * Don't modify recipe find logic until postload finishes * Reformat reserved MTE ids * Fix check for too few inputs on recipe addition * Move replicator logic to backend * Stop un-hiding assline recipes * Allow setting custom recipe comparator & implement for fusion * Update AE2FC * Rename getRecipeList and getRecipes -> getRecipeMap * Automatically register recipe catalysts * Cleanup the way to detect recipe collision * Make use of BasicUIProperties for basic machines * Make use of BasicUIProperties for UIHelper * Rename specialHandler -> recipeTransformer * Add way to automatically register handler info * Add recipe category * Add some APIs for addons * Rename blastRecipes -> blastFurnaceRecipes * Remove GT_MetaTileEntity_BasicMachine_GT_Recipe#mSharedTank and #mRequiresFluidForFiltering * Don't require setting duration and EU/t for fuel recipes * Don't require setting EU/t for primitive blast furnace recipes * Revert change to addMultiblockChemicalRecipe * Fix large boiler general desc recipe not being added * Hide duration and EU/t from large boiler * Cleanup recipe stacktrace draw * Extend metadata usage of recipe builder to recipe itself * Implement metadata handling & NEI comparator for PCB factory * Some rename around NEIRecipeInfo * Some toString implementations * Add more APIs for addons & some rename * Infer handler icon from recipe catalyst if one is not set * Also shrink recipe title when OC is not used * Remove rare earth centrifuge recipe * Use metadata for replicator backend * Adjust geothermal generator output slot * Allow having multiple transferrects * Store recipemap reference in backend * Rename vacuumRecipes -> vacuumFreezerRecipes * Add config to tweak visibility of recipe categories * Remove mHideRecyclingRecipes in favor of recipe category config * Fix typo fluidSolidfierRecipes -> fluidSolidifierRecipes * Refactor findRecipe and ProcessingLogic to use Stream * Fix BBF handler icon & remove bronze blast furnace * Add fluent API for findRecipe * Add way to stop adding progressbar * Change arg order for special texture * Avoid overwriting interesting failure with NO_RECIPE * Some changes for FuelBackend * Set space project icon * Remove localization from TT * Remove CNC recipe adder * Move recipe extractor from AE2FC * Minor internal change for ProcessingLogic#applyRecipe * More javadoc on #getAvailableRecipeMaps * Better implementation of #ofSupplier * Move replicator exponent config to GT_Proxy * Remove RC & IC2 macerator handling * Rename StreamUtil -> GT_StreamUtil * Refactor code around RecipeMetadataStorage * Revise #compileRecipe javadoc * Switch extreme diesel recipe loader to downstream recipe map * Optimize #reMap * Rename reload -> reloadNEICache * Minor tweak for drawEnergyInfo * a bit more doc * Adjust recipe catalysts * Add toString implementation for GT_Fluid for debug * Minor revision for OilCrackerBackend * Index replicator recipes by material --------- Co-authored-by: Glease <4586901+Glease@users.noreply.github.com>
Diffstat (limited to 'src/main/java/gregtech/api/logic')
-rw-r--r--src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java7
-rw-r--r--src/main/java/gregtech/api/logic/ProcessingLogic.java174
2 files changed, 90 insertions, 91 deletions
diff --git a/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java b/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java
index 05d39cd02c..3c7974db9e 100644
--- a/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java
+++ b/src/main/java/gregtech/api/logic/ComplexParallelProcessingLogic.java
@@ -6,6 +6,7 @@ import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
import gregtech.api.multitileentity.multiblock.base.Controller;
+import gregtech.api.recipe.RecipeMap;
import gregtech.api.util.GT_OverclockCalculator;
import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_Recipe;
@@ -13,7 +14,7 @@ import gregtech.api.util.GT_Recipe;
public class ComplexParallelProcessingLogic {
protected Controller<?> tileEntity;
- protected GT_Recipe.GT_Recipe_Map recipeMap;
+ protected RecipeMap<?> recipeMap;
protected boolean hasPerfectOverclock;
protected final int maxComplexParallels;
protected final ItemStack[][] outputItems;
@@ -30,7 +31,7 @@ public class ComplexParallelProcessingLogic {
this(null, maxComplexParallels);
}
- public ComplexParallelProcessingLogic(GT_Recipe.GT_Recipe_Map recipeMap, int maxComplexParallels) {
+ public ComplexParallelProcessingLogic(RecipeMap<?> recipeMap, int maxComplexParallels) {
this.maxComplexParallels = maxComplexParallels;
this.recipeMap = recipeMap;
inputItems = new ItemStack[maxComplexParallels][];
@@ -44,7 +45,7 @@ public class ComplexParallelProcessingLogic {
isFluidVoidProtected = new boolean[maxComplexParallels];
}
- public ComplexParallelProcessingLogic setRecipeMap(GT_Recipe.GT_Recipe_Map recipeMap) {
+ public ComplexParallelProcessingLogic setRecipeMap(RecipeMap<?> recipeMap) {
this.recipeMap = recipeMap;
return this;
}
diff --git a/src/main/java/gregtech/api/logic/ProcessingLogic.java b/src/main/java/gregtech/api/logic/ProcessingLogic.java
index 803abafbe3..6b9f2d454f 100644
--- a/src/main/java/gregtech/api/logic/ProcessingLogic.java
+++ b/src/main/java/gregtech/api/logic/ProcessingLogic.java
@@ -2,6 +2,7 @@ package gregtech.api.logic;
import java.util.List;
import java.util.function.Supplier;
+import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -13,15 +14,13 @@ import org.jetbrains.annotations.NotNull;
import gregtech.api.interfaces.tileentity.IRecipeLockable;
import gregtech.api.interfaces.tileentity.IVoidable;
+import gregtech.api.recipe.RecipeMap;
import gregtech.api.recipe.check.CheckRecipeResult;
import gregtech.api.recipe.check.CheckRecipeResultRegistry;
-import gregtech.api.recipe.check.FindRecipeResult;
-import gregtech.api.recipe.check.RecipeValidator;
import gregtech.api.recipe.check.SingleRecipeCheck;
import gregtech.api.util.GT_OverclockCalculator;
import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_Recipe;
-import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
/**
* Logic class to calculate result of recipe check from inputs, based on recipemap.
@@ -31,9 +30,9 @@ public class ProcessingLogic {
protected IVoidable machine;
protected IRecipeLockable recipeLockableMachine;
- protected Supplier<GT_Recipe_Map> recipeMapSupplier;
+ protected Supplier<RecipeMap<?>> recipeMapSupplier;
protected GT_Recipe lastRecipe;
- protected GT_Recipe_Map lastRecipeMap;
+ protected RecipeMap<?> lastRecipeMap;
protected ItemStack specialSlotItem;
protected ItemStack[] inputItems;
protected ItemStack[] outputItems;
@@ -146,11 +145,11 @@ public class ProcessingLogic {
return this;
}
- public ProcessingLogic setRecipeMap(GT_Recipe_Map recipeMap) {
+ public ProcessingLogic setRecipeMap(RecipeMap<?> recipeMap) {
return setRecipeMapSupplier(() -> recipeMap);
}
- public ProcessingLogic setRecipeMapSupplier(Supplier<GT_Recipe_Map> supplier) {
+ public ProcessingLogic setRecipeMapSupplier(Supplier<RecipeMap<?>> supplier) {
this.recipeMapSupplier = supplier;
return this;
}
@@ -263,7 +262,7 @@ public class ProcessingLogic {
*/
@Nonnull
public CheckRecipeResult process() {
- GT_Recipe_Map recipeMap;
+ RecipeMap<?> recipeMap;
if (recipeMapSupplier == null) {
recipeMap = null;
} else {
@@ -278,6 +277,13 @@ public class ProcessingLogic {
maxParallel = maxParallelSupplier.get();
}
+ if (inputItems == null) {
+ inputItems = new ItemStack[0];
+ }
+ if (inputFluids == null) {
+ inputFluids = new FluidStack[0];
+ }
+
if (isRecipeLocked && recipeLockableMachine != null && recipeLockableMachine.getSingleRecipeCheck() != null) {
// Recipe checker is already built, we'll use it
SingleRecipeCheck singleRecipeCheck = recipeLockableMachine.getSingleRecipeCheck();
@@ -287,55 +293,39 @@ public class ProcessingLogic {
return CheckRecipeResultRegistry.NO_RECIPE;
}
- return processRecipe(
+ return validateAndCalculateRecipe(
recipeLockableMachine.getSingleRecipeCheck()
- .getRecipe());
+ .getRecipe()).checkRecipeResult;
}
- FindRecipeResult findRecipeResult = findRecipe(recipeMap);
- // If processRecipe is not overridden, advanced recipe validation logic is used, and we can reuse calculations.
- if (findRecipeResult.hasRecipeValidator()) {
- RecipeValidator recipeValidator = findRecipeResult.getRecipeValidator();
-
- // There are two cases:
- // 1 - there are actually no matching recipes
- // 2 - there are some matching recipes, but we rejected it due to our advanced validation (e.g. OUTPUT_FULL)
- if (findRecipeResult.getState() == FindRecipeResult.State.NOT_FOUND
- && recipeValidator.getFirstCheckResult() != null) {
- // Here we're handling case 2
- // If there are matching recipes but our validation rejected them,
- // we should return a first one to display a proper error in the machine GUI
- return recipeValidator.getFirstCheckResult();
+ Stream<GT_Recipe> matchedRecipes = findRecipeMatches(recipeMap);
+ Iterable<GT_Recipe> recipeIterable = matchedRecipes::iterator;
+ CheckRecipeResult checkRecipeResult = CheckRecipeResultRegistry.NO_RECIPE;
+ for (GT_Recipe matchedRecipe : recipeIterable) {
+ CalculationResult foundResult = validateAndCalculateRecipe(matchedRecipe);
+ if (foundResult.successfullyConsumedInputs) {
+ // Successfully found and set recipe, so return it
+ return foundResult.checkRecipeResult;
}
-
- // If everything is ok, reuse our calculations
- if (recipeValidator.isExecutedAtLeastOnce() && findRecipeResult.isSuccessful()) {
- return applyRecipe(
- findRecipeResult.getRecipeNonNull(),
- recipeValidator.getLastParallelHelper(),
- recipeValidator.getLastOverclockCalculator(),
- recipeValidator.getLastCheckResult());
+ if (foundResult.checkRecipeResult != CheckRecipeResultRegistry.NO_RECIPE) {
+ // Recipe failed in interesting way, so remember that and continue searching
+ checkRecipeResult = foundResult.checkRecipeResult;
}
}
-
- if (!findRecipeResult.isSuccessful()) {
- return CheckRecipeResultRegistry.NO_RECIPE;
- }
-
- return processRecipe(findRecipeResult.getRecipeNonNull());
+ return checkRecipeResult;
}
/**
- * Checks if supplied recipe is valid for process.
- * If so, additionally performs input consumption, output calculation with parallel, and overclock calculation.
+ * Checks if supplied recipe is valid for process. This involves voltage check, output full check. If successful,
+ * additionally performs input consumption, output calculation with parallel, and overclock calculation.
*
* @param recipe The recipe which will be checked and processed
*/
@Nonnull
- protected CheckRecipeResult processRecipe(@Nonnull GT_Recipe recipe) {
+ private CalculationResult validateAndCalculateRecipe(@Nonnull GT_Recipe recipe) {
CheckRecipeResult result = validateRecipe(recipe);
if (!result.wasSuccessful()) {
- return result;
+ return CalculationResult.ofFailure(result);
}
GT_ParallelHelper helper = createParallelHelper(recipe);
@@ -343,19 +333,20 @@ public class ProcessingLogic {
helper.setCalculator(calculator);
helper.build();
- return applyRecipe(recipe, helper, calculator, result);
+ if (!helper.getResult()
+ .wasSuccessful()) {
+ return CalculationResult.ofFailure(helper.getResult());
+ }
+
+ return CalculationResult.ofSuccess(applyRecipe(recipe, helper, calculator, result));
}
/**
- * Applies the recipe and calculated parameters
+ * Check has been succeeded, so it applies the recipe and calculated parameters.
+ * At this point, inputs have been already consumed.
*/
private CheckRecipeResult applyRecipe(@NotNull GT_Recipe recipe, GT_ParallelHelper helper,
GT_OverclockCalculator calculator, CheckRecipeResult result) {
- if (!helper.getResult()
- .wasSuccessful()) {
- return helper.getResult();
- }
-
if (recipe.mCanBeBuffered) {
lastRecipe = recipe;
} else {
@@ -398,30 +389,31 @@ public class ProcessingLogic {
}
/**
- * Override if you don't work with regular gt recipe maps
+ * Finds a list of matched recipes. At this point no additional check to the matched recipe has been done.
+ * <p>
+ * Override {@link #validateRecipe} to have custom check.
+ * <p>
+ * Override this method if it doesn't work with normal recipemaps.
*/
@Nonnull
- protected FindRecipeResult findRecipe(@Nullable GT_Recipe_Map map) {
- if (map == null) return FindRecipeResult.NOT_FOUND;
-
- RecipeValidator recipeValidator = new RecipeValidator(
- this::validateRecipe,
- this::createParallelHelper,
- this::createOverclockCalculator);
-
- FindRecipeResult findRecipeResult = map.findRecipeWithResult(
- lastRecipe,
- recipeValidator,
- false,
- false,
- amperageOC ? availableVoltage * availableAmperage : availableVoltage,
- inputFluids,
- specialSlotItem,
- inputItems);
-
- findRecipeResult.setRecipeValidator(recipeValidator);
+ protected Stream<GT_Recipe> findRecipeMatches(@Nullable RecipeMap<?> map) {
+ if (map == null) {
+ return Stream.empty();
+ }
+ return map.findRecipeQuery()
+ .items(inputItems)
+ .fluids(inputFluids)
+ .specialSlot(specialSlotItem)
+ .cachedRecipe(lastRecipe)
+ .findAll();
+ }
- return findRecipeResult;
+ /**
+ * Override to do additional check for found recipe if needed.
+ */
+ @Nonnull
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
/**
@@ -443,24 +435,6 @@ public class ProcessingLogic {
}
/**
- * Override to do additional check for finding recipe if needed, mainly for special value of the recipe.
- */
- @Nonnull
- protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
- return CheckRecipeResultRegistry.SUCCESSFUL;
- }
-
- /**
- * Use {@link #createOverclockCalculator(GT_Recipe)}
- */
- @Nonnull
- @Deprecated
- protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe,
- @Nullable GT_ParallelHelper helper) {
- return createOverclockCalculator(recipe);
- }
-
- /**
* Override to tweak overclock logic if needed.
*/
@Nonnull
@@ -514,4 +488,28 @@ public class ProcessingLogic {
}
// endregion
+
+ /**
+ * Represents the status of check recipe calculation. {@link #successfullyConsumedInputs} does not necessarily mean
+ * {@link #checkRecipeResult} being successful, when duration or power is overflowed. Being failure means
+ * recipe cannot meet requirements and recipe search should be continued if possible.
+ */
+ protected final static class CalculationResult {
+
+ public final boolean successfullyConsumedInputs;
+ public final CheckRecipeResult checkRecipeResult;
+
+ public static CalculationResult ofSuccess(CheckRecipeResult checkRecipeResult) {
+ return new CalculationResult(true, checkRecipeResult);
+ }
+
+ public static CalculationResult ofFailure(CheckRecipeResult checkRecipeResult) {
+ return new CalculationResult(false, checkRecipeResult);
+ }
+
+ private CalculationResult(boolean successfullyConsumedInputs, CheckRecipeResult checkRecipeResult) {
+ this.successfullyConsumedInputs = successfullyConsumedInputs;
+ this.checkRecipeResult = checkRecipeResult;
+ }
+ }
}