aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api/logic
diff options
context:
space:
mode:
authorSKProCH <29896317+SKProCH@users.noreply.github.com>2023-09-05 07:54:47 +0300
committerGitHub <noreply@github.com>2023-09-05 06:54:47 +0200
commit8beb872db7d19665a09518c5a5d90577b9f3f847 (patch)
treea024db315009e544c2ffc1a0a87dc9a82692d157 /src/main/java/gregtech/api/logic
parent1249b547f0813db813d1c12713b5dafbf46996df (diff)
downloadGT5-Unofficial-8beb872db7d19665a09518c5a5d90577b9f3f847.tar.gz
GT5-Unofficial-8beb872db7d19665a09518c5a5d90577b9f3f847.tar.bz2
GT5-Unofficial-8beb872db7d19665a09518c5a5d90577b9f3f847.zip
Proper recipe selection for output overflow in LCR and other multiblocks (#2247)
* Implement Stream<FindRecipeResult> findRecipesWithResult for GT_RecipeMap * Change ProcessingLogic.process to actually use new findRecipesWithResult * Change ProcessingLogic.process to start finding something only for OUTPUT_FULL result * Refactor ProcessingLogic.process to make logic more readable * Replace while with for loop, remove NOT_FOUND return in end of findRecipesWithResult * Apply spotless * Make findRecipe use findRecipes, add annotation to GT_Recipe and FindRecipeResult for processRecipe and make method protected, replace wildcard imports * Remake isRecipeWithOutputFullFound * Add @Nonnull to methods * Apply spotless * Remove Stream version of findRecipeWithResult, replace with predicate one. Add GT_Predicated_Recipe_Map class for utilizing this method. Changes some existent recipe maps to inherit from base class. * Remove GT_Predicated_Recipe_Map, add Predicate directly to GT_Recipe_Map#findRecipeWithResult. Add AdvancedRecipeValidatorPredicate and FindRecipeWithAdvancedValidatorResult to allow store validation calculations for further use and proper errors displaying. * Fix InsufficientVoltage errors * Changes according to review comments. Integrate FindRecipeWithAdvancedValidatorResult to FindRecipeResult, rename AdvancedRecipeValidatorPredicate, encapsulate AdvancedRecipeValidatorPredicate fields, fixes some typos, etc * Moves InsufficientVoltage check to GT_ParallelHelper. Removes FindRecipeResult#State#INSUFFICIENT_VOLTAGE * Return an old findRecipeWithResult * Renames things, call old methods for singleblocks * Renames things, makes FindRecipeResult ctor private * Apply spotless * Move RecipeValidator, fix comments typos
Diffstat (limited to 'src/main/java/gregtech/api/logic')
-rw-r--r--src/main/java/gregtech/api/logic/ProcessingLogic.java99
1 files changed, 72 insertions, 27 deletions
diff --git a/src/main/java/gregtech/api/logic/ProcessingLogic.java b/src/main/java/gregtech/api/logic/ProcessingLogic.java
index 6fa25a6c40..345a3e59dd 100644
--- a/src/main/java/gregtech/api/logic/ProcessingLogic.java
+++ b/src/main/java/gregtech/api/logic/ProcessingLogic.java
@@ -9,12 +9,11 @@ import javax.annotation.Nullable;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import gregtech.api.interfaces.tileentity.IRecipeLockable;
import gregtech.api.interfaces.tileentity.IVoidable;
-import gregtech.api.recipe.check.CheckRecipeResult;
-import gregtech.api.recipe.check.CheckRecipeResultRegistry;
-import gregtech.api.recipe.check.FindRecipeResult;
-import gregtech.api.recipe.check.SingleRecipeCheck;
+import gregtech.api.recipe.check.*;
import gregtech.api.util.GT_OverclockCalculator;
import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_Recipe;
@@ -275,7 +274,6 @@ public class ProcessingLogic {
maxParallel = maxParallelSupplier.get();
}
- FindRecipeResult findRecipeResult;
if (isRecipeLocked && recipeLockableMachine != null && recipeLockableMachine.getSingleRecipeCheck() != null) {
// Recipe checker is already built, we'll use it
SingleRecipeCheck singleRecipeCheck = recipeLockableMachine.getSingleRecipeCheck();
@@ -284,45 +282,81 @@ public class ProcessingLogic {
if (singleRecipeCheck.checkRecipeInputs(false, 1, inputItems, inputFluids) == 0) {
return CheckRecipeResultRegistry.NO_RECIPE;
}
- findRecipeResult = FindRecipeResult.ofSuccess(
+
+ return processRecipe(
recipeLockableMachine.getSingleRecipeCheck()
.getRecipe());
- } else {
- findRecipeResult = findRecipe(recipeMap);
}
- GT_Recipe recipe;
- CheckRecipeResult result;
- if (findRecipeResult.isSuccessful()) {
- recipe = findRecipeResult.getRecipeNonNull();
- result = validateRecipe(recipe);
- if (!result.wasSuccessful()) {
- return result;
- } else {
- if (recipe.mCanBeBuffered) {
- lastRecipe = recipe;
- } else {
- lastRecipe = null;
- }
+ 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();
}
- } else {
- if (findRecipeResult.getState() == FindRecipeResult.State.INSUFFICIENT_VOLTAGE) {
- return CheckRecipeResultRegistry.insufficientPower(findRecipeResult.getRecipeNonNull().mEUt);
- } else {
- return CheckRecipeResultRegistry.NO_RECIPE;
+
+ // If everything is ok, reuse our calculations
+ if (recipeValidator.isExecutedAtLeastOnce() && findRecipeResult.isSuccessful()) {
+ return applyRecipe(
+ findRecipeResult.getRecipeNonNull(),
+ recipeValidator.getLastParallelHelper(),
+ recipeValidator.getLastOverclockCalculator(),
+ recipeValidator.getLastCheckResult());
}
}
+ if (!findRecipeResult.isSuccessful()) {
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+
+ return processRecipe(findRecipeResult.getRecipeNonNull());
+ }
+
+ /**
+ * Checks if supplied recipe is valid for process.
+ * If so, 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) {
+ CheckRecipeResult result = validateRecipe(recipe);
+ if (!result.wasSuccessful()) {
+ return result;
+ }
+
GT_ParallelHelper helper = createParallelHelper(recipe);
GT_OverclockCalculator calculator = createOverclockCalculator(recipe);
helper.setCalculator(calculator);
helper.build();
+ return applyRecipe(recipe, helper, calculator, result);
+ }
+
+ /**
+ * Applies the recipe and calculated parameters
+ */
+ 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 {
+ lastRecipe = null;
+ }
calculatedParallels = helper.getCurrentParallel();
if (calculator.getConsumption() == Long.MAX_VALUE) {
@@ -360,14 +394,25 @@ public class ProcessingLogic {
@Nonnull
protected FindRecipeResult findRecipe(@Nullable GT_Recipe_Map map) {
if (map == null) return FindRecipeResult.NOT_FOUND;
- return map.findRecipeWithResult(
+
+ 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);
+
+ return findRecipeResult;
}
/**