diff options
author | miozune <miozune@gmail.com> | 2023-12-04 05:34:27 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-12-03 21:34:27 +0100 |
commit | f74c7cc297d1d19d38a19683cd277ad9ce605d3a (patch) | |
tree | b2a5d66ec5a959099240fb1db239ffc0f9531839 /src/main/java/gregtech/api/logic | |
parent | b08cde7de4ec93cba05fb070991ad1dffb800ce1 (diff) | |
download | GT5-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.java | 7 | ||||
-rw-r--r-- | src/main/java/gregtech/api/logic/ProcessingLogic.java | 174 |
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; + } + } } |