From fe0387946550f89a403b09f4e8cf6e43ee8f2e8f Mon Sep 17 00:00:00 2001 From: Maxim Date: Mon, 10 Jul 2023 10:13:04 +0200 Subject: 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 --- .../api/metatileentity/BaseMetaTileEntity.java | 12 ++ .../api/metatileentity/MetaTileEntity.java | 6 + .../GT_MetaTileEntity_BasicMachine.java | 16 +- ...MetaTileEntity_ExtendedPowerMultiBlockBase.java | 69 ++++++ .../GT_MetaTileEntity_MultiBlockBase.java | 236 ++++++++++++++++++--- 5 files changed, 306 insertions(+), 33 deletions(-) (limited to 'src/main/java/gregtech/api/metatileentity') 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; @@ -126,6 +131,70 @@ public abstract class GT_MetaTileEntity_ExtendedPowerMultiBlockBase 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; 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 mInputHatches = new ArrayList<>(); public ArrayList mOutputHatches = new ArrayList<>(); @@ -120,6 +127,7 @@ public abstract class GT_MetaTileEntity_MultiBlockBase extends MetaTileEntity public ArrayList mEnergyHatches = new ArrayList<>(); public ArrayList mMaintenanceHatches = new ArrayList<>(); protected List 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. + *

+ * 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. + *

+ * 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 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. + *

+ * 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() -- cgit