aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/common/tileentities/machines/multi/MTELargeTurbine.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gregtech/common/tileentities/machines/multi/MTELargeTurbine.java')
-rw-r--r--src/main/java/gregtech/common/tileentities/machines/multi/MTELargeTurbine.java490
1 files changed, 490 insertions, 0 deletions
diff --git a/src/main/java/gregtech/common/tileentities/machines/multi/MTELargeTurbine.java b/src/main/java/gregtech/common/tileentities/machines/multi/MTELargeTurbine.java
new file mode 100644
index 0000000000..15dc5def03
--- /dev/null
+++ b/src/main/java/gregtech/common/tileentities/machines/multi/MTELargeTurbine.java
@@ -0,0 +1,490 @@
+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.transpose;
+import static gregtech.api.enums.HatchElement.Dynamo;
+import static gregtech.api.enums.HatchElement.InputBus;
+import static gregtech.api.enums.HatchElement.InputHatch;
+import static gregtech.api.enums.HatchElement.Maintenance;
+import static gregtech.api.enums.HatchElement.Muffler;
+import static gregtech.api.enums.HatchElement.OutputBus;
+import static gregtech.api.enums.HatchElement.OutputHatch;
+import static gregtech.api.enums.Textures.BlockIcons.TURBINE_NEW;
+import static gregtech.api.enums.Textures.BlockIcons.TURBINE_NEW_ACTIVE;
+import static gregtech.api.enums.Textures.BlockIcons.TURBINE_NEW_EMPTY;
+import static gregtech.api.util.GTStructureUtility.buildHatchAdder;
+import static gregtech.api.util.GTUtility.filterValidMTEs;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.client.renderer.RenderBlocks;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+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.IAlignmentLimits;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.alignment.enumerable.ExtendedFacing;
+import com.gtnewhorizon.structurelib.alignment.enumerable.Flip;
+import com.gtnewhorizon.structurelib.alignment.enumerable.Rotation;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.MetaGeneratedTool;
+import gregtech.api.metatileentity.implementations.MTEEnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.MTEHatchDynamo;
+import gregtech.api.metatileentity.implementations.MTEHatchMuffler;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.util.GTUtility;
+import gregtech.api.util.LightingHelper;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+import gregtech.common.items.MetaGeneratedTool01;
+import gregtech.common.render.GTRenderUtil;
+
+public abstract class MTELargeTurbine extends MTEEnhancedMultiBlockBase<MTELargeTurbine>
+ implements ISurvivalConstructable {
+
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final ClassValue<IStructureDefinition<MTELargeTurbine>> STRUCTURE_DEFINITION = new ClassValue<>() {
+
+ @Override
+ protected IStructureDefinition<MTELargeTurbine> computeValue(Class<?> type) {
+ return StructureDefinition.<MTELargeTurbine>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { " ", " ", " ", " ", " ", },
+ { " --- ", " ccc ", " hhh ", " hhh ", " hhh ", },
+ { " --- ", " c~c ", " h-h ", " h-h ", " hdh ", },
+ { " --- ", " ccc ", " hhh ", " hhh ", " hhh ", },
+ { " ", " ", " ", " ", " ", }, }))
+ .addElement('c', lazy(t -> ofBlock(t.getCasingBlock(), t.getCasingMeta())))
+ .addElement('d', lazy(t -> Dynamo.newAny(t.getCasingTextureIndex(), 1)))
+ .addElement(
+ 'h',
+ lazy(
+ t -> buildHatchAdder(MTELargeTurbine.class)
+ .atLeast(Maintenance, InputHatch, OutputHatch, OutputBus, InputBus, Muffler)
+ .casingIndex(t.getCasingTextureIndex())
+ .dot(2)
+ .buildAndChain(t.getCasingBlock(), t.getCasingMeta())))
+ .build();
+ }
+ };
+
+ protected int baseEff = 0;
+ protected int optFlow = 0;
+ protected double realOptFlow = 0;
+ protected int storedFluid = 0;
+ protected int counter = 0;
+ protected boolean looseFit = false;
+ protected int overflowMultiplier = 0;
+ protected final float[] flowMultipliers = new float[] { 1, 1, 1 };
+
+ // client side stuff
+ protected boolean mHasTurbine;
+ // mMachine got overwritten by StructureLib extended facing query response
+ // so we use a separate field for this
+ protected boolean mFormed;
+
+ public MTELargeTurbine(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public MTELargeTurbine(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return getMaxEfficiency(aStack) > 0;
+ }
+
+ @Override
+ public IStructureDefinition<MTELargeTurbine> getStructureDefinition() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ @Override
+ protected IAlignmentLimits getInitialAlignmentLimits() {
+ return (d, r, f) -> r.isNotRotated() && f.isNotFlipped();
+ }
+
+ @Override
+ protected ExtendedFacing getCorrectedAlignment(ExtendedFacing aOldFacing) {
+ return aOldFacing.with(Flip.NONE)
+ .with(Rotation.NORMAL);
+ }
+
+ @Override
+ public boolean isFlipChangeAllowed() {
+ return false;
+ }
+
+ @Override
+ public boolean isRotationChangeAllowed() {
+ return false;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ return checkPiece(STRUCTURE_PIECE_MAIN, 2, 2, 1) && mMaintenanceHatches.size() == 1
+ && mMufflerHatches.isEmpty() == (getPollutionPerTick(null) == 0);
+ }
+
+ public abstract Block getCasingBlock();
+
+ public abstract byte getCasingMeta();
+
+ public abstract int getCasingTextureIndex();
+
+ public boolean isNewStyleRendering() {
+ return false;
+ }
+
+ public IIconContainer[] getTurbineTextureActive() {
+ return TURBINE_NEW_ACTIVE;
+ }
+
+ public IIconContainer[] getTurbineTextureFull() {
+ return TURBINE_NEW;
+ }
+
+ public IIconContainer[] getTurbineTextureEmpty() {
+ return TURBINE_NEW_EMPTY;
+ }
+
+ @Override
+ public boolean renderInWorld(IBlockAccess aWorld, int aX, int aY, int aZ, Block aBlock, RenderBlocks aRenderer) {
+ if (!isNewStyleRendering() || !mFormed) return false;
+ int[] tABCCoord = new int[] { -1, -1, 0 };
+ int[] tXYZOffset = new int[3];
+ final ForgeDirection tFacing = getBaseMetaTileEntity().getFrontFacing();
+ final ExtendedFacing tExtendedFacing = getExtendedFacing();
+ final ForgeDirection tDirection = tExtendedFacing.getDirection();
+ final LightingHelper tLighting = new LightingHelper(aRenderer);
+
+ // for some reason +x and -z need this field set to true, but not any other sides
+ if (tFacing == ForgeDirection.NORTH || tFacing == ForgeDirection.EAST) aRenderer.field_152631_f = true;
+ final Block tBlock = getCasingBlock();
+
+ IIconContainer[] tTextures;
+ if (getBaseMetaTileEntity().isActive()) tTextures = getTurbineTextureActive();
+ else if (hasTurbine()) tTextures = getTurbineTextureFull();
+ else tTextures = getTurbineTextureEmpty();
+
+ assert tTextures != null && tTextures.length == tABCCoord.length;
+
+ for (int i = 0; i < 9; i++) {
+ if (i != 4) { // do not draw ourselves again.
+ tExtendedFacing.getWorldOffset(tABCCoord, tXYZOffset);
+ // since structure check passed, we can assume it is turbine casing
+ int tX = tXYZOffset[0] + aX;
+ int tY = tXYZOffset[1] + aY;
+ int tZ = tXYZOffset[2] + aZ;
+ // we skip the occlusion test, as we always require a working turbine to have a block of air before it
+ // so the front face cannot be occluded whatsoever in the most cases.
+ Tessellator.instance.setBrightness(
+ tBlock.getMixedBrightnessForBlock(
+ aWorld,
+ aX + tDirection.offsetX,
+ tY + tDirection.offsetY,
+ aZ + tDirection.offsetZ));
+ tLighting.setupLighting(tBlock, tX, tY, tZ, tFacing)
+ .setupColor(tFacing, Dyes._NULL.mRGBa);
+ GTRenderUtil.renderBlockIcon(
+ aRenderer,
+ tBlock,
+ tX + tDirection.offsetX * 0.01,
+ tY + tDirection.offsetY * 0.01,
+ tZ + tDirection.offsetZ * 0.01,
+ tTextures[i].getIcon(),
+ tFacing);
+ }
+ if (++tABCCoord[0] == 2) {
+ tABCCoord[0] = -1;
+ tABCCoord[1]++;
+ }
+ }
+
+ aRenderer.field_152631_f = false;
+ return false;
+ }
+
+ @Override
+ public void onValueUpdate(byte aValue) {
+ mHasTurbine = (aValue & 0x1) != 0;
+ mFormed = (aValue & 0x2) != 0;
+ super.onValueUpdate(aValue);
+ }
+
+ @Override
+ public byte getUpdateData() {
+ return (byte) ((hasTurbine() ? 1 : 0) | (mMachine ? 2 : 0));
+ }
+
+ @Override
+ public boolean addToMachineList(IGregTechTileEntity tTileEntity, int aBaseCasingIndex) {
+ return addMaintenanceToMachineList(tTileEntity, getCasingTextureIndex())
+ || addInputToMachineList(tTileEntity, getCasingTextureIndex())
+ || addOutputToMachineList(tTileEntity, getCasingTextureIndex())
+ || addMufflerToMachineList(tTileEntity, getCasingTextureIndex());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ @NotNull
+ public CheckRecipeResult checkProcessing() {
+ ItemStack controllerSlot = getControllerSlot();
+ if ((counter & 7) == 0 && (controllerSlot == null || !(controllerSlot.getItem() instanceof MetaGeneratedTool)
+ || controllerSlot.getItemDamage() < 170
+ || controllerSlot.getItemDamage() > 179)) {
+ stopMachine(ShutDownReasonRegistry.NO_TURBINE);
+ return CheckRecipeResultRegistry.NO_TURBINE_FOUND;
+ }
+ ArrayList<FluidStack> tFluids = getStoredFluids();
+ if (!tFluids.isEmpty()) {
+
+ if (baseEff == 0 || optFlow == 0
+ || counter >= 512
+ || this.getBaseMetaTileEntity()
+ .hasWorkJustBeenEnabled()
+ || this.getBaseMetaTileEntity()
+ .hasInventoryBeenModified()) {
+ counter = 0;
+ baseEff = GTUtility.safeInt(
+ (long) ((5F + ((MetaGeneratedTool) controllerSlot.getItem()).getToolCombatDamage(controllerSlot))
+ * 1000F));
+ optFlow = GTUtility.safeInt(
+ (long) Math.max(
+ Float.MIN_NORMAL,
+ ((MetaGeneratedTool) controllerSlot.getItem()).getToolStats(controllerSlot)
+ .getSpeedMultiplier() * MetaGeneratedTool.getPrimaryMaterial(controllerSlot).mToolSpeed
+ * 50));
+
+ overflowMultiplier = getOverflowMultiplier(controllerSlot);
+
+ flowMultipliers[0] = MetaGeneratedTool.getPrimaryMaterial(controllerSlot).mSteamMultiplier;
+ flowMultipliers[1] = MetaGeneratedTool.getPrimaryMaterial(controllerSlot).mGasMultiplier;
+ flowMultipliers[2] = MetaGeneratedTool.getPrimaryMaterial(controllerSlot).mPlasmaMultiplier;
+
+ if (optFlow <= 0 || baseEff <= 0) {
+ stopMachine(ShutDownReasonRegistry.NONE); // in case the turbine got removed
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+ } else {
+ counter++;
+ }
+ }
+
+ int newPower = fluidIntoPower(tFluids, optFlow, baseEff, overflowMultiplier, flowMultipliers); // How much the
+ // turbine should
+ // be producing
+ // with this flow
+ int difference = newPower - this.mEUt; // difference between current output and new output
+
+ // Magic numbers: can always change by at least 10 eu/t, but otherwise by at most 1 percent of the difference in
+ // power level (per tick)
+ // This is how much the turbine can actually change during this tick
+ int maxChangeAllowed = Math.max(10, GTUtility.safeInt((long) Math.abs(difference) / 100));
+
+ if (Math.abs(difference) > maxChangeAllowed) { // If this difference is too big, use the maximum allowed change
+ int change = maxChangeAllowed * (difference > 0 ? 1 : -1); // Make the change positive or negative.
+ this.mEUt += change; // Apply the change
+ } else this.mEUt = newPower;
+
+ if (this.mEUt <= 0) {
+ // stopMachine();
+ this.mEUt = 0;
+ this.mEfficiency = 0;
+ 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 CheckRecipeResultRegistry.GENERATING;
+ }
+ }
+
+ abstract int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff, int overflowMultiplier,
+ float[] flowMultipliers);
+
+ abstract float getOverflowEfficiency(int totalFlow, int actualOptimalFlow, int overflowMultiplier);
+
+ // Gets the maximum output that the turbine currently can handle. Going above this will cause the turbine to explode
+ public long getMaximumOutput() {
+ long aTotal = 0;
+ for (MTEHatchDynamo aDynamo : filterValidMTEs(mDynamoHatches)) {
+ long aVoltage = aDynamo.maxEUOutput();
+ aTotal = aDynamo.maxAmperesOut() * aVoltage;
+ }
+ return aTotal;
+ }
+
+ public int getOverflowMultiplier(ItemStack aStack) {
+ int aOverflowMultiplier = 0;
+ int toolQualityLevel = MetaGeneratedTool.getPrimaryMaterial(aStack).mToolQuality;
+ if (toolQualityLevel >= 6) {
+ aOverflowMultiplier = 3;
+ } else if (toolQualityLevel >= 3) {
+ aOverflowMultiplier = 2;
+ } else {
+ aOverflowMultiplier = 1;
+ }
+ return aOverflowMultiplier;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 1;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ if (GTUtility.isStackInvalid(aStack)) {
+ return 0;
+ }
+ if (aStack.getItem() instanceof MetaGeneratedTool01) {
+ return 10000;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = 0;
+ for (MTEHatchMuffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ mPollutionReduction = Math.max(tHatch.calculatePollutionReduction(100), mPollutionReduction);
+ }
+
+ String tRunning = mMaxProgresstime > 0
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.running.true")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.running.false")
+ + EnumChatFormatting.RESET;
+ String tMaintainance = getIdealStatus() == getRepairStatus()
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.maintenance.false")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.maintenance.true")
+ + EnumChatFormatting.RESET;
+ int tDura = 0;
+
+ if (mInventory[1] != null && mInventory[1].getItem() instanceof MetaGeneratedTool01) {
+ tDura = GTUtility.safeInt(
+ (long) (100.0f / MetaGeneratedTool.getToolMaxDamage(mInventory[1])
+ * (MetaGeneratedTool.getToolDamage(mInventory[1])) + 1));
+ }
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (MTEHatchDynamo tHatch : filterValidMTEs(mDynamoHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+ String[] ret = new String[] {
+ // 8 Lines available for information panels
+ tRunning + ": "
+ + EnumChatFormatting.RED
+ + GTUtility.formatNumbers(((long) mEUt * mEfficiency) / 10000)
+ + EnumChatFormatting.RESET
+ + " EU/t", /* 1 */
+ tMaintainance, /* 2 */
+ StatCollector.translateToLocal("GT5U.turbine.efficiency") + ": "
+ + EnumChatFormatting.YELLOW
+ + (mEfficiency / 100F)
+ + EnumChatFormatting.RESET
+ + "%", /* 2 */
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GTUtility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + /* 3 */ EnumChatFormatting.YELLOW
+ + GTUtility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.turbine.flow") + ": "
+ + EnumChatFormatting.YELLOW
+ + GTUtility.formatNumbers(GTUtility.safeInt((long) realOptFlow))
+ + EnumChatFormatting.RESET
+ + " L/t"
+ + /* 4 */ EnumChatFormatting.YELLOW
+ + " ("
+ + (looseFit ? StatCollector.translateToLocal("GT5U.turbine.loose")
+ : StatCollector.translateToLocal("GT5U.turbine.tight"))
+ + ")", /* 5 */
+ StatCollector.translateToLocal("GT5U.turbine.fuel") + ": "
+ + EnumChatFormatting.GOLD
+ + GTUtility.formatNumbers(storedFluid)
+ + EnumChatFormatting.RESET
+ + "L", /* 6 */
+ StatCollector.translateToLocal(
+ "GT5U.turbine.dmg") + ": " + EnumChatFormatting.RED + tDura + EnumChatFormatting.RESET + "%", /* 7 */
+ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %" /* 8 */
+ };
+ if (!this.getClass()
+ .getName()
+ .contains("Steam"))
+ ret[4] = StatCollector.translateToLocal("GT5U.turbine.flow") + ": "
+ + EnumChatFormatting.YELLOW
+ + GTUtility.safeInt((long) realOptFlow)
+ + EnumChatFormatting.RESET
+ + " L/t";
+ return ret;
+ }
+
+ public boolean hasTurbine() {
+ return getBaseMetaTileEntity() != null && getBaseMetaTileEntity().isClientSide() ? mHasTurbine
+ : this.getMaxEfficiency(mInventory[1]) > 0;
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 2, 2, 1);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 2, 2, 1, elementBudget, env, false, true);
+ }
+}