From 1b820de08a05070909a267e17f033fcf58ac8710 Mon Sep 17 00:00:00 2001 From: NotAPenguin Date: Mon, 2 Sep 2024 23:17:17 +0200 Subject: 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 --- .../metaTileEntity/multi/base/INameFunction.java | 6 + .../metaTileEntity/multi/base/IStatusFunction.java | 6 + .../thing/metaTileEntity/multi/base/LedStatus.java | 64 + .../metaTileEntity/multi/base/Parameters.java | 327 +++ .../thing/metaTileEntity/multi/base/SoundLoop.java | 59 + .../multi/base/TTMultiblockBase.java | 2760 ++++++++++++++++++++ .../render/TTRenderedExtendedFacingTexture.java | 25 + 7 files changed, 3247 insertions(+) create mode 100644 src/main/java/tectech/thing/metaTileEntity/multi/base/INameFunction.java create mode 100644 src/main/java/tectech/thing/metaTileEntity/multi/base/IStatusFunction.java create mode 100644 src/main/java/tectech/thing/metaTileEntity/multi/base/LedStatus.java create mode 100644 src/main/java/tectech/thing/metaTileEntity/multi/base/Parameters.java create mode 100644 src/main/java/tectech/thing/metaTileEntity/multi/base/SoundLoop.java create mode 100644 src/main/java/tectech/thing/metaTileEntity/multi/base/TTMultiblockBase.java create mode 100644 src/main/java/tectech/thing/metaTileEntity/multi/base/render/TTRenderedExtendedFacingTexture.java (limited to 'src/main/java/tectech/thing/metaTileEntity/multi/base') diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/base/INameFunction.java b/src/main/java/tectech/thing/metaTileEntity/multi/base/INameFunction.java new file mode 100644 index 0000000000..697c748ba4 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/base/INameFunction.java @@ -0,0 +1,6 @@ +package tectech.thing.metaTileEntity.multi.base; + +public interface INameFunction { + + String apply(T t, Parameters.IParameter iParameter); +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/base/IStatusFunction.java b/src/main/java/tectech/thing/metaTileEntity/multi/base/IStatusFunction.java new file mode 100644 index 0000000000..b051f0dfa3 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/base/IStatusFunction.java @@ -0,0 +1,6 @@ +package tectech.thing.metaTileEntity.multi.base; + +public interface IStatusFunction { + + LedStatus apply(T t, Parameters.IParameter iParameter); +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/base/LedStatus.java b/src/main/java/tectech/thing/metaTileEntity/multi/base/LedStatus.java new file mode 100644 index 0000000000..022408f688 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/base/LedStatus.java @@ -0,0 +1,64 @@ +package tectech.thing.metaTileEntity.multi.base; + +import java.util.function.Supplier; + +import net.minecraft.util.EnumChatFormatting; + +import tectech.TecTech; + +public enum LedStatus { + + STATUS_UNUSED(() -> EnumChatFormatting.DARK_GRAY + "Unused", true), // + STATUS_TOO_LOW(() -> EnumChatFormatting.BLUE + "Too Low", false), // + STATUS_LOW(() -> EnumChatFormatting.AQUA + "Low", true), // + STATUS_WRONG(() -> EnumChatFormatting.DARK_PURPLE + "Wrong", false), // + STATUS_OK(() -> EnumChatFormatting.GREEN + "Valid", true), // + STATUS_TOO_HIGH(() -> EnumChatFormatting.RED + "Too High", false), // + STATUS_HIGH(() -> EnumChatFormatting.GOLD + "High", true), // + STATUS_UNDEFINED(() -> EnumChatFormatting.GRAY + "Unknown", false), + STATUS_NEUTRAL(() -> EnumChatFormatting.WHITE + "Neutral", true), + STATUS_WTF(() -> LedStatus.values()[TecTech.RANDOM.nextInt(9)].name.get(), false); + + public final Supplier name; + public final boolean isOk; + + LedStatus(Supplier name, boolean ok) { + this.name = name; + this.isOk = ok; + } + + public byte getOrdinalByte() { + return (byte) ordinal(); + } + + public static LedStatus getStatus(byte value) { + try { + return LedStatus.values()[value]; + } catch (Exception e) { + return STATUS_UNDEFINED; + } + } + + public static LedStatus[] makeArray(int count, LedStatus defaultValue) { + LedStatus[] statuses = new LedStatus[count]; + for (int i = 0; i < count; i++) { + statuses[i] = defaultValue; + } + return statuses; + } + + public static LedStatus fromLimitsInclusiveOuterBoundary(double value, double min, double low, double high, + double max, double... excludedNumbers) { + if (value < min) return STATUS_TOO_LOW; + if (value > max) return STATUS_TOO_HIGH; + + if (value < low) return STATUS_LOW; + if (value > high) return STATUS_HIGH; + for (double val : excludedNumbers) { + if (val == value) return STATUS_WRONG; + } + if (Double.isNaN(value)) return STATUS_WRONG; + return STATUS_OK; + } + +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/base/Parameters.java b/src/main/java/tectech/thing/metaTileEntity/multi/base/Parameters.java new file mode 100644 index 0000000000..27eb961166 --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/base/Parameters.java @@ -0,0 +1,327 @@ +package tectech.thing.metaTileEntity.multi.base; + +import java.util.ArrayList; + +/** + * Instantiate parameters as field in parametersInstantiation_EM(); + */ +public class Parameters { + + private static final IStatusFunction LED_STATUS_FUNCTION_DEFAULT = (b, p) -> LedStatus.STATUS_UNDEFINED; + private static final INameFunction NAME_FUNCTION_DEFAULT = (b, p) -> "Undefined"; + + final Group[] groups = new Group[10]; + + double[] iParamsIn = new double[20]; // number I from parametrizers + double[] iParamsOut = new double[20]; // number O to parametrizers + final ArrayList parameterInArrayList = new ArrayList<>(); + final ArrayList parameterOutArrayList = new ArrayList<>(); + + // package private for use in gui + LedStatus[] eParamsInStatus = LedStatus.makeArray(20, LedStatus.STATUS_UNUSED); // LED status for I + LedStatus[] eParamsOutStatus = LedStatus.makeArray(20, LedStatus.STATUS_UNUSED); // LED status for O + + double getIn(int hatchNo, int parameterId) { + return iParamsIn[hatchNo + 10 * parameterId]; + } + + double getOut(int hatchNo, int parameterId) { + return iParamsOut[hatchNo + 10 * parameterId]; + } + + LedStatus getStatusIn(int hatchNo, int parameterId) { + return eParamsInStatus[hatchNo + 10 * parameterId]; + } + + LedStatus getStatusOut(int hatchNo, int parameterId) { + return eParamsOutStatus[hatchNo + 10 * parameterId]; + } + + private final TTMultiblockBase parent; + + Parameters(TTMultiblockBase parent) { + this.parent = parent; + } + + public boolean trySetParameters(int hatch, double parameter0, double parameter1) { + Group p = groups[hatch]; + if (parent.mMaxProgresstime <= 0 || (p != null && p.updateWhileRunning)) { + iParamsIn[hatch] = parameter0; + iParamsIn[hatch + 10] = parameter1; + return true; + } + return false; + } + + @SuppressWarnings("unused") // Used in GTNH-Intergalactic, do not delete. + public boolean trySetParameters(int hatchNo, int parameterId, double parameter) { + Group p = groups[hatchNo]; + if (parent.mMaxProgresstime <= 0 || (p != null && p.updateWhileRunning)) { + iParamsIn[hatchNo + 10 * parameterId] = parameter; + return true; + } + return false; + } + + public void setToDefaults(int hatch, boolean defaultIn, boolean defaultOut) { + Group p = groups[hatch]; + if (p == null) { + if (defaultIn) { + iParamsIn[hatch] = 0; + iParamsIn[hatch + 10] = 0; + } + if (defaultOut) { + iParamsOut[hatch] = 0; + iParamsOut[hatch + 10] = 0; + } + } else { + p.setToDefaults(defaultIn, defaultOut); + } + } + + public void setToDefaults(boolean defaultIn, boolean defaultOut) { + for (int hatch = 0; hatch < 10; hatch++) { + setToDefaults(hatch, defaultIn, defaultOut); + } + } + + public Group getGroup(int hatchNo, boolean updateWhileRunning) { + return groups[hatchNo] != null ? groups[hatchNo] : new Group(hatchNo, updateWhileRunning); + } + + public Group getGroup(int hatchNo) { + return groups[hatchNo] != null ? groups[hatchNo] : new Group(hatchNo, false); + } + + public interface IParameter { + + double get(); + + double getDefault(); + + void updateStatus(); + + LedStatus getStatus(boolean update); + + int id(); + + int hatchId(); + + int parameterId(); + + String getBrief(); + } + + /** + * most likely used locally in parametersInstantiation_EM() + */ + public class Group { + + private final int hatchNo; + public final ParameterIn[] parameterIn = new ParameterIn[2]; + public final ParameterOut[] parameterOut = new ParameterOut[2]; + public boolean updateWhileRunning; + + private Group(int hatchNo, boolean updateWhileRunning) { + if (hatchNo < 0 || hatchNo >= 10) { + throw new IllegalArgumentException("Hatch id must be in 0 to 9 range"); + } + this.hatchNo = hatchNo; + this.updateWhileRunning = updateWhileRunning; + groups[hatchNo] = this; + } + + public ParameterIn makeInParameter(int paramID, double defaultValue, INameFunction name, + IStatusFunction status) { + return new ParameterIn(paramID, defaultValue, name, status); + } + + public ParameterOut makeOutParameter(int paramID, double defaultValue, INameFunction name, + IStatusFunction status) { + return new ParameterOut(paramID, defaultValue, name, status); + } + + public void setToDefaults(boolean defaultIn, boolean defaultOut) { + if (defaultIn) { + if (this.parameterIn[0] != null) { + this.parameterIn[0].setDefault(); + } else { + iParamsIn[hatchNo] = 0; + } + if (this.parameterIn[1] != null) { + this.parameterIn[1].setDefault(); + } else { + iParamsIn[hatchNo + 10] = 0; + } + } + if (defaultOut) { + if (this.parameterOut[0] != null) { + this.parameterOut[0].setDefault(); + } else { + iParamsOut[hatchNo] = 0; + } + if (this.parameterOut[1] != null) { + this.parameterOut[1].setDefault(); + } else { + iParamsOut[hatchNo + 10] = 0; + } + } + } + + /** + * Make a field out of this... + */ + public class ParameterOut implements IParameter { + + public final int id; + public final double defaultValue; + IStatusFunction status; + INameFunction name; + + private ParameterOut(int paramID, double defaultValue, INameFunction name, IStatusFunction status) { + this.name = name == null ? NAME_FUNCTION_DEFAULT : name; + if (paramID < 0 || paramID > 2) { + throw new IllegalArgumentException("Parameter id must be in 0 to 1 range"); + } + if (parameterOut[paramID] != null) { + throw new IllegalArgumentException("Parameter id already occupied"); + } + this.id = hatchNo + 10 * paramID; + this.defaultValue = defaultValue; + this.status = status == null ? LED_STATUS_FUNCTION_DEFAULT : status; + parameterOutArrayList.add(this); + parameterOut[paramID] = this; + } + + void setDefault() { + set(defaultValue); + } + + @Override + public double get() { + return iParamsOut[id]; + } + + @Override + public double getDefault() { + return defaultValue; + } + + public void set(double value) { + iParamsOut[id] = value; + } + + @SuppressWarnings("unchecked") + @Override + public void updateStatus() { + eParamsOutStatus[id] = status.apply(parent, this); + } + + @Override + public LedStatus getStatus(boolean update) { + if (update) { + updateStatus(); + } + return eParamsOutStatus[id]; + } + + @Override + public String getBrief() { + return name.apply(parent, this); + } + + @Override + public int id() { + return id; + } + + @Override + public int hatchId() { + return id % 10; + } + + @Override + public int parameterId() { + return id / 10; + } + } + + /** + * Make a field out of this... + */ + public class ParameterIn implements IParameter { + + public final int id; + public final double defaultValue; + IStatusFunction status; + INameFunction name; + + private ParameterIn(int paramID, double defaultValue, INameFunction name, IStatusFunction status) { + this.name = name == null ? NAME_FUNCTION_DEFAULT : name; + this.id = hatchNo + 10 * paramID; + if (paramID < 0 || paramID > 2) { + throw new IllegalArgumentException("Parameter id must be in 0 to 1 range"); + } + if (parameterIn[paramID] != null) { + throw new IllegalArgumentException("Parameter id already occupied"); + } + this.defaultValue = defaultValue; + this.status = status == null ? LED_STATUS_FUNCTION_DEFAULT : status; + parameterInArrayList.add(this); + parameterIn[paramID] = this; + } + + void setDefault() { + set(defaultValue); + } + + @Override + public double get() { + return iParamsIn[id]; + } + + void set(double value) { + iParamsIn[id] = value; + } + + @Override + public double getDefault() { + return defaultValue; + } + + @SuppressWarnings("unchecked") + @Override + public void updateStatus() { + eParamsInStatus[id] = status.apply(parent, this); + } + + @Override + public LedStatus getStatus(boolean update) { + if (update) { + updateStatus(); + } + return eParamsInStatus[id]; + } + + @Override + public String getBrief() { + return name.apply(parent, this); + } + + @Override + public int id() { + return id; + } + + @Override + public int hatchId() { + return id % 10; + } + + @Override + public int parameterId() { + return id / 10; + } + } + } +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/base/SoundLoop.java b/src/main/java/tectech/thing/metaTileEntity/multi/base/SoundLoop.java new file mode 100644 index 0000000000..c337f5093e --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/base/SoundLoop.java @@ -0,0 +1,59 @@ +package tectech.thing.metaTileEntity.multi.base; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.MovingSound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.World; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; + +@SideOnly(Side.CLIENT) +public class SoundLoop extends MovingSound { + + private final boolean whileActive; + private final boolean whileInactive; + private final int worldID; + private boolean fadeMe = false; + + public SoundLoop(ResourceLocation p_i45104_1_, IGregTechTileEntity base, boolean stopWhenActive, + boolean stopWhenInactive) { + super(p_i45104_1_); + this.whileActive = stopWhenActive; + this.whileInactive = stopWhenInactive; + xPosF = base.getXCoord(); + yPosF = base.getYCoord(); + zPosF = base.getZCoord(); + worldID = base.getWorld().provider.dimensionId; + repeat = true; + volume = 0.0625f; + } + + @Override + public void update() { + if (donePlaying) { + return; + } + if (fadeMe) { + volume -= 0.0625f; + if (volume <= 0) { + volume = 0; + donePlaying = true; + } + } else if (volume < 1) { + volume += 0.0625f; + } + World world = Minecraft.getMinecraft().thePlayer.worldObj; + donePlaying = world.provider.dimensionId != worldID + || !world.checkChunksExist((int) xPosF, (int) yPosF, (int) zPosF, (int) xPosF, (int) yPosF, (int) zPosF); + if (donePlaying) return; + TileEntity tile = world.getTileEntity((int) xPosF, (int) yPosF, (int) zPosF); + if (!(tile instanceof IGregTechTileEntity)) { + donePlaying = true; + return; + } + fadeMe |= ((IGregTechTileEntity) tile).isActive() ? whileActive : whileInactive; + } +} diff --git a/src/main/java/tectech/thing/metaTileEntity/multi/base/TTMultiblockBase.java b/src/main/java/tectech/thing/metaTileEntity/multi/base/TTMultiblockBase.java new file mode 100644 index 0000000000..22a2d38c0a --- /dev/null +++ b/src/main/java/tectech/thing/metaTileEntity/multi/base/TTMultiblockBase.java @@ -0,0 +1,2760 @@ +package tectech.thing.metaTileEntity.multi.base; + +import static gregtech.api.enums.GTValues.V; +import static gregtech.api.enums.GTValues.VN; +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.metatileentity.BaseTileEntity.TOOLTIP_DELAY; +import static gregtech.api.util.GTUtility.filterValidMTEs; +import static java.lang.Math.min; +import static tectech.thing.casing.BlockGTCasingsTT.texturePage; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.annotation.Nonnull; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.texture.IIconRegister; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.common.util.ForgeDirection; +import net.minecraftforge.fluids.FluidStack; + +import org.jetbrains.annotations.NotNull; +import org.lwjgl.opengl.GL11; + +import com.google.common.collect.Iterables; +import com.gtnewhorizon.structurelib.StructureLibAPI; +import com.gtnewhorizon.structurelib.alignment.IAlignment; +import com.gtnewhorizon.structurelib.alignment.IAlignmentProvider; +import com.gtnewhorizon.structurelib.structure.IStructureDefinition; +import com.gtnewhorizon.structurelib.structure.IStructureElement; +import com.gtnewhorizon.structurelib.util.Vec3Impl; +import com.gtnewhorizons.modularui.api.NumberFormatMUI; +import com.gtnewhorizons.modularui.api.drawable.IDrawable; +import com.gtnewhorizons.modularui.api.drawable.UITexture; +import com.gtnewhorizons.modularui.api.math.Alignment; +import com.gtnewhorizons.modularui.api.math.Color; +import com.gtnewhorizons.modularui.api.math.Pos2d; +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.internal.wrapper.BaseSlot; +import com.gtnewhorizons.modularui.common.widget.ButtonWidget; +import com.gtnewhorizons.modularui.common.widget.DrawableWidget; +import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; +import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; +import com.gtnewhorizons.modularui.common.widget.SlotWidget; +import com.gtnewhorizons.modularui.common.widget.TextWidget; +import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import gregtech.api.enums.Textures; +import gregtech.api.gui.modularui.GTUITextures; +import gregtech.api.interfaces.IHatchElement; +import gregtech.api.interfaces.ITexture; +import gregtech.api.interfaces.metatileentity.IMetaTileEntity; +import gregtech.api.interfaces.modularui.IBindPlayerInventoryUI; +import gregtech.api.interfaces.tileentity.IGregTechTileEntity; +import gregtech.api.metatileentity.BaseTileEntity; +import gregtech.api.metatileentity.MetaTileEntity; +import gregtech.api.metatileentity.implementations.MTEExtendedPowerMultiBlockBase; +import gregtech.api.metatileentity.implementations.MTEHatch; +import gregtech.api.metatileentity.implementations.MTEHatchDynamo; +import gregtech.api.metatileentity.implementations.MTEHatchEnergy; +import gregtech.api.metatileentity.implementations.MTEHatchInput; +import gregtech.api.metatileentity.implementations.MTEHatchInputBus; +import gregtech.api.metatileentity.implementations.MTEHatchMaintenance; +import gregtech.api.metatileentity.implementations.MTEHatchMuffler; +import gregtech.api.metatileentity.implementations.MTEHatchOutput; +import gregtech.api.metatileentity.implementations.MTEHatchOutputBus; +import gregtech.api.recipe.check.CheckRecipeResult; +import gregtech.api.recipe.check.CheckRecipeResultRegistry; +import gregtech.api.util.GTUtility; +import gregtech.api.util.HatchElementBuilder; +import gregtech.api.util.IGTHatchAdder; +import gregtech.api.util.MultiblockTooltipBuilder; +import gregtech.api.util.shutdown.ShutDownReason; +import gregtech.api.util.shutdown.ShutDownReasonRegistry; +import gregtech.api.util.shutdown.SimpleShutDownReason; +import gregtech.common.Pollution; +import gregtech.common.tileentities.machines.IDualInputHatch; +import tectech.Reference; +import tectech.TecTech; +import tectech.loader.TecTechConfig; +import tectech.thing.gui.TecTechUITextures; +import tectech.thing.metaTileEntity.hatch.MTEHatchDataConnector; +import tectech.thing.metaTileEntity.hatch.MTEHatchDataInput; +import tectech.thing.metaTileEntity.hatch.MTEHatchDataOutput; +import tectech.thing.metaTileEntity.hatch.MTEHatchDynamoMulti; +import tectech.thing.metaTileEntity.hatch.MTEHatchEnergyMulti; +import tectech.thing.metaTileEntity.hatch.MTEHatchParam; +import tectech.thing.metaTileEntity.hatch.MTEHatchUncertainty; +import tectech.thing.metaTileEntity.multi.base.render.TTRenderedExtendedFacingTexture; +import tectech.util.CommonValues; +import tectech.util.TTUtility; + +/** + * Created by danie_000 on 27.10.2016. + */ +public abstract class TTMultiblockBase extends MTEExtendedPowerMultiBlockBase + implements IAlignment, IBindPlayerInventoryUI { + // region Client side variables (static - one per class) + + // Front icon holders - static so it is default one for my blocks + // just add new static ones in your class and and override getTexture + protected static Textures.BlockIcons.CustomIcon ScreenOFF; + protected static Textures.BlockIcons.CustomIcon ScreenON; + + /** Base ID for the LED window popup. LED 1 I0 will have ID 100, LED 1 I1 101... */ + protected static int LED_WINDOW_BASE_ID = 100; + + // Sound resource - same as with screen but override getActivitySound + public static final ResourceLocation activitySound = new ResourceLocation(Reference.MODID + ":fx_lo_freq"); + + @SideOnly(Side.CLIENT) + private SoundLoop activitySoundLoop; + // endregion + + // region HATCHES ARRAYS - they hold info about found hatches, add hatches to them... (auto structure magic does it + // tho) + + // HATCHES!!!, should be added and removed in check machine + protected ArrayList eParamHatches = new ArrayList<>(); + protected ArrayList eUncertainHatches = new ArrayList<>(); + // multi amp hatches in/out + protected ArrayList eEnergyMulti = new ArrayList<>(); + protected ArrayList eDynamoMulti = new ArrayList<>(); + // data hatches + protected ArrayList eInputData = new ArrayList<>(); + protected ArrayList eOutputData = new ArrayList<>(); + + // endregion + + // region parameters + public final Parameters parametrization; + // endregion + + // region Control variables + + // should explode on dismatle?, set it in constructor, if true machine will explode if invalidated structure while + // active + protected boolean eDismantleBoom = false; + + // what is the amount of A required + public long eAmpereFlow = 1; // analogue of EU/t but for amperes used (so eu/t is actually eu*A/t) USE ONLY POSITIVE + // NUMBERS! + + // set to what you need it to be in check recipe + // data required to operate + protected long eRequiredData = 0; + + // Counter for the computation timeout. Will be initialized one to the max time and then only decreased. + protected int eComputationTimeout = MAX_COMPUTATION_TIMEOUT; + + // Max timeout of computation in ticks + protected static int MAX_COMPUTATION_TIMEOUT = 100; + + // are parameters correct - change in check recipe/output/update params etc. (maintenance status boolean) + protected boolean eParameters = true; + + // what type of certainty inconvenience is used - can be used as in Computer - more info in uncertainty hatch + protected byte eCertainMode = 0, eCertainStatus = 0; + + // minimal repair status to make the machine even usable (how much unfixed fixed stuff is needed) + // if u need to force some things to be fixed - u might need to override doRandomMaintenanceDamage + protected byte minRepairStatus = 3; + + // whether there is a maintenance hatch in the multi and whether checks are necessary (for now only used in a + // transformer) + protected boolean hasMaintenanceChecks = true; + + // is power pass cover present + public boolean ePowerPassCover = false; + + // functionality toggles - changed by buttons in gui also + public boolean ePowerPass = false, eSafeVoid = false; + + // endregion + + // region READ ONLY unless u really need to change it + + // max amperes machine can take in after computing it to the lowest tier (exchange packets to min tier count) + protected long eMaxAmpereFlow = 0, eMaxAmpereGen = 0; + + // What is the max and minimal tier of eu hatches installed + private long maxEUinputMin = 0, maxEUinputMax = 0, maxEUoutputMin = 0, maxEUoutputMax = 0; + + // read only unless you are making computation generator - read computer class + protected long eAvailableData = 0; // data being available + + // just some info - private so hidden + private boolean explodedThisTick = false; + + /** Flag if the new long power variable should be used */ + protected boolean useLongPower = false; + + // Locale-aware formatting of numbers. + protected static NumberFormatMUI numberFormat; + static { + numberFormat = new NumberFormatMUI(); + numberFormat.setMaximumFractionDigits(8); + } + + // endregion + + protected TTMultiblockBase(int aID, String aName, String aNameRegional) { + super(aID, aName, aNameRegional); + parametrization = new Parameters(this); + parametersInstantiation_EM(); + parametrization.setToDefaults(true, true); + } + + protected TTMultiblockBase(String aName) { + super(aName); + parametrization = new Parameters(this); + parametersInstantiation_EM(); + parametrization.setToDefaults(true, true); + } + + // region SUPER STRUCT + + /** + * Gets structure + * + * @return STATIC INSTANCE OF STRUCTURE + */ + public abstract IStructureDefinition getStructure_EM(); + + @SuppressWarnings("unchecked") + private IStructureDefinition getStructure_EM_Internal() { + return (IStructureDefinition) getStructure_EM(); + } + + @Override + public IStructureDefinition getStructureDefinition() { + return getStructure_EM_Internal(); + } + + public final boolean structureCheck_EM(String piece, int horizontalOffset, int verticalOffset, int depthOffset) { + IGregTechTileEntity baseMetaTileEntity = getBaseMetaTileEntity(); + return getStructure_EM_Internal().check( + this, + piece, + baseMetaTileEntity.getWorld(), + getExtendedFacing(), + baseMetaTileEntity.getXCoord(), + baseMetaTileEntity.getYCoord(), + baseMetaTileEntity.getZCoord(), + horizontalOffset, + verticalOffset, + depthOffset, + !mMachine); + } + + public final boolean structureBuild_EM(String piece, int horizontalOffset, int verticalOffset, int depthOffset, + ItemStack trigger, boolean hintsOnly) { + IGregTechTileEntity baseMetaTileEntity = getBaseMetaTileEntity(); + return getStructure_EM_Internal().buildOrHints( + this, + trigger, + piece, + baseMetaTileEntity.getWorld(), + getExtendedFacing(), + baseMetaTileEntity.getXCoord(), + baseMetaTileEntity.getYCoord(), + baseMetaTileEntity.getZCoord(), + horizontalOffset, + verticalOffset, + depthOffset, + hintsOnly); + } + // endregion + + // region METHODS TO OVERRIDE - general functionality, recipe check, output + + /** + * Check structure here, also add hatches + * + * @param iGregTechTileEntity - the tile entity + * @param itemStack - what is in the controller input slot + * @return is structure valid + */ + protected boolean checkMachine_EM(IGregTechTileEntity iGregTechTileEntity, ItemStack itemStack) { + return false; + } + + /** + * Checks Recipes (when all machine is complete and can work) + *

+ * can get/set Parameters here also + * + * @deprecated Use {@link #createProcessingLogic()} ()} or {@link #checkProcessing_EM()} + * + * @param itemStack item in the controller + * @return is recipe is valid + */ + @Deprecated + public boolean checkRecipe_EM(ItemStack itemStack) { + return false; + } + + @NotNull + protected CheckRecipeResult checkProcessing_EM() { + if (processingLogic == null) { + return checkRecipe_EM(getControllerSlot()) ? CheckRecipeResultRegistry.SUCCESSFUL + : CheckRecipeResultRegistry.NO_RECIPE; + } + return super.checkProcessing(); + } + + /** + * Put EM stuff from outputEM into EM output hatches here or do other stuff - it is basically on recipe succeded + *

+ * based on "machine state" do output, this must move to outputEM to EM output hatches and can also modify output + * items/fluids/EM, remaining EM is NOT overflowed. (Well it can be overflowed if machine didn't finished, + * soft-hammered/disabled/not enough EU) Setting available data processing + */ + public void outputAfterRecipe_EM() {} + // endregion + + // region tooltip and scanner result + + public ArrayList getFullLedDescriptionIn(int hatchNo, int paramID) { + ArrayList list = new ArrayList<>(); + list.add( + EnumChatFormatting.WHITE + "ID: " + + EnumChatFormatting.AQUA + + hatchNo + + EnumChatFormatting.YELLOW + + ":" + + EnumChatFormatting.AQUA + + paramID + + EnumChatFormatting.YELLOW + + ":" + + EnumChatFormatting.AQUA + + "I " + + parametrization.getStatusIn(hatchNo, paramID).name.get()); + list.add( + EnumChatFormatting.WHITE + "Value: " + + EnumChatFormatting.AQUA + + numberFormat.format(parametrization.getIn(hatchNo, paramID))); + try { + list.add(parametrization.groups[hatchNo].parameterIn[paramID].getBrief()); + } catch (NullPointerException | IndexOutOfBoundsException e) { + list.add("Unused"); + } + return list; + } + + public ArrayList getFullLedDescriptionOut(int hatchNo, int paramID) { + ArrayList list = new ArrayList<>(); + list.add( + EnumChatFormatting.WHITE + "ID: " + + EnumChatFormatting.AQUA + + hatchNo + + EnumChatFormatting.YELLOW + + ":" + + EnumChatFormatting.AQUA + + paramID + + EnumChatFormatting.YELLOW + + ":" + + EnumChatFormatting.AQUA + + "O " + + parametrization.getStatusOut(hatchNo, paramID).name.get()); + list.add( + EnumChatFormatting.WHITE + "Value: " + + EnumChatFormatting.AQUA + + numberFormat.format(parametrization.getOut(hatchNo, paramID))); + try { + list.add(parametrization.groups[hatchNo].parameterOut[paramID].getBrief()); + } catch (NullPointerException | IndexOutOfBoundsException e) { + list.add("Unused"); + } + return list; + } + + @Override + protected MultiblockTooltipBuilder createTooltip() { + final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); + tt.addInfo("Nothing special just override me") + .toolTipFinisher(CommonValues.TEC_MARK_GENERAL); + return tt; + } + + /** + * scanner gives it + */ + @Override + public String[] getInfoData() { // TODO Do it + long storedEnergy = 0; + long maxEnergy = 0; + for (MTEHatchEnergy tHatch : filterValidMTEs(mEnergyHatches)) { + storedEnergy += tHatch.getBaseMetaTileEntity() + .getStoredEU(); + maxEnergy += tHatch.getBaseMetaTileEntity() + .getEUCapacity(); + } + for (MTEHatchEnergyMulti tHatch : filterValidMTEs(eEnergyMulti)) { + storedEnergy += tHatch.getBaseMetaTileEntity() + .getStoredEU(); + maxEnergy += tHatch.getBaseMetaTileEntity() + .getEUCapacity(); + } + + return new String[] { "Progress:", + EnumChatFormatting.GREEN + GTUtility.formatNumbers(mProgresstime / 20) + + EnumChatFormatting.RESET + + " s / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(mMaxProgresstime / 20) + + EnumChatFormatting.RESET + + " s", + "Energy Hatches:", + EnumChatFormatting.GREEN + GTUtility.formatNumbers(storedEnergy) + + EnumChatFormatting.RESET + + " EU / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(maxEnergy) + + EnumChatFormatting.RESET + + " EU", + (getPowerFlow() * eAmpereFlow <= 0 ? "Probably uses: " : "Probably makes: ") + EnumChatFormatting.RED + + GTUtility.formatNumbers(Math.abs(getPowerFlow())) + + EnumChatFormatting.RESET + + " EU/t at " + + EnumChatFormatting.RED + + GTUtility.formatNumbers(eAmpereFlow) + + EnumChatFormatting.RESET + + " A", + "Tier Rating: " + EnumChatFormatting.YELLOW + + VN[getMaxEnergyInputTier_EM()] + + EnumChatFormatting.RESET + + " / " + + EnumChatFormatting.GREEN + + VN[getMinEnergyInputTier_EM()] + + EnumChatFormatting.RESET + + " Amp Rating: " + + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(eMaxAmpereFlow) + + EnumChatFormatting.RESET + + " A", + "Problems: " + EnumChatFormatting.RED + + (getIdealStatus() - getRepairStatus()) + + EnumChatFormatting.RESET + + " Efficiency: " + + EnumChatFormatting.YELLOW + + mEfficiency / 100.0F + + EnumChatFormatting.RESET + + " %", + "PowerPass: " + EnumChatFormatting.BLUE + + ePowerPass + + EnumChatFormatting.RESET + + " SafeVoid: " + + EnumChatFormatting.BLUE + + eSafeVoid, + "Computation: " + EnumChatFormatting.GREEN + + GTUtility.formatNumbers(eAvailableData) + + EnumChatFormatting.RESET + + " / " + + EnumChatFormatting.YELLOW + + GTUtility.formatNumbers(eRequiredData) + + EnumChatFormatting.RESET }; + } + + /** + * should it work with scanner? HELL YES + */ + @Override + public boolean isGivingInformation() { + return true; + } + + // endregion + + // region GUI/SOUND/RENDER + + /** + * add more textures + */ + @Override + @SideOnly(Side.CLIENT) + public void registerIcons(IIconRegister aBlockIconRegister) { + ScreenOFF = new Textures.BlockIcons.CustomIcon("iconsets/EM_CONTROLLER"); + ScreenON = new Textures.BlockIcons.CustomIcon("iconsets/EM_CONTROLLER_ACTIVE"); + super.registerIcons(aBlockIconRegister); + } + + /** + * actually use textures + */ + @Override + public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing, + int colorIndex, boolean aActive, boolean aRedstone) { + if (side == facing) { + return new ITexture[] { Textures.BlockIcons.casingTexturePages[texturePage][4], + new TTRenderedExtendedFacingTexture(aActive ? ScreenON : ScreenOFF) }; + } + return new ITexture[] { Textures.BlockIcons.casingTexturePages[texturePage][4] }; + } + + /** + * should return your activity sound + */ + @SideOnly(Side.CLIENT) + protected ResourceLocation getActivitySound() { + return activitySound; + } + + /** + * plays the sounds auto magically + */ + @SideOnly(Side.CLIENT) + protected void soundMagic(ResourceLocation activitySound) { + if (getBaseMetaTileEntity().isActive()) { + if (activitySoundLoop == null) { + activitySoundLoop = new SoundLoop(activitySound, getBaseMetaTileEntity(), false, true); + Minecraft.getMinecraft() + .getSoundHandler() + .playSound(activitySoundLoop); + } + } else { + if (activitySoundLoop != null) { + activitySoundLoop = null; + } + } + } + + // endregion + + // region Methods to maybe override (if u implement certain stuff) + + /** + * is the thing inside controller a valid item to make the machine work + */ + @Override + public boolean isCorrectMachinePart(ItemStack itemStack) { + return true; + } + + /** + * how much damage to apply to thing in controller - not sure how it does it + */ + @Override + public int getDamageToComponent(ItemStack itemStack) { + return 0; + } + + /** + * called when removing from map - not when unloading? //todo check + */ + @Override + public void onRemoval() { + try { + if (ePowerPass && getEUVar() > V[3] + || eDismantleBoom && mMaxProgresstime > 0 && areChunksAroundLoaded_EM()) { + explodeMultiblock(); + } + } catch (Exception e) { + if (TecTechConfig.DEBUG_MODE) { + e.printStackTrace(); + } + } + } + + /** + * prevents spontaneous explosions when the chunks unloading would cause them should cover 3 chunks radius + */ + protected boolean areChunksAroundLoaded_EM() { + if (this.isValid() && getBaseMetaTileEntity().isServerSide()) { + IGregTechTileEntity base = getBaseMetaTileEntity(); + return base.getWorld() + .doChunksNearChunkExist(base.getXCoord(), base.getYCoord(), base.getZCoord(), 3); + // todo check if it is actually checking if chunks are loaded + } else { + return false; + } + } + + /** + * instantiate parameters in CONSTRUCTOR! CALLED ONCE on creation, don't call it in your classes + */ + protected void parametersInstantiation_EM() {} + + /** + * It is automatically called OFTEN update status of parameters in guis (and "machine state" if u wish) Called + * before check recipe, before outputting, and every second the machine is complete + *

+ * good place to update parameter statuses, default implementation handles it well + * + * @param machineBusy is machine doing stuff + */ + protected void parametersStatusesWrite_EM(boolean machineBusy) { // todo unimplement? + if (!machineBusy) { + for (Parameters.Group.ParameterIn parameterIn : parametrization.parameterInArrayList) { + if (parameterIn != null) { + parameterIn.updateStatus(); + } + } + } else { + for (Parameters.Group hatch : parametrization.groups) { + if (hatch != null && hatch.updateWhileRunning) { + for (Parameters.Group.ParameterIn in : hatch.parameterIn) { + if (in != null) { + in.updateStatus(); + } + } + } + } + } + for (Parameters.Group.ParameterOut parameterOut : parametrization.parameterOutArrayList) { + if (parameterOut != null) { + parameterOut.updateStatus(); + } + } + } + + /** + * For extra types of hatches initiation, LOOK HOW IT IS CALLED! in onPostTick + * + * @param mMachine was the machine considered complete at that point in onPostTick + */ + protected void hatchInit_EM(boolean mMachine) {} + + /** + * called when the multiblock is exploding - if u want to add more EXPLOSIONS, for ex. new types of hatches also + * have to explode + */ + protected void extraExplosions_EM() {} // For that extra hatches explosions, and maybe some MOORE EXPLOSIONS + + /** + * Get Available data, Override only on data outputters should return mAvailableData that is set in check recipe + * + * @return available data + */ + protected long getAvailableData_EM() { + long result = 0; + IGregTechTileEntity baseMetaTileEntity = getBaseMetaTileEntity(); + Vec3Impl pos = new Vec3Impl( + baseMetaTileEntity.getXCoord(), + baseMetaTileEntity.getYCoord(), + baseMetaTileEntity.getZCoord()); + for (MTEHatchDataInput in : eInputData) { + if (in.q != null) { + Long value = in.q.contentIfNotInTrace(pos); + if (value != null) { + result += value; + } + } + } + return result; + } + + protected long getPowerFlow() { + return useLongPower ? lEUt : mEUt; + } + + protected void setPowerFlow(long lEUt) { + if (useLongPower) { + this.lEUt = lEUt; + } else { + mEUt = (int) Math.min(Integer.MAX_VALUE, lEUt); + } + } + + @Override + protected long getActualEnergyUsage() { + return -(useLongPower ? lEUt : mEUt) * eAmpereFlow * 10_000 / Math.max(1_000, mEfficiency); + } + + /** + * Extra hook on cyclic updates (not really needed for machines smaller than 1 chunk) BUT NEEDED WHEN - machine + * blocks are not touching each other or they don't implement IMachineBlockUpdateable (ex. air,stone,weird TE's) + */ + protected boolean cyclicUpdate_EM() { + return mUpdate <= -1000; // set to false to disable cyclic update + // default is once per 50s; mUpdate is decremented every tick + } + + /** + * get pollution per tick + * + * @param itemStack what is in controller + * @return how much pollution is produced + */ + @Override + public int getPollutionPerTick(ItemStack itemStack) { + return 0; + } + + /** + * EM pollution per tick + * + * @param itemStack - item in controller + * @return how much excess matter is there + */ + public float getExcessMassPerTick_EM(ItemStack itemStack) { + return 0f; + } + + /** + * triggered if machine is not allowed to work after completing a recipe, override to make it not shutdown for + * instance (like turbines). bu just replacing it with blank - active transformer is doing it + *

+ * CALLED DIRECTLY when soft hammered to offline state - usually should stop the machine unless some other mechanics + * should do it + */ + protected void notAllowedToWork_stopMachine_EM() { + stopMachine(); + } + + /** + * store data + */ + @Override + public void saveNBTData(NBTTagCompound aNBT) { + super.saveNBTData(aNBT); + aNBT.setLong("eMaxGenEUmin", maxEUoutputMin); + aNBT.setLong("eMaxGenEUmax", maxEUoutputMax); + aNBT.setLong("eGenRating", eMaxAmpereGen); + aNBT.setLong("eMaxEUmin", maxEUinputMin); + aNBT.setLong("eMaxEUmax", maxEUinputMax); + aNBT.setLong("eRating", eAmpereFlow); + aNBT.setLong("eMaxA", eMaxAmpereFlow); + aNBT.setLong("eDataR", eRequiredData); + aNBT.setLong("eDataA", eAvailableData); + aNBT.setByte("eCertainM", eCertainMode); + aNBT.setByte("eCertainS", eCertainStatus); + aNBT.setByte("eMinRepair", minRepairStatus); + aNBT.setBoolean("eParam", eParameters); + aNBT.setBoolean("ePass", ePowerPass); + aNBT.setBoolean("ePowerPassCover", ePowerPassCover); + aNBT.setBoolean("eVoid", eSafeVoid); + aNBT.setBoolean("eBoom", eDismantleBoom); + aNBT.setBoolean("eOK", mMachine); + // Ensures compatibility + if (mOutputItems != null) { + aNBT.setInteger("mOutputItemsLength", mOutputItems.length); + for (int i = 0; i < mOutputItems.length; i++) { + if (mOutputItems[i] != null) { + NBTTagCompound tNBT = new NBTTagCompound(); + mOutputItems[i].writeToNBT(tNBT); + aNBT.setTag("mOutputItem" + i, tNBT); + } + } + } + + // Ensures compatibility + if (mOutputFluids != null) { + aNBT.setInteger("mOutputFluidsLength", mOutputFluids.length); + for (int i = 0; i < mOutputFluids.length; i++) { + if (mOutputFluids[i] != null) { + NBTTagCompound tNBT = new NBTTagCompound(); + mOutputFluids[i].writeToNBT(tNBT); + aNBT.setTag("mOutputFluids" + i, tNBT); + } + } + } + + aNBT.setInteger("eOutputStackCount", 0); + aNBT.removeTag("outputEM"); + + NBTTagCompound paramI = new NBTTagCompound(); + for (int i = 0; i < parametrization.iParamsIn.length; i++) { + paramI.setDouble(Integer.toString(i), parametrization.iParamsIn[i]); + } + aNBT.setTag("eParamsInD", paramI); + + NBTTagCompound paramO = new NBTTagCompound(); + for (int i = 0; i < parametrization.iParamsOut.length; i++) { + paramO.setDouble(Integer.toString(i), parametrization.iParamsOut[i]); + } + aNBT.setTag("eParamsOutD", paramO); + + NBTTagCompound paramIs = new NBTTagCompound(); + for (int i = 0; i < parametrization.eParamsInStatus.length; i++) { + paramIs.setByte(Integer.toString(i), parametrization.eParamsInStatus[i].getOrdinalByte()); + } + aNBT.setTag("eParamsInS", paramIs); + + NBTTagCompound paramOs = new NBTTagCompound(); + for (int i = 0; i < parametrization.eParamsOutStatus.length; i++) { + paramOs.setByte(Integer.toString(i), parametrization.eParamsOutStatus[i].getOrdinalByte()); + } + aNBT.setTag("eParamsOutS", paramOs); + } + + /** + * load data + */ + @Override + public void loadNBTData(NBTTagCompound aNBT) { + super.loadNBTData(aNBT); + maxEUoutputMin = aNBT.getLong("eMaxGenEUmin"); + maxEUoutputMax = aNBT.getLong("eMaxGenEUmax"); + eMaxAmpereGen = aNBT.getLong("eGenRating"); + maxEUinputMin = aNBT.getLong("eMaxEUmin"); + maxEUinputMax = aNBT.getLong("eMaxEUmax"); + eAmpereFlow = aNBT.hasKey("eRating") ? aNBT.getLong("eRating") : 1; + eMaxAmpereFlow = aNBT.getLong("eMaxA"); + eRequiredData = aNBT.getLong("eDataR"); + eAvailableData = aNBT.getLong("eDataA"); + eCertainMode = aNBT.getByte("eCertainM"); + eCertainStatus = aNBT.getByte("eCertainS"); + minRepairStatus = aNBT.hasKey("eMinRepair") ? aNBT.getByte("eMinRepair") : 3; + eParameters = !aNBT.hasKey("eParam") || aNBT.getBoolean("eParam"); + ePowerPass = aNBT.getBoolean("ePass"); + ePowerPassCover = aNBT.getBoolean("ePowerPassCover"); + eSafeVoid = aNBT.getBoolean("eVoid"); + eDismantleBoom = aNBT.getBoolean("eBoom"); + mMachine = aNBT.getBoolean("eOK"); + + // Ensures compatibility + int aOutputItemsLength = aNBT.getInteger("mOutputItemsLength"); + if (aOutputItemsLength > 0) { + mOutputItems = new ItemStack[aOutputItemsLength]; + for (int i = 0; i < mOutputItems.length; i++) { + mOutputItems[i] = GTUtility.loadItem(aNBT, "mOutputItem" + i); + } + } + + // Ensures compatibility + int aOutputFluidsLength = aNBT.getInteger("mOutputFluidsLength"); + if (aOutputFluidsLength > 0) { + mOutputFluids = new FluidStack[aOutputFluidsLength]; + for (int i = 0; i < mOutputFluids.length; i++) { + mOutputFluids[i] = GTUtility.loadFluid(aNBT, "mOutputFluids" + i); + } + } + + if (aNBT.hasKey("eParamsIn") && aNBT.hasKey("eParamsOut") && aNBT.hasKey("eParamsB")) { + NBTTagCompound paramI = aNBT.getCompoundTag("eParamsIn"); + NBTTagCompound paramO = aNBT.getCompoundTag("eParamsOut"); + NBTTagCompound paramB = aNBT.getCompoundTag("eParamsB"); + for (int i = 0; i < 10; i++) { + if (paramB.getBoolean(Integer.toString(i))) { + parametrization.iParamsIn[i] = Float.intBitsToFloat(paramI.getInteger(Integer.toString(i))); + parametrization.iParamsOut[i] = Float.intBitsToFloat(paramO.getInteger(Integer.toString(i))); + } else { + parametrization.iParamsIn[i] = paramI.getInteger(Integer.toString(i)); + parametrization.iParamsOut[i] = paramO.getInteger(Integer.toString(i)); + } + } + } else { + NBTTagCompound paramI = aNBT.getCompoundTag("eParamsInD"); + for (int i = 0; i < parametrization.iParamsIn.length; i++) { + parametrization.iParamsIn[i] = paramI.getDouble(Integer.toString(i)); + } + NBTTagCompound paramO = aNBT.getCompoundTag("eParamsOutD"); + for (int i = 0; i < parametrization.iParamsOut.length; i++) { + parametrization.iParamsOut[i] = paramO.getDouble(Integer.toString(i)); + } + } + + NBTTagCompound paramIs = aNBT.getCompoundTag("eParamsInS"); + for (int i = 0; i < parametrization.eParamsInStatus.length; i++) { + parametrization.eParamsInStatus[i] = LedStatus.getStatus(paramIs.getByte(Integer.toString(i))); + } + + NBTTagCompound paramOs = aNBT.getCompoundTag("eParamsOutS"); + for (int i = 0; i < parametrization.eParamsOutStatus.length; i++) { + parametrization.eParamsOutStatus[i] = LedStatus.getStatus(paramOs.getByte(Integer.toString(i))); + } + } + + /** + * Override if needed but usually call super method at start! On machine stop - NOT called directly when soft + * hammered to offline state! - it SHOULD cause a full stop like power failure does + */ + @Override + public void stopMachine(@Nonnull ShutDownReason reason) { + if (!ShutDownReasonRegistry.isRegistered(reason.getID())) { + throw new RuntimeException(String.format("Reason %s is not registered for registry", reason.getID())); + } + for (MTEHatchDataOutput data : eOutputData) { + data.q = null; + } + + mOutputItems = null; + mOutputFluids = null; + mEfficiency = 0; + mEfficiencyIncrease = 0; + mProgresstime = 0; + mMaxProgresstime = 0; + eAvailableData = 0; + hatchesStatusUpdate_EM(); + getBaseMetaTileEntity().disableWorking(); + getBaseMetaTileEntity().setShutDownReason(reason); + getBaseMetaTileEntity().setShutdownStatus(true); + if (reason.wasCritical()) { + sendSound(INTERRUPT_SOUND_INDEX); + } + } + + /** + * After recipe check failed helper method so i don't have to set that params to nothing at all times + */ + protected void afterRecipeCheckFailed() { + + for (MTEHatchDataOutput data : eOutputData) { + data.q = null; + } + + mOutputItems = null; + mOutputFluids = null; + mEfficiency = 0; + mEfficiencyIncrease = 0; + mProgresstime = 0; + mMaxProgresstime = 0; + eAvailableData = 0; + } + + /** + * cyclic check even when not working, called LESS frequently + */ + private boolean cyclicUpdate() { + if (cyclicUpdate_EM()) { + mUpdate = 0; + return true; + } + return false; + } + + /** + * mining level... + */ + @Override + public byte getTileEntityBaseType() { + return 3; + } + + // endregion + + // region internal + + /** + * internal check machine + */ + @Override + public final boolean checkMachine(IGregTechTileEntity iGregTechTileEntity, ItemStack itemStack) { + return checkMachine_EM(iGregTechTileEntity, itemStack); + } + + /** + * internal check recipe + */ + @Override + public final boolean checkRecipe(ItemStack itemStack) { // do recipe checks, based on "machine content and state" + hatchesStatusUpdate_EM(); + startRecipeProcessing(); + boolean result = checkRecipe_EM(itemStack); // if had no - set default params + endRecipeProcessing(); + hatchesStatusUpdate_EM(); + return result; + } + + @NotNull + @Override + public final CheckRecipeResult checkProcessing() { + hatchesStatusUpdate_EM(); + CheckRecipeResult result = checkProcessing_EM(); + hatchesStatusUpdate_EM(); + return result; + } + + /** + * callback for updating parameters and new hatches + */ + protected void hatchesStatusUpdate_EM() { + if (getBaseMetaTileEntity().isClientSide()) { + return; + } + boolean busy = mMaxProgresstime > 0; + if (busy) { // write from buffer to hatches only + for (MTEHatchParam hatch : filterValidMTEs(eParamHatches)) { + if (hatch.param < 0) { + continue; + } + int hatchId = hatch.param; + if (parametrization.groups[hatchId] != null && parametrization.groups[hatchId].updateWhileRunning) { + parametrization.iParamsIn[hatchId] = hatch.value0D; + parametrization.iParamsIn[hatchId + 10] = hatch.value1D; + } + hatch.input0D = parametrization.iParamsOut[hatchId]; + hatch.input1D = parametrization.iParamsOut[hatchId + 10]; + } + } else { // if has nothing to do update all + for (MTEHatchParam hatch : filterValidMTEs(eParamHatches)) { + if (hatch.param < 0) { + continue; + } + int hatchId = hatch.param; + parametrization.iParamsIn[hatchId] = hatch.value0D; + parametrization.iParamsIn[hatchId + 10] = hatch.value1D; + hatch.input0D = parametrization.iParamsOut[hatchId]; + hatch.input1D = parametrization.iParamsOut[hatchId + 10]; + } + } + for (MTEHatchUncertainty uncertainty : eUncertainHatches) { + eCertainStatus = uncertainty.update(eCertainMode); + } + eAvailableData = getAvailableData_EM(); + parametersStatusesWrite_EM(busy); + } + + @Deprecated + public final int getAmountOfOutputs() { + throw new NoSuchMethodError("Deprecated Do not use"); + } + // endregion + + // region TICKING functions + + public void onFirstTick_EM(IGregTechTileEntity aBaseMetaTileEntity) {} + + @Override + public final void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) { + isFacingValid(aBaseMetaTileEntity.getFrontFacing()); + if (getBaseMetaTileEntity().isClientSide()) { + StructureLibAPI.queryAlignment((IAlignmentProvider) aBaseMetaTileEntity); + } + onFirstTick_EM(aBaseMetaTileEntity); + } + + /** + * called every tick the machines is active + */ + @Override + public boolean onRunningTick(ItemStack aStack) { + return onRunningTickCheck(aStack); + } + + public boolean onRunningTickCheck_EM(ItemStack aStack) { + if (eRequiredData > eAvailableData) { + if (!checkComputationTimeout()) { + if (energyFlowOnRunningTick_EM(aStack, false)) { + stopMachine(SimpleShutDownReason.ofCritical("computation_loss")); + } + return false; + } + } + return energyFlowOnRunningTick_EM(aStack, true); + } + + public boolean onRunningTickCheck(ItemStack aStack) { + if (eRequiredData > eAvailableData) { + if (!checkComputationTimeout()) { + if (energyFlowOnRunningTick(aStack, false)) { + stopMachine(SimpleShutDownReason.ofCritical("computation_loss")); + } + return false; + } + } + return energyFlowOnRunningTick(aStack, true); + } + + /** + * CAREFUL!!! it calls most of the callbacks, like everything else in here + */ + @Override + public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { + if (aBaseMetaTileEntity.isServerSide()) { + mTotalRunTime++; + explodedThisTick = false; + if (mEfficiency < 0) { + mEfficiency = 0; + } + + if (--mUpdate == 0 || --mStartUpCheck == 0 + || cyclicUpdate() + || aBaseMetaTileEntity.hasWorkJustBeenEnabled()) { + clearHatches_EM(); + + if (aBaseMetaTileEntity instanceof BaseTileEntity) { + ((BaseTileEntity) aBaseMetaTileEntity).ignoreUnloadedChunks = mMachine; + } + mMachine = checkMachine(aBaseMetaTileEntity, mInventory[1]); + + if (!mMachine) { + if (ePowerPass && getEUVar() > V[3] + || eDismantleBoom && mMaxProgresstime > 0 && areChunksAroundLoaded_EM()) { + explodeMultiblock(); + } + } + + if (eUncertainHatches.size() > 1) { + mMachine = false; + } + + if (mMachine) { + setupHatches_EM(); + + setupEnergyHatchesVariables_EM(); + + if (getEUVar() > maxEUStore()) { + setEUVar(maxEUStore()); + } + } else { + maxEUinputMin = 0; + maxEUinputMax = 0; + eMaxAmpereFlow = 0; + setEUVar(0); + } + hatchInit_EM(mMachine); + } + + if (mStartUpCheck < 0) { // E + if (mMachine) { // S + byte Tick = (byte) (aTick % 20); + if (CommonValues.MULTI_CHECK_AT == Tick) { + checkMaintenance(); + } + + if (getRepairStatus() >= minRepairStatus) { // S + if (CommonValues.MULTI_CHECK_AT == Tick) { + hatchesStatusUpdate_EM(); + } + + dischargeController_EM(aBaseMetaTileEntity); + chargeController_EM(aBaseMetaTileEntity); + + if (mMaxProgresstime > 0 && doRandomMaintenanceDamage()) { // Start + if (onRunningTick(mInventory[1])) { // Compute EU + if (!polluteEnvironment(getPollutionPerTick(mInventory[1]))) { + stopMachine(ShutDownReasonRegistry.POLLUTION_FAIL); + } + + if (mMaxProgresstime > 0 && ++mProgresstime >= mMaxProgresstime) { // progress increase + // and done + hatchesStatusUpdate_EM(); + + outputAfterRecipe_EM(); + + addClassicOutputs_EM(); + + updateSlots(); + mProgresstime = 0; + mMaxProgresstime = 0; + mEfficiencyIncrease = 0; + + if (aBaseMetaTileEntit