aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech
diff options
context:
space:
mode:
authorMaxim <maxim235@gmx.de>2023-07-10 10:13:04 +0200
committerGitHub <noreply@github.com>2023-07-10 10:13:04 +0200
commitfe0387946550f89a403b09f4e8cf6e43ee8f2e8f (patch)
tree6b56a553c2a5bbf2427a93e92724452ba5bc60f7 /src/main/java/gregtech
parent9fe44bf0eaa55825c1c3cdf90f69aeeb668f45b1 (diff)
downloadGT5-Unofficial-fe0387946550f89a403b09f4e8cf6e43ee8f2e8f.tar.gz
GT5-Unofficial-fe0387946550f89a403b09f4e8cf6e43ee8f2e8f.tar.bz2
GT5-Unofficial-fe0387946550f89a403b09f4e8cf6e43ee8f2e8f.zip
Generic processing logic (#2096)
* Added enumeration for check recipe result * Rework processing logic to work with MTEs too * Switched first few multiblocks to new checkRecipe method * Applied generic logic to EBF * Added support for long power base and applied generic processing logic to more machines * Address some feedback * Added more setter to further configure the processing logic * Change internal checkRecipe to work with checkRecipeResult, to allow the injection of custom failure messages * Suppress warning, change access * Merge recipeMap and mapSupplier * Move calls to setMetaTEController and setRecipeMap to base classes * Make processingLogic final * Make results non-null * Rename `ProcessingLogic#checkRecipe` -> `#validateRecipe` Otherwise it's confusing with `GT_MetaTileEntity_MultiBlockBase#checkRecipe` * oops * Added recipe locking to generic processing logic * Rename: getWorldObject -> getIHasWorldObjectAndCoords * Annotate missing overrides * Renamed recipeLockableController -> recipeLockableMachine * Migrated Cleanroom * Migrated pyrolyse oven * Migrated driller * Migrated charcoal pit * Migrated DT * Rename: controller -> machine * Make recipemaps override base `findRecipe` and mark others final * Remove unused maps * Add FindRecipeResult * Remove IHasWorldObjectAndCoords parameter from findRecipe This removes argument for printer recipemap to pass for GT_ModHandler.getAllRecipeOutput, but I don't think there's any mod that adds world-specific coloring recipe. * Added method to set processing logic power so machines can override it on demand * Restructure CheckRecipeResult, show voltage required and move package * Reword: insufficient voltage -> power * Change text color: dark gray -> gray * Added findRecipeResult for insufficient heat * Migrated PCB factory * Fix result not being reset on shut down * Show coil tier for heat * clean * Reverted migration of driller base * Migrated TPM * Moved getting of parallel supplier, to accomodate TPM * Migrated power gen multiblocks * Migrated Assembling Line * Migrated fusion * Migrated multi smelter * Migrated boiler * Migrated DTPF * Migrated ore factory * Migrated heat exchanger * Make checkRecipe() final, javadoc, minor cleanup * Fix overclock behavior with multiple hatches, javadoc, minor cleanup * Minor fix for javadoc * Fixed creation of OC calculator not factoring in batch mode correctly * Make GT_ParallelHelper#setRecipe nonnull * Rework SimpleCheckRecipeResult to not require registration * Migrate charcoal pit and cleanroom * Fix result not being reset when turning off machine * Add API for BW to make recipemap sensitive to special slot on recipe search * Migrated PA * Migrated driller base * Make ProcessingLogic#duration int * Minor cleanup * missing recipe locking for long multi * Fix NPE * Show crash message and turn off machine * minor javadoc fix * Fixed power setting for extended power base * Integrate SingleRecipeCheck into ProcessingLogic, fix duration overflow, fix duration for batch mode, migrate PA for GT_MetaTileEntity_ExtendedPowerMultiBlockBase * Fixed ME stocking busses * Minor PA fixes * Cleanup item collecting logic & apply to normal multi as well * Oversight * Derp * Multiple voltage instead of amperage with recipe map amperage, since usually amperage is intended for parallel, not for recipe checking * Fix missing EU modifiers on PCB factory OC calculator * Removed left over OC method * Fixed duration calculation of PCB not applying roughness multiplier * Fixed OC parameters * Make createOverclockCalculator nonnull & more nonnull annotations * Fixed input processing voltage * Round down voltage for other machines too * Revert Nano Forge, return correct long voltage * Use region / endregion --------- Co-authored-by: miozune <miozune@gmail.com>
Diffstat (limited to 'src/main/java/gregtech')
-rw-r--r--src/main/java/gregtech/api/enums/HeatingCoilLevel.java31
-rw-r--r--src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java3
-rw-r--r--src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java19
-rw-r--r--src/main/java/gregtech/api/interfaces/tileentity/IHasWorldObjectAndCoords.java5
-rw-r--r--src/main/java/gregtech/api/interfaces/tileentity/IRecipeLockable.java34
-rw-r--r--src/main/java/gregtech/api/logic/ProcessingLogic.java308
-rw-r--r--src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java12
-rw-r--r--src/main/java/gregtech/api/metatileentity/MetaTileEntity.java6
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java16
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java69
-rw-r--r--src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java236
-rw-r--r--src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java7
-rw-r--r--src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java16
-rw-r--r--src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java42
-rw-r--r--src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java111
-rw-r--r--src/main/java/gregtech/api/recipe/check/FindRecipeResult.java107
-rw-r--r--src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java57
-rw-r--r--src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java54
-rw-r--r--src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java56
-rw-r--r--src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java78
-rw-r--r--src/main/java/gregtech/api/recipe/check/SingleRecipeCheck.java404
-rw-r--r--src/main/java/gregtech/api/util/GT_OverclockCalculator.java13
-rw-r--r--src/main/java/gregtech/api/util/GT_ParallelHelper.java137
-rw-r--r--src/main/java/gregtech/api/util/GT_ProcessingArray_Manager.java9
-rw-r--r--src/main/java/gregtech/api/util/GT_Recipe.java893
-rw-r--r--src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java421
-rw-r--r--src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java244
-rw-r--r--src/main/java/gregtech/api/util/GT_Utility.java17
-rw-r--r--src/main/java/gregtech/api/util/VoidProtectionHelper.java2
-rw-r--r--src/main/java/gregtech/common/gui/modularui/widget/CheckRecipeResultSyncer.java26
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java22
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java13
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java9
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java18
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java70
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java37
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java147
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java15
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java13
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java44
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java13
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java19
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java69
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java52
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java50
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java16
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java85
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java51
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java251
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java24
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java491
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java69
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java95
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java33
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java9
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java15
-rw-r--r--src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java1
-rw-r--r--src/main/java/gregtech/nei/HeatingCoilSpecialValueFormatter.java10
58 files changed, 2719 insertions, 2455 deletions
diff --git a/src/main/java/gregtech/api/enums/HeatingCoilLevel.java b/src/main/java/gregtech/api/enums/HeatingCoilLevel.java
index f80f8139c6..f281695d5a 100644
--- a/src/main/java/gregtech/api/enums/HeatingCoilLevel.java
+++ b/src/main/java/gregtech/api/enums/HeatingCoilLevel.java
@@ -1,5 +1,7 @@
package gregtech.api.enums;
+import javax.annotation.Nonnull;
+
import net.minecraft.util.StatCollector;
public enum HeatingCoilLevel {
@@ -32,7 +34,7 @@ public enum HeatingCoilLevel {
}
/**
- * @return the coil tier, used for discount in the Pyrolyse Oven for example.
+ * @return the coil tier, used for discount in the Pyrolyse Oven for example. LV == 0
*/
public byte getTier() {
return (byte) (this.ordinal() - 2);
@@ -52,16 +54,43 @@ public enum HeatingCoilLevel {
return 1 << Math.max(0, this.ordinal() - 5);
}
+ /**
+ * @return Translated name of this coil
+ */
public String getName() {
return StatCollector.translateToLocal("GT5U.coil." + this);
}
+ @Nonnull
public static HeatingCoilLevel getFromTier(byte tier) {
if (tier < 0 || tier > getMaxTier()) return HeatingCoilLevel.None;
return VALUES[tier + 2];
}
+ /**
+ * @param applyColor Whether to apply tiered color
+ * @return Translated coil name. Heat exceeding MAX is represented as "Eternal+".
+ */
+ @Nonnull
+ public static String getDisplayNameFromHeat(int heat, boolean applyColor) {
+ for (HeatingCoilLevel heatLevel : VALUES) {
+ if (heatLevel == HeatingCoilLevel.None || heatLevel == HeatingCoilLevel.ULV) continue;
+ if (heatLevel.getHeat() >= heat) {
+ String name = heatLevel.getName();
+ if (applyColor) {
+ name = GT_Values.TIER_COLORS[heatLevel.getTier() + 1] + name;
+ }
+ return name;
+ }
+ }
+ String name = HeatingCoilLevel.MAX.getName() + "+";
+ if (applyColor) {
+ name = GT_Values.TIER_COLORS[HeatingCoilLevel.MAX.getTier() + 1] + name;
+ }
+ return name;
+ }
+
public static int size() {
return VALUES.length;
}
diff --git a/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java b/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java
index 9a60092121..7b29f185c6 100644
--- a/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java
+++ b/src/main/java/gregtech/api/interfaces/metatileentity/IMetaTileEntity.java
@@ -298,8 +298,7 @@ public interface IMetaTileEntity extends ISidedInventory, IFluidTank, IFluidHand
void receiveClientEvent(byte aEventID, byte aValue);
/**
- * Called to actually play the Sound. Do not insert Client/Server checks. That is already done for you. Do not
- * use @playSoundEffect, Minecraft doesn't like that at all. Use @playSound instead.
+ * Called to actually play the sound on client side. Client/Server check is already done.
*/
void doSound(byte aIndex, double aX, double aY, double aZ);
diff --git a/src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java b/src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java
index 9f862e254d..3d4ed80f67 100644
--- a/src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java
+++ b/src/main/java/gregtech/api/interfaces/modularui/ControllerWithOptionalFeatures.java
@@ -20,6 +20,7 @@ import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
import gregtech.api.enums.SoundResource;
import gregtech.api.enums.VoidingMode;
import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.tileentity.IRecipeLockable;
import gregtech.api.interfaces.tileentity.IVoidable;
/**
@@ -33,7 +34,7 @@ import gregtech.api.interfaces.tileentity.IVoidable;
* <li>Recipe locking</li>
* </ul>
*/
-public interface ControllerWithOptionalFeatures extends IVoidable {
+public interface ControllerWithOptionalFeatures extends IVoidable, IRecipeLockable {
boolean isAllowedToWork();
@@ -233,22 +234,6 @@ public interface ControllerWithOptionalFeatures extends IVoidable {
return (ButtonWidget) button;
}
- /**
- * Override this if you are a multi-block that has added support for single recipe locking.
- */
- boolean supportsSingleRecipeLocking();
-
- /**
- * @return true if recipe locking is enabled, else false. This is getter is used for displaying the icon in the GUI
- */
- boolean isRecipeLockingEnabled();
-
- void setRecipeLocking(boolean enabled);
-
- default boolean getDefaultRecipeLockingMode() {
- return false;
- }
-
Pos2d getRecipeLockingButtonPos();
default ButtonWidget createLockToSingleRecipeButton(IWidgetBuilder<?> builder) {
diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IHasWorldObjectAndCoords.java b/src/main/java/gregtech/api/interfaces/tileentity/IHasWorldObjectAndCoords.java
index 64d206aff7..6d81d5c401 100644
--- a/src/main/java/gregtech/api/interfaces/tileentity/IHasWorldObjectAndCoords.java
+++ b/src/main/java/gregtech/api/interfaces/tileentity/IHasWorldObjectAndCoords.java
@@ -136,8 +136,9 @@ public interface IHasWorldObjectAndCoords {
boolean isDead();
/**
- * Sends a Block Event to the Client TileEntity, the byte Parameters are only for validation as Minecraft doesn't
- * properly write Packet Data.
+ * Sends a Block Event to the Client TileEntity.
+ *
+ * @param aValue value to sync
*/
void sendBlockEvent(byte aID, byte aValue);
diff --git a/src/main/java/gregtech/api/interfaces/tileentity/IRecipeLockable.java b/src/main/java/gregtech/api/interfaces/tileentity/IRecipeLockable.java
new file mode 100644
index 0000000000..f793221a50
--- /dev/null
+++ b/src/main/java/gregtech/api/interfaces/tileentity/IRecipeLockable.java
@@ -0,0 +1,34 @@
+package gregtech.api.interfaces.tileentity;
+
+import gregtech.api.recipe.check.SingleRecipeCheck;
+import gregtech.api.util.GT_Recipe;
+
+/**
+ * Machines implementing this interface can have logic to lock to a single recipe.
+ */
+public interface IRecipeLockable {
+
+ /**
+ * @return if this machine supports single recipe locking.
+ */
+ boolean supportsSingleRecipeLocking();
+
+ /**
+ * @return true if recipe locking is enabled, else false. This is getter is used for displaying the icon in the GUI
+ */
+ boolean isRecipeLockingEnabled();
+
+ void setRecipeLocking(boolean enabled);
+
+ default boolean getDefaultRecipeLockingMode() {
+ return false;
+ }
+
+ default SingleRecipeCheck getSingleRecipeCheck() {
+ return null;
+ }
+
+ default void setSingleRecipeCheck(SingleRecipeCheck recipeCheck) {}
+
+ GT_Recipe.GT_Recipe_Map getRecipeMap();
+}
diff --git a/src/main/java/gregtech/api/logic/ProcessingLogic.java b/src/main/java/gregtech/api/logic/ProcessingLogic.java
index fa0d285401..db97ac151f 100644
--- a/src/main/java/gregtech/api/logic/ProcessingLogic.java
+++ b/src/main/java/gregtech/api/logic/ProcessingLogic.java
@@ -1,39 +1,89 @@
package gregtech.api.logic;
+import java.util.List;
+import java.util.function.Supplier;
+
+import javax.annotation.Nonnull;
+
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
+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.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
+import gregtech.api.util.GT_Recipe;
import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
-public abstract class ProcessingLogic {
+/**
+ * Logic class to calculate result of recipe check from inputs, based on recipemap.
+ */
+@SuppressWarnings({ "unused", "UnusedReturnValue" })
+public class ProcessingLogic {
- protected GT_Recipe_Map recipeMap;
+ protected IVoidable machine;
+ protected IRecipeLockable recipeLockableMachine;
+ protected Supplier<GT_Recipe_Map> recipeMapSupplier;
+ protected GT_Recipe lastRecipe;
protected ItemStack[] inputItems;
protected ItemStack[] outputItems;
protected ItemStack[] currentOutputItems;
protected FluidStack[] inputFluids;
protected FluidStack[] outputFluids;
protected FluidStack[] currentOutputFluids;
- protected long eut;
- protected long duration;
+ protected long calculatedEut;
+ protected int duration;
+ protected long availableVoltage;
+ protected long availableAmperage;
+ protected int overClockTimeReduction = 1;
+ protected int overClockPowerIncrease = 2;
+ protected boolean protectItems;
+ protected boolean protectFluids;
+ protected boolean isRecipeLocked;
+ protected int maxParallel = 1;
+ protected int calculatedParallels = 0;
+ protected Supplier<Integer> maxParallelSupplier;
+ protected int batchSize = 1;
public ProcessingLogic() {}
+ // region Setters
+
public ProcessingLogic setInputItems(ItemStack... itemInputs) {
this.inputItems = itemInputs;
return this;
}
+ public ProcessingLogic setInputItems(List<ItemStack> itemOutputs) {
+ this.inputItems = itemOutputs.toArray(new ItemStack[0]);
+ return this;
+ }
+
public ProcessingLogic setInputFluids(FluidStack... fluidInputs) {
this.inputFluids = fluidInputs;
return this;
}
+ public ProcessingLogic setInputFluids(List<FluidStack> fluidInputs) {
+ this.inputFluids = fluidInputs.toArray(new FluidStack[0]);
+ return this;
+ }
+
+ /**
+ * Overwrites item output result of the calculation.
+ */
public ProcessingLogic setOutputItems(ItemStack... itemOutputs) {
this.outputItems = itemOutputs;
return this;
}
+ /**
+ * Overwrites fluid output result of the calculation.
+ */
public ProcessingLogic setOutputFluids(FluidStack... fluidOutputs) {
this.outputFluids = fluidOutputs;
return this;
@@ -49,35 +99,263 @@ public abstract class ProcessingLogic {
return this;
}
+ /**
+ * Enables single recipe locking mode.
+ */
+ public ProcessingLogic setRecipeLocking(IRecipeLockable recipeLockableMachine, boolean isRecipeLocked) {
+ this.recipeLockableMachine = recipeLockableMachine;
+ this.isRecipeLocked = isRecipeLocked;
+ return this;
+ }
+
+ /**
+ * Sets max amount of parallel.
+ */
+ public ProcessingLogic setMaxParallel(int maxParallel) {
+ this.maxParallel = maxParallel;
+ return this;
+ }
+
+ /**
+ * Sets method to get max amount of parallel.
+ */
+ public ProcessingLogic setMaxParallelSupplier(Supplier<Integer> supplier) {
+ this.maxParallelSupplier = supplier;
+ return this;
+ }
+
+ /**
+ * Sets batch size for batch mode.
+ */
+ public ProcessingLogic setBatchSize(int size) {
+ this.batchSize = size;
+ return this;
+ }
+
public ProcessingLogic setRecipeMap(GT_Recipe_Map recipeMap) {
- this.recipeMap = recipeMap;
+ return setRecipeMapSupplier(() -> recipeMap);
+ }
+
+ public ProcessingLogic setRecipeMapSupplier(Supplier<GT_Recipe_Map> supplier) {
+ this.recipeMapSupplier = supplier;
+ return this;
+ }
+
+ /**
+ * Sets machine used for void protection logic.
+ */
+ public ProcessingLogic setMachine(IVoidable machine) {
+ this.machine = machine;
return this;
}
- public ProcessingLogic setDuration(long duration) {
+ /**
+ * Overwrites duration result of the calculation.
+ */
+ public ProcessingLogic setDuration(int duration) {
this.duration = duration;
return this;
}
- public ProcessingLogic setEut(long eut) {
- this.eut = eut;
+ /**
+ * Overwrites EU/t result of the calculation.
+ */
+ public ProcessingLogic setCalculatedEut(long calculatedEut) {
+ this.calculatedEut = calculatedEut;
+ return this;
+ }
+
+ /**
+ * Sets voltage of the machine. It doesn't need to be actual voltage (excluding amperage) of the machine;
+ * For example, most of the multiblock machines set maximum possible input power (including amperage) as voltage
+ * and 1 as amperage. That way recipemap search will be executed with overclocked voltage.
+ */
+ public ProcessingLogic setAvailableVoltage(long voltage) {
+ availableVoltage = voltage;
+ return this;
+ }
+
+ /**
+ * Sets amperage of the machine. This amperage doesn't involve in EU/t when searching recipemap.
+ * Useful for preventing tier skip but still considering amperage for parallel.
+ */
+ public ProcessingLogic setAvailableAmperage(long amperage) {
+ availableAmperage = amperage;
return this;
}
+ public ProcessingLogic setVoidProtection(boolean protectItems, boolean protectFluids) {
+ this.protectItems = protectItems;
+ this.protectFluids = protectFluids;
+ return this;
+ }
+
+ /**
+ * Sets custom overclock ratio. 2/4 by default.
+ * Parameters represent number of bit shift, so 1 -> 2x, 2 -> 4x.
+ */
+ public ProcessingLogic setOverclock(int timeReduction, int powerIncrease) {
+ this.overClockTimeReduction = timeReduction;
+ this.overClockPowerIncrease = powerIncrease;
+ return this;
+ }
+
+ /**
+ * Sets overclock ratio to 4/4.
+ */
+ public ProcessingLogic enablePerfectOverclock() {
+ return this.setOverclock(2, 2);
+ }
+
/**
- * Clears everything stored in the Processing Logic other than the Recipe map used
+ * Clears calculated results and provided machine inputs to prepare for the next machine operation.
*/
public ProcessingLogic clear() {
this.inputItems = null;
this.inputFluids = null;
this.outputItems = null;
this.outputFluids = null;
- this.eut = 0;
+ this.calculatedEut = 0;
this.duration = 0;
+ this.calculatedParallels = 0;
return this;
}
- public abstract boolean process();
+ // endregion
+
+ // region Logic
+
+ /**
+ * Executes the recipe check: Find recipe from recipemap, Calculate parallel, overclock and outputs.
+ */
+ @Nonnull
+ public CheckRecipeResult process() {
+ if (recipeMapSupplier == null) return CheckRecipeResultRegistry.NO_RECIPE;
+
+ GT_Recipe_Map recipeMap = recipeMapSupplier.get();
+ if (recipeMap == null) return CheckRecipeResultRegistry.NO_RECIPE;
+
+ if (maxParallelSupplier != null) {
+ 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();
+ // Validate recipe here, otherwise machine will show "not enough output space"
+ // even if recipe cannot be found
+ if (singleRecipeCheck.checkRecipeInputs(false, 1, inputItems, inputFluids) == 0) {
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+ findRecipeResult = FindRecipeResult.ofSuccess(
+ recipeLockableMachine.getSingleRecipeCheck()
+ .getRecipe());
+ } else {
+ findRecipeResult = recipeMap
+ .findRecipeWithResult(lastRecipe, false, false, availableVoltage, inputFluids, null, inputItems);
+ }
+
+ GT_Recipe recipe;
+ if (findRecipeResult.isSuccessful()) {
+ recipe = findRecipeResult.getRecipeNonNull();
+ CheckRecipeResult result = validateRecipe(recipe);
+ if (!result.wasSuccessful()) {
+ return result;
+ } else {
+ lastRecipe = recipe;
+ }
+ } else {
+ if (findRecipeResult.getState() == FindRecipeResult.State.INSUFFICIENT_VOLTAGE) {
+ return CheckRecipeResultRegistry.insufficientPower(findRecipeResult.getRecipeNonNull().mEUt);
+ } else {
+ return CheckRecipeResultRegistry.NO_RECIPE;
+ }
+ }
+
+ GT_ParallelHelper helper = createParallelHelper(recipe);
+
+ helper.build();
+
+ if (helper.getCurrentParallel() <= 0) return CheckRecipeResultRegistry.OUTPUT_FULL;
+
+ calculatedParallels = helper.getCurrentParallel();
+
+ GT_OverclockCalculator calculator = createOverclockCalculator(recipe, helper);
+
+ calculator.calculate();
+ if (calculator.getConsumption() == Long.MAX_VALUE) {
+ return CheckRecipeResultRegistry.POWER_OVERFLOW;
+ }
+ if (calculator.getDuration() == Integer.MAX_VALUE) {
+ return CheckRecipeResultRegistry.DURATION_OVERFLOW;
+ }
+
+ calculatedEut = calculator.getConsumption();
+
+ double finalDuration = calculateDuration(recipe, helper, calculator);
+ if (finalDuration >= Integer.MAX_VALUE) {
+ return CheckRecipeResultRegistry.DURATION_OVERFLOW;
+ }
+ duration = (int) finalDuration;
+
+ outputItems = helper.getItemOutputs();
+ outputFluids = helper.getFluidOutputs();
+
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ /**
+ * Override to tweak final duration that will be set as a result of this logic class.
+ */
+ protected double calculateDuration(@Nonnull GT_Recipe recipe, @Nonnull GT_ParallelHelper helper,
+ @Nonnull GT_OverclockCalculator calculator) {
+ return calculator.getDuration() * helper.getDurationMultiplierDouble();
+ }
+
+ /**
+ * Override to tweak parallel logic if needed.
+ */
+ @Nonnull
+ protected GT_ParallelHelper createParallelHelper(@Nonnull GT_Recipe recipe) {
+ return new GT_ParallelHelper().setRecipe(recipe)
+ .setItemInputs(inputItems)
+ .setFluidInputs(inputFluids)
+ .setAvailableEUt(availableVoltage * availableAmperage)
+ .setMachine(machine, protectItems, protectFluids)
+ .setRecipeLocked(recipeLockableMachine, isRecipeLocked)
+ .setMaxParallel(maxParallel)
+ .enableBatchMode(batchSize)
+ .enableConsumption()
+ .enableOutputCalculation();
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Override to tweak overclock logic if needed.
+ */
+ @Nonnull
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe,
+ @Nonnull GT_ParallelHelper helper) {
+ return new GT_OverclockCalculator().setRecipeEUt(recipe.mEUt)
+ .setParallel((int) Math.floor(helper.getCurrentParallel() / helper.getDurationMultiplierDouble()))
+ .setDuration(recipe.mDuration)
+ .setAmperage(availableAmperage)
+ .setEUt(availableVoltage)
+ .setDurationDecreasePerOC(overClockTimeReduction)
+ .setEUtIncreasePerOC(overClockPowerIncrease);
+ }
+
+ // endregion
+
+ // region Getters
public ItemStack[] getOutputItems() {
return outputItems;
@@ -87,11 +365,13 @@ public abstract class ProcessingLogic {
return outputFluids;
}
- public long getDuration() {
+ public int getDuration() {
return duration;
}
- public long getEut() {
- return eut;
+ public long getCalculatedEut() {
+ return calculatedEut;
}
+
+ // endregion
}
diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
index a23fbd8a85..72ca9f9124 100644
--- a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
@@ -595,6 +595,12 @@ public class BaseMetaTileEntity extends CommonMetaTileEntity
} catch (Throwable e) {
e.printStackTrace();
e.printStackTrace(GT_Log.err);
+ try {
+ mMetaTileEntity.onTickFail(this, mTickTimer);
+ } catch (Throwable ex) {
+ ex.printStackTrace();
+ ex.printStackTrace(GT_Log.err);
+ }
}
if (aSideServer && hasValidMetaTileEntity()) {
@@ -1020,6 +1026,9 @@ public class BaseMetaTileEntity extends CommonMetaTileEntity
@Override
public void disableWorking() {
mWorks = false;
+ if (hasValidMetaTileEntity()) {
+ mMetaTileEntity.onDisableWorking();
+ }
}
@Override
@@ -1060,6 +1069,9 @@ public class BaseMetaTileEntity extends CommonMetaTileEntity
@Override
public void setActive(boolean aActive) {
mActive = aActive;
+ if (hasValidMetaTileEntity()) {
+ mMetaTileEntity.onSetActive(aActive);
+ }
}
@Override
diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java
index 453849923d..1ac42a2ea1 100644
--- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java
@@ -319,6 +319,12 @@ public abstract class MetaTileEntity implements IMetaTileEntity, ICleanroomRecei
}
}
+ public void onTickFail(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {}
+
+ public void onSetActive(boolean active) {}
+
+ public void onDisableWorking() {}
+
@Override
public void inValidate() {
/* Do nothing */
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java
index f251b5c02f..ac037b7919 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_BasicMachine.java
@@ -69,6 +69,7 @@ import gregtech.api.interfaces.modularui.IAddGregtechLogo;
import gregtech.api.interfaces.modularui.IAddUIWidgets;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.recipe.check.FindRecipeResult;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_ClientPreference;
import gregtech.api.util.GT_CoverBehaviorBase;
@@ -1085,15 +1086,24 @@ public abstract class GT_MetaTileEntity_BasicMachine extends GT_MetaTileEntity_B
public int checkRecipe(boolean skipOC) {
GT_Recipe_Map tMap = getRecipeList();
if (tMap == null) return DID_NOT_FIND_RECIPE;
- GT_Recipe tRecipe = tMap.findRecipe(
- getBaseMetaTileEntity(),
+ FindRecipeResult result = tMap.findRecipeWithResult(
mLastRecipe,
false,
+ false,
V[mTier],
new FluidStack[] { getFillableStack() },
getSpecialSlot(),
getAllInputs());
- if (tRecipe == null) return DID_NOT_FIND_RECIPE;
+ if (result.getState() == FindRecipeResult.State.EXPLODE && getBaseMetaTileEntity() != null) {
+ getBaseMetaTileEntity().doExplosion(V[mTier] * 4);
+ return DID_NOT_FIND_RECIPE;
+ }
+ if (result.getState() == FindRecipeResult.State.ON_FIRE && getBaseMetaTileEntity() != null) {
+ getBaseMetaTileEntity().setOnFire();
+ return DID_NOT_FIND_RECIPE;
+ }
+ if (!result.isSuccessful()) return DID_NOT_FIND_RECIPE;
+ GT_Recipe tRecipe = result.getRecipeNonNull();
if (GT_Mod.gregtechproxy.mLowGravProcessing && (tRecipe.mSpecialValue == -100 || tRecipe.mSpecialValue == -300)
&& !isValidForLowGravity(tRecipe, getBaseMetaTileEntity().getWorld().provider.dimensionId))
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java
index 47dd69ba6c..ef3f587c01 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ExtendedPowerMultiBlockBase.java
@@ -5,6 +5,8 @@ import static gregtech.api.enums.GT_Values.VN;
import java.util.ArrayList;
import java.util.List;
+import javax.annotation.Nonnull;
+
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -14,6 +16,9 @@ import net.minecraft.util.StatCollector;
import net.minecraft.world.World;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.util.GT_ExoticEnergyInputHelper;
import gregtech.api.util.GT_Utility;
@@ -127,6 +132,70 @@ public abstract class GT_MetaTileEntity_ExtendedPowerMultiBlockBase<T extends GT
}
@Override
+ public @Nonnull CheckRecipeResult checkProcessing() {
+ // If no logic is found, try legacy checkRecipe
+ if (processingLogic == null) {
+ // noinspection deprecation
+ return checkRecipe(mInventory[1]) ? CheckRecipeResultRegistry.SUCCESSFUL
+ : CheckRecipeResultRegistry.NO_RECIPE;
+ }
+
+ CheckRecipeResult result = CheckRecipeResultRegistry.NO_RECIPE;
+
+ processingLogic.clear();
+ processingLogic.setMachine(this);
+ processingLogic.setRecipeMapSupplier(this::getRecipeMap);
+ processingLogic.setVoidProtection(protectsExcessItem(), protectsExcessFluid());
+ processingLogic.setBatchSize(isBatchModeEnabled() ? getMaxBatchSize() : 1);
+ processingLogic.setRecipeLocking(this, isRecipeLockingEnabled());
+ processingLogic.setInputFluids(getStoredFluids());
+ setProcessingLogicPower(processingLogic);
+ if (isInputSeparationEnabled()) {
+ for (GT_MetaTileEntity_Hatch_InputBus bus : mInputBusses) {
+ List<ItemStack> inputItems = new ArrayList<>();
+ for (int i = bus.getSizeInventory() - 1; i >= 0; i--) {
+ ItemStack stored = bus.getStackInSlot(i);
+ if (stored != null) {
+ inputItems.add(stored);
+ }
+ }
+ processingLogic.setInputItems(inputItems.toArray(new ItemStack[0]));
+ result = processingLogic.process();
+ if (result.wasSuccessful()) break;
+ }
+ } else {
+ processingLogic.setInputItems(getStoredInputs());
+ result = processingLogic.process();
+ }
+
+ // inputs are consumed by `process()`
+ updateSlots();
+
+ if (!result.wasSuccessful()) return result;
+
+ mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
+ mEfficiencyIncrease = 10000;
+
+ lEUt = processingLogic.getCalculatedEut();
+ mMaxProgresstime = processingLogic.getDuration();
+
+ if (lEUt > 0) {
+ lEUt = (-lEUt);
+ }
+
+ mOutputItems = processingLogic.getOutputItems();
+ mOutputFluids = processingLogic.getOutputFluids();
+
+ return result;
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(GT_Utility.roundDownVoltage(getAverageInputVoltage()));
+ logic.setAvailableAmperage(getMaxInputAmps());
+ }
+
+ @Override
public String[] getInfoData() {
int mPollutionReduction = 0;
for (GT_MetaTileEntity_Hatch_Muffler tHatch : mMufflerHatches) {
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
index 1c93779f01..0d383bc768 100644
--- a/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
+++ b/src/main/java/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_MultiBlockBase.java
@@ -30,10 +30,12 @@ import net.minecraftforge.common.util.Constants;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.TestOnly;
import org.lwjgl.input.Keyboard;
import com.google.common.collect.Iterables;
+import com.gtnewhorizons.modularui.api.math.Alignment;
import com.gtnewhorizons.modularui.api.math.Pos2d;
import com.gtnewhorizons.modularui.api.screen.ModularWindow;
import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
@@ -60,26 +62,28 @@ import gregtech.api.interfaces.modularui.IAddUIWidgets;
import gregtech.api.interfaces.modularui.IBindPlayerInventoryUI;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.MetaTileEntity;
import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SingleRecipeCheck;
import gregtech.api.util.GT_ExoticEnergyInputHelper;
import gregtech.api.util.GT_Log;
-import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_Recipe;
import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
-import gregtech.api.util.GT_Single_Recipe_Check;
import gregtech.api.util.GT_Utility;
import gregtech.api.util.GT_Waila;
import gregtech.api.util.OutputHatchWrapper;
import gregtech.api.util.VoidProtectionHelper;
import gregtech.client.GT_SoundLoop;
import gregtech.common.GT_Pollution;
+import gregtech.common.gui.modularui.widget.CheckRecipeResultSyncer;
import gregtech.common.items.GT_MetaGenerated_Tool_01;
import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_InputBus_ME;
import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_OutputBus_ME;
import gregtech.common.tileentities.machines.GT_MetaTileEntity_Hatch_Output_ME;
-import gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_DrillerBase;
import gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_LargeTurbine;
import mcp.mobius.waila.api.IWailaConfigHandler;
import mcp.mobius.waila.api.IWailaDataAccessor;
@@ -105,11 +109,14 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
protected boolean inputSeparation = getDefaultInputSeparationMode();
protected VoidingMode voidingMode = getDefaultVoidingMode();
protected boolean batchMode = getDefaultBatchMode();
+ private @Nonnull CheckRecipeResult checkRecipeResult = CheckRecipeResultRegistry.NONE;
+ private boolean isScheduledForResetCheckRecipeResult;
+
protected static final String INPUT_SEPARATION_NBT_KEY = "inputSeparation";
protected static final String VOID_EXCESS_NBT_KEY = "voidExcess";
protected static final String VOIDING_MODE_NBT_KEY = "voidingMode";
protected static final String BATCH_MODE_NBT_KEY = "batchMode";
- public GT_Single_Recipe_Check mSingleRecipeCheck = null;
+ protected SingleRecipeCheck mSingleRecipeCheck = null;
public ArrayList<GT_MetaTileEntity_Hatch_Input> mInputHatches = new ArrayList<>();
public ArrayList<GT_MetaTileEntity_Hatch_Output> mOutputHatches = new ArrayList<>();
@@ -120,6 +127,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
public ArrayList<GT_MetaTileEntity_Hatch_Energy> mEnergyHatches = new ArrayList<>();
public ArrayList<GT_MetaTileEntity_Hatch_Maintenance> mMaintenanceHatches = new ArrayList<>();
protected List<GT_MetaTileEntity_Hatch> mExoticEnergyHatches = new ArrayList<>();
+ protected final ProcessingLogic processingLogic;
@SideOnly(Side.CLIENT)
protected GT_SoundLoop activitySoundLoop;
@@ -130,6 +138,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
public GT_MetaTileEntity_MultiBlockBase(int aID, String aName, String aNameRegional) {
super(aID, aName, aNameRegional, 2);
+ this.processingLogic = null;
GT_MetaTileEntity_MultiBlockBase.disableMaintenance = GregTech_API.sMachineFile
.get(ConfigCategories.machineconfig, "MultiBlockMachines.disableMaintenance", false);
this.damageFactorLow = GregTech_API.sMachineFile
@@ -141,6 +150,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
public GT_MetaTileEntity_MultiBlockBase(String aName) {
super(aName, 2);
+ this.processingLogic = createProcessingLogic();
GT_MetaTileEntity_MultiBlockBase.disableMaintenance = GregTech_API.sMachineFile
.get(ConfigCategories.machineconfig, "MultiBlockMachines.disableMaintenance", false);
this.damageFactorLow = GregTech_API.sMachineFile
@@ -273,7 +283,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
if (supportsSingleRecipeLocking()) {
mLockedToSingleRecipe = aNBT.getBoolean("mLockedToSingleRecipe");
if (mLockedToSingleRecipe && aNBT.hasKey("mSingleRecipeCheck", Constants.NBT.TAG_COMPOUND)) {
- GT_Single_Recipe_Check c = loadSingleRecipeChecker(aNBT.getCompoundTag("mSingleRecipeCheck"));
+ SingleRecipeCheck c = loadSingleRecipeChecker(aNBT.getCompoundTag("mSingleRecipeCheck"));
if (c != null) mSingleRecipeCheck = c;
// the old recipe is gone. we disable the machine to prevent making garbage in case of shared inputs
// maybe use a better way to inform player in the future.
@@ -311,8 +321,8 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
mCrowbar = aNBT.getBoolean("mCrowbar");
}
- protected GT_Single_Recipe_Check loadSingleRecipeChecker(NBTTagCompound aNBT) {
- return GT_Single_Recipe_Check.tryLoad(this, aNBT);
+ protected SingleRecipeCheck loadSingleRecipeChecker(NBTTagCompound aNBT) {
+ return SingleRecipeCheck.tryLoad(getRecipeMap(), aNBT);
}
@Override
@@ -411,6 +421,17 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
}
}
+ @Override
+ public void onTickFail(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onTickFail(aBaseMetaTileEntity, aTick);
+ if (aBaseMetaTileEntity.isServerSide()) {
+ aBaseMetaTileEntity.disableWorking();
+ checkRecipeResult = CheckRecipeResultRegistry.CRASH;
+ // Don't let `onSetActive` to overwrite
+ isScheduledForResetCheckRecipeResult = false;
+ }
+ }
+
private void checkMaintenance() {
if (disableMaintenance) {
mWrench = true;
@@ -444,14 +465,26 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
}
}
- protected boolean checkRecipe() {
+ /**
+ * Starts checking recipe with some operations needed to actually run the check. Overriding this without due care
+ * may result in dupe of items, hence it's marked as final.
+ * <p>
+ * See {@link #createProcessingLogic()} or {@link #checkProcessing()} for what you want to override.
+ *
+ * @return If successfully found recipe and/or started processing
+ */
+ protected final boolean checkRecipe() {
startRecipeProcessing();
- boolean result = checkRecipe(mInventory[1]);
- if (result && getProcessStartSound() != null) {
- sendLoopStart(PROCESS_START_SOUND_INDEX);
+ CheckRecipeResult result = checkProcessing();
+ if (!CheckRecipeResultRegistry.isRegistered(result.getID())) {
+ throw new RuntimeException(String.format("Result %s is not registered for registry", result.getID()));
+ }
+ if (result.wasSuccessful()) {
+ sendStartMultiBlockSoundLoop();
}
+ this.checkRecipeResult = result;
endRecipeProcessing();
- return result;
+ return result.wasSuccessful();
}
private boolean shouldCheckRecipeThisTick(long aTick) {
@@ -544,6 +577,12 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
return mPollution < 10000;
}
+ protected void sendStartMultiBlockSoundLoop() {
+ if (getProcessStartSound() != null) {
+ sendLoopStart(PROCESS_START_SOUND_INDEX);
+ }
+ }
+
@Override
public void doSound(byte aIndex, double aX, double aY, double aZ) {
super.doSound(aIndex, aX, aY, aZ);
@@ -631,9 +670,86 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
public abstract boolean isCorrectMachinePart(ItemStack aStack);
/**
- * Checks the Recipe
+ * @deprecated Use {@link #createProcessingLogic()} or {@link #checkProcessing()}
+ */
+ @Deprecated
+ public boolean checkRecipe(ItemStack aStack) {
+ return false;
+ }
+
+ /**
+ * Checks recipe and setup machine if it's successful.
+ * <p>
+ * For generic machine working with recipemap, use {@link #createProcessingLogic()} to make use of shared codebase.
*/
- public abstract boolean checkRecipe(ItemStack aStack);
+ @Nonnull
+ public CheckRecipeResult checkProcessing() {
+ // If no logic is found, try legacy checkRecipe
+ if (processingLogic == null) {
+ return checkRecipe(mInventory[1]) ? CheckRecipeResultRegistry.SUCCESSFUL
+ : CheckRecipeResultRegistry.NO_RECIPE;
+ }
+
+ CheckRecipeResult result = CheckRecipeResultRegistry.NO_RECIPE;
+
+ processingLogic.clear();
+ processingLogic.setMachine(this);
+ processingLogic.setRecipeMapSupplier(this::getRecipeMap);
+ processingLogic.setVoidProtection(protectsExcessItem(), protectsExcessFluid());
+ processingLogic.setBatchSize(isBatchModeEnabled() ? getMaxBatchSize() : 1);
+ processingLogic.setRecipeLocking(this, isRecipeLockingEnabled());
+ processingLogic.setInputFluids(getStoredFluids());
+ setProcessingLogicPower(processingLogic);
+ if (isInputSeparationEnabled()) {
+ for (GT_MetaTileEntity_Hatch_InputBus bus : mInputBusses) {
+ List<ItemStack> inputItems = new ArrayList<>();
+ for (int i = bus.getSizeInventory() - 1; i >= 0; i--) {
+ ItemStack stored = bus.getStackInSlot(i);
+ if (stored != null) {
+ inputItems.add(stored);
+ }
+ }
+ processingLogic.setInputItems(inputItems.toArray(new ItemStack[0]));
+ result = processingLogic.process();
+ if (result.wasSuccessful()) break;
+ }
+ } else {
+ processingLogic.setInputItems(getStoredInputs());
+ result = processingLogic.process();
+ }
+
+ // inputs are consumed by `process()`
+ updateSlots();
+
+ if (!result.wasSuccessful()) return result;
+
+ mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
+ mEfficiencyIncrease = 10000;
+
+ if (processingLogic.getCalculatedEut() > Integer.MAX_VALUE) {
+ return CheckRecipeResultRegistry.POWER_OVERFLOW;
+ }
+ mEUt = (int) processingLogic.getCalculatedEut();
+ mMaxProgresstime = processingLogic.getDuration();
+
+ if (mEUt > 0) {
+ mEUt = (-mEUt);
+ }
+
+ mOutputItems = processingLogic.getOutputItems();
+ mOutputFluids = processingLogic.getOutputFluids();
+
+ return result;
+ }
+
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(GT_Utility.roundDownVoltage(getMaxInputVoltage()));
+ logic.setAvailableAmperage(1);
+ }
+
+ protected int getMaxBatchSize() {
+ return 128;
+ }
/**
* Checks the Machine. You have to assign the MetaTileEntities for the Hatches here.
@@ -678,6 +794,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
mMaxProgresstime = 0;
mEfficiencyIncrease = 0;
getBaseMetaTileEntity().disableWorking();
+ checkRecipeResult = CheckRecipeResultRegistry.NONE;
}
public void criticalStopMachine() {
@@ -839,6 +956,9 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
return injected > 0;
}
+ /**
+ * Sums up voltage of energy hatches. Amperage does not matter.
+ */
public long getMaxInputVoltage() {
long rVoltage = 0;
for (GT_MetaTileEntity_Hatch_Energy tHatch : mEnergyHatches)
@@ -847,6 +967,21 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
return rVoltage;
}
+ /**
+ * Sums up max input EU/t of energy hatches, amperage included.
+ */
+ public long getMaxInputPower() {
+ long eut = 0;
+ for (GT_MetaTileEntity_Hatch_Energy tHatch : mEnergyHatches) if (isValidMetaTileEntity(tHatch)) {
+ IGregTechTileEntity baseTile = tHatch.getBaseMetaTileEntity();
+ eut += baseTile.getInputVoltage() * baseTile.getInputAmperage();
+ }
+ return eut;
+ }
+
+ /**
+ * Returns voltage tier of energy hatches. If multiple tiers are found, returns 0.
+ */
public long getInputVoltageTier() {
long rTier = 0;
if (mEnergyHatches.size() > 0) {
@@ -1130,10 +1265,21 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
return rList;
}
+ @Override
public GT_Recipe_Map getRecipeMap() {
return null;
}
+ /**
+ * Creates logic to run recipe check based on recipemap. This runs only once, on class instantiation.
+ * <p>
+ * If this machine doesn't use recipemap or does some complex things, override {@link #checkProcessing()}.
+ */
+ @ApiStatus.OverrideOnly
+ protected ProcessingLogic createProcessingLogic() {
+ return null;
+ }
+
public void updateSlots() {
for (GT_MetaTileEntity_Hatch_Input tHatch : mInputHatches)
if (isValidMetaTileEntity(tHatch)) tHatch.updateSlots();
@@ -1523,6 +1669,20 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
}
}
+ @Override
+ public void onSetActive(boolean active) {
+ if (isScheduledForResetCheckRecipeResult && !active) {
+ checkRecipeResult = CheckRecipeResultRegistry.NONE;
+ isScheduledForResetCheckRecipeResult = false;
+ }
+ }
+
+ @Override
+ public void onDisableWorking() {
+ // This prevents deleting result instantly when turning off machine
+ isScheduledForResetCheckRecipeResult = true;
+ }
+
protected void setMufflers(boolean state) {
for (GT_MetaTileEntity_Hatch_Muffler aMuffler : mMufflerHatches) {
final IGregTechTileEntity iGTTileEntity = aMuffler.getBaseMetaTileEntity();
@@ -1614,17 +1774,25 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
@Override
public boolean isAllowedToWork() {
- return getBaseMetaTileEntity().isAllowedToWork();
+ return getBaseMetaTileEntity() != null && getBaseMetaTileEntity().isAllowedToWork();
}
@Override
public void disableWorking() {
- getBaseMetaTileEntity().disableWorking();
+ if (getBaseMetaTileEntity() != null) {
+ getBaseMetaTileEntity().disableWorking();
+ }
}
@Override
public void enableWorking() {
- getBaseMetaTileEntity().enableWorking();
+ if (getBaseMetaTileEntity() != null) {
+ getBaseMetaTileEntity().enableWorking();
+ }
+ }
+
+ public ItemStack getControllerSlot() {
+ return mInventory[1];
}
@Override
@@ -1764,7 +1932,20 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
@Override
public void setRecipeLocking(boolean enabled) {
- this.mLockedToSingleRecipe = enabled;
+ mLockedToSingleRecipe = enabled;
+ if (!enabled) {
+ setSingleRecipeCheck(null);
+ }
+ }
+
+ @Override
+ public void setSingleRecipeCheck(SingleRecipeCheck recipeCheck) {
+ mSingleRecipeCheck = recipeCheck;
+ }
+
+ @Override
+ public SingleRecipeCheck getSingleRecipeCheck() {
+ return mSingleRecipeCheck;
}
@Override
@@ -1889,22 +2070,17 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity
new TextWidget(GT_Utility.trans("142", "Running perfectly.")).setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(
widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0 && getBaseMetaTileEntity().isActive()));
-
screenElements.widget(
- new TextWidget(GT_Utility.trans("143", "Missing Mining Pipe")).setDefaultColor(COLOR_TEXT_WHITE.get())
- .setEnabled(widget -> {
- if (getBaseMetaTileEntity().getErrorDisplayID() == 0
- && this instanceof GT_MetaTileEntity_DrillerBase) {
- final ItemStack tItem = inventorySlot.getMcSlot()
- .getStack();
- return tItem == null
- || !GT_Utility.areStacksEqual(tItem, GT_ModHandler.getIC2Item("miningPipe", 1L));
- }
- return false;
- }));
+ TextWidget.dynamicString(() -> checkRecipeResult.getDisplayString())
+ .setSynced(false)
+ .setTextAlignment(Alignment.CenterLeft)
+ .setEnabled(widget -> GT_Utility.isStringValid(checkRecipeResult.getDisplayString())))
+ .widget(new CheckRecipeResultSyncer(() -> checkRecipeResult, (result) -> checkRecipeResult = result));
+
screenElements.widget(
new TextWidget(GT_Utility.trans("144", "Missing Turbine Rotor")).setDefaultColor(COLOR_TEXT_WHITE.get())
.setEnabled(widget -> {
+ if (getBaseMetaTileEntity().isAllowedToWork()) return false;
if (getBaseMetaTileEntity().getErrorDisplayID() == 0
&& this instanceof GT_MetaTileEntity_LargeTurbine) {
final ItemStack tItem = inventorySlot.getMcSlot()
diff --git a/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java b/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java
index 61adafce13..b8ac727a91 100644
--- a/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java
+++ b/src/main/java/gregtech/api/multitileentity/machine/MultiTileBasicMachine.java
@@ -42,6 +42,7 @@ import gregtech.api.multitileentity.MultiTileEntityRegistry;
import gregtech.api.multitileentity.base.TickableMultiTileEntity;
import gregtech.api.multitileentity.interfaces.IMultiTileMachine;
import gregtech.api.net.GT_Packet_MultiTileEntity;
+import gregtech.api.recipe.check.CheckRecipeResult;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Utility;
import gregtech.client.GT_SoundLoop;
@@ -539,17 +540,17 @@ public abstract class MultiTileBasicMachine extends TickableMultiTileEntity impl
}
ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic();
logic.clear();
- boolean result = logic.setInputItems(getInputItems())
+ CheckRecipeResult result = logic.setInputItems(getInputItems())
.setInputFluids(getInputFluids())
.setCurrentOutputItems(
outputInventory.getStacks()
.toArray(new ItemStack[0]))
.process();
setDuration(logic.getDuration());
- setEut(logic.getEut());
+ setEut(logic.getCalculatedEut());
setItemOutputs(logic.getOutputItems());
setFluidOutputs(logic.getOutputFluids());
- return result;
+ return result.wasSuccessful();
}
/**
diff --git a/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java
index b96a822e4b..cdefa21e71 100644
--- a/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java
+++ b/src/main/java/gregtech/api/multitileentity/multiblock/base/Controller.java
@@ -95,7 +95,10 @@ import gregtech.api.multitileentity.machine.MultiTileBasicMachine;
import gregtech.api.multitileentity.multiblock.casing.FunctionalCasing;
import gregtech.api.multitileentity.multiblock.casing.UpgradeCasing;
import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe;
import gregtech.api.util.GT_Utility;
import gregtech.api.util.GT_Waila;
import gregtech.common.tileentities.casings.upgrade.Inventory;
@@ -1675,7 +1678,7 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
ProcessingLogic logic = ((ProcessingLogicHost) this).getProcessingLogic();
logic.clear();
- boolean result = false;
+ CheckRecipeResult result = CheckRecipeResultRegistry.NO_RECIPE;
if (isSeparateInputs()) {
// TODO: Add separation with fluids
for (Pair<ItemStack[], String> inventory : getItemInputsForEachInventory()) {
@@ -1684,7 +1687,7 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
result = logic.setInputItems(inventory.getLeft())
.setCurrentOutputItems(getOutputItems())
.process();
- if (result) {
+ if (result.wasSuccessful()) {
inventoryName = inventory.getRight();
break;
}
@@ -1698,10 +1701,10 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
.process();
}
setDuration(logic.getDuration());
- setEut(logic.getEut());
+ setEut(logic.getCalculatedEut());
setItemOutputs(logic.getOutputItems());
setFluidOutputs(logic.getOutputFluids());
- return result;
+ return result.wasSuccessful();
}
public IItemHandlerModifiable getOutputInventory() {
@@ -2067,6 +2070,11 @@ public abstract class Controller<T extends Controller<T>> extends MultiTileBasic
}
@Override
+ public GT_Recipe.GT_Recipe_Map getRecipeMap() {
+ return null;
+ }
+
+ @Override
public Pos2d getRecipeLockingButtonPos() {
return new Pos2d(0, 0);
}
diff --git a/src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java b/src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java
new file mode 100644
index 0000000000..ab1db6ecd2
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/check/CheckRecipeResult.java
@@ -0,0 +1,42 @@
+package gregtech.api.recipe.check;
+
+import net.minecraft.network.PacketBuffer;
+
+/**
+ * Class to indicate the result of recipe check in the machine. It doesn't need to be actual result of recipemap check,
+ * but can also be status of whether to start the machine. Examples can be found at {@link CheckRecipeResultRegistry}.
+ * <p>
+ * Sample instance must be registered to {@link CheckRecipeResultRegistry}.
+ */
+public interface CheckRecipeResult {
+
+ /**
+ * @return Unique registry ID
+ */
+ String getID();
+
+ /**
+ * @return If recipe check is successful
+ */
+ boolean wasSuccessful();
+
+ /**
+ * @return Actual text to show on client GUI
+ */
+ String getDisplayString();
+
+ /**
+ * Create new instance to receive packet.
+ */
+ CheckRecipeResult newInstance();
+
+ /**
+ * Encode value to sync.
+ */
+ void encode(PacketBuffer buffer);
+
+ /**
+ * Decode synced value.
+ */
+ void decode(PacketBuffer buffer);
+}
diff --git a/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java b/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java
new file mode 100644
index 0000000000..26f9dedd7d
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/check/CheckRecipeResultRegistry.java
@@ -0,0 +1,111 @@
+package gregtech.api.recipe.check;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public final class CheckRecipeResultRegistry {
+
+ private static final Map<String, CheckRecipeResult> registry = new HashMap<>();
+
+ /**
+ * Registers CheckRecipeResult. No duplicated IDs are allowed.
+ *
+ * @param sample Sample object to register
+ */
+ public static void register(CheckRecipeResult sample) {
+ if (isRegistered(sample.getID())) {
+ throw new IllegalStateException(
+ String.format(
+ "ID %s is already registered for %s",
+ sample.getID(),
+ registry.get(sample.getID())
+ .getClass()
+ .getCanonicalName()));
+ }
+ registry.put(sample.getID(), sample);
+ }
+
+ public static CheckRecipeResult getSampleFromRegistry(String id) {
+ if (!isRegistered(id)) {
+ throw new RuntimeException("Unknown id: " + id);
+ }
+ return registry.get(id);
+ }
+
+ public static boolean isRegistered(String id) {
+ return registry.containsKey(id);
+ }
+
+ /**
+ * Successfully found recipe.
+ */
+ public static final CheckRecipeResult SUCCESSFUL = SimpleCheckRecipeResult.ofSuccess("success");
+ /**
+ * All requirements met to generator power.
+ */
+ public static final CheckRecipeResult GENERATING = SimpleCheckRecipeResult.ofSuccess("generating");
+ /**
+ * Cannot find recipe.
+ */
+ public static final CheckRecipeResult NO_RECIPE = SimpleCheckRecipeResult.ofFailure("no_recipe");
+ /**
+ * Cannot process recipe because output is full.
+ */
+ public static final CheckRecipeResult OUTPUT_FULL = SimpleCheckRecipeResult.ofFailure("output_full");
+ /**
+ * Default unknown state.
+ */
+ public static final CheckRecipeResult NONE = SimpleCheckRecipeResult.ofFailure("none");
+ /**
+ * Code crashed.
+ */
+ public static final CheckRecipeResult CRASH = SimpleCheckRecipeResult.ofFailure("crash");
+ /**
+ * Cannot find valid fuel for generator.
+ */
+ public static final CheckRecipeResult NO_FUEL_FOUND = SimpleCheckRecipeResult.ofFailure("no_fuel");
+ /**
+ * Cannot find valid turbine.
+ */
+ public static final CheckRecipeResult NO_TURBINE_FOUND = SimpleCheckRecipeResult.ofFailure("no_turbine");
+ /**
+ * No data sticks found for Assembly Line.
+ */
+ public static final CheckRecipeResult NO_DATA_STICKS = SimpleCheckRecipeResult.ofFailure("no_data_sticks");
+ /**
+ * EU/t overflowed.
+ */
+ public static final CheckRecipeResult POWER_OVERFLOW = SimpleCheckRecipeResult.ofFailure("power_overflow");
+ /**
+ * Progress time overflowed.
+ */
+ public static final CheckRecipeResult DURATION_OVERFLOW = SimpleCheckRecipeResult.ofFailure("duration_overflow");
+
+ /**
+ * Cannot process recipe because the machine cannot handle required EUt.
+ */
+ public static CheckRecipeResult insufficientPower(long required) {
+ return new ResultInsufficientPower(required);
+ }
+
+ /**
+ * Cannot process recipe because the machine cannot handle its heat.
+ */
+ public static CheckRecipeResult insufficientHeat(int required) {
+ return new ResultInsufficientHeat(required);
+ }
+
+ /**
+ * Cannot process recipe because the machine is tiered and its tier is too low.
+ */
+ public static CheckRecipeResult insufficientMachineTier(int required) {
+ return new ResultInsufficientMachineTier(required);
+ }
+
+ static {
+ register(new SimpleCheckRecipeResult(false, ""));
+ register(new ResultInsufficientPower(0));
+ register(new ResultInsufficientHeat(0));
+ register(new ResultInsufficientMachineTier(0));
+ }
+}
diff --git a/src/main/java/gregtech/api/recipe/check/FindRecipeResult.java b/src/main/java/gregtech/api/recipe/check/FindRecipeResult.java
new file mode 100644
index 0000000000..5791cb05e1
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/check/FindRecipeResult.java
@@ -0,0 +1,107 @@
+package gregtech.api.recipe.check;
+
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import gregtech.api.util.GT_Recipe;
+
+/**
+ * Wrapper class to get result of recipe search for recipemap. Note that this only validates recipe input and voltage,
+ * and does not involve in actual check in the machine such as output space or special value.
+ */
+public class FindRecipeResult {
+
+ @Nonnull
+ private final State state;
+ @Nullable
+ private final GT_Recipe recipe;
+
+ private FindRecipeResult(@Nonnull State state, @Nullable GT_Recipe recipe) {
+ this.state = state;
+ this.recipe = recipe;
+ }
+
+ @Nonnull
+ public State getState() {
+ return state;
+ }
+
+ public boolean isSuccessful() {
+ return state.success;
+ }
+
+ /**
+ * If you already checked {@link #isSuccessful()}, you can use {@link #getRecipeNonNull()} instead.
+ */
+ @Nullable
+ public GT_Recipe getRecipe() {
+ return recipe;
+ }
+
+ /**
+ * You should use this ONLY WHEN state == FOUND or INSUFFICIENT_VOLTAGE.
+ */
+ @Nonnull
+ public GT_Recipe getRecipeNonNull() {
+ return Objects.requireNonNull(recipe);
+ }
+
+ /**
+ * Successfully found recipe.
+ */
+ public static FindRecipeResult ofSuccess(@Nonnull GT_Recipe recipe) {
+ return new FindRecipeResult(State.FOUND, Objects.requireNonNull(recipe));
+ }
+
+ /**
+ * Recipe was found, but voltage is not sufficient to run.
+ */
+ public static FindRecipeResult ofInsufficientVoltage(@Nonnull GT_Recipe recipe) {
+ return new FindRecipeResult(State.INSUFFICIENT_VOLTAGE, Objects.requireNonNull(recipe));
+ }
+
+ /**
+ * No recipe found.
+ */
+ public static final FindRecipeResult NOT_FOUND = new FindRecipeResult(State.NOT_FOUND, null);
+ /**
+ * For Microwave.
+ */
+ public static final FindRecipeResult EXPLODE = new FindRecipeResult(State.EXPLODE, null);
+ /**
+ * For Microwave.
+ */
+ public static final FindRecipeResult ON_FIRE = new FindRecipeResult(State.ON_FIRE, null);
+
+ public enum State {
+
+ /**
+ * Successfully found recipe.
+ */
+ FOUND(true),
+ /**
+ * Recipe was found, but voltage is not sufficient to run.
+ */
+ INSUFFICIENT_VOLTAGE(false),
+ /**
+ * No recipe found.
+ */
+ NOT_FOUND(false),
+ /**
+ * For Microwave.
+ */
+ EXPLODE(false),
+ /**
+ * For Microwave.
+ */
+ ON_FIRE(false);
+
+ private final boolean success;
+
+ State(boolean success) {
+ this.success = success;
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java b/src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java
new file mode 100644
index 0000000000..96c8955130
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/check/ResultInsufficientHeat.java
@@ -0,0 +1,57 @@
+package gregtech.api.recipe.check;
+
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.StatCollector;
+
+import gregtech.api.enums.HeatingCoilLevel;
+import gregtech.api.util.GT_Utility;
+
+public class ResultInsufficientHeat implements CheckRecipeResult {
+
+ private int required;
+
+ ResultInsufficientHeat(int required) {
+ this.required = required;
+ }
+
+ @Override
+ public String getID() {
+ return "insufficient_heat";
+ }
+
+ @Override
+ public boolean wasSuccessful() {
+ return false;
+ }
+
+ @Override
+ public String getDisplayString() {
+ return StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.insufficient_heat",
+ GT_Utility.formatNumbers(required),
+ HeatingCoilLevel.getDisplayNameFromHeat(required, true));
+ }
+
+ @Override
+ public CheckRecipeResult newInstance() {
+ return new ResultInsufficientHeat(0);
+ }
+
+ @Override
+ public void encode(PacketBuffer buffer) {
+ buffer.writeVarIntToBuffer(required);
+ }
+
+ @Override
+ public void decode(PacketBuffer buffer) {
+ required = buffer.readVarIntFromBuffer();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ResultInsufficientHeat that = (ResultInsufficientHeat) o;
+ return required == that.required;
+ }
+}
diff --git a/src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java b/src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java
new file mode 100644
index 0000000000..1e00e791d1
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/check/ResultInsufficientMachineTier.java
@@ -0,0 +1,54 @@
+package gregtech.api.recipe.check;
+
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.StatCollector;
+
+import gregtech.api.util.GT_Utility;
+
+public class ResultInsufficientMachineTier implements CheckRecipeResult {
+
+ private int required;
+
+ ResultInsufficientMachineTier(int required) {
+ this.required = required;
+ }
+
+ @Override
+ public String getID() {
+ return "insufficient_machine_tier";
+ }
+
+ @Override
+ public boolean wasSuccessful() {
+ return false;
+ }
+
+ @Override
+ public String getDisplayString() {
+ return StatCollector
+ .translateToLocalFormatted("GT5U.gui.text.insufficient_machine_tier", GT_Utility.formatNumbers(required));
+ }
+
+ @Override
+ public CheckRecipeResult newInstance() {
+ return new ResultInsufficientMachineTier(0);
+ }
+
+ @Override
+ public void encode(PacketBuffer buffer) {
+ buffer.writeVarIntToBuffer(required);
+ }
+
+ @Override
+ public void decode(PacketBuffer buffer) {
+ required = buffer.readVarIntFromBuffer();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ResultInsufficientMachineTier that = (ResultInsufficientMachineTier) o;
+ return required == that.required;
+ }
+}
diff --git a/src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java b/src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java
new file mode 100644
index 0000000000..ca6b31ccef
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/check/ResultInsufficientPower.java
@@ -0,0 +1,56 @@
+package gregtech.api.recipe.check;
+
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.StatCollector;
+
+import gregtech.api.util.GT_Utility;
+
+public class ResultInsufficientPower implements CheckRecipeResult {
+
+ private long required;
+
+ ResultInsufficientPower(long required) {
+ this.required = required;
+ }
+
+ @Override
+ public String getID() {
+ return "insufficient_power";
+ }
+
+ @Override
+ public boolean wasSuccessful() {
+ return false;
+ }
+
+ @Override
+ public String getDisplayString() {
+ return StatCollector.translateToLocalFormatted(
+ "GT5U.gui.text.insufficient_power",
+ GT_Utility.formatNumbers(required),
+ GT_Utility.getColoredTierNameFromVoltage(required));
+ }
+
+ @Override
+ public CheckRecipeResult newInstance() {
+ return new ResultInsufficientPower(0);
+ }
+
+ @Override
+ public void encode(PacketBuffer buffer) {
+ buffer.writeLong(required);
+ }
+
+ @Override
+ public void decode(PacketBuffer buffer) {
+ required = buffer.readLong();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ResultInsufficientPower that = (ResultInsufficientPower) o;
+ return required == that.required;
+ }
+}
diff --git a/src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java b/src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java
new file mode 100644
index 0000000000..767a168125
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/check/SimpleCheckRecipeResult.java
@@ -0,0 +1,78 @@
+package gregtech.api.recipe.check;
+
+import java.util.Objects;
+
+import net.minecraft.network.PacketBuffer;
+import net.minecraft.util.StatCollector;
+
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+
+/**
+ * Simple implementation of {@link CheckRecipeResult}. You can create new object without registering it.
+ */
+public class SimpleCheckRecipeResult implements CheckRecipeResult {
+
+ private boolean success;
+ private String key;
+
+ SimpleCheckRecipeResult(boolean success, String key) {
+ this.success = success;
+ this.key = key;
+ }
+
+ @Override
+ public String getID() {
+ return "simple_result";
+ }
+
+ @Override
+ public boolean wasSuccessful() {
+ return success;
+ }
+
+ @Override
+ public String getDisplayString() {
+ return StatCollector.translateToLocal("GT5U.gui.text." + key);
+ }
+
+ @Override
+ public CheckRecipeResult newInstance() {
+ return new SimpleCheckRecipeResult(false, "");
+ }
+
+ @Override
+ public void encode(PacketBuffer buffer) {
+ buffer.writeBoolean(success);
+ NetworkUtils.writeStringSafe(buffer, key);
+ }
+
+ @Override
+ public void decode(PacketBuffer buffer) {
+ success = buffer.readBoolean();
+ key = NetworkUtils.readStringSafe(buffer);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SimpleCheckRecipeResult that = (SimpleCheckRecipeResult) o;
+ return success == that.success && Objects.equals(key, that.key);
+ }
+
+ /**
+ * Creates new result with successful state. Add your localized description with `GT5U.gui.text.{key}`.
+ * This is already registered to registry.
+ */
+ public static CheckRecipeResult ofSuccess(String key) {
+ return new SimpleCheckRecipeResult(true, key);
+ }
+
+ /**
+ * Creates new result object with failed state. Add your localized description with `GT5U.gui.text.{key}`.
+ * This is already registered to registry.
+ */
+ public static CheckRecipeResult ofFailure(String key) {
+ return new SimpleCheckRecipeResult(false, key);
+ }
+}
diff --git a/src/main/java/gregtech/api/recipe/check/SingleRecipeCheck.java b/src/main/java/gregtech/api/recipe/check/SingleRecipeCheck.java
new file mode 100644
index 0000000000..d0a952b8d5
--- /dev/null
+++ b/src/main/java/gregtech/api/recipe/check/SingleRecipeCheck.java
@@ -0,0 +1,404 @@
+package gregtech.api.recipe.check;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.common.util.Constants;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.google.common.collect.ImmutableMap;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.GT_Utility.ItemId;
+
+/**
+ * Used by machines that are locked to a single recipe, for faster recipe check.
+ * <p>
+ * Computation time will be like these:
+ * <ul>
+ * Normal recipe check:
+ * <ul>
+ * {@link GT_Recipe.GT_Recipe_Map#findRecipeWithResult Find recipe from recipemap}: O(NCR)
+ * where N = number of machine inputs, C = average amount of recipe candidates found for specific input,
+ * R = computation time to {@link GT_Recipe#isRecipeInputEqual check if inputs match to recipe}
+ * </ul>
+ * <ul>
+ * {@link GT_Recipe#isRecipeInputEqual Check if inputs match to recipe}: O(NM)
+ * where N = number of machine inputs, M = number of recipe inputs
+ * </ul>
+ * </ul>
+ * <ul>
+ * {@link #checkRecipeInputs Single recipe check}: O(N + M)
+ * where N = number of machine inputs, M = number of recipe inputs
+ * </ul>
+ */
+public class SingleRecipeCheck {
+
+ @Nonnull
+ private final GT_Recipe recipe;
+ @Nonnull
+ private final GT_Recipe.GT_Recipe_Map recipeMap;
+ @Nonnull
+ private final ImmutableMap<ItemId, Integer> itemCost;
+ @Nonnull
+ private final ImmutableMap<Fluid, Integer> fluidCost;
+
+ private final int totalItemCost;
+ private final int totalFluidCost;
+
+ private SingleRecipeCheck(@Nonnull GT_Recipe recipe, @Nonnull GT_Recipe.GT_Recipe_Map recipeMap,
+ @Nonnull ImmutableMap<ItemId, Integer> itemCost, @Nonnull ImmutableMap<Fluid, Integer> fluidCost) {
+ this.recipe = recipe;
+ this.recipeMap = recipeMap;
+ this.itemCost = itemCost;
+ this.fluidCost = fluidCost;
+
+ this.totalItemCost = itemCost.values()
+ .stream()
+ .mapToInt(Integer::intValue)
+ .sum();
+ this.totalFluidCost = fluidCost.values()
+ .stream()
+ .mapToInt(Integer::intValue)
+ .sum();
+ }
+
+ @Nonnull
+ public GT_Recipe getRecipe() {
+ return recipe;
+ }
+
+ @Nonnull
+ public GT_Recipe.GT_Recipe_Map getRecipeMap() {
+ return recipeMap;
+ }
+
+ /**
+ * Returns the number of parallel recipes, or 0 if recipe is not satisfied at all.
+ */
+ public int checkRecipeInputs(boolean consumeInputs, int maxParallel, ItemStack[] itemInputs,
+ FluidStack[] fluidInputs) {
+ int currentParallel = maxParallel;
+
+ if (totalItemCost > 0) {
+ // Create map for item -> stored amount
+ Map<ItemId, Integer> itemMap = new HashMap<>();
+ for (ItemStack itemStack : itemInputs) {
+ if (itemStack == null) continue;
+ itemMap.merge(ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
+ }
+
+ // Check how many parallels can it perform for each item
+ for (Map.Entry<ItemId, Integer> costEntry : itemCost.entrySet()) {
+ currentParallel = Math
+ .min(currentParallel, itemMap.getOrDefault(costEntry.getKey(), 0) / costEntry.getValue());
+ if (currentParallel <= 0) {
+ return 0;
+ }
+ }
+ }
+
+ if (totalFluidCost > 0) {
+ // Create map for fluid -> stored amount
+ Map<Fluid, Integer> fluidMap = new HashMap<>();
+ for (FluidStack fluidStack : fluidInputs) {
+ if (fluidStack == null) continue;
+ fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
+ }
+
+ // Check how many parallels can it perform for each fluid
+ for (Map.Entry<Fluid, Integer> costEntry : fluidCost.entrySet()) {
+ currentParallel = Math
+ .min(currentParallel, fluidMap.getOrDefault(costEntry.getKey(), 0) / costEntry.getValue());
+ if (currentParallel <= 0) {
+ return 0;
+ }
+ }
+ }
+
+ final int finalParallel = currentParallel;
+ if (consumeInputs) {
+ if (totalItemCost > 0) {
+ int remainingItemCost = totalItemCost * finalParallel;
+ Map<ItemId, Integer> runningItemCost = itemCost.entrySet()
+ .stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue() * finalParallel));
+
+ for (ItemStack itemStack : itemInputs) {
+ if (itemStack == null) continue;
+ ItemId key = ItemId.createNoCopy(itemStack);
+ int runningCost = runningItemCost.getOrDefault(key, 0);
+ int paid = Math.min(itemStack.stackSize, runningCost);
+ itemStack.stackSize -= paid;
+ runningItemCost.put(key, runningCost - paid);
+
+ remainingItemCost -= paid;
+ // If all item costs are paid, we don't need to iterate inputs furthermore
+ if (remainingItemCost <= 0) {
+ break;
+ }
+ }
+ }
+
+ if (totalFluidCost > 0) {
+ int remainingFluidCost = totalFluidCost * finalParallel;
+ Map<Fluid, Integer> runningFluidCost = fluidCost.entrySet()
+ .stream()
+ .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue() * finalParallel));
+
+ for (FluidStack fluidStack : fluidInputs) {
+ if (fluidStack == null) continue;
+ Fluid key = fluidStack.getFluid();
+ int runningCost = runningFluidCost.getOrDefault(key, 0);
+ int paid = Math.min(fluidStack.amount, runningCost);
+ fluidStack.amount -= paid;
+ runningFluidCost.put(key, runningCost - paid);
+
+ remainingFluidCost -= paid;
+ // If all fluid costs are paid, we don't need to iterate inputs furthermore
+ if (remainingFluidCost <= 0) {
+ break;
+ }
+ }
+ }
+ }
+
+ return finalParallel;
+ }
+
+ public NBTTagCompound writeToNBT() {
+ // Here we encode recipe input, output and all other important values.
+ // At load time we do a recipe check again, so in case the recipe is gone, we can stop tracking.
+ // Of course the next step would be auto migrating to new recipe (if any), but given
+ // we don't yet have a mean to uniquely name a recipe, this will have to make do.
+ // Consider move serialization code to GT_Recipe once this has been proven to work
+ NBTTagCompound tag = new NBTTagCompound();
+ tag.setString("recipemap", recipeMap.mUnlocalizedName);
+ if (recipe.mInputs != null) {
+ tag.setTag("inputs", writeList(recipe.mInputs, GT_Utility::saveItem));
+ }
+ if (recipe.mOutputs != null) {
+ tag.setTag("outputs", writeList(recipe.mOutputs, GT_Utility::saveItem));
+ }
+ if (recipe.mChances != null) {
+ tag.setIntArray("chances", recipe.mChances);
+ }
+ if (recipe.mFluidInputs != null) {
+ tag.setTag(
+ "fInputs",
+ writeList(
+ recipe.mFluidInputs,
+ s -> s == null ? new NBTTagCompound() : s.writeToNBT(new NBTTagCompound())));
+ }
+ if (recipe.mFluidOutputs != null) {
+ tag.setTag(
+ "fOutputs",
+ writeList(
+ recipe.mFluidOutputs,
+ s -> s == null ? new NBTTagCompound() : s.writeToNBT(new NBTTagCompound())));
+ }
+ tag.setInteger("eut", recipe.mEUt);
+ tag.setInteger("duration", recipe.mDuration);
+ tag.setInteger("specialValue", recipe.mSpecialValue);
+ tag.setTag("itemCost", writeList(itemCost.entrySet(), e -> {
+ NBTTagCompound ret = new NBTTagCompound();
+ ret.setTag(
+ "id",
+ e.getKey()
+ .writeToNBT());
+ ret.setInteger("count", e.getValue());
+ return ret;
+ }));
+ tag.setTag("fluidCost", writeList(fluidCost.entrySet(), e -> {
+ NBTTagCompound ret = new NBTTagCompound();
+ ret.setString(
+ "id",
+ e.getKey()
+ .getName());
+ ret.setInteger("count", e.getValue());
+ return ret;
+ }));
+ return tag;
+ }
+
+ private static <T, NBT extends NBTBase> NBTTagList writeList(T[] arr, Function<T, NBT> ser) {
+ return writeList(Arrays.asList(arr), ser);
+ }
+
+ private static <T, NBT extends NBTBase> NBTTagList writeList(Collection<T> arr, Function<T, NBT> ser) {
+ NBTTagList l = new NBTTagList();
+ for (T t : arr) {
+ l.appendTag(ser.apply(t));
+ }
+ return l;
+ }
+
+ @Nullable
+ public static SingleRecipeCheck tryLoad(GT_Recipe.GT_Recipe_Map recipeMap, NBTTagCompound tag) {
+ if (tag == null || tag.hasNoTags()) return null;
+
+ GT_Recipe.GT_Recipe_Map mapToUse;
+ if (tag.hasKey("recipemap")) {
+ String mapName = tag.getString("recipemap");
+ GT_Recipe.GT_Recipe_Map foundMap = GT_Recipe.GT_Recipe_Map.findRecipeMap(mapName);
+ if (foundMap != null) {
+ mapToUse = foundMap;
+ } else {
+ mapToUse = recipeMap;
+ }
+ } else {
+ mapToUse = recipeMap;
+ }
+ if (mapToUse == null) {
+ return null;
+ }
+
+ GT_Recipe foundRecipe = tryFindRecipe(mapToUse, tag);
+ if (foundRecipe == null) return null;
+ return new SingleRecipeCheck(foundRecipe, mapToUse, loadItemCost(tag), loadFluidCost(tag));
+ }
+
+ private static ImmutableMap<Fluid, Integer> loadFluidCost(NBTTagCompound tag) {
+ return GT_Utility.streamCompounds(tag.getTagList("fluidCost", Constants.NBT.TAG_COMPOUND))
+ .collect(
+ GT_Utility
+ .toImmutableMapSerial(t -> FluidRegistry.getFluid(t.getString("id")), t -> t.getInteger("count")));
+ }
+
+ private static ImmutableMap<ItemId, Integer> loadItemCost(NBTTagCompound tag) {
+ return GT_Utility.streamCompounds(tag.getTagList("itemCost", Constants.NBT.TAG_COMPOUND))
+ .collect(
+ GT_Utility
+ .toImmutableMapSerial(t -> ItemId.create(t.getCompoundTag("id")), t -> t.getInteger("count")));
+ }
+
+ private static GT_Recipe tryFindRecipe(@Nonnull GT_Recipe.GT_Recipe_Map recipeMap, NBTTagCompound tag) {
+ ItemStack[] inputs = GT_Utility.streamCompounds(tag.getTagList("inputs", Constants.NBT.TAG_COMPOUND))
+ .map(GT_Utility::loadItem)
+ .toArray(ItemStack[]::new);
+ ItemStack[] outputs = GT_Utility.streamCompounds(tag.getTagList("outputs", Constants.NBT.TAG_COMPOUND))
+ .map(GT_Utility::loadItem)
+ .toArray(ItemStack[]::new);
+ FluidStack[] fInputs = GT_Utility.streamCompounds(tag.getTagList("fInputs", Constants.NBT.TAG_COMPOUND))
+ .map(FluidStack::loadFluidStackFromNBT)
+ .toArray(FluidStack[]::new);
+ FluidStack[] fOutputs = GT_Utility.streamCompounds(tag.getTagList("fOutputs", Constants.NBT.TAG_COMPOUND))
+ .map(FluidStack::loadFluidStackFromNBT)
+ .toArray(FluidStack[]::new);
+ int eut = tag.getInteger("eut");
+ GT_Recipe found = recipeMap.findRecipe(null, false, GT_Values.V[GT_Utility.getTier(eut)], fInputs, inputs);
+ int[] chances = tag.getIntArray("chances");
+ if (chances.length == 0) chances = null;
+ if (found == null || !GT_Utility.equals(inputs, found.mInputs)
+ || !Arrays.equals(fInputs, found.mFluidInputs)
+ || !GT_Utility.equals(outputs, found.mOutputs)
+ || !Arrays.equals(fOutputs, found.mFluidOutputs)
+ || !Arrays.equals(chances, found.mChances)
+ || found.mDuration != tag.getInteger("duration")
+ || found.mEUt != eut
+ || found.mSpecialValue != tag.getInteger("specialValue")) return null;
+ return found;
+ }
+
+ private static ImmutableMap<ItemId, Integer> buildItemMap(ItemStack[] inputs) {
+ Map<ItemId, Integer> itemMap = new HashMap<>();
+ for (ItemStack itemStack : inputs) {
+ if (itemStack == null) continue;
+ itemMap.merge(ItemId.create(itemStack), itemStack.stackSize, Integer::sum);
+ }
+ return ImmutableMap.copyOf(itemMap);
+ }
+
+ private static ImmutableMap<Fluid, Integer> buildFluidMap(FluidStack[] fluids) {
+ Map<Fluid, Integer> fluidMap = new HashMap<>();
+ for (FluidStack fluidStack : fluids) {
+ if (fluidStack == null) continue;
+ fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
+ }
+ return ImmutableMap.copyOf(fluidMap);
+ }
+
+ public static Builder builder(@Nonnull GT_Recipe.GT_Recipe_Map recipeMap) {
+ return new Builder(Objects.requireNonNull(recipeMap));
+ }
+
+ public static class Builder {
+
+ private final GT_Recipe.GT_Recipe_Map recipeMap;
+
+ // In order to compute which items and fluids are consumed by the recipe, we compare the
+ // multi-block's items and fluids before and after inputs are consumed by the recipe.
+ private Map<ItemId, Integer> beforeItems;
+ private Map<Fluid, Integer> beforeFluids;
+ private Map<ItemId, Integer> afterItems;
+ private Map<Fluid, Integer> afterFluids;
+
+ private GT_Recipe recipe;
+
+ private Builder(@Nonnull GT_Recipe.GT_Recipe_Map recipeMap) {
+ this.recipeMap = recipeMap;
+ }
+
+ public Builder setBefore(ItemStack[] inputs, FluidStack[] fluids) {
+ beforeItems = buildItemMap(inputs);
+ beforeFluids = buildFluidMap(fluids);
+ return this;
+ }
+
+ public Builder setAfter(ItemStack[] inputs, FluidStack[] fluids) {
+ afterItems = buildItemMap(inputs);
+ afterFluids = buildFluidMap(fluids);
+ return this;
+ }
+
+ public Builder setRecipe(@Nonnull GT_Recipe recipe) {
+ this.recipe = recipe;
+ return this;
+ }
+
+ private ImmutableMap<ItemId, Integer> buildItemCost() {
+ ImmutableMap.Builder<ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
+ for (Map.Entry<ItemId, Integer> entry : beforeItems.entrySet()) {
+ int cost = entry.getValue() - afterItems.getOrDefault(entry.getKey(), 0);
+ if (cost > 0) {
+ itemCostBuilder.put(entry.getKey(), cost);
+ }
+ }
+ return itemCostBuilder.build();
+ }
+
+ private ImmutableMap<Fluid, Integer> buildFluidCost() {
+ ImmutableMap.Builder<Fluid, Integer> fluidCostBuilder = ImmutableMap.builder();
+ for (Map.Entry<Fluid, Integer> entry : beforeFluids.entrySet()) {
+ int cost = entry.getValue() - afterFluids.getOrDefault(entry.getKey(), 0);
+ if (cost > 0) {
+ fluidCostBuilder.put(entry.getKey(), cost);
+ }
+ }
+ return fluidCostBuilder.build();
+ }
+
+ public SingleRecipeCheck build() {
+ if (recipe == null) {
+ throw new IllegalStateException("recipe is not set");
+ }
+ return new SingleRecipeCheck(recipe, recipeMap, buildItemCost(), buildFluidCost());
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/util/GT_OverclockCalculator.java b/src/main/java/gregtech/api/util/GT_OverclockCalculator.java
index ba90240f14..6636b27bc7 100644
--- a/src/main/java/gregtech/api/util/GT_OverclockCalculator.java
+++ b/src/main/java/gregtech/api/util/GT_OverclockCalculator.java
@@ -1,5 +1,7 @@
package gregtech.api.util;
+import javax.annotation.Nonnull;
+
public class GT_OverclockCalculator {
/**
@@ -15,7 +17,7 @@ public class GT_OverclockCalculator {
* GT++ machines
* mHeatDiscountAmount - The value used for discount final eut per 900 heat
*/
- private float mEUtDiscount = 1, mSpeedBoost = 1, mHeatDiscountAmount = 0.95f;
+ private double mEUtDiscount = 1, mSpeedBoost = 1, mHeatDiscountAmount = 0.95f;
/**
* mEUtIncreasePerOC - How much the bits should be moved to the left when it is overclocking (Going up, 2 meaning
* it is multiplied with 4x)
@@ -42,6 +44,15 @@ public class GT_OverclockCalculator {
private static final int HEAT_PERFECT_OVERCLOCK_THRESHOLD = 1800;
/**
+ * Creates calculator that doesn't do OC at all.
+ */
+ public static GT_OverclockCalculator ofNoOverclock(@Nonnull GT_Recipe recipe) {
+ return new GT_OverclockCalculator().setRecipeEUt(recipe.mEUt)
+ .setDuration(recipe.mDuration)
+ .setEUt(recipe.mEUt);
+ }
+
+ /**
* An Overclock helper for calculating overclocks in many different situations
*/
public GT_OverclockCalculator() {}
diff --git a/src/main/java/gregtech/api/util/GT_ParallelHelper.java b/src/main/java/gregtech/api/util/GT_ParallelHelper.java
index 9ceec7af44..4c9f53745b 100644
--- a/src/main/java/gregtech/api/util/GT_ParallelHelper.java
+++ b/src/main/java/gregtech/api/util/GT_ParallelHelper.java
@@ -1,11 +1,17 @@
package gregtech.api.util;
+import java.util.Objects;
+
+import javax.annotation.Nonnull;
+
import net.minecraft.item.ItemStack;
import net.minecraftforge.fluids.FluidStack;
+import gregtech.api.interfaces.tileentity.IRecipeLockable;
import gregtech.api.interfaces.tileentity.IVoidable;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
import gregtech.api.objects.XSTR;
+import gregtech.api.recipe.check.SingleRecipeCheck;
@SuppressWarnings({ "unused", "UnusedReturnValue" })
public class GT_ParallelHelper {
@@ -15,6 +21,14 @@ public class GT_ParallelHelper {
*/
private IVoidable machine;
/**
+ * Machine used for single recipe locking calculation
+ */
+ private IRecipeLockable singleRecipeMachine;
+ /**
+ * Is locked to a single recipe?
+ */
+ private boolean isRecipeLocked;
+ /**
* Recipe used when trying to calculate parallels
*/
private GT_Recipe mRecipe;
@@ -79,7 +93,7 @@ public class GT_ParallelHelper {
/**
* What is the duration multiplier with batch mode enabled
*/
- private float mDurationMultiplier;
+ private double mDurationMultiplier;
/**
* Modifier which is applied on the recipe eut. Useful for GT++ machines
*/
@@ -128,8 +142,14 @@ public class GT_ParallelHelper {
/**
* Sets the recipe, which will be used for the parallel calculation
*/
- public GT_ParallelHelper setRecipe(GT_Recipe aRecipe) {
- mRecipe = aRecipe;
+ public GT_ParallelHelper setRecipe(@Nonnull GT_Recipe aRecipe) {
+ mRecipe = Objects.requireNonNull(aRecipe);
+ return this;
+ }
+
+ public GT_ParallelHelper setRecipeLocked(IRecipeLockable singleRecipeMachine, boolean isRecipeLocked) {
+ this.singleRecipeMachine = singleRecipeMachine;
+ this.isRecipeLocked = isRecipeLocked;
return this;
}
@@ -186,7 +206,7 @@ public class GT_ParallelHelper {
* modifier of 1 does nothing
*/
public GT_ParallelHelper enableBatchMode(int aBatchModifier) {
- mBatchMode = true;
+ mBatchMode = aBatchModifier > 1;
mBatchModifier = aBatchModifier;
return this;
}
@@ -207,6 +227,9 @@ public class GT_ParallelHelper {
if (mBuilt) {
throw new IllegalStateException("Tried to build twice");
}
+ if (mRecipe == null) {
+ throw new IllegalStateException("Recipe is not set");
+ }
mBuilt = true;
determineParallel();
return this;
@@ -225,7 +248,7 @@ public class GT_ParallelHelper {
/**
* @return The duration multiplier if batch mode was enabled for the multiblock
*/
- public float getDurationMultiplier() {
+ public double getDurationMultiplierDouble() {
if (!mBuilt) {
throw new IllegalStateException("Tried to get duration multiplier before building");
}
@@ -236,6 +259,14 @@ public class GT_ParallelHelper {
}
/**
+ * @deprecated Use {@link #getDurationMultiplierDouble()}
+ */
+ @Deprecated
+ public float getDurationMultiplier() {
+ return (float) getDurationMultiplierDouble();
+ }
+
+ /**
* @return The ItemOutputs from the recipe
*/
public ItemStack[] getItemOutputs() {
@@ -264,35 +295,50 @@ public class GT_ParallelHelper {
if (mRecipe.mEUt > mAvailableEUt) {
return;
}
- ItemStack[] tItemInputs = null;
- FluidStack[] tFluidInputs = null;
- long tCurrentUsage = 0;
- // see if people want to consume their inputs with the Parallel Helper or not
+ if (mItemInputs == null) {
+ mItemInputs = new ItemStack[0];
+ }
+ if (mFluidInputs == null) {
+ mFluidInputs = new FluidStack[0];
+ }
+
+ ItemStack[] tItemInputs;
+ FluidStack[] tFluidInputs;
+ // see if people want to consume their inputs or not
if (mConsume) {
tItemInputs = mItemInputs;
tFluidInputs = mFluidInputs;
} else {
- if (mItemInputs == null) {
- tItemInputs = new ItemStack[] {};
- } else {
- tItemInputs = new ItemStack[mItemInputs.length];
- for (int i = 0; i < mItemInputs.length; i++) {
- tItemInputs[i] = mItemInputs[i].copy();
- }
+ // copy to prevent consuming original inputs
+ tItemInputs = new ItemStack[mItemInputs.length];
+ for (int i = 0; i < mItemInputs.length; i++) {
+ tItemInputs[i] = mItemInputs[i].copy();
}
-
- if (mFluidInputs == null) {
- mFluidInputs = new FluidStack[] {};
- } else {
- tFluidInputs = new FluidStack[mFluidInputs.length];
- for (int i = 0; i < mFluidInputs.length; i++) {
- tFluidInputs[i] = mFluidInputs[i].copy();
- }
+ tFluidInputs = new FluidStack[mFluidInputs.length];
+ for (int i = 0; i < mFluidInputs.length; i++) {
+ tFluidInputs[i] = mFluidInputs[i].copy();
}
}
+
if (mBatchMode) {
mMaxParallel *= mBatchModifier;
}
+
+ SingleRecipeCheck recipeCheck = null;
+ SingleRecipeCheck.Builder tSingleRecipeCheckBuilder = null;
+ if (isRecipeLocked && singleRecipeMachine != null) {
+ recipeCheck = singleRecipeMachine.getSingleRecipeCheck();
+ if (recipeCheck == null) {
+ // Machine is configured to lock to a single recipe, but haven't built the recipe checker yet.
+ // Build the checker on next successful recipe.
+ GT_Recipe.GT_Recipe_Map recipeMap = singleRecipeMachine.getRecipeMap();
+ if (recipeMap != null) {
+ tSingleRecipeCheckBuilder = SingleRecipeCheck.builder(recipeMap)
+ .setBefore(tItemInputs, tFluidInputs);
+ }
+ }
+ }
+
// Let's look at how many parallels we can get with void protection
if (protectExcessItem || protectExcessFluid) {
if (machine == null) {
@@ -307,31 +353,50 @@ public class GT_ParallelHelper {
mMaxParallel = Math.min(voidProtectionHelper.getMaxParallel(), mMaxParallel);
}
- float tRecipeEUt = mRecipe.mEUt * mEUtModifier;
+ final int tRecipeEUt = (int) Math.ceil(mRecipe.mEUt * mEUtModifier);
+ final int batchCorrectedMaxParallel = mMaxParallel / mBatchModifier;
// Consume inputs to determine normal parallel
- for (; mCurrentParallel < mMaxParallel / mBatchModifier
- && tCurrentUsage < (mAvailableEUt - tRecipeEUt); mCurrentParallel++) {
- if (mRecipe.isRecipeInputEqual(true, false, tFluidInputs, tItemInputs)) {
+ if (recipeCheck != null) {
+ int actualMaxParallel = (int) Math.min(batchCorrectedMaxParallel, mAvailableEUt / tRecipeEUt);
+ mCurrentParallel = recipeCheck.checkRecipeInputs(true, actualMaxParallel, tItemInputs, tFluidInputs);
+ } else {
+ long tCurrentUsage = 0;
+ boolean builtRecipeCheck = false;
+ for (; mCurrentParallel < batchCorrectedMaxParallel
+ && tCurrentUsage < (mAvailableEUt - tRecipeEUt); mCurrentParallel++) {
+ if (!mRecipe.isRecipeInputEqual(true, false, tFluidInputs, tItemInputs)) {
+ break;
+ }
tCurrentUsage += tRecipeEUt;
- } else {
- break;
+ if (tSingleRecipeCheckBuilder != null && !builtRecipeCheck) {
+ // If recipe checker is not built yet, build and set it
+ SingleRecipeCheck builtCheck = tSingleRecipeCheckBuilder.setAfter(tItemInputs, tFluidInputs)
+ .setRecipe(mRecipe)
+ .build();
+ singleRecipeMachine.setSingleRecipeCheck(builtCheck);
+ builtRecipeCheck = true;
+ }
}
}
// If Batch Mode is enabled determine how many extra parallels we can get
- if (mBatchMode) {
+ if (mBatchMode && mCurrentParallel > 0) {
int tExtraParallels = 0;
- while (tExtraParallels < mCurrentParallel * (mBatchModifier - 1)
- && mRecipe.isRecipeInputEqual(false, false, tFluidInputs, tItemInputs)) {
- mRecipe.isRecipeInputEqual(true, false, tFluidInputs, tItemInputs);
- tExtraParallels++;
+ final int maxExtraParallels = mCurrentParallel * (mBatchModifier - 1);
+ if (recipeCheck != null) {
+ tExtraParallels = recipeCheck.checkRecipeInputs(true, maxExtraParallels, tItemInputs, tFluidInputs);
+ } else {
+ while (tExtraParallels < maxExtraParallels
+ && mRecipe.isRecipeInputEqual(true, false, tFluidInputs, tItemInputs)) {
+ tExtraParallels++;
+ }
}
mDurationMultiplier = 1.0f + (float) tExtraParallels / mCurrentParallel;
mCurrentParallel += tExtraParallels;
}
// If we want to calculate outputs we do it here
- if (mCalculateOutputs) {
+ if (mCalculateOutputs && mCurrentParallel > 0) {
if (mRecipe.mOutputs != null) {
mItemOutputs = new ItemStack[mRecipe.mOutputs.length];
for (int i = 0; i < mRecipe.mOutputs.length; i++) {
diff --git a/src/main/java/gregtech/api/util/GT_ProcessingArray_Manager.java b/src/main/java/gregtech/api/util/GT_ProcessingArray_Manager.java
index 66bc16cae3..0ef28bd705 100644
--- a/src/main/java/gregtech/api/util/GT_ProcessingArray_Manager.java
+++ b/src/main/java/gregtech/api/util/GT_ProcessingArray_Manager.java
@@ -2,6 +2,8 @@ package gregtech.api.util;
import java.util.HashMap;
+import net.minecraft.item.ItemStack;
+
import gregtech.api.enums.SoundResource;
import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
@@ -38,4 +40,11 @@ public class GT_ProcessingArray_Manager {
}
return null;
}
+
+ public static String getMachineName(ItemStack stack) {
+ int length = stack.getUnlocalizedName()
+ .length();
+ return stack.getUnlocalizedName()
+ .substring(17, length - 8); // trim "gt.blockmachines." and ".tier.xx"
+ }
}
diff --git a/src/main/java/gregtech/api/util/GT_Recipe.java b/src/main/java/gregtech/api/util/GT_Recipe.java
index 748b922b44..d26b8105cf 100644
--- a/src/main/java/gregtech/api/util/GT_Recipe.java
+++ b/src/main/java/gregtech/api/util/GT_Recipe.java
@@ -9,6 +9,7 @@ import static gregtech.api.enums.Mods.GTPlusPlus;
import static gregtech.api.enums.Mods.GregTech;
import static gregtech.api.enums.Mods.NEICustomDiagrams;
import static gregtech.api.enums.Mods.Railcraft;
+import static gregtech.api.recipe.check.FindRecipeResult.*;
import static gregtech.api.util.GT_RecipeBuilder.handleRecipeCollision;
import static gregtech.api.util.GT_RecipeConstants.ADDITIVE_AMOUNT;
import static gregtech.api.util.GT_RecipeMapUtil.FIRST_FLUIDSTACK_INPUT;
@@ -104,11 +105,11 @@ import gregtech.api.gui.modularui.FallbackableSteamTexture;
import gregtech.api.gui.modularui.GT_UITextures;
import gregtech.api.gui.modularui.SteamTexture;
import gregtech.api.interfaces.IGT_RecipeMap;
-import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.interfaces.tileentity.IHasWorldObjectAndCoords;
import gregtech.api.objects.GT_ItemStack;
import gregtech.api.objects.ItemData;
import gregtech.api.objects.MaterialStack;
+import gregtech.api.recipe.check.FindRecipeResult;
import gregtech.api.util.extensions.ArrayExt;
import gregtech.common.gui.modularui.UIHelper;
import gregtech.common.items.GT_FluidDisplayItem;
@@ -3051,6 +3052,14 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
.orElse(Collections.emptyList())));
}
+ @Nullable
+ public static GT_Recipe_Map findRecipeMap(@Nonnull String unlocalizedName) {
+ return sMappings.stream()
+ .filter(m -> unlocalizedName.equals(m.mUnlocalizedName))
+ .findFirst()
+ .orElse(null);
+ }
+
/**
* HashMap of Recipes based on their Items
*/
@@ -3105,6 +3114,11 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
private boolean mUsesSpecialSlot = false;
/**
+ * Whether this recipemap checks for equality of special slot when searching recipe.
+ */
+ private boolean isSpecialSlotSensitive = false;
+
+ /**
* How many fluid inputs does this recipemap has at most. Currently used only for NEI slot placements and does
* not actually restrict number of fluids used in the recipe.
*/
@@ -3188,6 +3202,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
private int neiTextColorOverride = -1;
private INEISpecialInfoFormatter neiSpecialInfoFormatter;
+
private final boolean checkForCollision = true;
private boolean allowNoInput;
private boolean allowNoInputFluid;
@@ -3293,6 +3308,11 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
return this;
}
+ public GT_Recipe_Map setSpecialSlotSensitive(boolean isSpecialSlotSensitive) {
+ this.isSpecialSlotSensitive = isSpecialSlotSensitive;
+ return this;
+ }
+
public GT_Recipe_Map setNEIUnificateOutput(boolean mNEIUnificateOutput) {
this.mNEIUnificateOutput = mNEIUnificateOutput;
return this;
@@ -3882,12 +3902,14 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
return aFluid != null && mRecipeFluidNameMap.contains(aFluid.getName());
}
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, boolean aNotUnificated, long aVoltage,
+ @Nullable
+ public final GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, boolean aNotUnificated, long aVoltage,
FluidStack[] aFluids, ItemStack... aInputs) {
return findRecipe(aTileEntity, null, aNotUnificated, aVoltage, aFluids, null, aInputs);
}
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, boolean aNotUnificated,
+ @Nullable
+ public final GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, boolean aNotUnificated,
boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack... aInputs) {
return findRecipe(
aTileEntity,
@@ -3900,13 +3922,16 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aInputs);
}
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack... aInputs) {
+ @Nullable
+ public final GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe,
+ boolean aNotUnificated, long aVoltage, FluidStack[] aFluids, ItemStack... aInputs) {
return findRecipe(aTileEntity, aRecipe, aNotUnificated, aVoltage, aFluids, null, aInputs);
}
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack... aInputs) {
+ @Nullable
+ public final GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe,
+ boolean aNotUnificated, boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids,
+ ItemStack... aInputs) {
return findRecipe(
aTileEntity,
aRecipe,
@@ -3918,16 +3943,32 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aInputs);
}
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
+ @Nullable
+ public final GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe,
+ boolean aNotUnificated, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
return findRecipe(aTileEntity, aRecipe, aNotUnificated, false, aVoltage, aFluids, aSpecialSlot, aInputs);
}
+ // TODO: make this final after migrating BW
+ @SuppressWarnings("unused")
+ @Nullable
+ public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
+ FindRecipeResult result = findRecipeWithResult(
+ aRecipe,
+ aNotUnificated,
+ aDontCheckStackSizes,
+ aVoltage,
+ aFluids,
+ aSpecialSlot,
+ aInputs);
+ return result.isSuccessful() ? result.getRecipe() : null;
+ }
+
/**
* finds a Recipe matching the aFluid and ItemStack Inputs.
*
- * @param aTileEntity an Object representing the current coordinates of the executing
- * Block/Entity/Whatever. This may be null, especially during Startup.
* @param aRecipe in case this is != null it will try to use this Recipe first when looking things
* up.
* @param aNotUnificated if this is T the Recipe searcher will unificate the ItemStack Inputs
@@ -3938,13 +3979,14 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
* @param aSpecialSlot the content of the Special Slot, the regular Manager doesn't do anything with
* this, but some custom ones do.
* @param aInputs the Item Inputs
- * @return the Recipe it has found or null for no matching Recipe
+ * @return Result of the recipe search
*/
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
+ @Nonnull
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
ItemStack... aInputs) {
// No Recipes? Well, nothing to be found then.
- if (mRecipeList.isEmpty()) return null;
+ if (mRecipeList.isEmpty()) return NOT_FOUND;
// Some Recipe Classes require a certain amount of Inputs of certain kinds. Like "at least 1 Fluid + 1
// Stack" or "at least 2 Stacks" before they start searching for Recipes.
@@ -3952,16 +3994,16 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
// their Machines to select Sub Recipes.
if (GregTech_API.sPostloadFinished) {
if (mMinimalInputFluids > 0) {
- if (aFluids == null) return null;
+ if (aFluids == null) return NOT_FOUND;
int tAmount = 0;
for (FluidStack aFluid : aFluids) if (aFluid != null) tAmount++;
- if (tAmount < mMinimalInputFluids) return null;
+ if (tAmount < mMinimalInputFluids) return NOT_FOUND;
}
if (mMinimalInputItems > 0) {
- if (aInputs == null) return null;
+ if (aInputs == null) return NOT_FOUND;
int tAmount = 0;
for (ItemStack aInput : aInputs) if (aInput != null) tAmount++;
- if (tAmount < mMinimalInputItems) return null;
+ if (tAmount < mMinimalInputItems) return NOT_FOUND;
}
}
@@ -3970,19 +4012,37 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
// Check the Recipe which has been used last time in order to not have to search for it again, if possible.
if (aRecipe != null) if (!aRecipe.mFakeRecipe && aRecipe.mCanBeBuffered
- && aRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs))
- return aRecipe.mEnabled && aVoltage * mAmperage >= aRecipe.mEUt ? aRecipe : null;
+ && aRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs)) {
+ if (!isSpecialSlotSensitive
+ || GT_Utility.areStacksEqualOrNull((ItemStack) aRecipe.mSpecialItems, aSpecialSlot)) {
+ return aRecipe.mEnabled && aVoltage * mAmperage >= aRecipe.mEUt
+ ? FindRecipeResult.ofSuccess(aRecipe)
+ : FindRecipeResult.ofInsufficientVoltage(aRecipe);
+ }
+ }
// Now look for the Recipes inside the Item HashMaps, but only when the Recipes usually have Items.
if (mUsualInputCount > 0 && aInputs != null) for (ItemStack tStack : aInputs) if (tStack != null) {
Collection<GT_Recipe> tRecipes = mRecipeItemMap.get(new GT_ItemStack(tStack));
if (tRecipes != null) for (GT_Recipe tRecipe : tRecipes) if (!tRecipe.mFakeRecipe
- && tRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs))
- return tRecipe.mEnabled && aVoltage * mAmperage >= tRecipe.mEUt ? tRecipe : null;
+ && tRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs)) {
+ if (!isSpecialSlotSensitive
+ || GT_Utility.areStacksEqualOrNull((ItemStack) tRecipe.mSpecialItems, aSpecialSlot)) {
+ return tRecipe.mEnabled && aVoltage * mAmperage >= tRecipe.mEUt
+ ? FindRecipeResult.ofSuccess(tRecipe)
+ : FindRecipeResult.ofInsufficientVoltage(tRecipe);
+ }
+ }
tRecipes = mRecipeItemMap.get(new GT_ItemStack(tStack, true));
if (tRecipes != null) for (GT_Recipe tRecipe : tRecipes) if (!tRecipe.mFakeRecipe
- && tRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs))
- return tRecipe.mEnabled && aVoltage * mAmperage >= tRecipe.mEUt ? tRecipe : null;
+ && tRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs)) {
+ if (!isSpecialSlotSensitive
+ || GT_Utility.areStacksEqualOrNull((ItemStack) tRecipe.mSpecialItems, aSpecialSlot)) {
+ return tRecipe.mEnabled && aVoltage * mAmperage >= tRecipe.mEUt
+ ? FindRecipeResult.ofSuccess(tRecipe)
+ : FindRecipeResult.ofInsufficientVoltage(tRecipe);
+ }
+ }
}
// If the minimal Amount of Items for the Recipe is 0, then it could be a Fluid-Only Recipe, so check that
@@ -3990,12 +4050,18 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
if (mMinimalInputItems == 0 && aFluids != null) for (FluidStack aFluid : aFluids) if (aFluid != null) {
Collection<GT_Recipe> tRecipes = mRecipeFluidMap.get(aFluid.getFluid());
if (tRecipes != null) for (GT_Recipe tRecipe : tRecipes) if (!tRecipe.mFakeRecipe
- && tRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs))
- return tRecipe.mEnabled && aVoltage * mAmperage >= tRecipe.mEUt ? tRecipe : null;
+ && tRecipe.isRecipeInputEqual(false, aDontCheckStackSizes, aFluids, aInputs)) {
+ if (!isSpecialSlotSensitive
+ || GT_Utility.areStacksEqualOrNull((ItemStack) tRecipe.mSpecialItems, aSpecialSlot)) {
+ return tRecipe.mEnabled && aVoltage * mAmperage >= tRecipe.mEUt
+ ? FindRecipeResult.ofSuccess(tRecipe)
+ : FindRecipeResult.ofInsufficientVoltage(tRecipe);
+ }
+ }
}
// And nothing has been found.
- return null;
+ return NOT_FOUND;
}
protected GT_Recipe addToItemMap(GT_Recipe aRecipe) {
@@ -4854,24 +4920,28 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return null;
- if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs)) return aRecipe;
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
+ if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return NOT_FOUND;
+ if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs))
+ return FindRecipeResult.ofSuccess(aRecipe);
ItemStack tOutput = GT_ModHandler.getSmeltingOutput(aInputs[0], false, null);
- return tOutput == null ? null
- : new GT_Recipe(
- false,
- new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
- new ItemStack[] { tOutput },
- null,
- null,
- null,
- null,
- 128,
- 4,
- 0);
+ return tOutput == null ? NOT_FOUND
+ : FindRecipeResult.ofSuccess(
+ new GT_Recipe(
+ false,
+ new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
+ new ItemStack[] { tOutput },
+ null,
+ null,
+ null,
+ null,
+ 128,
+ 4,
+ 0));
}
@Override
@@ -4907,25 +4977,30 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return null;
- if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs)) return aRecipe;
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
+ if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return NOT_FOUND;
+ if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs))
+ return FindRecipeResult.ofSuccess(aRecipe);
ItemStack tOutput = GT_ModHandler.getSmeltingOutput(aInputs[0], false, null);
if (GT_Utility.areStacksEqual(aInputs[0], new ItemStack(Items.book, 1, W))) {
- return new GT_Recipe(
- false,
- new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
- new ItemStack[] { GT_Utility.getWrittenBook("Manual_Microwave", ItemList.Book_Written_03.get(1)) },
- null,
- null,
- null,
- null,
- 32,
- 4,
- 0);
+ return FindRecipeResult.ofSuccess(
+ new GT_Recipe(
+ false,
+ new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
+ new ItemStack[] {
+ GT_Utility.getWrittenBook("Manual_Microwave", ItemList.Book_Written_03.get(1)) },
+ null,
+ null,
+ null,
+ null,
+ 32,
+ 4,
+ 0));
}
// Check Container Item of Input since it is around the Input, then the Input itself, then Container Item of
@@ -4938,12 +5013,9 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
|| GT_Utility.areStacksEqual(tStack, new ItemStack(Items.firework_charge, 1, W), true)
|| GT_Utility.areStacksEqual(tStack, new ItemStack(Items.fireworks, 1, W), true)
|| GT_Utility.areStacksEqual(tStack, new ItemStack(Items.fire_charge, 1, W), true)) {
- if (aTileEntity instanceof IGregTechTileEntity) {
- GT_Log.exp.println(
- "Microwave Explosion due to TNT || EGG || FIREWORKCHARGE || FIREWORK || FIRE CHARGE");
- ((IGregTechTileEntity) aTileEntity).doExplosion(aVoltage * 4);
- }
- return null;
+ GT_Log.exp.println(
+ "Microwave Explosion due to TNT || EGG || FIREWORKCHARGE || FIREWORK || FIRE CHARGE");
+ return EXPLODE;
}
ItemData tData = GT_OreDictUnificator.getItemData(tStack);
@@ -4951,59 +5023,45 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
if (tData.mMaterial != null && tData.mMaterial.mMaterial != null) {
if (tData.mMaterial.mMaterial.contains(SubTag.METAL)
|| tData.mMaterial.mMaterial.contains(SubTag.EXPLOSIVE)) {
- if (aTileEntity instanceof IGregTechTileEntity) {
- GT_Log.exp.println("Microwave Explosion due to METAL insertion");
- ((IGregTechTileEntity) aTileEntity).doExplosion(aVoltage * 4);
- }
- return null;
+ GT_Log.exp.println("Microwave Explosion due to METAL insertion");
+ return EXPLODE;
}
if (tData.mMaterial.mMaterial.contains(SubTag.FLAMMABLE)) {
- if (aTileEntity instanceof IGregTechTileEntity) {
- GT_Log.exp.println("Microwave INFLAMMATION due to FLAMMABLE insertion");
- ((IGregTechTileEntity) aTileEntity).setOnFire();
- }
- return null;
+ GT_Log.exp.println("Microwave INFLAMMATION due to FLAMMABLE insertion");
+ return ON_FIRE;
}
}
for (MaterialStack tMaterial : tData.mByProducts) if (tMaterial != null) {
if (tMaterial.mMaterial.contains(SubTag.METAL)
|| tMaterial.mMaterial.contains(SubTag.EXPLOSIVE)) {
- if (aTileEntity instanceof IGregTechTileEntity) {
- GT_Log.exp.println("Microwave Explosion due to METAL insertion");
- ((IGregTechTileEntity) aTileEntity).doExplosion(aVoltage * 4);
- }
- return null;
+ GT_Log.exp.println("Microwave Explosion due to METAL insertion");
+ return EXPLODE;
}
if (tMaterial.mMaterial.contains(SubTag.FLAMMABLE)) {
- if (aTileEntity instanceof IGregTechTileEntity) {
- ((IGregTechTileEntity) aTileEntity).setOnFire();
- GT_Log.exp.println("Microwave INFLAMMATION due to FLAMMABLE insertion");
- }
- return null;
+ GT_Log.exp.println("Microwave INFLAMMATION due to FLAMMABLE insertion");
+ return ON_FIRE;
}
}
}
if (TileEntityFurnace.getItemBurnTime(tStack) > 0) {
- if (aTileEntity instanceof IGregTechTileEntity) {
- ((IGregTechTileEntity) aTileEntity).setOnFire();
- GT_Log.exp.println("Microwave INFLAMMATION due to BURNABLE insertion");
- }
- return null;
+ GT_Log.exp.println("Microwave INFLAMMATION due to BURNABLE insertion");
+ return ON_FIRE;
}
}
- return tOutput == null ? null
- : new GT_Recipe(
- false,
- new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
- new ItemStack[] { tOutput },
- null,
- null,
- null,
- null,
- 32,
- 4,
- 0);
+ return tOutput == null ? NOT_FOUND
+ : FindRecipeResult.ofSuccess(
+ new GT_Recipe(
+ false,
+ new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
+ new ItemStack[] { tOutput },
+ null,
+ null,
+ null,
+ null,
+ 32,
+ 4,
+ 0));
}
@Override
@@ -5039,14 +5097,29 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
if (aInputs == null || aInputs.length == 0 || !ItemList.IC2_Scrapbox.isStackEqual(aInputs[0], false, true))
- return super.findRecipe(aTileEntity, aRecipe, aNotUnificated, aVoltage, aFluids, aSpecialSlot, aInputs);
+ return super.findRecipeWithResult(
+ aRecipe,
+ aNotUnificated,
+ aDontCheckStackSizes,
+ aVoltage,
+ aFluids,
+ aSpecialSlot,
+ aInputs);
ItemStack tOutput = GT_ModHandler.getRandomScrapboxDrop();
- if (tOutput == null)
- return super.findRecipe(aTileEntity, aRecipe, aNotUnificated, aVoltage, aFluids, aSpecialSlot, aInputs);
+ if (tOutput == null) return super.findRecipeWithResult(
+ aRecipe,
+ aNotUnificated,
+ aDontCheckStackSizes,
+ aVoltage,
+ aFluids,
+ aSpecialSlot,
+ aInputs);
GT_Recipe rRecipe = new GT_Recipe(
false,
new ItemStack[] { ItemList.IC2_Scrapbox.get(1) },
@@ -5063,7 +5136,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
// Due to its randomness it is not good if there are Items in the Output Slot, because those Items could
// manipulate the outcome.
rRecipe.mNeedsEmptyOutput = true;
- return rRecipe;
+ return FindRecipeResult.ofSuccess(rRecipe);
}
@Override
@@ -5099,39 +5172,46 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- GT_Recipe rRecipe = super.findRecipe(
- aTileEntity,
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
+ FindRecipeResult result = super.findRecipeWithResult(
aRecipe,
aNotUnificated,
+ aDontCheckStackSizes,
aVoltage,
aFluids,
aSpecialSlot,
aInputs);
if (aInputs == null || aInputs.length == 0
|| aInputs[0] == null
- || rRecipe != null
- || !GregTech_API.sPostloadFinished) return rRecipe;
+ || result.isSuccessful()
+ || !GregTech_API.sPostloadFinished) return result;
+
if (aFluids != null && aFluids.length > 0 && aFluids[0] != null) {
ItemStack tOutput = GT_Utility.fillFluidContainer(aFluids[0], aInputs[0], false, true);
FluidStack tFluid = GT_Utility.getFluidForFilledItem(tOutput, true);
- if (tFluid != null) rRecipe = new GT_Recipe(
- false,
- new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
- new ItemStack[] { tOutput },
- null,
- null,
- new FluidStack[] { tFluid },
- null,
- Math.max(tFluid.amount / 64, 16),
- 1,
- 0);
+ if (tFluid != null) {
+ GT_Recipe recipe = new GT_Recipe(
+ false,
+ new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
+ new ItemStack[] { tOutput },
+ null,
+ null,
+ new FluidStack[] { tFluid },
+ null,
+ Math.max(tFluid.amount / 64, 16),
+ 1,
+ 0);
+ recipe.mCanBeBuffered = false;
+ return FindRecipeResult.ofSuccess(recipe);
+ }
}
- if (rRecipe == null) {
- FluidStack tFluid = GT_Utility.getFluidForFilledItem(aInputs[0], true);
- if (tFluid != null) rRecipe = new GT_Recipe(
+ FluidStack tFluid = GT_Utility.getFluidForFilledItem(aInputs[0], true);
+ if (tFluid != null) {
+ GT_Recipe recipe = new GT_Recipe(
false,
new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
new ItemStack[] { GT_Utility.getContainerItem(aInputs[0], true) },
@@ -5142,9 +5222,10 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
Math.max(tFluid.amount / 64, 16),
1,
0);
+ recipe.mCanBeBuffered = false;
+ return FindRecipeResult.ofSuccess(recipe);
}
- if (rRecipe != null) rRecipe.mCanBeBuffered = false;
- return rRecipe;
+ return NOT_FOUND;
}
@Override
@@ -5191,329 +5272,31 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return null;
- if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs)) return aRecipe;
- return new GT_Recipe(
- false,
- new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
- new ItemStack[] { GT_ModHandler.getRecyclerOutput(aInputs[0], 0) },
- null,
- new int[] { 1250 },
- null,
- null,
- 45,
- 1,
- 0);
- }
-
- @Override
- public boolean containsInput(ItemStack aStack) {
- return GT_ModHandler.getRecyclerOutput(aStack, 0) != null;
- }
- }
-
- /**
- * Special Class for Compressor Recipe handling.
- */
- public static class GT_Recipe_Map_Compressor extends GT_Recipe_Map_NonGTRecipes {
-
- public GT_Recipe_Map_Compressor(Collection<GT_Recipe> aRecipeList, String aUnlocalizedName, String aLocalName,
- String aNEIName, String aNEIGUIPath, int aUsualInputCount, int aUsualOutputCount, int aMinimalInputItems,
- int aMinimalInputFluids, int aAmperage, String aNEISpecialValuePre, int aNEISpecialValueMultiplier,
- String aNEISpecialValuePost, boolean aShowVoltageAmperageInNEI, boolean aNEIAllowed) {
- super(
- aRecipeList,
- aUnlocalizedName,
- aLocalName,
- aNEIName,
- aNEIGUIPath,
- aUsualInputCount,
- aUsualOutputCount,
- aMinimalInputItems,
- aMinimalInputFluids,
- aAmperage,
- aNEISpecialValuePre,
- aNEISpecialValueMultiplier,
- aNEISpecialValuePost,
- aShowVoltageAmperageInNEI,
- aNEIAllowed);
- }
-
- @Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return null;
- if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs)) return aRecipe;
- ItemStack tComparedInput = GT_Utility.copyOrNull(aInputs[0]);
- ItemStack[] tOutputItems = GT_ModHandler.getMachineOutput(
- tComparedInput,
- ic2.api.recipe.Recipes.compressor.getRecipes(),
- true,
- new NBTTagCompound(),
- null,
- null,
- null);
- return GT_Utility.arrayContainsNonNull(tOutputItems)
- ? new GT_Recipe(
- false,
- new ItemStack[] {
- GT_Utility.copyAmount(aInputs[0].stackSize - tComparedInput.stackSize, aInputs[0]) },
- tOutputItems,
- null,
- null,
- null,
- null,
- 400,
- 2,
- 0)
- : null;
- }
-
- @Override
- public boolean containsInput(ItemStack aStack) {
- return GT_Utility.arrayContainsNonNull(
- GT_ModHandler.getMachineOutput(
- GT_Utility.copyAmount(64, aStack),
- ic2.api.recipe.Recipes.compressor.getRecipes(),
- false,
- new NBTTagCompound(),
- null,
- null,
- null));
- }
- }
-
- /**
- * Special Class for Extractor Recipe handling.
- */
- public static class GT_Recipe_Map_Extractor extends GT_Recipe_Map_NonGTRecipes {
-
- public GT_Recipe_Map_Extractor(Collection<GT_Recipe> aRecipeList, String aUnlocalizedName, String aLocalName,
- String aNEIName, String aNEIGUIPath, int aUsualInputCount, int aUsualOutputCount, int aMinimalInputItems,
- int aMinimalInputFluids, int aAmperage, String aNEISpecialValuePre, int aNEISpecialValueMultiplier,
- String aNEISpecialValuePost, boolean aShowVoltageAmperageInNEI, boolean aNEIAllowed) {
- super(
- aRecipeList,
- aUnlocalizedName,
- aLocalName,
- aNEIName,
- aNEIGUIPath,
- aUsualInputCount,
- aUsualOutputCount,
- aMinimalInputItems,
- aMinimalInputFluids,
- aAmperage,
- aNEISpecialValuePre,
- aNEISpecialValueMultiplier,
- aNEISpecialValuePost,
- aShowVoltageAmperageInNEI,
- aNEIAllowed);
- }
-
- @Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return null;
- if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs)) return aRecipe;
- ItemStack tComparedInput = GT_Utility.copyOrNull(aInputs[0]);
- ItemStack[] tOutputItems = GT_ModHandler.getMachineOutput(
- tComparedInput,
- ic2.api.recipe.Recipes.extractor.getRecipes(),
- true,
- new NBTTagCompound(),
- null,
- null,
- null);
- return GT_Utility.arrayContainsNonNull(tOutputItems)
- ? new GT_Recipe(
- false,
- new ItemStack[] {
- GT_Utility.copyAmount(aInputs[0].stackSize - tComparedInput.stackSize, aInputs[0]) },
- tOutputItems,
- null,
- null,
- null,
- null,
- 400,
- 2,
- 0)
- : null;
- }
-
- @Override
- public boolean containsInput(ItemStack aStack) {
- return GT_Utility.arrayContainsNonNull(
- GT_ModHandler.getMachineOutput(
- GT_Utility.copyAmount(64, aStack),
- ic2.api.recipe.Recipes.extractor.getRecipes(),
- false,
- new NBTTagCompound(),
- null,
- null,
- null));
- }
- }
-
- /**
- * Special Class for Thermal Centrifuge Recipe handling.
- */
- public static class GT_Recipe_Map_ThermalCentrifuge extends GT_Recipe_Map_NonGTRecipes {
-
- public GT_Recipe_Map_ThermalCentrifuge(Collection<GT_Recipe> aRecipeList, String aUnlocalizedName,
- String aLocalName, String aNEIName, String aNEIGUIPath, int aUsualInputCount, int aUsualOutputCount,
- int aMinimalInputItems, int aMinimalInputFluids, int aAmperage, String aNEISpecialValuePre,
- int aNEISpecialValueMultiplier, String aNEISpecialValuePost, boolean aShowVoltageAmperageInNEI,
- boolean aNEIAllowed) {
- super(
- aRecipeList,
- aUnlocalizedName,
- aLocalName,
- aNEIName,
- aNEIGUIPath,
- aUsualInputCount,
- aUsualOutputCount,
- aMinimalInputItems,
- aMinimalInputFluids,
- aAmperage,
- aNEISpecialValuePre,
- aNEISpecialValueMultiplier,
- aNEISpecialValuePost,
- aShowVoltageAmperageInNEI,
- aNEIAllowed);
- }
-
- @Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return null;
- if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs)) return aRecipe;
- ItemStack tComparedInput = GT_Utility.copyOrNull(aInputs[0]);
- ItemStack[] tOutputItems = GT_ModHandler.getMachineOutput(
- tComparedInput,
- ic2.api.recipe.Recipes.centrifuge.getRecipes(),
- true,
- new NBTTagCompound(),
- null,
- null,
- null);
- return GT_Utility.arrayContainsNonNull(tOutputItems)
- ? new GT_Recipe(
- false,
- new ItemStack[] {
- GT_Utility.copyAmount(aInputs[0].stackSize - tComparedInput.stackSize, aInputs[0]) },
- tOutputItems,
- null,
- null,
- null,
- null,
- 400,
- 48,
- 0)
- : null;
- }
-
- @Override
- public boolean containsInput(ItemStack aStack) {
- return GT_Utility.arrayContainsNonNull(
- GT_ModHandler.getMachineOutput(
- GT_Utility.copyAmount(64, aStack),
- ic2.api.recipe.Recipes.centrifuge.getRecipes(),
- false,
- new NBTTagCompound(),
- null,
- null,
- null));
- }
- }
-
- /**
- * Special Class for Ore Washer Recipe handling.
- */
- public static class GT_Recipe_Map_OreWasher extends GT_Recipe_Map_NonGTRecipes {
-
- public GT_Recipe_Map_OreWasher(Collection<GT_Recipe> aRecipeList, String aUnlocalizedName, String aLocalName,
- String aNEIName, String aNEIGUIPath, int aUsualInputCount, int aUsualOutputCount, int aMinimalInputItems,
- int aMinimalInputFluids, int aAmperage, String aNEISpecialValuePre, int aNEISpecialValueMultiplier,
- String aNEISpecialValuePost, boolean aShowVoltageAmperageInNEI, boolean aNEIAllowed) {
- super(
- aRecipeList,
- aUnlocalizedName,
- aLocalName,
- aNEIName,
- aNEIGUIPath,
- aUsualInputCount,
- aUsualOutputCount,
- aMinimalInputItems,
- aMinimalInputFluids,
- aAmperage,
- aNEISpecialValuePre,
- aNEISpecialValueMultiplier,
- aNEISpecialValuePost,
- aShowVoltageAmperageInNEI,
- aNEIAllowed);
- }
-
- @Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- if (aInputs == null || aInputs.length == 0
- || aInputs[0] == null
- || aFluids == null
- || aFluids.length < 1
- || !GT_ModHandler.isWater(aFluids[0])) return null;
- if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs)) return aRecipe;
- ItemStack tComparedInput = GT_Utility.copyOrNull(aInputs[0]);
- NBTTagCompound aRecipeMetaData = new NBTTagCompound();
- ItemStack[] tOutputItems = GT_ModHandler.getMachineOutput(
- tComparedInput,
- ic2.api.recipe.Recipes.oreWashing.getRecipes(),
- true,
- aRecipeMetaData,
- null,
- null,
- null);
- return GT_Utility.arrayContainsNonNull(tOutputItems)
- ? new GT_Recipe(
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
+ if (aInputs == null || aInputs.length == 0 || aInputs[0] == null) return NOT_FOUND;
+ if (aRecipe != null && aRecipe.isRecipeInputEqual(false, true, aFluids, aInputs))
+ return FindRecipeResult.ofSuccess(aRecipe);
+ return FindRecipeResult.ofSuccess(
+ new GT_Recipe(
false,
- new ItemStack[] {
- GT_Utility.copyAmount(aInputs[0].stackSize - tComparedInput.stackSize, aInputs[0]) },
- tOutputItems,
+ new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
+ new ItemStack[] { GT_ModHandler.getRecyclerOutput(aInputs[0], 0) },
null,
+ new int[] { 1250 },
null,
- new FluidStack[] { new FluidStack(
- aFluids[0].getFluid(),
- ((NBTTagCompound) aRecipeMetaData.getTag("return")).getInteger("amount")) },
null,
- 400,
- 16,
- 0)
- : null;
+ 45,
+ 1,
+ 0));
}
@Override
public boolean containsInput(ItemStack aStack) {
- return GT_Utility.arrayContainsNonNull(
- GT_ModHandler.getMachineOutput(
- GT_Utility.copyAmount(64, aStack),
- ic2.api.recipe.Recipes.oreWashing.getRecipes(),
- false,
- new NBTTagCompound(),
- null,
- null,
- null));
- }
-
- @Override
- public boolean containsInput(FluidStack aFluid) {
- return GT_ModHandler.isWater(aFluid);
- }
-
- @Override
- public boolean containsInput(Fluid aFluid) {
- return GT_ModHandler.isWater(new FluidStack(aFluid, 0));
+ return GT_ModHandler.getRecyclerOutput(aStack, 0) != null;
}
}
@@ -5544,20 +5327,36 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
if (aInputs == null || aInputs.length == 0 || aInputs[0] == null || !GregTech_API.sPostloadFinished)
- return super.findRecipe(aTileEntity, aRecipe, aNotUnificated, aVoltage, aFluids, aSpecialSlot, aInputs);
- aRecipe = super.findRecipe(aTileEntity, aRecipe, aNotUnificated, aVoltage, aFluids, aSpecialSlot, aInputs);
- if (aRecipe != null) return aRecipe;
+ return super.findRecipeWithResult(
+ aRecipe,
+ aNotUnificated,
+ aDontCheckStackSizes,
+ aVoltage,
+ aFluids,
+ aSpecialSlot,
+ aInputs);
+ FindRecipeResult result = super.findRecipeWithResult(
+ aRecipe,
+ aNotUnificated,
+ aDontCheckStackSizes,
+ aVoltage,
+ aFluids,
+ aSpecialSlot,
+ aInputs);
+ if (result.isSuccessful()) return result;
try {
List<ItemStack> tRecipeOutputs = mods.railcraft.api.crafting.RailcraftCraftingManager.rockCrusher
.getRecipe(GT_Utility.copyAmount(1, aInputs[0]))
.getRandomizedOuputs();
if (tRecipeOutputs != null) {
- aRecipe = new GT_Recipe(
+ GT_Recipe recipe = new GT_Recipe(
false,
new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
tRecipeOutputs.toArray(new ItemStack[0]),
@@ -5568,9 +5367,9 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
800,
2,
0);
- aRecipe.mCanBeBuffered = false;
- aRecipe.mNeedsEmptyOutput = true;
- return aRecipe;
+ recipe.mCanBeBuffered = false;
+ recipe.mNeedsEmptyOutput = true;
+ return FindRecipeResult.ofSuccess(recipe);
}
} catch (NoClassDefFoundError e) {
if (D1) GT_Log.err.println("Railcraft Not loaded");
@@ -5587,20 +5386,22 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
null,
null,
null);
- return GT_Utility.arrayContainsNonNull(tOutputItems)
- ? new GT_Recipe(
- false,
- new ItemStack[] {
- GT_Utility.copyAmount(aInputs[0].stackSize - tComparedInput.stackSize, aInputs[0]) },
- tOutputItems,
- null,
- null,
- null,
- null,
- 400,
- 2,
- 0)
- : null;
+ if (tComparedInput != null && GT_Utility.arrayContainsNonNull(tOutputItems)) {
+ return FindRecipeResult.ofSuccess(
+ new GT_Recipe(
+ false,
+ new ItemStack[] {
+ GT_Utility.copyAmount(aInputs[0].stackSize - tComparedInput.stackSize, aInputs[0]) },
+ tOutputItems,
+ null,
+ null,
+ null,
+ null,
+ 400,
+ 2,
+ 0));
+ }
+ return NOT_FOUND;
}
@Override
@@ -5644,11 +5445,20 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
- GT_Recipe rRecipe = super.findRecipe(aTileEntity, aRecipe, true, aVoltage, aFluids, aSpecialSlot, aInputs);
+ FindRecipeResult result = super.findRecipeWithResult(
+ aRecipe,
+ true,
+ aDontCheckStackSizes,
+ aVoltage,
+ aFluids,
+ aSpecialSlot,
+ aInputs);
/*
* Doesnt work, keep it as a reminder tho if (rRecipe == null){ Set<ItemStack> aInputs2 = new
* TreeSet<ItemStack>(); for (ItemStack aInput : aInputs) { aInputs2.add(aInput); } for (ItemStack aInput :
@@ -5662,9 +5472,10 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
*/
if (aInputs == null || aInputs.length == 0
|| aInputs[0] == null
- || rRecipe == null
- || !GregTech_API.sPostloadFinished) return rRecipe;
+ || !result.isSuccessful()
+ || !GregTech_API.sPostloadFinished) return result;
+ GT_Recipe rRecipe = result.getRecipeNonNull();
for (ItemStack aInput : aInputs) {
if (ItemList.Paper_Printed_Pages.isStackEqual(aInput, false, true)) {
rRecipe = rRecipe.copy();
@@ -5672,7 +5483,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
rRecipe.mOutputs[0].setTagCompound(aInput.getTagCompound());
}
}
- return rRecipe;
+ return FindRecipeResult.ofSuccess(rRecipe);
}
}
@@ -5703,12 +5514,12 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
ItemStack... aInputs) {
- GT_Recipe rRecipe = super.findRecipe(
- aTileEntity,
+ FindRecipeResult result = super.findRecipeWithResult(
aRecipe,
aNotUnificated,
aDontCheckStackSizes,
@@ -5716,8 +5527,10 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aFluids,
aSpecialSlot,
aInputs);
- if (aInputs == null || aInputs.length < 2 || !GregTech_API.sPostloadFinished) return rRecipe;
- if (rRecipe == null) return findRenamingRecipe(aInputs);
+ if (aInputs == null || aInputs.length < 2 || !GregTech_API.sPostloadFinished) return result;
+ if (!result.isSuccessful()) {
+ return findRenamingRecipe(aInputs);
+ }
for (ItemStack aMold : aInputs) {
if (ItemList.Shape_Mold_Credit.isStackEqual(aMold, false, true)) {
NBTTagCompound tNBT = aMold.getTagCompound();
@@ -5725,13 +5538,14 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
if (!tNBT.hasKey("credit_security_id")) tNBT.setLong("credit_security_id", System.nanoTime());
aMold.setTagCompound(tNBT);
+ GT_Recipe rRecipe = result.getRecipeNonNull();
rRecipe = rRecipe.copy();
rRecipe.mCanBeBuffered = false;
rRecipe.mOutputs[0].setTagCompound(tNBT);
- return rRecipe;
+ return FindRecipeResult.ofSuccess(rRecipe);
}
}
- return rRecipe;
+ return result;
}
private ItemStack findNameMoldIndex(ItemStack[] inputs) {
@@ -5749,12 +5563,14 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
return null;
}
- private GT_Recipe findRenamingRecipe(ItemStack[] inputs) {
+ @Nonnull
+ private FindRecipeResult findRenamingRecipe(ItemStack[] inputs) {
ItemStack mold = findNameMoldIndex(inputs);
- if (mold == null) return null;
+ if (mold == null) return NOT_FOUND;
ItemStack input = findStackToRename(inputs, mold);
- if (input == null) return null;
+ if (input == null) return NOT_FOUND;
ItemStack output = GT_Utility.copyAmount(1, input);
+ if (output == null) return NOT_FOUND;
output.setStackDisplayName(mold.getDisplayName());
GT_Recipe recipe = new GT_Recipe(
false,
@@ -5768,7 +5584,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
8,
0);
recipe.mCanBeBuffered = false;
- return recipe;
+ return FindRecipeResult.ofSuccess(recipe);
}
}
@@ -5799,13 +5615,15 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aNEIAllowed);
}
+ @Nonnull
@Override
- public GT_Recipe findRecipe(IHasWorldObjectAndCoords aTileEntity, GT_Recipe aRecipe, boolean aNotUnificated,
- long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot, ItemStack... aInputs) {
- GT_Recipe rRecipe = super.findRecipe(
- aTileEntity,
+ public FindRecipeResult findRecipeWithResult(GT_Recipe aRecipe, boolean aNotUnificated,
+ boolean aDontCheckStackSizes, long aVoltage, FluidStack[] aFluids, ItemStack aSpecialSlot,
+ ItemStack... aInputs) {
+ FindRecipeResult result = super.findRecipeWithResult(
aRecipe,
aNotUnificated,
+ aDontCheckStackSizes,
aVoltage,
aFluids,
aSpecialSlot,
@@ -5815,7 +5633,7 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
|| aFluids == null
|| aFluids.length == 0
|| aFluids[0] == null
- || !GregTech_API.sPostloadFinished) return rRecipe;
+ || !GregTech_API.sPostloadFinished) return result;
Dyes aDye = null;
for (Dyes tDye : Dyes.VALUES) if (tDye.isFluidDye(aFluids[0])) {
@@ -5823,11 +5641,11 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
break;
}
- if (aDye == null) return rRecipe;
+ if (aDye == null) return result;
- if (rRecipe == null) {
+ if (!result.isSuccessful()) {
ItemStack tOutput = GT_ModHandler.getAllRecipeOutput(
- aTileEntity == null ? null : aTileEntity.getWorld(),
+ null,
aInputs[0],
aInputs[0],
aInputs[0],
@@ -5837,67 +5655,72 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
aInputs[0],
aInputs[0],
aInputs[0]);
- if (tOutput != null) return addRecipe(
- new GT_Recipe(
- true,
- new ItemStack[] { GT_Utility.copyAmount(8, aInputs[0]) },
- new ItemStack[] { tOutput },
- null,
- null,
- new FluidStack[] { new FluidStack(aFluids[0].getFluid(), (int) L) },
- null,
- 256,
- 2,
- 0),
- false,
- false,
- true);
+ if (tOutput != null) {
+ GT_Recipe recipe = addRecipe(
+ new GT_Recipe(
+ true,
+ new ItemStack[] { GT_Utility.copyAmount(8, aInputs[0]) },
+ new ItemStack[] { tOutput },
+ null,
+ null,
+ new FluidStack[] { new FluidStack(aFluids[0].getFluid(), (int) L) },
+ null,
+ 256,
+ 2,
+ 0),
+ false,
+ false,
+ true);
+ return recipe != null ? FindRecipeResult.ofSuccess(recipe) : NOT_FOUND;
+ }
- tOutput = GT_ModHandler.getAllRecipeOutput(
- aTileEntity == null ? null : aTileEntity.getWorld(),
- aInputs[0],
- ItemList.DYE_ONLY_ITEMS[aDye.mIndex].get(1));
- if (tOutput != null) return addRecipe(
- new GT_Recipe(
- true,
- new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
- new ItemStack[] { tOutput },
- null,
- null,
- new FluidStack[] { new FluidStack(aFluids[0].getFluid(), (int) L) },
- null,
- 32,
- 2,
- 0),
- false,
- false,
- true);
+ tOutput = GT_ModHandler
+ .getAllRecipeOutput(null, aInputs[0], ItemList.DYE_ONLY_ITEMS[aDye.mIndex].get(1));
+ if (tOutput != null) {
+ GT_Recipe recipe = addRecipe(
+ new GT_Recipe(
+ true,
+ new ItemStack[] { GT_Utility.copyAmount(1, aInputs[0]) },
+ new ItemStack[] { tOutput },
+ null,
+ null,
+ new FluidStack[] { new FluidStack(aFluids[0].getFluid(), (int) L) },
+ null,
+ 32,
+ 2,
+ 0),
+ false,
+ false,
+ true);
+ return recipe != null ? FindRecipeResult.ofSuccess(recipe) : NOT_FOUND;
+ }
} else {
+ GT_Recipe rRecipe = result.getRecipeNonNull();
if (aInputs[0].getItem() == Items.paper) {
- if (!ItemList.Tool_DataStick.isStackEqual(aSpecialSlot, false, true)) return null;
+ if (!ItemList.Tool_DataStick.isStackEqual(aSpecialSlot, false, true)) return NOT_FOUND;
NBTTagCompound tNBT = aSpecialSlot.getTagCompound();
if (tNBT == null || GT_Utility.isStringInvalid(tNBT.getString("title"))
- || GT_Utility.isStringInvalid(tNBT.getString("author"))) return null;
+ || GT_Utility.isStringInvalid(tNBT.getString("author"))) return NOT_FOUND;
rRecipe = rRecipe.copy();
rRecipe.mCanBeBuffered = false;
rRecipe.mOutputs[0].setTagCompound(tNBT);
- return rRecipe;
+ return FindRecipeResult.ofSuccess(rRecipe);
}
if (aInputs[0].getItem() == Items.map) {
- if (!ItemList.Tool_DataStick.isStackEqual(aSpecialSlot, false, true)) return null;
+ if (!ItemList.Tool_DataStick.isStackEqual(aSpecialSlot, false, true)) return NOT_FOUND;
NBTTagCompound tNBT = aSpecialSlot.getTagCompound();
- if (tNBT == null || !tNBT.hasKey("map_id")) return null;
+ if (tNBT == null || !tNBT.hasKey("map_id")) return NOT_FOUND;
rRecipe = rRecipe.copy();
rRecipe.mCanBeBuffered = false;
rRecipe.mOutputs[0].setItemDamage(tNBT.getShort("map_id"));
- return rRecipe;
+ return FindRecipeResult.ofSuccess(rRecipe);
}
if (ItemList.Paper_Punch_Card_Empty.isStackEqual(aInputs[0], false, true)) {
- if (!ItemList.Tool_DataStick.isStackEqual(aSpecialSlot, false, true)) return null;
+ if (!ItemList.Tool_DataStick.isStackEqual(aSpecialSlot, false, true)) return NOT_FOUND;
NBTTagCompound tNBT = aSpecialSlot.getTagCompound();
- if (tNBT == null || !tNBT.hasKey("GT.PunchCardData")) return null;
+ if (tNBT == null || !tNBT.hasKey("GT.PunchCardData")) return NOT_FOUND;
rRecipe = rRecipe.copy();
rRecipe.mCanBeBuffered = false;
@@ -5906,10 +5729,10 @@ public class GT_Recipe implements Comparable<GT_Recipe> {
new NBTTagCompound(),
"GT.PunchCardData",
tNBT.getString("GT.PunchCardData")));
- return rRecipe;
+ return FindRecipeResult.ofSuccess(rRecipe);
}
}
- return rRecipe;
+ return result;
}
@Override
diff --git a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java
deleted file mode 100644
index f939275e6c..0000000000
--- a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check.java
+++ /dev/null
@@ -1,421 +0,0 @@
-package gregtech.api.util;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.function.Function;
-
-import javax.annotation.Nullable;
-
-import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTBase;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraft.nbt.NBTTagList;
-import net.minecraftforge.common.util.Constants;
-import net.minecraftforge.fluids.Fluid;
-import net.minecraftforge.fluids.FluidRegistry;
-import net.minecraftforge.fluids.FluidStack;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Maps;
-
-import gregtech.api.enums.GT_Values;
-import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
-
-/** Used by machines that are locked to a single recipe, for fast computation. */
-public class GT_Single_Recipe_Check {
-
- protected final GT_MetaTileEntity_MultiBlockBase multiBlockBase;
- protected final GT_Recipe recipe;
- protected final ImmutableMap<GT_Utility.ItemId, Integer> itemCost;
- protected final ImmutableMap<Fluid, Integer> fluidCost;
-
- protected final int totalItemCost;
- protected final int totalFluidCost;
-
- protected GT_Single_Recipe_Check(GT_MetaTileEntity_MultiBlockBase multiBlockBase, GT_Recipe recipe,
- ImmutableMap<GT_Utility.ItemId, Integer> itemCost, ImmutableMap<Fluid, Integer> fluidCost) {
- this.multiBlockBase = multiBlockBase;
- this.recipe = recipe;
- this.itemCost = itemCost;
- this.fluidCost = fluidCost;
-
- this.totalItemCost = itemCost.values()
- .stream()
- .mapToInt(Integer::intValue)
- .sum();
- this.totalFluidCost = fluidCost.values()
- .stream()
- .mapToInt(Integer::intValue)
- .sum();
- }
-
- public GT_Recipe getRecipe() {
- return recipe;
- }
-
- /**
- * Use this method if recipes cannot require more than a single stack of any item or fluid. In particular,
- * {@link GT_MetaTileEntity_MultiBlockBase#getCompactedInputs()} and
- * {@link GT_MetaTileEntity_MultiBlockBase#getCompactedFluids()} both enforce this single-stack restriction, so any
- * multi-block that calls those can use this method.
- */
- @SuppressWarnings("JavadocReference")
- public boolean checkRecipeInputsSingleStack(boolean consumeInputs) {
- Map<GT_Utility.ItemId, ItemStack> itemMap = null;
- if (totalItemCost > 0) {
- itemMap = new HashMap<>();
- for (ItemStack itemStack : multiBlockBase.getStoredInputs()) {
- itemMap.merge(
- GT_Utility.ItemId.createNoCopy(itemStack),
- itemStack,
- (a, b) -> a.stackSize >= b.stackSize ? a : b);
- }
-
- for (Map.Entry<GT_Utility.ItemId, Integer> entry : itemCost.entrySet()) {
- ItemStack itemStack = itemMap.get(entry.getKey());
- if (itemStack == null || itemStack.stackSize < entry.getValue()) {
- return false;
- }
- }
- }
-
- Map<Fluid, FluidStack> fluidMap = null;
- if (totalFluidCost > 0) {
- fluidMap = new HashMap<>();
- for (FluidStack fluidStack : multiBlockBase.getStoredFluids()) {
- fluidMap.merge(fluidStack.getFluid(), fluidStack, (a, b) -> a.amount >= b.amount ? a : b);
- }
-
- for (Map.Entry<Fluid, Integer> entry : fluidCost.entrySet()) {
- FluidStack fluidStack = fluidMap.get(entry.getKey());
- if (fluidStack == null || fluidStack.amount < entry.getValue()) {
- return false;
- }
- }
- }
-
- if (consumeInputs) {
- if (totalItemCost > 0) {
- for (Map.Entry<GT_Utility.ItemId, Integer> entry : itemCost.entrySet()) {
- itemMap.get(entry.getKey()).stackSize -= entry.getValue();
- }
- }
-
- if (totalFluidCost > 0) {
- for (Map.Entry<Fluid, Integer> entry : fluidCost.entrySet()) {
- fluidMap.get(entry.getKey()).amount -= entry.getValue();
- }
- }
- }
-
- return true;
- }
-
- /**
- * Use this method if recipes can require more than a single stack of any item or fluid. It is less efficient,
- * though.
- */
- public boolean checkRecipeInputs(boolean consumeInputs) {
- List<ItemStack> items = null;
- if (totalItemCost > 0) {
- items = multiBlockBase.getStoredInputs();
-
- Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>();
- for (ItemStack itemStack : items) {
- itemMap.merge(GT_Utility.ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
- }
-
- for (Map.Entry<GT_Utility.ItemId, Integer> entry : itemCost.entrySet()) {
- if (itemMap.getOrDefault(entry.getKey(), 0) < entry.getValue()) {
- return false;
- }
- }
- }
-
- List<FluidStack> fluids = null;
- if (totalFluidCost > 0) {
- fluids = multiBlockBase.getStoredFluids();
-
- Map<Fluid, Integer> fluidMap = new HashMap<>();
- for (FluidStack fluidStack : fluids) {
- fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
- }
-
- for (Map.Entry<Fluid, Integer> entry : fluidCost.entrySet()) {
- if (fluidMap.getOrDefault(entry.getKey(), 0) < entry.getValue()) {
- return false;
- }
- }
- }
-
- if (consumeInputs) {
- if (totalItemCost > 0) {
- int remainingItemCost = totalItemCost;
- Map<GT_Utility.ItemId, Integer> runningItemCost = Maps.newHashMap(itemCost);
- for (ItemStack itemStack : items) {
- GT_Utility.ItemId key = GT_Utility.ItemId.createNoCopy(itemStack);
- int runningCost = runningItemCost.getOrDefault(key, 0);
- int paid = Math.min(itemStack.stackSize, runningCost);
- itemStack.stackSize -= paid;
- runningItemCost.put(key, runningCost - paid);
-
- remainingItemCost -= paid;
- if (remainingItemCost <= 0) {
- break;
- }
- }
- }
-
- if (totalFluidCost > 0) {
- int remainingFluidCost = totalFluidCost;
- Map<Fluid, Integer> runningFluidCost = Maps.newHashMap(fluidCost);
- for (FluidStack fluidStack : fluids) {
- Fluid key = fluidStack.getFluid();
- int runningCost = runningFluidCost.getOrDefault(key, 0);
- int paid = Math.min(fluidStack.amount, runningCost);
- fluidStack.amount -= paid;
- runningFluidCost.put(key, runningCost - paid);
-
- remainingFluidCost -= paid;
- if (remainingFluidCost <= 0) {
- break;
- }
- }
- }
- }
-
- return true;
- }
-
- public NBTTagCompound writeToNBT() {
- // here we encode recipe input, output and all other important values
- // at load time we do a recipe check again, so in case the recipe is gone, we can stop tracking
- // of course the next step would be auto migrating to new recipe (if any), but given
- // we don't yet have a mean to uniquely name a recipe, this will have to make do.
- // consider move serialization code to GT_Recipe once this has been proven to work
- NBTTagCompound tag = new NBTTagCompound();
- if (recipe == null) return tag;
-
- if (recipe.mInputs != null) {
- tag.setTag("inputs", writeList(recipe.mInputs, GT_Utility::saveItem));
- }
- if (recipe.mOutputs != null) {
- tag.setTag("outputs", writeList(recipe.mOutputs, GT_Utility::saveItem));
- }
- if (recipe.mChances != null) {
- tag.setIntArray("chances", recipe.mChances);
- }
- if (recipe.mFluidInputs != null) {
- tag.setTag(
- "fInputs",
- writeList(
- recipe.mFluidInputs,
- s -> s == null ? new NBTTagCompound() : s.writeToNBT(new NBTTagCompound())));
- }
- if (recipe.mFluidOutputs != null) {
- tag.setTag(
- "fOutputs",
- writeList(
- recipe.mFluidOutputs,
- s -> s == null ? new NBTTagCompound() : s.writeToNBT(new NBTTagCompound())));
- }
- tag.setInteger("eut", recipe.mEUt);
- tag.setInteger("duration", recipe.mDuration);
- tag.setInteger("specialValue", recipe.mSpecialValue);
- if (itemCost != null) {
- tag.setTag("itemCost", writeList(itemCost.entrySet(), e -> {
- NBTTagCompound ret = new NBTTagCompound();
- ret.setTag(
- "id",
- e.getKey()
- .writeToNBT());
- ret.setInteger("count", e.getValue());
- return ret;
- }));
- }
- if (fluidCost != null) {
- tag.setTag("fluidCost", writeList(fluidCost.entrySet(), e -> {
- NBTTagCompound ret = new NBTTagCompound();
- ret.setString(
- "id",
- e.getKey()
- .getName());
- ret.setInteger("count", e.getValue());
- return ret;
- }));
- }
- return tag;
- }
-
- private static <T, NBT extends NBTBase> NBTTagList writeList(T[] arr, Function<T, NBT> ser) {
- return writeList(Arrays.asList(arr), ser);
- }
-
- private static <T, NBT extends NBTBase> NBTTagList writeList(Collection<T> arr, Function<T, NBT> ser) {
- NBTTagList l = new NBTTagList();
- for (T t : arr) {
- l.appendTag(ser.apply(t));
- }
- return l;
- }
-
- @Nullable
- public static GT_Single_Recipe_Check tryLoad(GT_MetaTileEntity_MultiBlockBase parent, NBTTagCompound tag) {
- return tryLoad(parent, parent.getRecipeMap(), tag);
- }
-
- @Nullable
-
- public static GT_Single_Recipe_Check tryLoad(GT_MetaTileEntity_MultiBlockBase parent,
- GT_Recipe.GT_Recipe_Map recipeMap, NBTTagCompound tag) {
- GT_Recipe found = tryFindRecipe(parent, recipeMap, tag);
- if (found == null) return null;
- return new GT_Single_Recipe_Check(parent, found, loadItemCost(tag), loadFluidCost(tag));
- }
-
- protected static ImmutableMap<Fluid, Integer> loadFluidCost(NBTTagCompound tag) {
- return GT_Utility.streamCompounds(tag.getTagList("fluidCost", Constants.NBT.TAG_COMPOUND))
- .collect(
- GT_Utility
- .toImmutableMapSerial(t -> FluidRegistry.getFluid(t.getString("id")), t -> t.getInteger("count")));
- }
-
- protected static ImmutableMap<GT_Utility.ItemId, Integer> loadItemCost(NBTTagCompound tag) {
- return GT_Utility.streamCompounds(tag.getTagList("itemCost", Constants.NBT.TAG_COMPOUND))
- .collect(
- GT_Utility.toImmutableMapSerial(
- t -> GT_Utility.ItemId.create(t.getCompoundTag("id")),
- t -> t.getInteger("count")));
- }
-
- protected static GT_Recipe tryFindRecipe(GT_MetaTileEntity_MultiBlockBase parent, GT_Recipe.GT_Recipe_Map recipeMap,
- NBTTagCompound tag) {
- if (tag == null || tag.hasNoTags()) return null;
- ItemStack[] inputs = GT_Utility.streamCompounds(tag.getTagList("inputs", Constants.NBT.TAG_COMPOUND))
- .map(GT_Utility::loadItem)
- .toArray(ItemStack[]::new);
- ItemStack[] outputs = GT_Utility.streamCompounds(tag.getTagList("outputs", Constants.NBT.TAG_COMPOUND))
- .map(GT_Utility::loadItem)
- .toArray(ItemStack[]::new);
- FluidStack[] fInputs = GT_Utility.streamCompounds(tag.getTagList("fInputs", Constants.NBT.TAG_COMPOUND))
- .map(FluidStack::loadFluidStackFromNBT)
- .toArray(FluidStack[]::new);
- FluidStack[] fOutputs = GT_Utility.streamCompounds(tag.getTagList("fOutputs", Constants.NBT.TAG_COMPOUND))
- .map(FluidStack::loadFluidStackFromNBT)
- .toArray(FluidStack[]::new);
- int eut = tag.getInteger("eut");
- GT_Recipe found = recipeMap
- .findRecipe(parent.getBaseMetaTileEntity(), false, GT_Values.V[GT_Utility.getTier(eut)], fInputs, inputs);
- int[] chances = tag.getIntArray("chances");
- if (chances.length == 0) chances = null;
- if (found == null || !GT_Utility.equals(inputs, found.mInputs)
- || !Arrays.equals(fInputs, found.mFluidInputs)
- || !GT_Utility.equals(outputs, found.mOutputs)
- || !Arrays.equals(fOutputs, found.mFluidOutputs)
- || !Arrays.equals(chances, found.mChances)
- || found.mDuration != tag.getInteger("duration")
- || found.mEUt != eut
- || found.mSpecialValue != tag.getInteger("specialValue")) return null;
- return found;
- }
-
- protected static Map<GT_Utility.ItemId, Integer> buildItemMap(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
- Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>();
- for (ItemStack itemStack : multiBlockBase.getStoredInputs()) {
- itemMap.merge(GT_Utility.ItemId.create(itemStack), itemStack.stackSize, Integer::sum);
- }
- return itemMap;
- }
-
- protected static Map<Fluid, Integer> buildFluidMap(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
- Map<Fluid, Integer> fluidMap = new HashMap<>();
- for (FluidStack fluidStack : multiBlockBase.getStoredFluids()) {
- fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
- }
- return fluidMap;
- }
-
- public static Builder builder(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
- return new Builder(multiBlockBase);
- }
-
- public static final class Builder {
-
- private final GT_MetaTileEntity_MultiBlockBase multiBlockBase;
-
- // In order to compute which items and fluids are consumed by the recipe, we compare the
- // multi-block's items and fluids before and after inputs are consumed by the recipe.
- private Map<GT_Utility.ItemId, Integer> beforeItems;
- private Map<Fluid, Integer> beforeFluids;
- private Map<GT_Utility.ItemId, Integer> afterItems;
- private Map<Fluid, Integer> afterFluids;
-
- private GT_Recipe recipe;
-
- private Builder(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
- this.multiBlockBase = multiBlockBase;
- }
-
- /** Call this before inputs are consumed by the recipe. */
- public Builder setBefore(ItemStack[] inputs, FluidStack[] fluids) {
- beforeItems = buildItemMapDirect(inputs);
- beforeFluids = buildFluidMapDirect(fluids);
- return this;
- }
-
- /** Call this after inputs are consumed by the recipe. */
- public Builder setAfter(ItemStack[] inputs, FluidStack[] fluids) {
- afterItems = buildItemMapDirect(inputs);
- afterFluids = buildFluidMapDirect(fluids);
- return this;
- }
-
- public Builder setRecipe(GT_Recipe recipe) {
- this.recipe = recipe;
- return this;
- }
-
- static Map<GT_Utility.ItemId, Integer> buildItemMapDirect(ItemStack[] inputs) {
- Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>();
- for (ItemStack itemStack : inputs) {
- itemMap.merge(GT_Utility.ItemId.create(itemStack), itemStack.stackSize, Integer::sum);
- }
- return itemMap;
- }
-
- static Map<Fluid, Integer> buildFluidMapDirect(FluidStack[] fluids) {
- Map<Fluid, Integer> fluidMap = new HashMap<>();
- for (FluidStack fluidStack : fluids) {
- fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
- }
- return fluidMap;
- }
-
- public GT_Single_Recipe_Check build() {
- ImmutableMap.Builder<GT_Utility.ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
- for (Map.Entry<GT_Utility.ItemId, Integer> entry : beforeItems.entrySet()) {
- int cost = entry.getValue() - afterItems.getOrDefault(entry.getKey(), 0);
- if (cost > 0) {
- itemCostBuilder.put(entry.getKey(), cost);
- }
- }
-
- ImmutableMap.Builder<Fluid, Integer> fluidCostBuilder = ImmutableMap.builder();
- for (Map.Entry<Fluid, Integer> entry : beforeFluids.entrySet()) {
- int cost = entry.getValue() - afterFluids.getOrDefault(entry.getKey(), 0);
- if (cost > 0) {
- fluidCostBuilder.put(entry.getKey(), cost);
- }
- }
-
- return new GT_Single_Recipe_Check(
- multiBlockBase,
- recipe,
- itemCostBuilder.build(),
- fluidCostBuilder.build());
- }
- }
-}
diff --git a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java b/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java
deleted file mode 100644
index ad0ca76a6d..0000000000
--- a/src/main/java/gregtech/api/util/GT_Single_Recipe_Check_Processing_Array.java
+++ /dev/null
@@ -1,244 +0,0 @@
-package gregtech.api.util;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.stream.Collectors;
-
-import javax.annotation.Nullable;
-
-import net.minecraft.item.ItemStack;
-import net.minecraft.nbt.NBTTagCompound;
-import net.minecraftforge.fluids.Fluid;
-import net.minecraftforge.fluids.FluidStack;
-
-import com.google.common.collect.ImmutableMap;
-
-import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
-
-/** Processing Array-specialized version of {@link gregtech.api.util.GT_Single_Recipe_Check}. */
-public class GT_Single_Recipe_Check_Processing_Array extends GT_Single_Recipe_Check {
-
- protected final int recipeAmperage;
-
- /**
- * The machine type that the locked recipe is for. We will not allow running with other machines.
- */
- protected final ItemStack machineStack;
-
- protected GT_Single_Recipe_Check_Processing_Array(GT_MetaTileEntity_MultiBlockBase multiBlockBase, GT_Recipe recipe,
- ImmutableMap<GT_Utility.ItemId, Integer> itemCost, ImmutableMap<Fluid, Integer> fluidCost, int recipeAmperage,
- ItemStack machineStack) {
- super(multiBlockBase, recipe, itemCost, fluidCost);
-
- this.recipeAmperage = recipeAmperage;
- this.machineStack = machineStack;
- }
-
- public int getRecipeAmperage() {
- return recipeAmperage;
- }
-
- @Override
- public boolean checkRecipeInputsSingleStack(boolean consumeInputs) {
- throw new UnsupportedOperationException("Use checkRecipeInputs(boolean, int) instead.");
- }
-
- @Override
- public boolean checkRecipeInputs(boolean consumeInputs) {
- throw new UnsupportedOperationException("Use checkRecipeInputs(boolean, int) instead.");
- }
-
- /** Returns the number of parallel recipes, or 0 if recipe is not satisfied at all. */
- public int checkRecipeInputs(boolean consumeInputs, int maxParallel) {
- if (!GT_Utility.areStacksEqual(machineStack, multiBlockBase.mInventory[1])) {
- // Machine stack was modified. This is not allowed, so stop processing.
- return 0;
- }
- int parallel = maxParallel;
-
- List<ItemStack> items = null;
- if (totalItemCost > 0) {
- items = multiBlockBase.getStoredInputs();
-
- Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>();
- for (ItemStack itemStack : items) {
- itemMap.merge(GT_Utility.ItemId.createNoCopy(itemStack), itemStack.stackSize, Integer::sum);
- }
-
- for (Map.Entry<GT_Utility.ItemId, Integer> entry : itemCost.entrySet()) {
- parallel = Math.min(parallel, itemMap.getOrDefault(entry.getKey(), 0) / entry.getValue());
- if (parallel <= 0) {
- return 0;
- }
- }
- }
-
- List<FluidStack> fluids = null;
- if (totalFluidCost > 0) {
- fluids = multiBlockBase.getStoredFluids();
-
- Map<Fluid, Integer> fluidMap = new HashMap<>();
- for (FluidStack fluidStack : fluids) {
- fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
- }
-
- for (Map.Entry<Fluid, Integer> entry : fluidCost.entrySet()) {
- parallel = Math.min(parallel, fluidMap.getOrDefault(entry.getKey(), 0) / entry.getValue());
- if (parallel <= 0) {
- return 0;
- }
- }
- }
-
- final int finalParallel = parallel;
- if (consumeInputs) {
- if (totalItemCost > 0) {
- int remainingItemCost = totalItemCost * finalParallel;
- Map<GT_Utility.ItemId, Integer> runningItemCost = itemCost.entrySet()
- .stream()
- .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue() * finalParallel));
-
- for (ItemStack itemStack : items) {
- GT_Utility.ItemId key = GT_Utility.ItemId.createNoCopy(itemStack);
- int runningCost = runningItemCost.getOrDefault(key, 0);
- int paid = Math.min(itemStack.stackSize, runningCost);
- itemStack.stackSize -= paid;
- runningItemCost.put(key, runningCost - paid);
-
- remainingItemCost -= paid;
- if (remainingItemCost <= 0) {
- break;
- }
- }
- }
-
- if (totalFluidCost > 0) {
- int remainingFluidCost = totalFluidCost * finalParallel;
- Map<Fluid, Integer> runningFluidCost = fluidCost.entrySet()
- .stream()
- .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue() * finalParallel));
-
- for (FluidStack fluidStack : fluids) {
- Fluid key = fluidStack.getFluid();
- int runningCost = runningFluidCost.getOrDefault(key, 0);
- int paid = Math.min(fluidStack.amount, runningCost);
- fluidStack.amount -= paid;
- runningFluidCost.put(key, runningCost - paid);
-
- remainingFluidCost -= paid;
- if (remainingFluidCost <= 0) {
- break;
- }
- }
- }
- }
-
- return finalParallel;
- }
-
- @Nullable
-
- public static GT_Single_Recipe_Check tryLoad(GT_MetaTileEntity_MultiBlockBase parent,
- GT_Recipe.GT_Recipe_Map recipeMap, NBTTagCompound tag, ItemStack machineStack) {
- if (recipeMap == null || machineStack == null) return null;
- GT_Recipe found = tryFindRecipe(parent, recipeMap, tag);
- if (found == null) return null;
- return new GT_Single_Recipe_Check_Processing_Array(
- parent,
- found,
- loadItemCost(tag),
- loadFluidCost(tag),
- recipeMap.mAmperage,
- machineStack.copy());
- }
-
- public static Builder processingArrayBuilder(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
- return new Builder(multiBlockBase);
- }
-
- public static final class Builder {
-
- private final GT_MetaTileEntity_MultiBlockBase multiBlockBase;
-
- // In order to compute which items and fluids are consumed by the recipe, we compare the
- // multi-block's items and fluids before and after inputs are consumed by the recipe.
- private Map<GT_Utility.ItemId, Integer> beforeItems;
- private Map<Fluid, Integer> beforeFluids;
- private Map<GT_Utility.ItemId, Integer> afterItems;
- private Map<Fluid, Integer> afterFluids;
-
- private GT_Recipe recipe;
- private int recipeAmperage;
-
- private Builder(GT_MetaTileEntity_MultiBlockBase multiBlockBase) {
- this.multiBlockBase = multiBlockBase;
- }
-
- /** Call this before inputs are consumed by the recipe. */
- public Builder setBefore(ItemStack[] inputs, FluidStack[] fluids) {
- beforeItems = buildItemMapDirect(inputs);
- beforeFluids = buildFluidMapDirect(fluids);
- return this;
- }
-
- static Map<GT_Utility.ItemId, Integer> buildItemMapDirect(ItemStack[] inputs) {
- Map<GT_Utility.ItemId, Integer> itemMap = new HashMap<>();
- for (ItemStack itemStack : inputs) {
- itemMap.merge(GT_Utility.ItemId.create(itemStack), itemStack.stackSize, Integer::sum);
- }
- return itemMap;
- }
-
- static Map<Fluid, Integer> buildFluidMapDirect(FluidStack[] fluids) {
- Map<Fluid, Integer> fluidMap = new HashMap<>();
- for (FluidStack fluidStack : fluids) {
- fluidMap.merge(fluidStack.getFluid(), fluidStack.amount, Integer::sum);
- }
- return fluidMap;
- }
-
- /** Call this after inputs are consumed by the recipe. */
- public Builder setAfter(ItemStack[] inputs, FluidStack[] fluids) {
- afterItems = buildItemMapDirect(inputs);
- afterFluids = buildFluidMapDirect(fluids);
- return this;
- }
-
- public Builder setRecipe(GT_Recipe recipe) {
- this.recipe = recipe;
- return this;
- }
-
- public Builder setRecipeAmperage(int recipeAmperage) {
- this.recipeAmperage = recipeAmperage;
- return this;
- }
-
- public GT_Single_Recipe_Check_Processing_Array build() {
- ImmutableMap.Builder<GT_Utility.ItemId, Integer> itemCostBuilder = ImmutableMap.builder();
- for (Map.Entry<GT_Utility.ItemId, Integer> entry : beforeItems.entrySet()) {
- int cost = entry.getValue() - afterItems.getOrDefault(entry.getKey(), 0);
- if (cost > 0) {
- itemCostBuilder.put(entry.getKey(), cost);
- }
- }
-
- ImmutableMap.Builder<Fluid, Integer> fluidCostBuilder = ImmutableMap.builder();
- for (Map.Entry<Fluid, Integer> entry : beforeFluids.entrySet()) {
- int cost = entry.getValue() - afterFluids.getOrDefault(entry.getKey(), 0);
- if (cost > 0) {
- fluidCostBuilder.put(entry.getKey(), cost);
- }
- }
-
- return new GT_Single_Recipe_Check_Processing_Array(
- multiBlockBase,
- recipe,
- itemCostBuilder.build(),
- fluidCostBuilder.build(),
- recipeAmperage,
- multiBlockBase.mInventory[1].copy());
- }
- }
-}
diff --git a/src/main/java/gregtech/api/util/GT_Utility.java b/src/main/java/gregtech/api/util/GT_Utility.java
index d891545122..108b9dc2d9 100644
--- a/src/main/java/gregtech/api/util/GT_Utility.java
+++ b/src/main/java/gregtech/api/util/GT_Utility.java
@@ -493,6 +493,16 @@ public class GT_Utility {
return ceilDiv(voltage, GT_Values.V[tier]);
}
+ /**
+ * Rounds down partial voltage that exceeds tiered voltage, e.g. 4096 -> 2048 (EV)
+ */
+ public static long roundDownVoltage(long voltage) {
+ if (voltage > V[V.length - 1]) {
+ return voltage;
+ }
+ return V[GT_Utility.getTier(voltage)];
+ }
+
public static String getColoredTierNameFromVoltage(long voltage) {
return getColoredTierNameFromTier(getTier(voltage));
}
@@ -501,6 +511,9 @@ public class GT_Utility {
return GT_Values.TIER_COLORS[tier] + GT_Values.VN[tier] + EnumChatFormatting.RESET;
}
+ /**
+ * @return e.g. {@code " (LV)"}
+ */
@Nonnull
public static String getTierNameWithParentheses(long voltage) {
byte tier = getTier(voltage);
@@ -1713,6 +1726,10 @@ public class GT_Utility {
|| Items.feather.getDamage(aStack2) == W);
}
+ public static boolean areStacksEqualOrNull(ItemStack stack1, ItemStack stack2) {
+ return (stack1 == null && stack2 == null) || GT_Utility.areStacksEqual(stack1, stack2);
+ }
+
/**
* Treat both null list, or both null item stack at same list position as equal.
* <p>
diff --git a/src/main/java/gregtech/api/util/VoidProtectionHelper.java b/src/main/java/gregtech/api/util/VoidProtectionHelper.java
index 94c2dfcaaf..3ca9621f06 100644
--- a/src/main/java/gregtech/api/util/VoidProtectionHelper.java
+++ b/src/main/java/gregtech/api/util/VoidProtectionHelper.java
@@ -243,6 +243,8 @@ public class VoidProtectionHelper {
Map<ItemStack, ParallelData> tParallels = new ItemStackMap<>();
int tSlotsFree = 0;
for (ItemStack tItem : itemOutputs) {
+ // GT_RecipeBuilder doesn't handle null item output
+ if (tItem == null) continue;
tItemOutputMap.merge(tItem, tItem.stackSize, Integer::sum);
tParallels.put(tItem, new ParallelData(0, 0));
}
diff --git a/src/main/java/gregtech/common/gui/modularui/widget/CheckRecipeResultSyncer.java b/src/main/java/gregtech/common/gui/modularui/widget/CheckRecipeResultSyncer.java
new file mode 100644
index 0000000000..9028c66be8
--- /dev/null
+++ b/src/main/java/gregtech/common/gui/modularui/widget/CheckRecipeResultSyncer.java
@@ -0,0 +1,26 @@
+package gregtech.common.gui.modularui.widget;
+
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+
+import com.gtnewhorizons.modularui.common.internal.network.NetworkUtils;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+
+public class CheckRecipeResultSyncer extends FakeSyncWidget<CheckRecipeResult> {
+
+ public CheckRecipeResultSyncer(Supplier<CheckRecipeResult> getter, Consumer<CheckRecipeResult> setter) {
+ super(getter, setter, (buffer, result) -> {
+ NetworkUtils.writeStringSafe(buffer, result.getID());
+ result.encode(buffer);
+ }, buffer -> {
+ String id = NetworkUtils.readStringSafe(buffer);
+ CheckRecipeResult result = CheckRecipeResultRegistry.getSampleFromRegistry(id)
+ .newInstance();
+ result.decode(buffer);
+ return result;
+ });
+ }
+}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java
index 454f04066f..5575b0f9f1 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_AssemblyLine.java
@@ -24,6 +24,8 @@ import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
@@ -32,7 +34,6 @@ import com.gtnewhorizon.structurelib.structure.StructureDefinition;
import gregtech.api.GregTech_API;
import gregtech.api.enums.GT_Values;
import gregtech.api.enums.ItemList;
-import gregtech.api.enums.SoundResource;
import gregtech.api.enums.Textures;
import gregtech.api.enums.Textures.BlockIcons;
import gregtech.api.interfaces.IHatchElement;
@@ -45,6 +46,8 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_DataA
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_MultiInput;
import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_AssemblyLineUtils;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
@@ -185,13 +188,14 @@ public class GT_MetaTileEntity_AssemblyLine
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
if (GT_Values.D1) {
GT_FML_LOGGER.info("Start ALine recipe check");
}
ArrayList<ItemStack> tDataStickList = getDataItems(2);
if (tDataStickList.isEmpty()) {
- return false;
+ return CheckRecipeResultRegistry.NO_DATA_STICKS;
}
if (GT_Values.D1) {
GT_FML_LOGGER.info("Stick accepted, " + tDataStickList.size() + " Data Sticks found");
@@ -305,7 +309,7 @@ public class GT_MetaTileEntity_AssemblyLine
// Best not to run this recipe.
if (!foundRecipe || tStack.length == 0) {
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
if (GT_Values.D1) {
@@ -340,7 +344,7 @@ public class GT_MetaTileEntity_AssemblyLine
if (GT_Values.D1) {
GT_FML_LOGGER.info("Recipe successful");
}
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
private static int isStackValidIngredient(ItemStack aSlotStack, ItemStack aIngredient, ItemStack[] alts) {
@@ -367,14 +371,6 @@ public class GT_MetaTileEntity_AssemblyLine
}
@Override
- public void startSoundLoop(byte aIndex, double aX, double aY, double aZ) {
- super.startSoundLoop(aIndex, aX, aY, aZ);
- if (aIndex == 20) {
- GT_Utility.doSoundAtClient(SoundResource.IC2_MACHINES_MAGNETIZER_LOOP, 10, 1.0F, aX, aY, aZ);
- }
- }
-
- @Override
public IStructureDefinition<GT_MetaTileEntity_AssemblyLine> getStructureDefinition() {
return STRUCTURE_DEFINITION;
}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java
index 6250b11300..392b77eb74 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Charcoal_Pit.java
@@ -9,6 +9,8 @@ import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
import java.util.ArrayList;
+import javax.annotation.Nonnull;
+
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
@@ -27,6 +29,8 @@ import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TooltipMultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
@@ -62,14 +66,15 @@ public class GT_MetaTileEntity_Charcoal_Pit extends GT_MetaTileEntity_TooltipMul
return true;
}
+ @Nonnull
@Override
- public boolean checkRecipe(ItemStack aStack) {
+ public CheckRecipeResult checkProcessing() {
if (!checkRecursiveBlocks()) {
mEfficiency = 0;
mEfficiencyIncrease = 0;
mMaxProgresstime = 0;
running = false;
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
if (mEfficiency == 0) {
@@ -79,13 +84,13 @@ public class GT_MetaTileEntity_Charcoal_Pit extends GT_MetaTileEntity_TooltipMul
// adds all the pollution at once when the recipe starts
GT_Pollution.addPollution(getBaseMetaTileEntity(), mMaxProgresstime * getPollutionPerTick(null));
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
} else {
mEfficiency = 0;
mEfficiencyIncrease = 0;
mMaxProgresstime = 0;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
- return false;
}
private boolean checkRecursiveBlocks() {
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java
index 07023bfdcf..4c308370aa 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_Cleanroom.java
@@ -12,6 +12,8 @@ import java.util.HashSet;
import java.util.Map;
import java.util.Set;
+import javax.annotation.Nonnull;
+
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
@@ -33,6 +35,8 @@ import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicHull;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TooltipMultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
@@ -116,15 +120,16 @@ public class GT_MetaTileEntity_Cleanroom extends GT_MetaTileEntity_TooltipMultiB
return new String[] { "The base can be rectangular." };
}
+ @Nonnull
@Override
- public boolean checkRecipe(ItemStack aStack) {
+ public CheckRecipeResult checkProcessing() {
mEfficiencyIncrease = 100;
// use the standard overclock mechanism to determine duration and estimate a maximum consumption
calculateOverclockedNessMultiInternal(40, 45 * Math.max(1, mHeight - 1), 1, getMaxInputVoltage(), false);
// negate it to trigger the special energy consumption function. divide by 10 to get the actual final
// consumption.
mEUt /= -10;
- return true;
+ return SimpleCheckRecipeResult.ofSuccess("cleanroom_running");
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java
index ff28a9e40a..ff8fa7eeb1 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DieselEngine.java
@@ -24,6 +24,8 @@ import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
@@ -38,6 +40,9 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
@@ -183,7 +188,8 @@ public class GT_MetaTileEntity_DieselEngine
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
ArrayList<FluidStack> tFluids = getStoredFluids();
// fast track lookup
@@ -219,30 +225,30 @@ public class GT_MetaTileEntity_DieselEngine
}
// Deplete that amount
- if (!depleteInput(tLiquid)) return false;
+ if (!depleteInput(tLiquid)) return CheckRecipeResultRegistry.NO_FUEL_FOUND;
boostEu = depleteInput(getBooster().getGas(2L * getAdditiveFactor()));
// Check to prevent burning HOG without consuming it, if not boosted
if (!boostEu && fuelValue > getNominalOutput()) {
- return false;
+ return SimpleCheckRecipeResult.ofFailure("fuel_quality_too_high");
}
// Deplete Lubricant. 1000L should = 1 hour of runtime (if baseEU = 2048)
if ((mRuntime % 72 == 0 || mRuntime == 0)
&& !depleteInput(Materials.Lubricant.getFluid((boostEu ? 2L : 1L) * getAdditiveFactor())))
- return false;
+ return SimpleCheckRecipeResult.ofFailure("no_lubricant");
fuelRemaining = tFluid.amount; // Record available fuel
this.mEUt = mEfficiency < 2000 ? 0 : getNominalOutput(); // Output 0 if startup is less than 20%
this.mProgresstime = 1;
this.mMaxProgresstime = 1;
this.mEfficiencyIncrease = getEfficiencyIncrease();
- return true;
+ return CheckRecipeResultRegistry.GENERATING;
}
}
this.mEUt = 0;
this.mEfficiency = 0;
- return false;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java
index 3a75cab071..e368e43518 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DistillationTower.java
@@ -40,12 +40,12 @@ import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.fluid.IFluidStore;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
-import gregtech.api.util.GT_Utility;
public class GT_MetaTileEntity_DistillationTower extends
GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_DistillationTower> implements ISurvivalConstructable {
@@ -191,72 +191,8 @@ public class GT_MetaTileEntity_DistillationTower extends
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- GT_Recipe tRecipe;
-
- ArrayList<ItemStack> tInputList = getStoredInputs();
- int tInputList_sS = tInputList.size();
- for (int i = 0; i < tInputList_sS - 1; i++) {
- for (int j = i + 1; j < tInputList_sS; j++) {
- if (GT_Utility.areStacksEqual(tInputList.get(i), tInputList.get(j))) {
- if (tInputList.get(i).stackSize >= tInputList.get(j).stackSize) {
- tInputList.remove(j--);
- tInputList_sS = tInputList.size();
- } else {
- tInputList.remove(i--);
- tInputList_sS = tInputList.size();
- break;
- }
- }
- }
- }
- ItemStack[] inputs = tInputList.toArray(new ItemStack[0]);
-
- ArrayList<FluidStack> tFluidList = getStoredFluids();
- for (int i = 0; i < tFluidList.size() - 1; i++) {
- for (int j = i + 1; j < tFluidList.size(); j++) {
- if (GT_Utility.areFluidsEqual(tFluidList.get(i), tFluidList.get(j))) {
- if (tFluidList.get(i).amount >= tFluidList.get(j).amount) {
- tFluidList.remove(j--);
- } else {
- tFluidList.remove(i--);
- break;
- }
- }
- }
- }
-
- long tVoltage = getMaxInputVoltage();
- byte tTier = (byte) Math.max(0, GT_Utility.getTier(tVoltage));
- FluidStack[] tFluids = tFluidList.toArray(new FluidStack[0]);
- for (FluidStack tFluid : tFluids) {
- tRecipe = GT_Recipe.GT_Recipe_Map.sDistillationRecipes.findRecipe(
- getBaseMetaTileEntity(),
- false,
- gregtech.api.enums.GT_Values.V[tTier],
- new FluidStack[] { tFluid },
- inputs);
- if (tRecipe != null) {
- if (!canOutputAll(tRecipe)) continue;
- if (tRecipe.isRecipeInputEqual(true, tFluids, inputs)) {
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
- calculateOverclockedNessMultiInternal(tRecipe.mEUt, tRecipe.mDuration, 1, tVoltage, false);
- // In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) return false;
- if (this.mEUt > 0) {
- this.mEUt = (-this.mEUt);
- }
- this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime);
- this.mOutputItems = new ItemStack[] { tRecipe.getOutput(0) };
- this.mOutputFluids = tRecipe.mFluidOutputs.clone();
- updateSlots();
- return true;
- }
- }
- }
-
- return false;
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic();
}
protected void onCasingFound() {
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java
index 8c671f69a8..77b5073c86 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_DrillerBase.java
@@ -33,6 +33,8 @@ import net.minecraft.world.ChunkCoordIntPair;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.common.util.ForgeDirection;
+import org.jetbrains.annotations.NotNull;
+
import com.google.common.collect.ImmutableList;
import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
@@ -53,6 +55,8 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_DataAccess;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_Utility;
@@ -414,21 +418,38 @@ public abstract class GT_MetaTileEntity_DrillerBase
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ItemStack controllerStack = getControllerSlot();
// Public pipe actions
setElectricityStats();
int oldYHead = yHead;
if (!checkPipesAndSetYHead() || !isEnergyEnough()) {
stopMachine();
- return false;
+ return SimpleCheckRecipeResult.ofFailure("no_mining_pipe");
}
putMiningPipesFromInputsInController();
- return switch (workState) {
- case STATE_DOWNWARD -> workingDownward(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead);
- case STATE_AT_BOTTOM -> workingAtBottom(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead);
- case STATE_UPWARD -> workingUpward(aStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead);
- default -> false;
- };
+ switch (workState) {
+ case STATE_DOWNWARD -> {
+ return workingDownward(controllerStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead)
+ ? SimpleCheckRecipeResult.ofSuccess("drilling")
+ : SimpleCheckRecipeResult.ofFailure("extracting_pipe");
+
+ }
+ case STATE_AT_BOTTOM -> {
+ return workingAtBottom(controllerStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead)
+ ? SimpleCheckRecipeResult.ofSuccess("drilling")
+ : SimpleCheckRecipeResult.ofFailure("no_mining_pipe");
+ }
+ case STATE_UPWARD -> {
+ return workingUpward(controllerStack, xDrill, yDrill, zDrill, xPipe, zPipe, yHead, oldYHead)
+ ? SimpleCheckRecipeResult.ofSuccess("retracting_pipe")
+ : SimpleCheckRecipeResult.ofFailure("no_mining_pipe");
+ }
+ default -> {
+ return SimpleCheckRecipeResult.ofFailure("no_mining_pipe");
+ }
+ }
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java
index 0557128b60..65890b0cc0 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ElectricBlastFurnace.java
@@ -8,7 +8,6 @@ import static gregtech.api.enums.GT_HatchElement.Maintenance;
import static gregtech.api.enums.GT_HatchElement.Muffler;
import static gregtech.api.enums.GT_HatchElement.OutputBus;
import static gregtech.api.enums.GT_HatchElement.OutputHatch;
-import static gregtech.api.enums.GT_Values.V;
import static gregtech.api.enums.GT_Values.VN;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ELECTRIC_BLAST_FURNACE_ACTIVE;
@@ -46,13 +45,17 @@ import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.fluid.IFluidStore;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
-import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_Recipe;
import gregtech.api.util.GT_Utility;
@@ -187,128 +190,29 @@ public class GT_MetaTileEntity_ElectricBlastFurnace extends
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- if (inputSeparation) {
- FluidStack[] tFluids = getStoredFluids().toArray(new FluidStack[0]);
- for (GT_MetaTileEntity_Hatch_InputBus tBus : mInputBusses) {
- ArrayList<ItemStack> tInputs = new ArrayList<>();
- tBus.mRecipeMap = getRecipeMap();
-
- if (isValidMetaTileEntity(tBus)) {
- for (int i = tBus.getBaseMetaTileEntity()
- .getSizeInventory() - 1; i >= 0; i--) {
- if (tBus.getBaseMetaTileEntity()
- .getStackInSlot(i) != null) {
- tInputs.add(
- tBus.getBaseMetaTileEntity()
- .getStackInSlot(i));
- }
- }
- }
- ItemStack[] tItems = tInputs.toArray(new ItemStack[0]);
- if (processRecipe(tItems, tFluids)) {
- return true;
- }
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe,
+ @Nonnull GT_ParallelHelper helper) {
+ return new GT_OverclockCalculator().setRecipeEUt(recipe.mEUt)
+ .setDuration(recipe.mDuration)
+ .setEUt(availableVoltage)
+ .setRecipeHeat(recipe.mSpecialValue)
+ .setMultiHeat(mHeatingCapacity)
+ .enableHeatOC()
+ .enableHeatDiscount()
+ .calculate();
}
- return false;
- } else {
- return processRecipe(getCompactedInputs(), getCompactedFluids());
- }
- }
-
- protected boolean processRecipe(ItemStack[] tItems, FluidStack[] tFluids) {
- if (tItems.length == 0) return false;
-
- long tVoltage = getMaxInputVoltage();
- byte tTier = (byte) Math.max(1, GT_Utility.getTier(tVoltage));
-
- GT_Recipe tRecipe = GT_Recipe.GT_Recipe_Map.sBlastRecipes
- .findRecipe(getBaseMetaTileEntity(), false, V[tTier], tFluids, tItems);
- if (tRecipe == null) return false;
- if (this.mHeatingCapacity < tRecipe.mSpecialValue) return false;
- if (!canOutputAll(tRecipe.mOutputs, getPollutionMultiplierAppliedFluids(tRecipe.mFluidOutputs))) return false;
- if (!tRecipe.isRecipeInputEqual(true, tFluids, tItems)) return false;
- // In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) return false;
-
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
-
- int tHeatCapacityDivTiers = (mHeatingCapacity - tRecipe.mSpecialValue) / 900;
- byte overclockCount = calculateOverclockednessEBF(tRecipe.mEUt, tRecipe.mDuration, tVoltage);
- if (this.mEUt > 0) {
- this.mEUt = (-this.mEUt);
- }
- if (tHeatCapacityDivTiers > 0) {
- this.mEUt = (int) (this.mEUt * (Math.pow(0.95, tHeatCapacityDivTiers)));
- this.mMaxProgresstime >>= Math.min(tHeatCapacityDivTiers / 2, overclockCount); // extra free overclocking if
- // possible
- if (this.mMaxProgresstime < 1) this.mMaxProgresstime = 1; // no eu efficiency correction
- }
- this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime);
- this.mOutputItems = new ItemStack[] { tRecipe.getOutput(0), tRecipe.getOutput(1) };
- this.mOutputFluids = new FluidStack[] { tRecipe.getFluidOutput(0) };
- updateSlots();
- return true;
- }
-
- /**
- * Calcualtes overclocked ness using long integers
- *
- * @param aEUt - recipe EUt
- * @param aDuration - recipe Duration
- */
- protected byte calculateOverclockednessEBF(int aEUt, int aDuration, long maxInputVoltage) {
- byte mTier = (byte) Math.max(0, GT_Utility.getTier(maxInputVoltage)), timesOverclocked = 0;
- if (mTier == 0) {
- // Long time calculation
- long xMaxProgresstime = ((long) aDuration) << 1;
- if (xMaxProgresstime > Integer.MAX_VALUE - 1) {
- // make impossible if too long
- mEUt = Integer.MAX_VALUE - 1;
- mMaxProgresstime = Integer.MAX_VALUE - 1;
- } else {
- mEUt = aEUt >> 2;
- mMaxProgresstime = (int) xMaxProgresstime;
- }
- // return 0;
- } else {
- // Long EUt calculation
- long xEUt = aEUt;
- // Isnt too low EUt check?
- long tempEUt = Math.max(xEUt, V[1]);
-
- mMaxProgresstime = aDuration;
-
- while (tempEUt <= V[mTier - 1]) {
- tempEUt <<= 2; // this actually controls overclocking
- // xEUt *= 4;//this is effect of everclocking
- mMaxProgresstime >>= 1; // this is effect of overclocking
- xEUt = mMaxProgresstime == 0 ? xEUt >> 1 : xEUt << 2; // U know, if the time is less than 1 tick make
- // the machine use less power
- timesOverclocked++;
- }
- if (xEUt > Integer.MAX_VALUE - 1) {
- mEUt = Integer.MAX_VALUE - 1;
- mMaxProgresstime = Integer.MAX_VALUE - 1;
- } else {
- mEUt = (int) xEUt;
- if (mEUt == 0) mEUt = 1;
- if (mMaxProgresstime == 0) mMaxProgresstime = 1; // set time to 1 tick
+ @Override
+ protected @Nonnull CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ return recipe.mSpecialValue <= mHeatingCapacity ? CheckRecipeResultRegistry.SUCCESSFUL
+ : CheckRecipeResultRegistry.insufficientHeat(recipe.mSpecialValue);
}
- }
- return timesOverclocked;
- }
-
- private FluidStack[] getPollutionMultiplierAppliedFluids(FluidStack[] original) {
- FluidStack[] fluids = GT_Utility.copyFluidArray(original);
- for (FluidStack fluid : fluids) {
- if (isPollutionFluid(fluid)) {
- multiplyPollutionFluidAmount(fluid);
- }
- }
- return fluids;
+ };
}
public boolean addOutputHatchToTopList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
@@ -481,6 +385,7 @@ public class GT_MetaTileEntity_ElectricBlastFurnace extends
public void loadNBTData(final NBTTagCompound aNBT) {
super.loadNBTData(aNBT);
if (aNBT.hasKey("isBussesSeparate")) {
+ // backward compatibility
inputSeparation = aNBT.getBoolean("isBussesSeparate");
}
}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java
index d7b51c8de6..fd77caa201 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_FusionComputer.java
@@ -22,6 +22,8 @@ import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import com.google.common.collect.ImmutableMap;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
@@ -52,6 +54,8 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energ
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
@@ -284,7 +288,8 @@ public abstract class GT_MetaTileEntity_FusionComputer
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
ArrayList<FluidStack> tFluidList = getStoredFluids();
int tFluidList_sS = tFluidList.size();
for (int i = 0; i < tFluidList_sS - 1; i++) {
@@ -315,9 +320,9 @@ public abstract class GT_MetaTileEntity_FusionComputer
if ((tRecipe == null && !mRunningOnLoad) || (maxEUStore() < tRecipe.mSpecialValue)) {
turnCasingActive(false);
this.mLastRecipe = null;
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
- if (!canOutputAll(tRecipe)) return false;
+ if (!canOutputAll(tRecipe)) return CheckRecipeResultRegistry.OUTPUT_FULL;
if (mRunningOnLoad || tRecipe.isRecipeInputEqual(true, tFluids)) {
this.mLastRecipe = tRecipe;
this.mEUt = (this.mLastRecipe.mEUt * overclock(this.mLastRecipe.mSpecialValue));
@@ -326,10 +331,10 @@ public abstract class GT_MetaTileEntity_FusionComputer
this.mOutputFluids = this.mLastRecipe.mFluidOutputs;
turnCasingActive(true);
mRunningOnLoad = false;
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
}
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
public abstract int tierOverclock();
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java
index d3c1267f3f..90413888b2 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_HeatExchanger.java
@@ -23,6 +23,8 @@ import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
@@ -38,6 +40,8 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMul
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_ModHandler;
@@ -176,8 +180,9 @@ public class GT_MetaTileEntity_HeatExchanger extends
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- if (mInputHotFluidHatch.getFluid() == null) return true;
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (mInputHotFluidHatch.getFluid() == null) return CheckRecipeResultRegistry.NO_RECIPE;
int fluidAmountToConsume = mInputHotFluidHatch.getFluidAmount(); // how much fluid is in hatch
@@ -224,7 +229,7 @@ public class GT_MetaTileEntity_HeatExchanger extends
} else {
// If we're working with neither, fail out
superheated_threshold = 0;
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
superheated = fluidAmountToConsume >= superheated_threshold; // set the internal superheated flag if we have
@@ -243,7 +248,7 @@ public class GT_MetaTileEntity_HeatExchanger extends
mOutputColdFluidHatch.fill(FluidRegistry.getFluidStack("molten.solarsaltcold", fluidAmountToConsume), true);
}
this.mEfficiencyIncrease = 80;
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
private int useWater(int steam) {
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java
index 3cceb98bf0..4fe75734c3 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ImplosionCompressor.java
@@ -7,8 +7,6 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_IMPLOSION_COM
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_IMPLOSION_COMPRESSOR_ACTIVE_GLOW;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_IMPLOSION_COMPRESSOR_GLOW;
-import java.util.ArrayList;
-
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
@@ -22,11 +20,11 @@ import gregtech.api.enums.Textures.BlockIcons;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_CubicMultiBlockBase;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
-import gregtech.api.util.GT_Utility;
public class GT_MetaTileEntity_ImplosionCompressor
extends GT_MetaTileEntity_CubicMultiBlockBase<GT_MetaTileEntity_ImplosionCompressor> {
@@ -108,44 +106,8 @@ public class GT_MetaTileEntity_ImplosionCompressor
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- ArrayList<ItemStack> tInputList = getStoredInputs();
- int tInputList_sS = tInputList.size();
- for (int i = 0; i < tInputList_sS - 1; i++) {
- for (int j = i + 1; j < tInputList_sS; j++) {
- if (GT_Utility.areStacksEqual(tInputList.get(i), tInputList.get(j))) {
- if (tInputList.get(i).stackSize >= tInputList.get(j).stackSize) {
- tInputList.remove(j--);
- tInputList_sS = tInputList.size();
- } else {
- tInputList.remove(i--);
- tInputList_sS = tInputList.size();
- break;
- }
- }
- }
- }
- ItemStack[] tInputs = tInputList.toArray(new ItemStack[0]);
- if (!tInputList.isEmpty()) {
- GT_Recipe tRecipe = GT_Recipe.GT_Recipe_Map.sImplosionRecipes
- .findRecipe(getBaseMetaTileEntity(), false, 9223372036854775807L, null, tInputs);
- if ((tRecipe != null) && canOutputAll(tRecipe) && tRecipe.isRecipeInputEqual(true, null, tInputs)) {
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
- // OC THAT EXPLOSIVE SHIT!!!
- calculateOverclockedNessMultiInternal(tRecipe.mEUt, tRecipe.mDuration, 1, getMaxInputVoltage(), false);
- // In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) return false;
- if (this.mEUt > 0) {
- this.mEUt = (-this.mEUt);
- }
- this.mOutputItems = new ItemStack[] { tRecipe.getOutput(0), tRecipe.getOutput(1) };
- sendLoopStart((byte) 20);
- updateSlots();
- return true;
- }
- }
- return false;
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic();
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java
index 438aa80219..af467e067b 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_IntegratedOreFactory.java
@@ -36,6 +36,8 @@ import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.oredict.OreDictionary;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
@@ -54,6 +56,8 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
@@ -256,7 +260,8 @@ public class GT_MetaTileEntity_IntegratedOreFactory extends
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
if (!isInit) {
initHash();
isInit = true;
@@ -311,7 +316,7 @@ public class GT_MetaTileEntity_IntegratedOreFactory extends
setCurrentParallelism(tRealUsed);
if (tRealUsed == 0) {
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
depleteInput(GT_ModHandler.getDistilledWater(tRealUsed * 200L));
@@ -349,7 +354,7 @@ public class GT_MetaTileEntity_IntegratedOreFactory extends
doCentrifuge(isImpureDust, isPureDust);
}
default -> {
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
}
@@ -362,7 +367,7 @@ public class GT_MetaTileEntity_IntegratedOreFactory extends
}
this.updateSlots();
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
@SafeVarargs
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java
index 37495c60ea..8d165e34f4 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeBoiler.java
@@ -27,6 +27,8 @@ import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
@@ -40,6 +42,8 @@ import gregtech.api.enums.Textures.BlockIcons;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_ModHandler;
@@ -239,8 +243,9 @@ public abstract class GT_MetaTileEntity_LargeBoiler
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- if (!isFuelValid()) return false;
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (!isFuelValid()) return CheckRecipeResultRegistry.NO_FUEL_FOUND;
// Do we have an integrated circuit with a valid configuration?
if (Circuit_Integrated.isStackEqual(mInventory[1], true, true)) {
int circuit_config = mInventory[1].getItemDamage();
@@ -263,7 +268,7 @@ public abstract class GT_MetaTileEntity_LargeBoiler
this.mMaxProgresstime = adjustBurnTimeForConfig(runtimeBoost(tRecipe.mSpecialValue / 2));
this.mEUt = adjustEUtForConfig(getEUt());
this.mEfficiencyIncrease = this.mMaxProgresstime * getEfficiencyIncrease() * 4;
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
}
}
@@ -276,7 +281,7 @@ public abstract class GT_MetaTileEntity_LargeBoiler
Math.max(1, runtimeBoost(tRecipe.mSpecialValue * 2)));
this.mEUt = adjustEUtForConfig(getEUt());
this.mEfficiencyIncrease = this.mMaxProgresstime * getEfficiencyIncrease();
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
}
}
@@ -302,7 +307,7 @@ public abstract class GT_MetaTileEntity_LargeBoiler
this.mEfficiencyIncrease = 0;
this.mSuperEfficencyIncrease = 20;
}
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
}
}
@@ -328,7 +333,7 @@ public abstract class GT_MetaTileEntity_LargeBoiler
this.mEfficiencyIncrease = 0;
this.mSuperEfficencyIncrease = 20;
}
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
}
}
@@ -336,7 +341,7 @@ public abstract class GT_MetaTileEntity_LargeBoiler
}
this.mMaxProgresstime = 0;
this.mEUt = 0;
- return false;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
}
abstract int runtimeBoost(int mTime);
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java
index 2c647aa458..ded2621fec 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeChemicalReactor.java
@@ -16,7 +16,6 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_LARGE_CHEMICA
import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
-import java.util.ArrayList;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
@@ -27,7 +26,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.IChatComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.FluidStack;
import com.gtnewhorizon.structurelib.StructureLibAPI;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
@@ -46,12 +44,11 @@ import gregtech.api.interfaces.IHeatingCoil;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
-import gregtech.api.util.GT_Single_Recipe_Check;
-import gregtech.api.util.GT_Utility;
public class GT_MetaTileEntity_LargeChemicalReactor extends
GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_LargeChemicalReactor> implements ISurvivalConstructable {
@@ -169,68 +166,8 @@ public class GT_MetaTileEntity_LargeChemicalReactor extends
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- long tVoltage = getMaxInputVoltage();
- byte tier = (byte) Math.max(1, GT_Utility.getTier(tVoltage));
- GT_Recipe tRecipe;
-
- if (mLockedToSingleRecipe && mSingleRecipeCheck != null) {
- if (!mSingleRecipeCheck.checkRecipeInputsSingleStack(true)) {
- return false;
- }
- tRecipe = mSingleRecipeCheck.getRecipe();
- } else {
- ArrayList<ItemStack> tInputList = getStoredInputs();
- ArrayList<FluidStack> tFluidList = getStoredFluids();
-
- ItemStack[] inputs = tInputList.toArray(new ItemStack[0]);
- FluidStack[] fluids = tFluidList.toArray(new FluidStack[0]);
-
- if (inputs.length == 0 && fluids.length == 0) {
- return false;
- }
-
- GT_Single_Recipe_Check.Builder tSingleRecipeCheckBuilder = null;
- if (mLockedToSingleRecipe) {
- // We're locked to a single recipe, but haven't built the recipe checker yet.
- // Build the checker on next successful recipe.
- tSingleRecipeCheckBuilder = GT_Single_Recipe_Check.builder(this)
- .setBefore(inputs, fluids);
- }
-
- tRecipe = GT_Recipe.GT_Recipe_Map.sMultiblockChemicalRecipes.findRecipe(
- getBaseMetaTileEntity(),
- false,
- false,
- gregtech.api.enums.GT_Values.V[tier],
- fluids,
- inputs);
-
- if (tRecipe == null || !canOutputAll(tRecipe) || !tRecipe.isRecipeInputEqual(true, fluids, inputs)) {
- return false;
- }
-
- if (mLockedToSingleRecipe) {
- mSingleRecipeCheck = tSingleRecipeCheckBuilder.setAfter(inputs, fluids)
- .setRecipe(tRecipe)
- .build();
- }
- }
-
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
-
- calculateOverclockedNessMultiInternal(tRecipe.mEUt, tRecipe.mDuration, 1, tVoltage, true);
- // In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) return false;
- if (this.mEUt > 0) {
- this.mEUt = (-this.mEUt);
- }
-
- this.mOutputItems = tRecipe.mOutputs;
- this.mOutputFluids = tRecipe.mFluidOutputs;
- this.updateSlots();
- return true;
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic().enablePerfectOverclock();
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java
index f31967674c..a8961ce542 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine.java
@@ -28,6 +28,8 @@ import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
@@ -41,6 +43,8 @@ import gregtech.api.items.GT_MetaGenerated_Tool;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.util.GT_Utility;
import gregtech.api.util.LightingHelper;
import gregtech.common.items.GT_MetaGenerated_Tool_01;
@@ -226,12 +230,15 @@ public abstract class GT_MetaTileEntity_LargeTurbine
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- if ((counter & 7) == 0 && (aStack == null || !(aStack.getItem() instanceof GT_MetaGenerated_Tool)
- || aStack.getItemDamage() < 170
- || aStack.getItemDamage() > 179)) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ItemStack controllerSlot = getControllerSlot();
+ if ((counter & 7) == 0
+ && (controllerSlot == null || !(controllerSlot.getItem() instanceof GT_MetaGenerated_Tool)
+ || controllerSlot.getItemDamage() < 170
+ || controllerSlot.getItemDamage() > 179)) {
stopMachine();
- return false;
+ return CheckRecipeResultRegistry.NO_TURBINE_FOUND;
}
ArrayList<FluidStack> tFluids = getStoredFluids();
if (!tFluids.isEmpty()) {
@@ -244,24 +251,25 @@ public abstract class GT_MetaTileEntity_LargeTurbine
.hasInventoryBeenModified()) {
counter = 0;
baseEff = GT_Utility.safeInt(
- (long) ((5F + ((GT_MetaGenerated_Tool) aStack.getItem()).getToolCombatDamage(aStack)) * 1000F));
- optFlow = GT_Utility
- .safeInt(
- (long) Math.max(
- Float.MIN_NORMAL,
- ((GT_MetaGenerated_Tool) aStack.getItem()).getToolStats(aStack)
- .getSpeedMultiplier() * GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mToolSpeed
- * 50));
-
- overflowMultiplier = getOverflowMultiplier(aStack);
-
- flowMultipliers[0] = GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mSteamMultiplier;
- flowMultipliers[1] = GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mGasMultiplier;
- flowMultipliers[2] = GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mPlasmaMultiplier;
+ (long) ((5F
+ + ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolCombatDamage(controllerSlot))
+ * 1000F));
+ optFlow = GT_Utility.safeInt(
+ (long) Math.max(
+ Float.MIN_NORMAL,
+ ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolStats(controllerSlot)
+ .getSpeedMultiplier() * GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mToolSpeed
+ * 50));
+
+ overflowMultiplier = getOverflowMultiplier(controllerSlot);
+
+ flowMultipliers[0] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mSteamMultiplier;
+ flowMultipliers[1] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mGasMultiplier;
+ flowMultipliers[2] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mPlasmaMultiplier;
if (optFlow <= 0 || baseEff <= 0) {
stopMachine(); // in case the turbine got removed
- return false;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
}
} else {
counter++;
@@ -288,12 +296,12 @@ public abstract class GT_MetaTileEntity_LargeTurbine
// stopMachine();
this.mEUt = 0;
this.mEfficiency = 0;
- return false;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
} else {
this.mMaxProgresstime = 1;
this.mEfficiencyIncrease = 10;
// Overvoltage is handled inside the MultiBlockBase when pushing out to dynamos. no need to do it here.
- return true;
+ return CheckRecipeResultRegistry.GENERATING;
}
}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java
index 9e54fe11a5..0eec9ef238 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_LargeTurbine_Plasma.java
@@ -16,6 +16,8 @@ import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import gregtech.api.GregTech_API;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
@@ -23,6 +25,8 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.items.GT_MetaGenerated_Tool;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
@@ -202,12 +206,15 @@ public class GT_MetaTileEntity_LargeTurbine_Plasma extends GT_MetaTileEntity_Lar
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- if ((counter & 7) == 0 && (aStack == null || !(aStack.getItem() instanceof GT_MetaGenerated_Tool)
- || aStack.getItemDamage() < 170
- || aStack.getItemDamage() > 179)) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ItemStack controllerSlot = getControllerSlot();
+ if ((counter & 7) == 0
+ && (controllerSlot == null || !(controllerSlot.getItem() instanceof GT_MetaGenerated_Tool)
+ || controllerSlot.getItemDamage() < 170
+ || controllerSlot.getItemDamage() > 179)) {
stopMachine();
- return false;
+ return CheckRecipeResultRegistry.NO_TURBINE_FOUND;
}
ArrayList<FluidStack> tFluids = getStoredFluids();
if (!tFluids.isEmpty()) {
@@ -219,19 +226,20 @@ public class GT_MetaTileEntity_LargeTurbine_Plasma extends GT_MetaTileEntity_Lar
.hasInventoryBeenModified()) {
counter = 0;
baseEff = GT_Utility.safeInt(
- (long) ((5F + ((GT_MetaGenerated_Tool) aStack.getItem()).getToolCombatDamage(aStack)) * 1000F));
- optFlow = GT_Utility
- .safeInt(
- (long) Math.max(
- Float.MIN_NORMAL,
- ((GT_MetaGenerated_Tool) aStack.getItem()).getToolStats(aStack)
- .getSpeedMultiplier() * GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mToolSpeed
- * 50));
- overflowMultiplier = getOverflowMultiplier(aStack);
-
- flowMultipliers[0] = GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mSteamMultiplier;
- flowMultipliers[1] = GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mGasMultiplier;
- flowMultipliers[2] = GT_MetaGenerated_Tool.getPrimaryMaterial(aStack).mPlasmaMultiplier;
+ (long) ((5F
+ + ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolCombatDamage(controllerSlot))
+ * 1000F));
+ optFlow = GT_Utility.safeInt(
+ (long) Math.max(
+ Float.MIN_NORMAL,
+ ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolStats(controllerSlot)
+ .getSpeedMultiplier() * GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mToolSpeed
+ * 50));
+ overflowMultiplier = getOverflowMultiplier(controllerSlot);
+
+ flowMultipliers[0] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mSteamMultiplier;
+ flowMultipliers[1] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mGasMultiplier;
+ flowMultipliers[2] = GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mPlasmaMultiplier;
} else {
counter++;
}
@@ -239,7 +247,7 @@ public class GT_MetaTileEntity_LargeTurbine_Plasma extends GT_MetaTileEntity_Lar
if (optFlow <= 0 || baseEff <= 0) {
stopMachine(); // in case the turbine got removed
- return false;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
}
int newPower = fluidIntoPower(tFluids, optFlow, baseEff, overflowMultiplier, flowMultipliers); // How much the
@@ -263,13 +271,13 @@ public class GT_MetaTileEntity_LargeTurbine_Plasma extends GT_MetaTileEntity_Lar
// stopMachine();
this.mEUt = 0;
this.mEfficiency = 0;
- return false;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
} else {
this.mMaxProgresstime = 20;
this.mEfficiencyIncrease = 200;
// Overvoltage is handled inside the MultiBlockBase when pushing out to dynamos. no need to do it here.
- return true;
+ return CheckRecipeResultRegistry.GENERATING;
}
}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java
index e04255c28b..c80062ff09 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_MultiFurnace.java
@@ -22,6 +22,8 @@ import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
@@ -35,6 +37,8 @@ import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
@@ -142,9 +146,10 @@ public class GT_MetaTileEntity_MultiFurnace
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
ArrayList<ItemStack> tInputList = getStoredInputs();
- if (tInputList.isEmpty()) return false;
+ if (tInputList.isEmpty()) return CheckRecipeResultRegistry.NO_RECIPE;
int mVolatage = GT_Utility.safeInt(getMaxInputVoltage());
int tMaxParallel = this.mLevel;
@@ -182,15 +187,16 @@ public class GT_MetaTileEntity_MultiFurnace
this.mEfficiencyIncrease = 10000;
calculateOverclockedNessMultiInternal(4, 512, 1, mVolatage, false);
// In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) return false;
+ if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1)
+ return CheckRecipeResultRegistry.NO_RECIPE;
this.mEUt = GT_Utility.safeInt(((long) mEUt) * (this.mLevel / 8) / (long) this.mCostDiscount, 1);
- if (mEUt == Integer.MAX_VALUE - 1) return false;
+ if (mEUt == Integer.MAX_VALUE - 1) return CheckRecipeResultRegistry.NO_RECIPE;
if (this.mEUt > 0) this.mEUt = (-this.mEUt);
}
updateSlots();
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java
index 6018cb7450..ca68d3ad4c 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_NanoForge.java
@@ -16,7 +16,7 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE
import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
import static gregtech.api.util.GT_StructureUtility.ofFrame;
-import java.util.ArrayList;
+import javax.annotation.Nonnull;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
@@ -24,7 +24,6 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.FluidStack;
import com.gtnewhorizon.structurelib.alignment.IAlignmentLimits;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
@@ -44,8 +43,10 @@ import gregtech.api.enums.Textures.BlockIcons;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
-import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
@@ -232,72 +233,21 @@ public class GT_MetaTileEntity_NanoForge extends
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- GT_Recipe.GT_Recipe_Map map = getRecipeMap();
- FluidStack[] tFluidInputs = getCompactedFluids();
- if (inputSeparation) {
- ArrayList<ItemStack> tInputList = new ArrayList<>();
- for (GT_MetaTileEntity_Hatch_InputBus tBus : mInputBusses) {
- for (int i = tBus.getSizeInventory() - 1; i >= 0; i--) {
- if (tBus.getStackInSlot(i) != null) tInputList.add(tBus.getStackInSlot(i));
- }
- ItemStack[] tInputs = tInputList.toArray(new ItemStack[0]);
- if (processRecipe(tInputs, tFluidInputs, map)) return true;
- else tInputList.clear();
- }
- } else {
- ItemStack[] tItemInputs = getStoredInputs().toArray(new ItemStack[0]);
- return processRecipe(tItemInputs, tFluidInputs, map);
- }
- return false;
- }
-
- private boolean processRecipe(ItemStack[] tItemInputs, FluidStack[] tFluidInputs, GT_Recipe.GT_Recipe_Map map) {
- lEUt = 0;
- mOutputItems = null;
- mOutputFluids = null;
- long tTotalEU = getMaxInputEu();
- GT_Recipe tRecipe = map
- .findRecipe(getBaseMetaTileEntity(), null, false, false, tTotalEU, tFluidInputs, null, tItemInputs);
-
- if (tRecipe == null) return false;
- if (tRecipe.mSpecialValue > mSpecialTier) return false;
- if (!canOutputAll(tRecipe)) return false;
-
- if (tRecipe.isRecipeInputEqual(true, tFluidInputs, tItemInputs)) {
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
- this.mMaxProgresstime = tRecipe.mDuration;
- this.lEUt = -tRecipe.mEUt;
- calculateOverclockedNessMultiInternal(
- tRecipe.mEUt,
- tRecipe.mDuration,
- 1,
- tTotalEU,
- tRecipe.mSpecialValue < mSpecialTier);
-
- if (this.lEUt == Long.MAX_VALUE - 1 || this.mMaxProgresstime == Integer.MAX_VALUE - 1) return false;
-
- if (this.lEUt > 0) {
- this.lEUt *= -1;
- }
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
- ArrayList<ItemStack> tOutputs = new ArrayList<>();
- for (int i = 0; i < tRecipe.mOutputs.length; i++) {
- if (getBaseMetaTileEntity().getRandomNumber(10000) < tRecipe.getOutputChance(i)) {
- tOutputs.add(tRecipe.getOutput(i));
- }
+ @Override
+ protected @Nonnull CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ return recipe.mSpecialValue <= mSpecialTier ? CheckRecipeResultRegistry.SUCCESSFUL
+ : CheckRecipeResultRegistry.NO_RECIPE;
}
+ };
+ }
- this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime);
- mOutputItems = tOutputs.toArray(new ItemStack[0]);
- mOutputFluids = tRecipe.mFluidOutputs.clone();
- updateSlots();
-
- return true;
- }
-
- return false;
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(getMaxInputEu());
+ logic.setAvailableAmperage(1);
}
@Override
@@ -371,7 +321,8 @@ public class GT_MetaTileEntity_NanoForge extends
@Override
public void loadNBTData(final NBTTagCompound aNBT) {
super.loadNBTData(aNBT);
- if (!aNBT.hasKey(INPUT_SEPARATION_NBT_KEY)) {
+ if (aNBT.hasKey("mSeparate")) {
+ // backward compatibility
inputSeparation = aNBT.getBoolean("mSeparate");
}
mSpecialTier = aNBT.getByte("mSpecialTier");
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java
index 2e82efa4f9..e531108e1a 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_OilCracker.java
@@ -14,6 +14,8 @@ import static gregtech.api.util.GT_StructureUtility.ofCoil;
import java.util.ArrayList;
import java.util.List;
+import javax.annotation.Nonnull;
+
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
@@ -29,14 +31,16 @@ import gregtech.api.enums.HeatingCoilLevel;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_MultiInput;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_Recipe;
-import gregtech.api.util.GT_Utility;
public class GT_MetaTileEntity_OilCracker extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_OilCracker>
implements ISurvivalConstructable {
@@ -168,42 +172,17 @@ public class GT_MetaTileEntity_OilCracker extends GT_MetaTileEntity_EnhancedMult
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- ArrayList<FluidStack> tInputList = getStoredFluids();
- FluidStack[] tFluidInputs = tInputList.toArray(new FluidStack[0]);
- long tVoltage = getMaxInputVoltage();
- byte tTier = (byte) Math.max(1, GT_Utility.getTier(tVoltage));
-
- GT_Recipe tRecipe = getRecipeMap().findRecipe(
- getBaseMetaTileEntity(),
- false,
- gregtech.api.enums.GT_Values.V[tTier],
- tFluidInputs,
- mInventory[1]);
-
- if (tRecipe == null) return false;
- if (!canOutputAll(tRecipe)) return false;
-
- if (tRecipe.isRecipeInputEqual(true, tFluidInputs, mInventory[1])) {
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
- calculateOverclockedNessMultiInternal(tRecipe.mEUt, tRecipe.mDuration, 1, tVoltage, false);
- // In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) return false;
-
- // heatLevel.getTier() starts at 0
- if (this.heatLevel.getTier() < 5) {
- this.mEUt *= 1 - (0.1D * (this.heatLevel.getTier() + 1));
- } else {
- this.mEUt *= 0.5;
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe,
+ @Nonnull GT_ParallelHelper helper) {
+ return super.createOverclockCalculator(recipe, helper)
+ .setEUtDiscount(Math.max((0.1F * (heatLevel.getTier() + 1.0F)), 0.5F));
}
-
- if (this.mEUt > 0) this.mEUt = (-this.mEUt);
-
- this.mOutputFluids = new FluidStack[] { tRecipe.getFluidOutput(0) };
- return true;
- }
- return false;
+ };
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java
index 8605f3643f..2cfbd1a30e 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PCBFactory.java
@@ -9,7 +9,6 @@ import static gregtech.api.enums.GT_HatchElement.InputHatch;
import static gregtech.api.enums.GT_HatchElement.Maintenance;
import static gregtech.api.enums.GT_HatchElement.OutputBus;
import static gregtech.api.enums.GT_Values.AuthorBlueWeabo;
-import static gregtech.api.enums.GT_Values.V;
import static gregtech.api.enums.GT_Values.VN;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE;
@@ -21,6 +20,8 @@ import static gregtech.api.util.GT_StructureUtility.ofFrame;
import java.util.ArrayList;
import java.util.List;
+import javax.annotation.Nonnull;
+
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
@@ -31,6 +32,8 @@ import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
@@ -63,13 +66,17 @@ import gregtech.api.gui.modularui.GT_UITextures;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.GregTechTileClientEvents;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
-import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.objects.ItemData;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
@@ -515,141 +522,116 @@ public class GT_MetaTileEntity_PCBFactory extends
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- mCurrentParallel = 0;
- GT_Recipe.GT_Recipe_Map aMap = getRecipeMap();
- FluidStack[] tFluidInputs = getStoredFluids().toArray(new FluidStack[0]);
- if (inputSeparation) {
- ArrayList<ItemStack> tInputList = new ArrayList<>();
- for (GT_MetaTileEntity_Hatch_InputBus tBus : mInputBusses) {
- for (int i = tBus.getSizeInventory() - 1; i >= 0; i--) {
- if (tBus.getStackInSlot(i) != null) tInputList.add(tBus.getStackInSlot(i));
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ // Here we check the dynamic parallels, which depend on the recipe
+ int numberOfNanites = 0;
+ ItemStack aNanite = recipe.getRepresentativeInput(1);
+ ItemData naniteData = GT_OreDictUnificator.getAssociation(aNanite);
+ if (naniteData != null && naniteData.mPrefix != null && naniteData.mPrefix.equals(OrePrefixes.nanite)) {
+ for (ItemStack aItem : inputItems) {
+ if (aItem != null && aItem.isItemEqual(aNanite)) {
+ numberOfNanites += aItem.stackSize;
+ }
+ }
}
- ItemStack[] tInputs = tInputList.toArray(new ItemStack[0]);
- if (processRecipe(aStack, tInputs, tFluidInputs, aMap)) return true;
- else tInputList.clear();
- }
- } else {
- ItemStack[] tItemInputs = getStoredInputs().toArray(new ItemStack[0]);
- return processRecipe(aStack, tItemInputs, tFluidInputs, aMap);
- }
+ maxParallel = (int) Math.max(Math.ceil(Math.log(numberOfNanites) / Math.log(2) + 0.00001), 1);
+ mMaxParallel = maxParallel;
- return false;
- }
-
- private boolean processRecipe(ItemStack aStack, ItemStack[] aItemInputs, FluidStack[] aFluidInputs,
- GT_Recipe.GT_Recipe_Map aMap) {
- mOutputItems = null;
- mOutputFluids = null;
- if (aItemInputs == null || aFluidInputs == null) {
- return false;
- }
+ int recipeBitMap = recipe.mSpecialValue;
- long voltage = getAverageInputVoltage();
- long amps = getMaxInputAmps();
- int tier = GT_Utility.getTier(voltage);
+ if (((recipeBitMap & mBioBitMap) == mBioBitMap && !mBioUpgrade))
+ return SimpleCheckRecipeResult.ofFailure("bio_upgrade_missing");
- GT_Recipe tRecipe = aMap
- .findRecipe(getBaseMetaTileEntity(), null, true, false, V[tier], aFluidInputs, aStack, aItemInputs);
+ int requiredPCBTier = 0;
+ if ((recipeBitMap & mTier3BitMap) == mTier3BitMap) requiredPCBTier = 3;
+ if ((recipeBitMap & mTier2BitMap) == mTier2BitMap) requiredPCBTier = 2;
+ if ((recipeBitMap & mTier1BitMap) == mTier1BitMap) requiredPCBTier = 1;
- if (tRecipe == null) {
- return false;
- }
+ if (requiredPCBTier > mTier) return CheckRecipeResultRegistry.insufficientMachineTier(requiredPCBTier);
- int recipeBitMap = tRecipe.mSpecialValue;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
- int aNanitesOfRecipe = 0;
+ @Override
+ protected double calculateDuration(@Nonnull GT_Recipe recipe, @Nonnull GT_ParallelHelper helper,
+ @Nonnull GT_OverclockCalculator calculator) {
+ if (isNoOC()) {
+ return super.calculateDuration(recipe, helper, calculator) * getDurationMultiplierFromRoughness();
+ }
+ return super.calculateDuration(recipe, helper, calculator);
+ }
- ItemStack aNanite = tRecipe.getRepresentativeInput(1);
- if (GT_OreDictUnificator.getAssociation(aNanite).mPrefix.equals(OrePrefixes.nanite)) {
- for (ItemStack aItem : aItemInputs) {
- if (aItem.isItemEqual(aNanite)) {
- aNanitesOfRecipe += aItem.stackSize;
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe,
+ @Nonnull GT_ParallelHelper helper) {
+ if (isNoOC()) {
+ return GT_OverclockCalculator.ofNoOverclock(recipe);
+ }
+ GT_OverclockCalculator calculator = super.createOverclockCalculator(recipe, helper)
+ .setEUtDiscount((float) Math.sqrt(mUpgradesInstalled == 0 ? 1 : mUpgradesInstalled))
+ .setSpeedBoost(getDurationMultiplierFromRoughness());
+ if (mOCTier2) {
+ calculator.enablePerfectOC();
}
+ return calculator;
}
- }
- int aMaxParallel = (int) Math.max(Math.ceil(Math.log(aNanitesOfRecipe) / Math.log(2) + 0.00001), 1);
- mMaxParallel = aMaxParallel;
- float aExtraPower = (float) Math.sqrt(mUpgradesInstalled == 0 ? 1 : mUpgradesInstalled);
+ @Nonnull
+ @Override
+ protected GT_ParallelHelper createParallelHelper(@Nonnull GT_Recipe recipe) {
+ return super.createParallelHelper(recipe)
+ .setEUtModifier((float) Math.sqrt(mUpgradesInstalled == 0 ? 1 : mUpgradesInstalled));
+ }
- if (tRecipe.mEUt > voltage) {
- return false;
- }
+ @NotNull
+ @Override
+ public CheckRecipeResult process() {
+ CheckRecipeResult result = super.process();
- boolean recipeAllowed = (((recipeBitMap & mTier1BitMap) == mTier1BitMap && (mTier >= 1))
- || ((recipeBitMap & mTier2BitMap) == mTier2BitMap && (mTier >= 2))
- || ((recipeBitMap & mTier3BitMap) == mTier3BitMap && (mTier >= 3)))
- && ((recipeBitMap & mBioBitMap) == 0 || ((recipeBitMap & mBioBitMap) == mBioBitMap && mBioUpgrade));
-
- if (recipeAllowed) {
- GT_ParallelHelper helper = new GT_ParallelHelper().setRecipe(tRecipe)
- .setMachine(this)
- .setItemInputs(aItemInputs)
- .setFluidInputs(aFluidInputs)
- .setMaxParallel(aMaxParallel)
- .setAvailableEUt(getMaxInputEu())
- .setEUtModifier(aExtraPower)
- .enableConsumption()
- .build();
- mCurrentParallel = helper.getCurrentParallel();
-
- if (mCurrentParallel > 0) {
- this.mEfficiency = (getMaxEfficiency(aStack) - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = getMaxEfficiency(aStack);
- this.lEUt = -(long) Math.ceil(tRecipe.mEUt * mCurrentParallel * aExtraPower);
- this.mMaxProgresstime = (int) Math.ceil(tRecipe.mDuration * Math.pow(mRoughnessMultiplier, 2));
-
- if (mOCTier1 || mOCTier2) {
- GT_OverclockCalculator calc = new GT_OverclockCalculator().setRecipeEUt(tRecipe.mEUt)
- .setDuration(tRecipe.mDuration)
- .setEUt(voltage)
- .setAmperage(amps)
- .setEUtDiscount(aExtraPower)
- .setSpeedBoost((float) Math.pow(mRoughnessMultiplier, 2));
- if (mOCTier2) {
- calc.enablePerfectOC();
- }
- calc.calculate();
- this.lEUt = calc.getConsumption();
- this.mMaxProgresstime = calc.getDuration();
+ if (!result.wasSuccessful()) {
+ return result;
}
- if (this.lEUt == Long.MAX_VALUE - 1 || this.mProgresstime == Integer.MAX_VALUE - 1) return false;
+ mCurrentParallel = calculatedParallels;
- if (this.lEUt > 0) {
- this.lEUt *= -1;
- }
+ ItemStack controllerStack = getControllerSlot();
- ArrayList<ItemStack> tOutputs = new ArrayList<>();
- int remainingEfficiency = getMaxEfficiency(aStack);
- for (int j = 0; j < (int) Math.ceil(getMaxEfficiency(aStack) / 10000.0f); j++) {
- int chanced = getBaseMetaTileEntity().getRandomNumber(10000);
- if (chanced >= remainingEfficiency) {
- continue;
- }
- for (ItemStack tOutput : tRecipe.mOutputs) {
- if (tOutput == null) {
- break;
+ if (mCurrentParallel > 0) {
+ ArrayList<ItemStack> chancedOutputs = new ArrayList<>();
+ int remainingEfficiency = getMaxEfficiency(controllerStack);
+ for (int j = 0; j < (int) Math.ceil(getMaxEfficiency(controllerStack) / 10000.0f); j++) {
+ int chanced = getBaseMetaTileEntity().getRandomNumber(10000);
+ if (chanced >= remainingEfficiency) {
+ continue;
+ }
+ for (ItemStack tOutput : outputItems) {
+ if (tOutput == null) {
+ break;
+ }
+ chancedOutputs.add(tOutput);
}
- tOutputs.add(tOutput.copy());
+ remainingEfficiency -= 10000;
}
- remainingEfficiency -= 10000;
+ setOutputItems(chancedOutputs.toArray(new ItemStack[0]));
}
- for (ItemStack itemStack : tOutputs) {
- itemStack.stackSize *= mCurrentParallel;
- }
-
- mOutputItems = tOutputs.toArray(new ItemStack[0]);
- mOutputFluids = tRecipe.mFluidOutputs.clone();
- updateSlots();
-
- return true;
+ return result;
}
- }
+ };
+ }
- return false;
+ private boolean isNoOC() {
+ return !mOCTier1 && !mOCTier2;
+ }
+
+ private float getDurationMultiplierFromRoughness() {
+ return (float) Math.pow(mRoughnessMultiplier, 2);
}
private int ticker = 0;
@@ -810,44 +792,6 @@ public class GT_MetaTileEntity_PCBFactory extends
}
@Override
- protected void calculateOverclockedNessMultiInternal(long aEUt, int aDuration, int mAmperage, long maxInputVoltage,
- boolean perfectOC) {
- int hatches = Math.max(getExoticEnergyHatches().size(), 1);
- long zTime = aDuration;
- long zEUt = aEUt;
- if (maxInputVoltage < zEUt) {
- this.lEUt = Long.MAX_VALUE - 1;
- this.mMaxProgresstime = Integer.MAX_VALUE - 1;
- return;
- }
-
- while (zEUt < maxInputVoltage) {
- zEUt = zEUt << 2;
- zTime = zTime >> (perfectOC ? 2 : 1);
- if (zTime <= 1) {
- break;
- }
- }
-
- if (zTime <= 0) {
- zTime = 1;
- }
-
- while (zEUt * mAmperage > maxInputVoltage * getMaxInputAmps() / hatches) {
- zEUt = zEUt >> 2;
- zTime = zTime << (perfectOC ? 2 : 1);
- }
-
- if (zEUt > maxInputVoltage) {
- zEUt = zEUt >> 2;
- zTime = zTime << (perfectOC ? 2 : 1);
- }
-
- this.lEUt = zEUt * mAmperage;
- this.mMaxProgresstime = (int) zTime;
- }
-
- @Override
protected long getActualEnergyUsage() {
return (-this.lEUt * 10000) / Math.min(Math.max(1000, mEfficiency), 10000);
}
@@ -1071,7 +1015,8 @@ public class GT_MetaTileEntity_PCBFactory extends
@Override
public void loadNBTData(final NBTTagCompound aNBT) {
super.loadNBTData(aNBT);
- if (!aNBT.hasKey(INPUT_SEPARATION_NBT_KEY)) {
+ if (aNBT.hasKey("mSeparate")) {
+ // backward compatibility
inputSeparation = aNBT.getBoolean("mSeparate");
}
mBioUpgrade = aNBT.getBoolean("mBioUpgrade");
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java
index 2a92fff523..d1a2a9dd7f 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PlasmaForge.java
@@ -33,6 +33,8 @@ import net.minecraft.world.ChunkCoordIntPair;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.FluidStack;
+import org.jetbrains.annotations.NotNull;
+
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
@@ -50,6 +52,8 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_ExoticEnergyInputHelper;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
@@ -661,18 +665,19 @@ public class GT_MetaTileEntity_PlasmaForge extends GT_MetaTileEntity_AbstractMul
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- boolean recipe_process = processRecipe(getCompactedInputs(), getCompactedFluids());
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ CheckRecipeResult recipe_process = processRecipe(getCompactedInputs(), getCompactedFluids());
// If recipe cannot be found then continuity is broken and reset running time to 0.
- if (!recipe_process) {
+ if (!recipe_process.wasSuccessful()) {
resetDiscount();
}
return recipe_process;
}
- protected boolean processRecipe(ItemStack[] tItems, FluidStack[] tFluids) {
+ protected CheckRecipeResult processRecipe(ItemStack[] tItems, FluidStack[] tFluids) {
// Gets the EU input of the
long tTotalEU = GT_ExoticEnergyInputHelper.getTotalEuMulti(getExoticAndNormalEnergyHatchList());
@@ -682,10 +687,11 @@ public class GT_MetaTileEntity_PlasmaForge extends GT_MetaTileEntity_AbstractMul
.findRecipe(getBaseMetaTileEntity(), false, tTotalEU, tFluids, tItems);
// Check if recipe found.
- if (tRecipe_0 == null) return false;
+ if (tRecipe_0 == null) return CheckRecipeResultRegistry.NO_RECIPE;
// If coil heat capacity is too low, refuse to start recipe.
- if (mHeatingCapacity <= tRecipe_0.mSpecialValue) return false;
+ if (mHeatingCapacity <= tRecipe_0.mSpecialValue)
+ return CheckRecipeResultRegistry.insufficientHeat(tRecipe_0.mSpecialValue);
// Reduce fuel quantity if machine has been running for long enough.
GT_Recipe tRecipe_1 = tRecipe_0.copy();
@@ -705,9 +711,9 @@ public class GT_MetaTileEntity_PlasmaForge extends GT_MetaTileEntity_AbstractMul
}
}
- if (!canOutputAll(tRecipe_1)) return false;
+ if (!canOutputAll(tRecipe_1)) return CheckRecipeResultRegistry.OUTPUT_FULL;
// Takes items/fluids from hatches/busses.
- if (!tRecipe_1.isRecipeInputEqual(true, tFluids, tItems)) return false;
+ if (!tRecipe_1.isRecipeInputEqual(true, tFluids, tItems)) return CheckRecipeResultRegistry.NO_RECIPE;
// Logic for overclocking calculations.
double EU_input_tier = log(tTotalEU) / log4;
@@ -727,7 +733,7 @@ public class GT_MetaTileEntity_PlasmaForge extends GT_MetaTileEntity_AbstractMul
// All conditions met so increment running_time.
running_time += mMaxProgresstime;
- return true;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java
index 1c4374fd34..ff918fe196 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_ProcessingArray.java
@@ -1,6 +1,10 @@
package gregtech.common.tileentities.machines.multi;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
import static gregtech.api.enums.GT_HatchElement.Energy;
import static gregtech.api.enums.GT_HatchElement.ExoticEnergy;
import static gregtech.api.enums.GT_HatchElement.InputBus;
@@ -8,8 +12,7 @@ import static gregtech.api.enums.GT_HatchElement.InputHatch;
import static gregtech.api.enums.GT_HatchElement.Maintenance;
import static gregtech.api.enums.GT_HatchElement.OutputBus;
import static gregtech.api.enums.GT_HatchElement.OutputHatch;
-import static gregtech.api.enums.GT_Values.V;
-import static gregtech.api.enums.GT_Values.VN;
+import static gregtech.api.enums.GT_Values.*;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE;
import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE_GLOW;
@@ -17,11 +20,9 @@ import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FRONT_PROCESSING_AR
import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
import static gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachine.isValidForLowGravity;
-import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
-import java.util.Objects;
-import java.util.stream.Stream;
+
+import javax.annotation.Nonnull;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
@@ -29,10 +30,14 @@ import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.StatCollector;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
import com.google.common.collect.ImmutableList;
-import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
import com.gtnewhorizons.modularui.api.drawable.IDrawable;
import com.gtnewhorizons.modularui.api.screen.ModularWindow;
import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
@@ -50,33 +55,55 @@ import gregtech.api.interfaces.IHatchElement;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
-import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_CubicMultiBlockBase;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TieredMachineBlock;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_ExoticEnergyInputHelper;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_ProcessingArray_Manager;
import gregtech.api.util.GT_Recipe;
import gregtech.api.util.GT_Recipe.GT_Recipe_Map;
-import gregtech.api.util.GT_Single_Recipe_Check;
-import gregtech.api.util.GT_Single_Recipe_Check_Processing_Array;
+import gregtech.api.util.GT_StructureUtility;
import gregtech.api.util.GT_Utility;
import gregtech.common.blocks.GT_Item_Machines;
-public class GT_MetaTileEntity_ProcessingArray
- extends GT_MetaTileEntity_CubicMultiBlockBase<GT_MetaTileEntity_ProcessingArray> {
+public class GT_MetaTileEntity_ProcessingArray extends
+ GT_MetaTileEntity_ExtendedPowerMultiBlockBase<GT_MetaTileEntity_ProcessingArray> implements ISurvivalConstructable {
+
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<GT_MetaTileEntity_ProcessingArray> STRUCTURE_DEFINITION = StructureDefinition
+ .<GT_MetaTileEntity_ProcessingArray>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(new String[][] { { "hhh", "hhh", "hhh" }, { "h~h", "h-h", "hhh" }, { "hhh", "hhh", "hhh" }, }))
+ .addElement(
+ 'h',
+ ofChain(
+ lazy(
+ t -> GT_StructureUtility.<GT_MetaTileEntity_ProcessingArray>buildHatchAdder()
+ .atLeastList(t.getAllowedHatches())
+ .casingIndex(48)
+ .dot(1)
+ .build()),
+ onElementPass(t -> t.mCasingAmount++, ofBlock(GregTech_API.sBlockCasings4, 0))))
+ .build();
+
+ private int mCasingAmount = 0;
private GT_Recipe_Map mLastRecipeMap;
- private GT_Recipe mLastRecipe;
+ private ItemStack lastControllerStack;
private int tTier = 0;
private int mMult = 0;
private boolean downtierUEV = true;
- private String mMachineName = "";
- // Value needed so that the PA can use energy above MAX voltage
- private long mEUPerTick = 0;
public GT_MetaTileEntity_ProcessingArray(int aID, String aName, String aNameRegional) {
super(aID, aName, aNameRegional);
@@ -148,24 +175,12 @@ public class GT_MetaTileEntity_ProcessingArray
return new ITexture[] { Textures.BlockIcons.casingTexturePages[0][48] };
}
- // TODO: Expand so it also does the non recipe map recipes
- /*
- * public void remoteRecipeCheck() { if (mInventory[1] == null) return; String tmp =
- * mInventory[1].getUnlocalizedName().replaceAll("gt.blockmachines.basicmachine.", ""); if
- * (tmp.startsWith("replicator")) { } else if (tmp.startsWith("brewery")) { } else if (tmp.startsWith("packer")) { }
- * else if (tmp.startsWith("printer")) { } else if (tmp.startsWith("disassembler")) { } else if
- * (tmp.startsWith("massfab")) { } else if (tmp.startsWith("scanner")) { } }
- */
-
- // Gets the recipe map for the given machine through its unlocalized name
@Override
public GT_Recipe_Map getRecipeMap() {
- if (isCorrectMachinePart(mInventory[1])) {
- int length = mInventory[1].getUnlocalizedName()
- .length();
- String aMachineName = mInventory[1].getUnlocalizedName()
- .substring(17, length - 8);
- return GT_ProcessingArray_Manager.giveRecipeMap(aMachineName);
+ if (isCorrectMachinePart(getControllerSlot())) {
+ // Gets the recipe map for the given machine through its unlocalized name
+ return GT_ProcessingArray_Manager
+ .giveRecipeMap(GT_ProcessingArray_Manager.getMachineName(getControllerSlot()));
}
return null;
}
@@ -177,8 +192,12 @@ public class GT_MetaTileEntity_ProcessingArray
}
@Override
- public boolean supportsSingleRecipeLocking() {
- return true;
+ protected void sendStartMultiBlockSoundLoop() {
+ SoundResource sound = GT_ProcessingArray_Manager
+ .getSoundResource(GT_ProcessingArray_Manager.getMachineName(getControllerSlot()));
+ if (sound != null) {
+ sendLoopStart((byte) sound.id);
+ }
}
@Override
@@ -191,220 +210,85 @@ public class GT_MetaTileEntity_ProcessingArray
}
@Override
- protected boolean checkRecipe() {
- startRecipeProcessing();
- boolean result = checkRecipe(mInventory[1]);
- if (result) {
- int length = mInventory[1].getUnlocalizedName()
- .length();
- String aMachineName = mInventory[1].getUnlocalizedName()
- .substring(17, length - 8);
- SoundResource sound = GT_ProcessingArray_Manager.getSoundResource(aMachineName);
- if (sound != null) {
- sendLoopStart((byte) sound.id);
- }
- }
- endRecipeProcessing();
- return result;
- }
-
- @Override
- public boolean checkRecipe(ItemStack aStack) {
- if (mLockedToSingleRecipe && mSingleRecipeCheck != null) {
- return processLockedRecipe();
- }
-
- if (!isCorrectMachinePart(mInventory[1])) {
- return false;
- }
- GT_Recipe.GT_Recipe_Map map = getRecipeMap();
- if (map == null) return false;
-
- if (!mMachineName.equals(mInventory[1].getUnlocalizedName())) {
- mLastRecipe = null;
- mMachineName = mInventory[1].getUnlocalizedName();
- }
-
- if (mLastRecipe == null) {
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ if (!GT_Utility.areStacksEqual(lastControllerStack, getControllerSlot())) {
+ // controller slot has changed
+ lastControllerStack = getControllerSlot();
+ mLastRecipeMap = getRecipeMap();
setTierAndMult();
}
- ArrayList<FluidStack> tFluidList = getStoredFluids();
- FluidStack[] tFluids = tFluidList.toArray(new FluidStack[0]);
- if (inputSeparation) {
- ArrayList<ItemStack> tInputList = new ArrayList<>();
- for (GT_MetaTileEntity_Hatch_InputBus tHatch : mInputBusses) {
- IGregTechTileEntity tInputBus = tHatch.getBaseMetaTileEntity();
- for (int i = tInputBus.getSizeInventory() - 1; i >= 0; i--) {
- if (tInputBus.getStackInSlot(i) != null) tInputList.add(tInputBus.getStackInSlot(i));
- }
- ItemStack[] tInputs = tInputList.toArray(new ItemStack[0]);
- if (processRecipe(tInputs, tFluids, map)) return true;
- else tInputList.clear();
+ if (mLastRecipeMap == null) return SimpleCheckRecipeResult.ofFailure("no_machine");
+ if (mLockedToSingleRecipe && mSingleRecipeCheck != null) {
+ if (mSingleRecipeCheck.getRecipeMap() != mLastRecipeMap) {
+ return SimpleCheckRecipeResult.ofFailure("machine_mismatch");
}
- } else {
- ArrayList<ItemStack> tInputList = getStoredInputs();
- ItemStack[] tInputs = tInputList.toArray(new ItemStack[0]);
- return processRecipe(tInputs, tFluids, map);
}
- return false;
- }
- private void setTierAndMult() {
- IMetaTileEntity aMachine = GT_Item_Machines.getMetaTileEntity(mInventory[1]);
- if (aMachine != null) tTier = ((GT_MetaTileEntity_TieredMachineBlock) aMachine).mTier;
- mMult = 0;
- if (downtierUEV && tTier > 9) {
- tTier--; // Lowers down the tier by 1 to allow for bigger parallel
- mMult = 2; // Multiplies Parallels by 4x, keeping the energy cost
- }
+ return super.checkProcessing();
}
- public boolean processLockedRecipe() {
- GT_Single_Recipe_Check_Processing_Array tSingleRecipeCheck = (GT_Single_Recipe_Check_Processing_Array) mSingleRecipeCheck;
-
- if (mLastRecipe == null) {
- setTierAndMult();
- mLastRecipe = tSingleRecipeCheck.getRecipe();
- }
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
- int machines = mInventory[1].stackSize << mMult;
- int parallel = tSingleRecipeCheck.checkRecipeInputs(true, machines);
-
- return processRecipeOutputs(
- tSingleRecipeCheck.getRecipe(),
- tSingleRecipeCheck.getRecipeAmperage(),
- parallel,
- 1);
- }
-
- public boolean processRecipe(ItemStack[] tInputs, FluidStack[] tFluids, GT_Recipe.GT_Recipe_Map map) {
- if (tInputs.length == 0 && tFluids.length == 0) return false;
- GT_Recipe tRecipe = map.findRecipe(
- getBaseMetaTileEntity(),
- mLastRecipe,
- false,
- gregtech.api.enums.GT_Values.V[tTier],
- tFluids,
- tInputs);
- if (tRecipe == null) return false;
- if (GT_Mod.gregtechproxy.mLowGravProcessing && tRecipe.mSpecialValue == -100
- && !isValidForLowGravity(tRecipe, getBaseMetaTileEntity().getWorld().provider.dimensionId)) return false;
-
- GT_Single_Recipe_Check_Processing_Array.Builder tSingleRecipeCheckBuilder = null;
- if (mLockedToSingleRecipe) {
- // We're locked to a single recipe, but haven't built the recipe checker yet.
- // Build the checker on next successful recipe.
- tSingleRecipeCheckBuilder = GT_Single_Recipe_Check_Processing_Array.processingArrayBuilder(this)
- .setBefore(tInputs, tFluids);
- }
+ @Override
+ protected double calculateDuration(@Nonnull GT_Recipe recipe, @Nonnull GT_ParallelHelper helper,
+ @Nonnull GT_OverclockCalculator calculator) {
+ return calculator.getDuration();
+ }
- boolean recipeLocked = false;
- mLastRecipe = tRecipe;
- int machines = mInventory[1].stackSize << mMult;
- int i = 0;
- for (; i < machines; i++) {
- if (!tRecipe.isRecipeInputEqual(true, tFluids, tInputs)) {
- break;
- } else if (mLockedToSingleRecipe && !recipeLocked) {
- // We want to lock to a single run of the recipe.
- mSingleRecipeCheck = tSingleRecipeCheckBuilder.setAfter(tInputs, tFluids)
- .setRecipe(tRecipe)
- .setRecipeAmperage(map.mAmperage)
- .build();
- recipeLocked = true;
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe,
+ @Nonnull GT_ParallelHelper helper) {
+ return new GT_OverclockCalculator().setRecipeEUt(recipe.mEUt)
+ .setParallel((int) Math.floor(helper.getCurrentParallel() / helper.getDurationMultiplierDouble()))
+ .setDuration((int) Math.ceil(recipe.mDuration * helper.getDurationMultiplierDouble()))
+ .setAmperage(availableAmperage)
+ .setEUt(availableVoltage)
+ .setDurationDecreasePerOC(overClockTimeReduction)
+ .setEUtIncreasePerOC(overClockPowerIncrease);
}
- }
- // Check how many times we can run the same recipe
- int multiplier = 1;
- if (batchMode && i == machines) {
- for (; multiplier < 128; ++multiplier) {
- if (!tRecipe.isRecipeInputEqual(true, false, machines, tFluids, tInputs)) {
- break;
+ @Nonnull
+ @Override
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ if (GT_Mod.gregtechproxy.mLowGravProcessing && recipe.mSpecialValue == -100
+ && !isValidForLowGravity(recipe, getBaseMetaTileEntity().getWorld().provider.dimensionId)) {
+ return SimpleCheckRecipeResult.ofFailure("high_gravity");
}
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
- }
- return processRecipeOutputs(tRecipe, map.mAmperage, i, multiplier);
+ }.setMaxParallelSupplier(this::getMaxParallel);
}
- public boolean processRecipeOutputs(GT_Recipe aRecipe, int aAmperage, int parallel, int multiplier) {
- this.mEUPerTick = 0;
- this.mOutputItems = null;
- this.mOutputFluids = null;
- if (parallel == 0) {
- return false;
- }
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ GT_Recipe_Map recipeMap = getRecipeMap();
+ logic.setAvailableVoltage(GT_Values.V[tTier] * (recipeMap != null ? recipeMap.mAmperage : 1));
+ logic.setAvailableAmperage(getMaxParallel());
+ }
- this.mMaxProgresstime = aRecipe.mDuration * multiplier;
-
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
- ProcessingArrayCalculateOverclock(
- aRecipe.mEUt,
- aRecipe.mDuration * multiplier,
- aAmperage,
- GT_Values.V[tTier],
- false);
- // In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUPerTick == Long.MAX_VALUE - 1) return false;
- mEUPerTick = mEUPerTick * parallel;
- if (mEUPerTick == Long.MAX_VALUE - 1) return false;
-
- if (mEUPerTick > 0) {
- mEUPerTick = (-mEUPerTick);
- }
- ItemStack[] tOut = new ItemStack[aRecipe.mOutputs.length];
- for (int h = 0; h < aRecipe.mOutputs.length; h++) {
- if (aRecipe.getOutput(h) != null) {
- tOut[h] = aRecipe.getOutput(h)
- .copy();
- tOut[h].stackSize = 0;
- }
- }
- FluidStack[] tFOut = new FluidStack[aRecipe.mFluidOutputs.length];
- for (int i = 0; i < aRecipe.mFluidOutputs.length; i++)
- if (aRecipe.getFluidOutput(i) != null) tFOut[i] = aRecipe.getFluidOutput(i)
- .copy();
- for (int f = 0; f < tOut.length; f++) {
- if (aRecipe.mOutputs[f] != null && tOut[f] != null) {
- for (int g = 0; g < parallel * multiplier; g++) {
- if (getBaseMetaTileEntity().getRandomNumber(10000) < aRecipe.getOutputChance(f))
- tOut[f].stackSize += aRecipe.mOutputs[f].stackSize;
- }
- }
+ private void setTierAndMult() {
+ IMetaTileEntity aMachine = GT_Item_Machines.getMetaTileEntity(getControllerSlot());
+ if (aMachine instanceof GT_MetaTileEntity_TieredMachineBlock) {
+ tTier = ((GT_MetaTileEntity_TieredMachineBlock) aMachine).mTier;
+ } else {
+ tTier = 0;
}
- byte oNumber = 0;
- for (FluidStack fluidStack : tFOut) {
- if (fluidStack != null) {
- int tSize = fluidStack.amount;
- tFOut[oNumber].amount = tSize * parallel * multiplier;
- }
- oNumber++;
+ mMult = 0;
+ if (downtierUEV && tTier > 9) {
+ tTier--; // Lowers down the tier by 1 to allow for bigger parallel
+ mMult = 2; // Multiplies Parallels by 4x, keeping the energy cost
}
- this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime);
- this.mOutputItems = Arrays.stream(tOut)
- .filter(Objects::nonNull)
- .flatMap(GT_MetaTileEntity_ProcessingArray::splitOversizedStack)
- .filter(is -> is.stackSize > 0)
- .toArray(ItemStack[]::new);
- this.mOutputFluids = tFOut;
- updateSlots();
- return true;
}
- private static Stream<ItemStack> splitOversizedStack(ItemStack aStack) {
- int tMaxStackSize = aStack.getMaxStackSize();
- if (aStack.stackSize <= tMaxStackSize) return Stream.of(aStack);
- int tRepeat = aStack.stackSize / tMaxStackSize;
- aStack.stackSize = aStack.stackSize % tMaxStackSize;
- Stream.Builder<ItemStack> tBuilder = Stream.builder();
- tBuilder.add(aStack);
- for (int i = 0; i < tRepeat; i++) {
- ItemStack rStack = aStack.copy();
- rStack.stackSize = tMaxStackSize;
- tBuilder.add(rStack);
+ private int getMaxParallel() {
+ if (getControllerSlot() == null) {
+ return 0;
}
- return tBuilder.build();
+ return getControllerSlot().stackSize << mMult;
}
@Override
@@ -421,43 +305,43 @@ public class GT_MetaTileEntity_ProcessingArray
}
@Override
- protected IStructureElement<GT_MetaTileEntity_CubicMultiBlockBase<?>> getCasingElement() {
- return ofBlock(GregTech_API.sBlockCasings4, 0);
+ public IStructureDefinition<GT_MetaTileEntity_ProcessingArray> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
}
@Override
- protected int getHatchTextureIndex() {
- return 48;
+ public void construct(ItemStack aStack, boolean aHintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, aStack, aHintsOnly, 1, 1, 0);
}
@Override
- protected int getRequiredCasingCount() {
- return 14;
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 1, 1, 0, elementBudget, env, false, true);
+ }
+
+ private boolean checkHatches() {
+ return mMaintenanceHatches.size() == 1;
}
@Override
public void saveNBTData(NBTTagCompound aNBT) {
super.saveNBTData(aNBT);
aNBT.setBoolean("downtierUEV", downtierUEV);
- aNBT.setLong("mEUPerTick", mEUPerTick);
}
@Override
public void loadNBTData(final NBTTagCompound aNBT) {
super.loadNBTData(aNBT);
- if (!aNBT.hasKey(INPUT_SEPARATION_NBT_KEY)) {
+ if (aNBT.hasKey("mSeparate")) {
+ // backward compatibility
inputSeparation = aNBT.getBoolean("mSeparate");
}
- if (!aNBT.hasKey(BATCH_MODE_NBT_KEY)) {
+ if (aNBT.hasKey("mUseMultiparallelMode")) {
+ // backward compatibility
batchMode = aNBT.getBoolean("mUseMultiparallelMode");
}
downtierUEV = aNBT.getBoolean("downtierUEV");
- mEUPerTick = aNBT.getLong("mEUPerTick");
- }
-
- @Override
- protected GT_Single_Recipe_Check loadSingleRecipeChecker(NBTTagCompound aNBT) {
- return GT_Single_Recipe_Check_Processing_Array.tryLoad(this, getRecipeMap(), aNBT, mInventory[1]);
}
@Override
@@ -483,13 +367,11 @@ public class GT_MetaTileEntity_ProcessingArray
} else {
GT_Utility.sendChatToPlayer(aPlayer, "Don't batch recipes");
}
- return true;
} else {
downtierUEV = !downtierUEV;
- mLastRecipe = null; // clears last recipe
GT_Utility.sendChatToPlayer(aPlayer, "Treat UEV+ machines as multiple UHV " + downtierUEV);
- return true;
}
+ return true;
}
@Override
@@ -507,20 +389,15 @@ public class GT_MetaTileEntity_ProcessingArray
return false;
}
- @Override
- protected List<IHatchElement<? super GT_MetaTileEntity_CubicMultiBlockBase<?>>> getAllowedHatches() {
+ private List<IHatchElement<? super GT_MetaTileEntity_ProcessingArray>> getAllowedHatches() {
return ImmutableList.of(InputHatch, OutputHatch, InputBus, OutputBus, Maintenance, Energy, ExoticEnergy);
}
@Override
public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
mExoticEnergyHatches.clear();
- return super.checkMachine(aBaseMetaTileEntity, aStack);
- }
-
- @Override
- public boolean drainEnergyInput(long aEU) {
- return GT_ExoticEnergyInputHelper.drainEnergy(aEU, getExoticAndNormalEnergyHatchList());
+ mCasingAmount = 0;
+ return checkPiece(STRUCTURE_PIECE_MAIN, 1, 1, 0) && mCasingAmount >= 14 && checkHatches();
}
@Override
@@ -557,7 +434,7 @@ public class GT_MetaTileEntity_ProcessingArray
+ " EU",
StatCollector.translateToLocal("GT5U.multiblock.usage") + ": "
+ EnumChatFormatting.RED
- + GT_Utility.formatNumbers(-mEUPerTick)
+ + GT_Utility.formatNumbers(-lEUt)
+ EnumChatFormatting.RESET
+ " EU/t",
StatCollector.translateToLocal("GT5U.multiblock.mei") + ": "
@@ -599,84 +476,22 @@ public class GT_MetaTileEntity_ProcessingArray
+ " x",
StatCollector.translateToLocal("GT5U.PA.parallel") + ": "
+ EnumChatFormatting.GREEN
- + GT_Utility.formatNumbers((mInventory[1] != null) ? ((long) mInventory[1].stackSize << mMult) : 0)
+ + GT_Utility.formatNumbers(getMaxParallel())
+ EnumChatFormatting.RESET };
}
- public List<GT_MetaTileEntity_Hatch> getExoticAndNormalEnergyHatchList() {
- List<GT_MetaTileEntity_Hatch> tHatches = new ArrayList<>();
- tHatches.addAll(mExoticEnergyHatches);
- tHatches.addAll(mEnergyHatches);
- return tHatches;
- }
-
@Override
- public boolean onRunningTick(ItemStack aStack) {
- if (mEUPerTick < 0) {
- if (!drainEnergyInput(-mEUPerTick)) {
- mEUPerTick = 0;
- criticalStopMachine();
- return false;
- }
- }
+ public boolean supportsInputSeparation() {
return true;
}
- protected void ProcessingArrayCalculateOverclock(long aEUt, int aDuration, int mAmperage, long maxInputVoltage,
- boolean perfectOC) {
- byte mTier = (byte) Math.max(0, GT_Utility.getTier(maxInputVoltage));
- if (mTier == 0) {
- // Long time calculation
- long xMaxProgresstime = ((long) aDuration) << 1;
- if (xMaxProgresstime > Integer.MAX_VALUE - 1) {
- // make impossible if too long
- mEUPerTick = Long.MAX_VALUE - 1;
- mMaxProgresstime = Integer.MAX_VALUE - 1;
- } else {
- mEUPerTick = aEUt >> 2;
- mMaxProgresstime = (int) xMaxProgresstime;
- }
- } else {
- // Long EUt calculation
- long xEUt = aEUt;
- // Isnt too low EUt check?
- long tempEUt = Math.max(xEUt, V[1]);
-
- mMaxProgresstime = aDuration;
-
- final int ocTimeShift = perfectOC ? 2 : 1;
-
- while (tempEUt <= V[mTier - 1] * mAmperage) {
- tempEUt <<= 2; // this actually controls overclocking
- // xEUt *= 4;//this is effect of everclocking
- int oldTime = mMaxProgresstime;
- mMaxProgresstime >>= ocTimeShift; // this is effect of overclocking
- if (mMaxProgresstime < 1) {
- if (oldTime == 1) break;
- xEUt *= (long) oldTime * (perfectOC ? 1 : 2);
- break;
- } else {
- xEUt <<= 2;
- }
- }
- if (xEUt > Long.MAX_VALUE - 1) {
- mEUPerTick = Long.MAX_VALUE - 1;
- mMaxProgresstime = Integer.MAX_VALUE - 1;
- } else {
- mEUPerTick = xEUt;
- if (mEUPerTick == 0) mEUPerTick = 1;
- if (mMaxProgresstime == 0) mMaxProgresstime = 1; // set time to 1 tick
- }
- }
- }
-
@Override
- public boolean supportsInputSeparation() {
+ public boolean supportsBatchMode() {
return true;
}
@Override
- public boolean supportsBatchMode() {
+ public boolean supportsSingleRecipeLocking() {
return true;
}
@@ -684,22 +499,24 @@ public class GT_MetaTileEntity_ProcessingArray
public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
super.addUIWidgets(builder, buildContext);
- builder.widget(
- new ButtonWidget().setOnClick((clickData, widget) -> downtierUEV = !downtierUEV)
- .setPlayClickSound(true)
- .setBackground(() -> {
- if (downtierUEV) {
- return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
- GT_UITextures.OVERLAY_BUTTON_DOWN_TIERING_ON };
- } else {
- return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
- GT_UITextures.OVERLAY_BUTTON_DOWN_TIERING_OFF };
- }
- })
- .setPos(80, 91)
- .setSize(16, 16)
- .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.down_tier"))
- .setTooltipShowUpDelay(TOOLTIP_DELAY))
+ builder.widget(new ButtonWidget().setOnClick((clickData, widget) -> {
+ downtierUEV = !downtierUEV;
+ setTierAndMult();
+ })
+ .setPlayClickSound(true)
+ .setBackground(() -> {
+ if (downtierUEV) {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD_PRESSED,
+ GT_UITextures.OVERLAY_BUTTON_DOWN_TIERING_ON };
+ } else {
+ return new IDrawable[] { GT_UITextures.BUTTON_STANDARD,
+ GT_UITextures.OVERLAY_BUTTON_DOWN_TIERING_OFF };
+ }
+ })
+ .setPos(80, 91)
+ .setSize(16, 16)
+ .addTooltip(StatCollector.translateToLocal("GT5U.gui.button.down_tier"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY))
.widget(new FakeSyncWidget.BooleanSyncer(() -> downtierUEV, val -> downtierUEV = val));
}
}
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java
index 2a36377acc..c76ac32863 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_PyrolyseOven.java
@@ -21,7 +21,8 @@ import static gregtech.api.util.GT_StructureUtility.ofCoil;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
@@ -37,12 +38,12 @@ import gregtech.api.enums.Textures.BlockIcons;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
-import gregtech.api.util.GT_Single_Recipe_Check;
-import gregtech.api.util.GT_Utility;
public class GT_MetaTileEntity_PyrolyseOven
extends GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_PyrolyseOven> implements ISurvivalConstructable {
@@ -157,56 +158,20 @@ public class GT_MetaTileEntity_PyrolyseOven
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- long tVoltage = getMaxInputVoltage();
- byte tTier = (byte) Math.max(1, GT_Utility.getTier(tVoltage));
- GT_Recipe tRecipe;
-
- if (mLockedToSingleRecipe && mSingleRecipeCheck != null) {
- if (!mSingleRecipeCheck.checkRecipeInputsSingleStack(true)) {
- return false;
- }
-
- tRecipe = mSingleRecipeCheck.getRecipe();
- } else {
- ItemStack[] tInputs = getCompactedInputs();
- FluidStack[] tFluids = getCompactedFluids();
-
- if (tInputs.length == 0) return false;
-
- GT_Single_Recipe_Check.Builder tSingleRecipeCheckBuilder = null;
- if (mLockedToSingleRecipe) {
- // We're locked to a single recipe, but haven't built the recipe checker yet.
- // Build the checker on next successful recipe.
- tSingleRecipeCheckBuilder = GT_Single_Recipe_Check.builder(this)
- .setBefore(tInputs, tFluids);
- }
-
- tRecipe = GT_Recipe.GT_Recipe_Map.sPyrolyseRecipes
- .findRecipe(getBaseMetaTileEntity(), false, gregtech.api.enums.GT_Values.V[tTier], tFluids, tInputs);
-
- if (tRecipe == null || !canOutputAll(tRecipe) || !tRecipe.isRecipeInputEqual(true, tFluids, tInputs))
- return false;
-
- if (mLockedToSingleRecipe) {
- mSingleRecipeCheck = tSingleRecipeCheckBuilder.setAfter(tInputs, tFluids)
- .setRecipe(tRecipe)
- .build();
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ public CheckRecipeResult process() {
+ CheckRecipeResult result = super.process();
+ if (!result.wasSuccessful()) {
+ return result;
+ }
+ duration = Math.max(duration * 2 / (1 + coilHeat.getTier()), 1);
+ return result;
}
- }
-
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
-
- calculateOverclockedNessMultiInternal(tRecipe.mEUt, tRecipe.mDuration, 1, tVoltage, false);
- // In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) return false;
- if (this.mEUt > 0) this.mEUt = (-this.mEUt);
- this.mMaxProgresstime = Math.max(mMaxProgresstime * 2 / (1 + coilHeat.getTier()), 1);
- if (tRecipe.mOutputs.length > 0) this.mOutputItems = new ItemStack[] { tRecipe.getOutput(0) };
- if (tRecipe.mFluidOutputs.length > 0) this.mOutputFluids = new FluidStack[] { tRecipe.getFluidOutput(0) };
- updateSlots();
- return true;
+ };
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java
index 429a8a4ddf..54f903299e 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_TranscendentPlasmaMixer.java
@@ -18,10 +18,13 @@ import static java.lang.Math.max;
import static net.minecraft.util.EnumChatFormatting.GOLD;
import static net.minecraft.util.EnumChatFormatting.GRAY;
+import javax.annotation.Nonnull;
+
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
@@ -33,9 +36,14 @@ import gregtech.api.interfaces.IGlobalWirelessEnergy;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
import gregtech.api.util.GT_Recipe;
import gregtech.common.items.GT_IntegratedCircuit_Item;
@@ -136,56 +144,53 @@ public class GT_MetaTileEntity_TranscendentPlasmaMixer
long mWirelessEUt = 0;
@Override
- public boolean checkRecipe(ItemStack aStack) {
- if (aStack != null && aStack.getItem() instanceof GT_IntegratedCircuit_Item) {
- multiplier = aStack.stackSize * max(1, aStack.getItemDamage());
- }
-
- return processRecipe(getCompactedInputs(), getCompactedFluids());
+ public GT_Recipe.GT_Recipe_Map getRecipeMap() {
+ return GT_Recipe.GT_Recipe_Map.sTranscendentPlasmaMixerRecipes;
}
- boolean processRecipe(ItemStack[] items, FluidStack[] fluids) {
-
- GT_Recipe originalRecipe = GT_Recipe.GT_Recipe_Map.sTranscendentPlasmaMixerRecipes
- .findRecipe(getBaseMetaTileEntity(), false, Long.MAX_VALUE, fluids, items);
-
- if (originalRecipe == null) {
- return false;
- }
- mWirelessEUt = 10L * (long) originalRecipe.mEUt * (long) multiplier;
- // 100L - recipe takes 100 ticks
- if (!addEUToGlobalEnergyMap(ownerUUID, mWirelessEUt * -100L)) {
- return false;
- }
-
- // Fluid handling.
- {
- // Output items/fluids.
- GT_Recipe modifiedRecipe = originalRecipe.copy();
-
- // Multiply up the input plasmas.
- for (FluidStack fluidStack : modifiedRecipe.mFluidInputs) {
- fluidStack.amount *= multiplier;
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ mWirelessEUt = 10L * (long) recipe.mEUt * (long) multiplier;
+ if (!addEUToGlobalEnergyMap(ownerUUID, -mWirelessEUt * recipe.mDuration)) {
+ return CheckRecipeResultRegistry.insufficientPower(mWirelessEUt * recipe.mDuration);
+ }
+ return CheckRecipeResultRegistry.SUCCESSFUL;
}
- // Multiply up the output fluid.
- modifiedRecipe.mFluidOutputs[0].amount *= multiplier;
-
- if (!canOutputAll(modifiedRecipe)) return false;
-
- // Takes items/fluids from hatches/busses.
- if (!modifiedRecipe.isRecipeInputEqual(true, fluids, items)) return false;
-
- mOutputFluids = modifiedRecipe.mFluidOutputs;
- mOutputItems = modifiedRecipe.mOutputs;
- }
-
- mMaxProgresstime = 100;
- mEUt = 0;
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe,
+ @Nonnull GT_ParallelHelper helper) {
+ return GT_OverclockCalculator.ofNoOverclock(recipe);
+ }
- updateSlots();
+ @NotNull
+ @Override
+ public CheckRecipeResult process() {
+ CheckRecipeResult result = super.process();
+ // Power will be directly consumed through wireless
+ setCalculatedEut(0);
+ return result;
+ }
+ }.setMaxParallelSupplier(() -> {
+ ItemStack controllerStack = getControllerSlot();
+ if (controllerStack != null && controllerStack.getItem() instanceof GT_IntegratedCircuit_Item) {
+ multiplier = controllerStack.stackSize * max(1, controllerStack.getItemDamage());
+ }
+ return multiplier;
+ });
+ }
- return true;
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ // The voltage is only used for recipe finding
+ logic.setAvailableVoltage(Long.MAX_VALUE);
+ logic.setAvailableAmperage(1);
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java
index 815515b555..e353d5d980 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/GT_MetaTileEntity_VacuumFreezer.java
@@ -8,7 +8,6 @@ import static gregtech.api.enums.Textures.BlockIcons.casingTexturePages;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.ForgeDirection;
-import net.minecraftforge.fluids.FluidStack;
import com.gtnewhorizon.structurelib.structure.IStructureElement;
import com.gtnewhorizon.structurelib.structure.StructureUtility;
@@ -17,11 +16,11 @@ import gregtech.api.GregTech_API;
import gregtech.api.interfaces.ITexture;
import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_CubicMultiBlockBase;
import gregtech.api.render.TextureFactory;
import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
import gregtech.api.util.GT_Recipe;
-import gregtech.api.util.GT_Utility;
public class GT_MetaTileEntity_VacuumFreezer
extends GT_MetaTileEntity_CubicMultiBlockBase<GT_MetaTileEntity_VacuumFreezer> {
@@ -102,34 +101,8 @@ public class GT_MetaTileEntity_VacuumFreezer
}
@Override
- public boolean checkRecipe(ItemStack aStack) {
- ItemStack[] tInputList = getCompactedInputs();
- FluidStack[] tFluidList = getCompactedFluids();
-
- long tVoltage = getMaxInputVoltage();
- byte tTier = (byte) Math.max(1, GT_Utility.getTier(tVoltage));
- GT_Recipe tRecipe = getRecipeMap()
- .findRecipe(getBaseMetaTileEntity(), false, gregtech.api.enums.GT_Values.V[tTier], tFluidList, tInputList);
- if (tRecipe != null) {
- if (!canOutputAll(tRecipe)) return false;
- if (tRecipe.isRecipeInputEqual(true, tFluidList, tInputList)) {
- this.mEfficiency = (10000 - (getIdealStatus() - getRepairStatus()) * 1000);
- this.mEfficiencyIncrease = 10000;
-
- calculateOverclockedNessMultiInternal(tRecipe.mEUt, tRecipe.mDuration, 1, tVoltage, false);
- // In case recipe is too OP for that machine
- if (mMaxProgresstime == Integer.MAX_VALUE - 1 && mEUt == Integer.MAX_VALUE - 1) return false;
- if (this.mEUt > 0) {
- this.mEUt = (-this.mEUt);
- }
- this.mMaxProgresstime = Math.max(1, this.mMaxProgresstime);
- this.mOutputItems = new ItemStack[] { tRecipe.getOutput(0) };
- this.mOutputFluids = new FluidStack[] { tRecipe.getFluidOutput(0) };
- updateSlots();
- return true;
- }
- }
- return false;
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic();
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java
index e9db6c2256..38152869e4 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/AdvChemicalReactor.java
@@ -78,9 +78,12 @@ public class AdvChemicalReactor extends ComplexParallelController<AdvChemicalRea
}
processFluidWhiteLists.add(processFluidTanks);
}
- processingLogic = new ComplexParallelProcessingLogic(
- GT_Recipe.GT_Recipe_Map_LargeChemicalReactor.sChemicalRecipes,
- MAX_PROCESSES);
+ processingLogic = new ComplexParallelProcessingLogic(getRecipeMap(), MAX_PROCESSES);
+ }
+
+ @Override
+ public GT_Recipe.GT_Recipe_Map getRecipeMap() {
+ return GT_Recipe.GT_Recipe_Map_LargeChemicalReactor.sChemicalRecipes;
}
@Override
diff --git a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java
index 4a84c1503f..046bb4a114 100644
--- a/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java
+++ b/src/main/java/gregtech/common/tileentities/machines/multiblock/logic/CokeOvenProcessingLogic.java
@@ -4,10 +4,14 @@ import static gregtech.api.enums.Mods.Railcraft;
import static net.minecraftforge.oredict.OreDictionary.getOreID;
import static net.minecraftforge.oredict.OreDictionary.getOreIDs;
+import javax.annotation.Nonnull;
+
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
import gregtech.api.util.GT_ModHandler;
import gregtech.api.util.GT_OreDictUnificator;
@@ -24,21 +28,22 @@ public class CokeOvenProcessingLogic extends ProcessingLogic {
private int timeMultiplier = 1;
@Override
- public boolean process() {
+ public @Nonnull CheckRecipeResult process() {
if (inputItems == null || inputItems[0] == null) {
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
ItemStack input = inputItems[0];
int originalStackSize = input.stackSize;
ItemStack output = findRecipe(input);
if (currentOutputItems != null && currentOutputItems[0] != null && !currentOutputItems[0].isItemEqual(output)) {
- return false;
+ return CheckRecipeResultRegistry.NO_RECIPE;
}
input.stackSize -= 1;
- setDuration((long) NORMAL_RECIPE_TIME * timeMultiplier);
+ setDuration(NORMAL_RECIPE_TIME * timeMultiplier);
setOutputItems(output);
- return originalStackSize > input.stackSize;
+ return originalStackSize > input.stackSize ? CheckRecipeResultRegistry.SUCCESSFUL
+ : CheckRecipeResultRegistry.NO_RECIPE;
}
protected ItemStack findRecipe(ItemStack input) {
diff --git a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java
index 123e193f03..dd76ddf45e 100644
--- a/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java
+++ b/src/main/java/gregtech/common/tileentities/storage/GT_MetaTileEntity_DigitalTankBase.java
@@ -476,6 +476,7 @@ public abstract class GT_MetaTileEntity_DigitalTankBase extends GT_MetaTileEntit
return allowOverflow() ? Integer.MAX_VALUE : getRealCapacity();
}
+ @Override
public int getRealCapacity() {
return commonSizeCompute(mTier);
}
diff --git a/src/main/java/gregtech/nei/HeatingCoilSpecialValueFormatter.java b/src/main/java/gregtech/nei/HeatingCoilSpecialValueFormatter.java
index f6f0a4099f..936aa6b715 100644
--- a/src/main/java/gregtech/nei/HeatingCoilSpecialValueFormatter.java
+++ b/src/main/java/gregtech/nei/HeatingCoilSpecialValueFormatter.java
@@ -16,15 +16,7 @@ public class HeatingCoilSpecialValueFormatter implements INEISpecialInfoFormatte
List<String> result = new ArrayList<>();
result.add(applyPrefixAndSuffix.apply(heat));
-
- for (HeatingCoilLevel heatLevel : HeatingCoilLevel.values()) {
- if (heatLevel == HeatingCoilLevel.None || heatLevel == HeatingCoilLevel.ULV) continue;
- if (heatLevel.getHeat() >= heat) {
- result.add(" (" + heatLevel.getName() + ")");
- return result;
- }
- }
- result.add(" (" + HeatingCoilLevel.MAX.getName() + "+)");
+ result.add(" (" + HeatingCoilLevel.getDisplayNameFromHeat(heat, false) + ")");
return result;
}
}