diff options
| author | NotAPenguin <michiel.vandeginste@gmail.com> | 2024-09-02 23:17:17 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-09-02 23:17:17 +0200 |
| commit | 1b820de08a05070909a267e17f033fcf58ac8710 (patch) | |
| tree | 02831a025986a06b20f87e5bcc69d1e0c639a342 /src/main/java/gregtech/api/metatileentity/implementations/MTEBasicMachine.java | |
| parent | afd3fd92b6a6ab9ab0d0dc3214e6bc8ff7a86c9b (diff) | |
| download | GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.tar.gz GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.tar.bz2 GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.zip | |
The Great Renaming (#3014)
* move kekztech to a single root dir
* move detrav to a single root dir
* move gtnh-lanthanides to a single root dir
* move tectech and delete some gross reflection in gt++
* remove more reflection inside gt5u
* delete more reflection in gt++
* fix imports
* move bartworks and bwcrossmod
* fix proxies
* move galactigreg and ggfab
* move gtneioreplugin
* try to fix gt++ bee loader
* apply the rename rules to BW
* apply rename rules to bwcrossmod
* apply rename rules to detrav scanner mod
* apply rename rules to galacticgreg
* apply rename rules to ggfab
* apply rename rules to goodgenerator
* apply rename rules to gtnh-lanthanides
* apply rename rules to gt++
* apply rename rules to kekztech
* apply rename rules to kubatech
* apply rename rules to tectech
* apply rename rules to gt
apply the rename rules to gt
* fix tt import
* fix mui hopefully
* fix coremod except intergalactic
* rename assline recipe class
* fix a class name i stumbled on
* rename StructureUtility to GTStructureUtility to prevent conflict with structurelib
* temporary rename of GTTooltipDataCache to old name
* fix gt client/server proxy names
Diffstat (limited to 'src/main/java/gregtech/api/metatileentity/implementations/MTEBasicMachine.java')
| -rw-r--r-- | src/main/java/gregtech/api/metatileentity/implementations/MTEBasicMachine.java | 1563 |
1 files changed, 1563 insertions, 0 deletions
diff --git a/src/main/java/gregtech/api/metatileentity/implementations/MTEBasicMachine.java b/src/main/java/gregtech/api/metatileentity/implementations/MTEBasicMachine.java new file mode 100644 index 0000000000..25dfb9b58b --- /dev/null +++ b/src/main/java/gregtech/api/metatileentity/implementations/MTEBasicMachine.java @@ -0,0 +1,1563 @@ +package gregtech.api.metatileentity.implementations; + +import static gregtech.api.enums.GTValues.V; +import static gregtech.api.enums.GTValues.debugCleanroom; +import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASINGS; +import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE_OUT; +import static gregtech.api.metatileentity.BaseTileEntity.FLUID_TRANSFER_TOOLTIP; +import static gregtech.api.metatileentity.BaseTileEntity.ITEM_TRANSFER_TOOLTIP; +import static gregtech.api.metatileentity.BaseTileEntity.NEI_TRANSFER_STEAM_TOOLTIP; +import static gregtech.api.metatileentity.BaseTileEntity.NEI_TRANSFER_VOLTAGE_TOOLTIP; +import static gregtech.api.metatileentity.BaseTileEntity.POWER_SOURCE_KEY; +import static gregtech.api.metatileentity.BaseTileEntity.SPECIAL_SLOT_TOOLTIP; +import static gregtech.api.metatileentity.BaseTileEntity.STALLED_STUTTERING_TOOLTIP; +import static gregtech.api.metatileentity.BaseTileEntity.STALLED_VENT_TOOLTIP; +import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; +import static gregtech.api.metatileentity.BaseTileEntity.UNUSED_SLOT_TOOLTIP; +import static gregtech.api.util.GTRecipeConstants.EXPLODE; +import static gregtech.api.util.GTRecipeConstants.ON_FIRE; +import static gregtech.api.util.GTUtility.moveMultipleItemStacks; +import static net.minecraftforge.common.util.ForgeDirection.DOWN; +import static net.minecraftforge.common.util.ForgeDirection.UNKNOWN; +import static net.minecraftforge.common.util.ForgeDirection.UP; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nonnull; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.StatCollector; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fluids.IFluidHandler; + +import org.apache.commons.lang3.tuple.Pair; + +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.math.Pos2d; +import com.gtnewhorizons.modularui.api.math.Size; +import com.gtnewhorizons.modularui.api.screen.ModularWindow; +import com.gtnewhorizons.modularui.api.screen.UIBuildContext; +import com.gtnewhorizons.modularui.api.widget.Widget; +import com.gtnewhorizons.modularui.common.fluid.FluidStackTank; +import com.gtnewhorizons.modularui.common.widget.CycleButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget; +import com.gtnewhorizons.modularui.common.widget.ProgressBar; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; + +import gregtech.GTMod; +import gregtech.api.GregTechAPI; +import gregtech.api.enums.SoundResource; +import gregtech.api.gui.modularui.GTUIInfos; +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.gui.modularui.SteamTexture; +import gregtech.api.interfaces.ICleanroom; +import gregtech.api.interfaces.IConfigurationCircuitSupport; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.modularui.IAddGregtechLogo; +import gregtech.api.interfaces.modularui.IAddUIWidgets; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.interfaces.tileentity.IOverclockDescriptionProvider; +import gregtech.api.interfaces.tileentity.RecipeMapWorkable; +import gregtech.api.objects.GTItemStack; +import gregtech.api.objects.overclockdescriber.EUOverclockDescriber; +import gregtech.api.objects.overclockdescriber.OverclockDescriber; +import gregtech.api.recipe.BasicUIProperties; +import gregtech.api.recipe.RecipeMap; +import gregtech.api.render.TextureFactory; +import gregtech.api.util.CoverBehaviorBase; +import gregtech.api.util.GTClientPreference; +import gregtech.api.util.GTLog; +import gregtech.api.util.GTOreDictUnificator; +import gregtech.api.util.GTRecipe; +import gregtech.api.util.GTUtility; +import gregtech.api.util.GTWaila; +import gregtech.api.util.GT_TooltipDataCache; +import gregtech.api.util.OverclockCalculator; +import gregtech.common.gui.modularui.UIHelper; +import mcp.mobius.waila.api.IWailaConfigHandler; +import mcp.mobius.waila.api.IWailaDataAccessor; + +/** + * NEVER INCLUDE THIS FILE IN YOUR MOD!!! + * <p/> + * This is the main construct for my Basic Machines such as the Automatic Extractor Extend this class to make a simple + * Machine + */ +public abstract class MTEBasicMachine extends MTEBasicTank implements RecipeMapWorkable, IConfigurationCircuitSupport, + IOverclockDescriptionProvider, IAddGregtechLogo, IAddUIWidgets { + + /** + * return values for checkRecipe() + */ + protected static final int DID_NOT_FIND_RECIPE = 0, FOUND_RECIPE_BUT_DID_NOT_MEET_REQUIREMENTS = 1, + FOUND_AND_SUCCESSFULLY_USED_RECIPE = 2; + + public static final int OTHER_SLOT_COUNT = 5; + public final ItemStack[] mOutputItems; + public final int mInputSlotCount, mAmperage; + public boolean mAllowInputFromOutputSide = false, mFluidTransfer = false, mItemTransfer = false, + mHasBeenUpdated = false, mStuttering = false, mCharge = false, mDecharge = false; + public boolean mDisableFilter = true; + public boolean mDisableMultiStack = true; + public int mProgresstime = 0, mMaxProgresstime = 0, mEUt = 0, mOutputBlocked = 0; + public ForgeDirection mMainFacing = ForgeDirection.WEST; + public FluidStack mOutputFluid; + protected final OverclockDescriber overclockDescriber; + + /** + * Contains the Recipe which has been previously used, or null if there was no previous Recipe, which could have + * been buffered + */ + protected GTRecipe mLastRecipe = null; + + private FluidStack mFluidOut; + protected final FluidStackTank fluidOutputTank = new FluidStackTank( + () -> mFluidOut, + fluidStack -> mFluidOut = fluidStack, + this::getCapacity); + + /** + * Registers machine with single-line description. + * + * @param aOverlays 0 = SideFacingActive 1 = SideFacingInactive 2 = FrontFacingActive 3 = FrontFacingInactive 4 = + * TopFacingActive 5 = TopFacingInactive 6 = BottomFacingActive 7 = BottomFacingInactive ----- Not + * all Array Elements have to be initialised, you can also just use 8 Parameters for the Default + * Pipe Texture Overlays ----- 8 = BottomFacingPipeActive 9 = BottomFacingPipeInactive 10 = + * TopFacingPipeActive 11 = TopFacingPipeInactive 12 = SideFacingPipeActive 13 = + * SideFacingPipeInactive + */ + public MTEBasicMachine(int aID, String aName, String aNameRegional, int aTier, int aAmperage, String aDescription, + int aInputSlotCount, int aOutputSlotCount, ITexture... aOverlays) { + super( + aID, + aName, + aNameRegional, + aTier, + OTHER_SLOT_COUNT + aInputSlotCount + aOutputSlotCount + 1, + aDescription, + aOverlays); + mInputSlotCount = Math.max(0, aInputSlotCount); + mOutputItems = new ItemStack[Math.max(0, aOutputSlotCount)]; + mAmperage = aAmperage; + overclockDescriber = createOverclockDescriber(); + } + + /** + * Registers machine with multi-line descriptions. + */ + public MTEBasicMachine(int aID, String aName, String aNameRegional, int aTier, int aAmperage, String[] aDescription, + int aInputSlotCount, int aOutputSlotCount, ITexture... aOverlays) { + super( + aID, + aName, + aNameRegional, + aTier, + OTHER_SLOT_COUNT + aInputSlotCount + aOutputSlotCount + 1, + aDescription, + aOverlays); + mInputSlotCount = Math.max(0, aInputSlotCount); + mOutputItems = new ItemStack[Math.max(0, aOutputSlotCount)]; + mAmperage = aAmperage; + overclockDescriber = createOverclockDescriber(); + } + + /** + * For {@link #newMetaEntity}. + */ + public MTEBasicMachine(String aName, int aTier, int aAmperage, String[] aDescription, ITexture[][][] aTextures, + int aInputSlotCount, int aOutputSlotCount) { + super(aName, aTier, OTHER_SLOT_COUNT + aInputSlotCount + aOutputSlotCount + 1, aDescription, aTextures); + mInputSlotCount = Math.max(0, aInputSlotCount); + mOutputItems = new ItemStack[Math.max(0, aOutputSlotCount)]; + mAmperage = aAmperage; + overclockDescriber = createOverclockDescriber(); + } + + /** + * To be called by the constructor to initialize this instance's overclock behavior + */ + protected OverclockDescriber createOverclockDescriber() { + return new EUOverclockDescriber(mTier, mAmperage); + } + + protected boolean isValidMainFacing(ForgeDirection side) { + return (side.flag & (UP.flag | DOWN.flag | UNKNOWN.flag)) == 0; // Horizontal + } + + public boolean setMainFacing(ForgeDirection side) { + if (!isValidMainFacing(side)) return false; + mMainFacing = side; + if (getBaseMetaTileEntity().getFrontFacing() == mMainFacing) { + getBaseMetaTileEntity().setFrontFacing(side.getOpposite()); + } + onFacingChange(); + onMachineBlockUpdate(); + return true; + } + + @Override + public void onFacingChange() { + super.onFacingChange(); + // Set up the correct facing (front towards player, output opposite) client-side before the server packet + // arrives + if (mMainFacing == UNKNOWN) { + IGregTechTileEntity te = getBaseMetaTileEntity(); + if (te != null && te.getWorld().isRemote) { + mMainFacing = te.getFrontFacing(); + te.setFrontFacing(te.getBackFacing()); + } + } + } + + @Override + public ITexture[][][] getTextureSet(ITexture[] aTextures) { + ITexture[][][] rTextures = new ITexture[14][17][]; + aTextures = Arrays.copyOf(aTextures, 14); + + for (int i = 0; i < aTextures.length; i++) if (aTextures[i] != null) for (byte c = -1; c < 16; c++) { + if (rTextures[i][c + 1] == null) + rTextures[i][c + 1] = new ITexture[] { MACHINE_CASINGS[mTier][c + 1], aTextures[i] }; + } + + for (byte c = -1; c < 16; c++) { + if (rTextures[0][c + 1] == null) rTextures[0][c + 1] = getSideFacingActive(c); + if (rTextures[1][c + 1] == null) rTextures[1][c + 1] = getSideFacingInactive(c); + if (rTextures[2][c + 1] == null) rTextures[2][c + 1] = getFrontFacingActive(c); + if (rTextures[3][c + 1] == null) rTextures[3][c + 1] = getFrontFacingInactive(c); + if (rTextures[4][c + 1] == null) rTextures[4][c + 1] = getTopFacingActive(c); + if (rTextures[5][c + 1] == null) rTextures[5][c + 1] = getTopFacingInactive(c); + if (rTextures[6][c + 1] == null) rTextures[6][c + 1] = getBottomFacingActive(c); + if (rTextures[7][c + 1] == null) rTextures[7][c + 1] = getBottomFacingInactive(c); + if (rTextures[8][c + 1] == null) rTextures[8][c + 1] = getBottomFacingPipeActive(c); + if (rTextures[9][c + 1] == null) rTextures[9][c + 1] = getBottomFacingPipeInactive(c); + if (rTextures[10][c + 1] == null) rTextures[10][c + 1] = getTopFacingPipeActive(c); + if (rTextures[11][c + 1] == null) rTextures[11][c + 1] = getTopFacingPipeInactive(c); + if (rTextures[12][c + 1] == null) rTextures[12][c + 1] = getSideFacingPipeActive(c); + if (rTextures[13][c + 1] == null) rTextures[13][c + 1] = getSideFacingPipeInactive(c); + } + return rTextures; + } + + @Override + public ITexture[] getTexture(IGregTechTileEntity baseMetaTileEntity, ForgeDirection sideDirection, + ForgeDirection facingDirection, int colorIndex, boolean active, boolean redstoneLevel) { + final int textureIndex; + if ((mMainFacing.flag & (UP.flag | DOWN.flag)) != 0) { // UP or DOWN + if (sideDirection == facingDirection) { + textureIndex = active ? 2 : 3; + } else { + textureIndex = switch (sideDirection) { + case DOWN -> active ? 6 : 7; + case UP -> active ? 4 : 5; + default -> active ? 0 : 1; + }; + } + } else { + if (sideDirection == mMainFacing) { + textureIndex = active ? 2 : 3; + } else { + if (showPipeFacing() && sideDirection == facingDirection) { + textureIndex = switch (sideDirection) { + case DOWN -> active ? 8 : 9; + case UP -> active ? 10 : 11; + default -> active ? 12 : 13; + }; + } else { + textureIndex = switch (sideDirection) { + case DOWN -> active ? 6 : 7; + case UP -> active ? 4 : 5; + default -> active ? 0 : 1; + }; + } + } + } + return mTextures[textureIndex][colorIndex + 1]; + } + + @Override + public boolean isSimpleMachine() { + return false; + } + + @Override + public boolean isOverclockerUpgradable() { + return false; + } + + @Override + public boolean isTransformerUpgradable() { + return false; + } + + @Override + public boolean isElectric() { + return true; + } + + @Override + public boolean isValidSlot(int aIndex) { + return aIndex > 0 && super.isValidSlot(aIndex) + && aIndex != getCircuitSlot() + && aIndex != OTHER_SLOT_COUNT + mInputSlotCount + mOutputItems.length; + } + + @Override + public boolean isFacingValid(ForgeDirection facing) { + // Either mMainFacing or mMainFacing is horizontal + return ((facing.flag | mMainFacing.flag) & ~(UP.flag | DOWN.flag | UNKNOWN.flag)) != 0; + } + + @Override + public boolean isEnetInput() { + return true; + } + + @Override + public boolean isInputFacing(ForgeDirection side) { + return side != mMainFacing; + } + + @Override + public boolean isOutputFacing(ForgeDirection side) { + return false; + } + + @Override + public boolean isTeleporterCompatible() { + return false; + } + + @Override + public boolean isLiquidInput(ForgeDirection side) { + return side != mMainFacing && (mAllowInputFromOutputSide || side != getBaseMetaTileEntity().getFrontFacing()); + } + + @Override + public boolean isLiquidOutput(ForgeDirection side) { + return side != mMainFacing; + } + + @Override + public long getMinimumStoredEU() { + return V[mTier] * 16L; + } + + @Override + public long maxEUStore() { + return V[mTier] * 64L; + } + + @Override + public long maxEUInput() { + return V[mTier]; + } + + @Override + public long maxSteamStore() { + return maxEUStore(); + } + + @Override + public long maxAmperesIn() { + return ((long) mEUt * 2L) / V[mTier] + 1L; + } + + @Override + public int getInputSlot() { + return OTHER_SLOT_COUNT; + } + + @Override + public int getOutputSlot() { + return OTHER_SLOT_COUNT + mInputSlotCount; + } + + public int getSpecialSlotIndex() { + return 3; + } + + @Override + public int getStackDisplaySlot() { + return 2; + } + + @Override + public int rechargerSlotStartIndex() { + return 1; + } + + @Override + public int dechargerSlotStartIndex() { + return 1; + } + + @Override + public int rechargerSlotCount() { + return mCharge ? 1 : 0; + } + + @Override + public int dechargerSlotCount() { + return mDecharge ? 1 : 0; + } + + @Override + public boolean isAccessAllowed(EntityPlayer aPlayer) { + return true; + } + + @Override + public int getProgresstime() { + return mProgresstime; + } + + @Override + public int maxProgresstime() { + return mMaxProgresstime; + } + + @Override + public int increaseProgress(int aProgress) { + mProgresstime += aProgress; + return mMaxProgresstime - mProgresstime; + } + + @Override + public boolean isFluidInputAllowed(FluidStack aFluid) { + return getFillableStack() != null || (getRecipeMap() != null && getRecipeMap().containsInput(aFluid)); + } + + @Override + public boolean isFluidChangingAllowed() { + return true; + } + + @Override + public boolean doesFillContainers() { + return false; + } + + @Override + public boolean doesEmptyContainers() { + return false; + } + + @Override + public boolean canTankBeFilled() { + return true; + } + + @Override + public boolean canTankBeEmptied() { + return true; + } + + @Override + public boolean displaysItemStack() { + return true; + } + + @Override + public boolean displaysStackSize() { + return true; + } + + @Override + public FluidStack getDrainableStack() { + return mFluidOut; + } + + @Override + public FluidStack setDrainableStack(FluidStack aFluid) { + markDirty(); + mFluidOut = aFluid; + return mFluidOut; + } + + @Override + public boolean isDrainableStackSeparate() { + return true; + } + + @Override + public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) { + if (aBaseMetaTileEntity.isClientSide()) return true; + if (!GTMod.gregtechproxy.mForceFreeFace) { + GTUIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer); + return true; + } + for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) { + if (aBaseMetaTileEntity.getAirAtSide(side)) { + GTUIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer); + return true; + } + } + GTUtility.sendChatToPlayer(aPlayer, "No free Side!"); + return true; + } + + @Override + public void initDefaultModes(NBTTagCompound aNBT) { + mMainFacing = ForgeDirection.UNKNOWN; + if (!getBaseMetaTileEntity().getWorld().isRemote) { + final GTClientPreference tPreference = GTMod.gregtechproxy + .getClientPreference(getBaseMetaTileEntity().getOwnerUuid()); + if (tPreference != null) { + mDisableFilter = !tPreference.isSingleBlockInitialFilterEnabled(); + mDisableMultiStack = !tPreference.isSingleBlockInitialMultiStackEnabled(); + } + } + } + + @Override + public void saveNBTData(NBTTagCompound aNBT) { + super.saveNBTData(aNBT); + aNBT.setBoolean("mFluidTransfer", mFluidTransfer); + aNBT.setBoolean("mItemTransfer", mItemTransfer); + aNBT.setBoolean("mHasBeenUpdated", mHasBeenUpdated); + aNBT.setBoolean("mAllowInputFromOutputSide", mAllowInputFromOutputSide); + aNBT.setBoolean("mDisableFilter", mDisableFilter); + aNBT.setBoolean("mDisableMultiStack", mDisableMultiStack); + aNBT.setInteger("mEUt", mEUt); + aNBT.setInteger("mMainFacing", mMainFacing.ordinal()); + aNBT.setInteger("mProgresstime", mProgresstime); + aNBT.setInteger("mMaxProgresstime", mMaxProgresstime); + if (mOutputFluid != null) aNBT.setTag("mOutputFluid", mOutputFluid.writeToNBT(new NBTTagCompound())); + if (mFluidOut != null) aNBT.setTag("mFluidOut", mFluidOut.writeToNBT(new NBTTagCompound())); + + for (int i = 0; i < mOutputItems.length; i++) + if (mOutputItems[i] != null) GTUtility.saveItem(aNBT, "mOutputItem" + i, mOutputItems[i]); + } + + @Override + public void loadNBTData(NBTTagCompound aNBT) { + super.loadNBTData(aNBT); + mFluidTransfer = aNBT.getBoolean("mFluidTransfer"); + mItemTransfer = aNBT.getBoolean("mItemTransfer"); + mHasBeenUpdated = aNBT.getBoolean("mHasBeenUpdated"); + mAllowInputFromOutputSide = aNBT.getBoolean("mAllowInputFromOutputSide"); + mDisableFilter = aNBT.getBoolean("mDisableFilter"); + mDisableMultiStack = aNBT.getBoolean("mDisableMultiStack"); + mEUt = aNBT.getInteger("mEUt"); + mMainFacing = ForgeDirection.getOrientation(aNBT.getInteger("mMainFacing")); + mProgresstime = aNBT.getInteger("mProgresstime"); + mMaxProgresstime = aNBT.getInteger("mMaxProgresstime"); + mOutputFluid = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mOutputFluid")); + mFluidOut = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mFluidOut")); + + for (int i = 0; i < mOutputItems.length; i++) mOutputItems[i] = GTUtility.loadItem(aNBT, "mOutputItem" + i); + } + + @Override + public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + super.onPostTick(aBaseMetaTileEntity, aTick); + + if (aBaseMetaTileEntity.isServerSide()) { + mCharge = aBaseMetaTileEntity.getStoredEU() / 2 > aBaseMetaTileEntity.getEUCapacity() / 3; + mDecharge = aBaseMetaTileEntity.getStoredEU() < aBaseMetaTileEntity.getEUCapacity() / 3; + + doDisplayThings(); + + boolean tSucceeded = false; + + if (mMaxProgresstime > 0 && (mProgresstime >= 0 || aBaseMetaTileEntity.isAllowedToWork())) { + markDirty(); + aBaseMetaTileEntity.setActive(true); + if (mProgresstime < 0 || drainEnergyForProcess(mEUt)) { + if (++mProgresstime >= mMaxProgresstime) { + for (int i = 0; i < mOutputItems.length; i++) + for (int j = 0; j < mOutputItems.length; j++) if (aBaseMetaTileEntity + .addStackToSlot(getOutputSlot() + ((j + i) % mOutputItems.length), mOutputItems[i])) + break; + if (mOutputFluid != null) + if (getDrainableStack() == null) setDrainableStack(mOutputFluid.copy()); + else if (mOutputFluid.isFluidEqual(getDrainableStack())) + getDrainableStack().amount += mOutputFluid.amount; + Arrays.fill(mOutputItems, null); + mOutputFluid = null; + mEUt = 0; + mProgresstime = 0; + mMaxProgresstime = 0; + mStuttering = false; + tSucceeded = true; + endProcess(); + } + if (mProgresstime > 5) mStuttering = false; + } else { + if (!mStuttering) { + stutterProcess(); + if (canHaveInsufficientEnergy()) mProgresstime = -100; + mStuttering = true; + } + } + } else { + aBaseMetaTileEntity.setActive(false); + } + + boolean tRemovedOutputFluid = false; + + if (doesAutoOutputFluids() && getDrainableStack() != null + && aBaseMetaTileEntity.getFrontFacing() != mMainFacing + && (tSucceeded || aTick % 20 == 0)) { + IFluidHandler tTank = aBaseMetaTileEntity.getITankContainerAtSide(aBaseMetaTileEntity.getFrontFacing()); + if (tTank != null) { + FluidStack tDrained = drain(1000, false); + if (tDrained != null) { + final int tFilledAmount = tTank.fill(aBaseMetaTileEntity.getBackFacing(), tDrained, false); + if (tFilledAmount > 0) + tTank.fill(aBaseMetaTileEntity.getBackFacing(), drain(tFilledAmount, true), true); + } + } + if (getDrainableStack() == null) tRemovedOutputFluid = true; + } + + if (doesAutoOutput() && !isOutputEmpty() + && aBaseMetaTileEntity.getFrontFacing() != mMainFacing + && (tSucceeded || mOutputBlocked % 300 == 1 + || aBaseMetaTileEntity.hasInventoryBeenModified() + || aTick % 600 == 0)) { + TileEntity tTileEntity2 = aBaseMetaTileEntity.getTileEntityAtSide(aBaseMetaTileEntity.getFrontFacing()); + long tStoredEnergy = aBaseMetaTileEntity.getUniversalEnergyStored(); + int tMaxStacks = (int) (tStoredEnergy / 64L); + if (tMaxStacks > mOutputItems.length) tMaxStacks = mOutputItems.length; + + moveMultipleItemStacks( + aBaseMetaTileEntity, + tTileEntity2, + aBaseMetaTileEntity.getFrontFacing(), + aBaseMetaTileEntity.getBackFacing(), + null, + false, + (byte) 64, + (byte) 1, + (byte) 64, + (byte) 1, + tMaxStacks); + } + + if (mOutputBlocked != 0) if (isOutputEmpty()) mOutputBlocked = 0; + else mOutputBlocked++; + + if (allowToCheckRecipe()) { + if (mMaxProgresstime <= 0 && aBaseMetaTileEntity.isAllowedToWork() + && (tRemovedOutputFluid || tSucceeded + || aBaseMetaTileEntity.hasInventoryBeenModified() + || aTick % 600 == 0 + || aBaseMetaTileEntity.hasWorkJustBeenEnabled()) + && hasEnoughEnergyToCheckRecipe()) { + if (checkRecipe() == FOUND_AND_SUCCESSFULLY_USED_RECIPE) { + if (getSpecialSlot() != null && getSpecialSlot().stackSize <= 0) + mInventory[getSpecialSlotIndex()] = null; + for (int i = getInputSlot(), j = i + mInputSlotCount; i < j; i++) + if (mInventory[i] != null && mInventory[i].stackSize <= 0) mInventory[i] = null; + for (int i = 0; i < mOutputItems.length; i++) { + mOutputItems[i] = GTUtility.copyOrNull(mOutputItems[i]); + if (mOutputItems[i] != null && mOutputItems[i].stackSize > 64) + mOutputItems[i].stackSize = 64; + mOutputItems[i] = GTOreDictUnificator.get(true, mOutputItems[i]); + } + if (mFluid != null && mFluid.amount <= 0) mFluid = null; + mMaxProgresstime = Math.max(1, mMaxProgresstime); + if (GTUtility.isDebugItem(mInventory[dechargerSlotStartIndex()])) { + mEUt = mMaxProgresstime = 1; + } + startProcess(); + } else { + mMaxProgresstime = 0; + Arrays.fill(mOutputItems, null); + mOutputFluid = null; + } + } + } else { + if (!mStuttering) { + stutterProcess(); + mStuttering = true; + } + } + } + // Only using mNeedsSteamVenting right now and assigning it to 64 to space in the range for more single block + // machine problems. + // Value | Class | Field + // 1 | GT_MetaTileEntity_BasicMachine | mStuttering + // 64 | GT_MetaTileEntity_BasicMachine_Bronze | mNeedsSteamVenting + aBaseMetaTileEntity.setErrorDisplayID((aBaseMetaTileEntity.getErrorDisplayID() & ~127)); // | (mStuttering ? 1 : + // 0)); + } + + protected void doDisplayThings() { + if (!isValidMainFacing(mMainFacing) && isValidMainFacing(getBaseMetaTileEntity().getFrontFacing())) { + mMainFacing = getBaseMetaTileEntity().getFrontFacing(); + } + if (isValidMainFacing(mMainFacing) && !mHasBeenUpdated) { + mHasBeenUpdated = true; + getBaseMetaTileEntity().setFrontFacing(getBaseMetaTileEntity().getBackFacing()); + } + } + + protected boolean hasEnoughEnergyToCheckRecipe() { + return getBaseMetaTileEntity().isUniversalEnergyStored(getMinimumStoredEU() / 2); + } + + protected boolean drainEnergyForProcess(long aEUt) { + return getBaseMetaTileEntity().decreaseStoredEnergyUnits(aEUt, false); + } + + /** + * Calculates overclock based on {@link #overclockDescriber}. + */ + protected void calculateCustomOverclock(GTRecipe recipe) { + OverclockCalculator calculator = overclockDescriber.createCalculator( + new OverclockCalculator().setRecipeEUt(recipe.mEUt) + .setDuration(recipe.mDuration) + .setOneTickDiscount(true), + recipe); + calculator.calculate(); + mEUt = (int) calculator.getConsumption(); + mMaxProgresstime = calculator.getDuration(); + } + + /** + * Helper method for calculating simple overclock. + */ + protected void calculateOverclockedNess(int eut, int duration) { + OverclockCalculator calculator = new OverclockCalculator().setRecipeEUt(eut) + .setEUt(V[mTier] * mAmperage) + .setDuration(duration) + .setOneTickDiscount(true) + .calculate(); + mEUt = (int) calculator.getConsumption(); + mMaxProgresstime = calculator.getDuration(); + } + + protected ItemStack getSpecialSlot() { + return mInventory[getSpecialSlotIndex()]; + } + + protected ItemStack getOutputAt(int aIndex) { + return mInventory[getOutputSlot() + aIndex]; + } + + protected ItemStack[] getAllOutputs() { + ItemStack[] rOutputs = new ItemStack[mOutputItems.length]; + for (int i = 0; i < mOutputItems.length; i++) rOutputs[i] = getOutputAt(i); + return rOutputs; + } + + protected boolean canOutput(GTRecipe aRecipe) { + return aRecipe != null && (aRecipe.mNeedsEmptyOutput ? isOutputEmpty() && getDrainableStack() == null + : canOutput(aRecipe.getFluidOutput(0)) && canOutput(aRecipe.mOutputs)); + } + + protected boolean canOutput(ItemStack... aOutputs) { + if (aOutputs == null) return true; + ItemStack[] tOutputSlots = getAllOutputs(); + for (int i = 0; i < tOutputSlots.length && i < aOutputs.length; i++) + if (tOutputSlots[i] != null && aOutputs[i] != null + && (!GTUtility.areStacksEqual(tOutputSlots[i], aOutputs[i], false) + || tOutputSlots[i].stackSize + aOutputs[i].stackSize > tOutputSlots[i].getMaxStackSize())) { + mOutputBlocked++; + return false; + } + return true; + } + + protected boolean canOutput(FluidStack aOutput) { + if (aOutput == null) return true; + FluidStack drainableStack = getDrainableStack(); + if (drainableStack != null && !drainableStack.isFluidEqual(aOutput)) return false; + return (drainableStack != null ? drainableStack.amount : 0) + aOutput.amount <= getCapacity(); + } + + protected ItemStack getInputAt(int aIndex) { + return mInventory[getInputSlot() + aIndex]; + } + + protected ItemStack[] getAllInputs() { + int tRealInputSlotCount = this.mInputSlotCount + (allowSelectCircuit() ? 1 : 0); + ItemStack[] rInputs = new ItemStack[tRealInputSlotCount]; + for (int i = 0; i < mInputSlotCount; i++) rInputs[i] = getInputAt(i); + if (allowSelectCircuit()) rInputs[mInputSlotCount] = getStackInSlot(getCircuitSlot()); + return rInputs; + } + + protected boolean isOutputEmpty() { + boolean rIsEmpty = true; + for (ItemStack tOutputSlotContent : getAllOutputs()) if (tOutputSlotContent != null) { + rIsEmpty = false; + break; + } + return rIsEmpty; + } + + @Override + public void onValueUpdate(byte aValue) { + mMainFacing = ForgeDirection.getOrientation(aValue); + } + + @Override + public byte getUpdateData() { + return (byte) mMainFacing.ordinal(); + } + + @Override + public void doSound(byte aIndex, double aX, double aY, double aZ) { + super.doSound(aIndex, aX, aY, aZ); + if (aIndex == 8) GTUtility.doSoundAtClient(SoundResource.IC2_MACHINES_INTERRUPT_ONE, 100, 1.0F, aX, aY, aZ); + } + + public boolean doesAutoOutput() { + return mItemTransfer; + } + + public boolean doesAutoOutputFluids() { + return mFluidTransfer; + } + + public boolean allowToCheckRecipe() { + return true; + } + + public boolean showPipeFacing() { + return true; + } + + /** + * Called whenever the Machine successfully started a Process, useful for Sound Effects + */ + public void startProcess() { + // + } + + /** + * Called whenever the Machine successfully finished a Process, useful for Sound Effects + */ + public void endProcess() { + // + } + + /** + * Called whenever the Machine aborted a Process, useful for Sound Effects + */ + public void abortProcess() { + // + } + + /** + * Called whenever the Machine aborted a Process but still works on it, useful for Sound Effects + */ + public void stutterProcess() { + if (useStandardStutterSound()) sendSound((byte) 8); + } + + /** + * If this Machine can have the Insufficient Energy Line Problem + */ + public boolean canHaveInsufficientEnergy() { + return true; + } + + public boolean useStandardStutterSound() { + return true; + } + + @Override + public String[] getInfoData() { + return new String[] { "Progress:", + EnumChatFormatting.GREEN + GTUtility.formatNumbers((mProgresstime / 20)) + + EnumChatFormatting.RESET + + " s / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(mMaxProgresstime / 20) |
