aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity')
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ChiselBus.java78
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_AirIntake.java128
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_AirIntake_Extreme.java37
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_DynamoBuffer.java67
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_ElementalDataOrbHolder.java229
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_FluidGenerator.java255
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBattery.java235
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Muffler_Adv.java370
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Naquadah.java203
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_OutputBattery.java222
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Reservoir.java75
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Solidifier.java72
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Steam_BusInput.java279
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Steam_BusOutput.java215
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Turbine.java435
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_TurbineProvider.java221
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_SuperBus_Input.java65
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_SuperBus_Output.java105
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaPipeEntityFluid.java117
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaPipeEntity_Cable.java156
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaTreeFarmerStructural.java49
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GT_MetaTileEntity_Hatch_CustomFluidBase.java214
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMetaTileEntity.java74
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMetaTransformerHiAmp.java117
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java1799
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_SteamMultiBase.java428
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechMetaBoilerBase.java361
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechMetaSolarGenerator.java241
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechRocketFuelGeneratorBase.java338
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/machines/GregtechMetaTreeFarmerBase.java180
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_Catalysts.java71
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_MillingBalls.java71
-rw-r--r--src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_NbtConsumable.java353
33 files changed, 7860 insertions, 0 deletions
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ChiselBus.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ChiselBus.java
new file mode 100644
index 0000000000..3009c80c80
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_ChiselBus.java
@@ -0,0 +1,78 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.util.EnumChatFormatting;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.Scrollable;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddUIWidgets;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+
+public class GT_MetaTileEntity_ChiselBus extends GT_MetaTileEntity_Hatch_InputBus implements IAddUIWidgets {
+
+ public GT_MetaTileEntity_ChiselBus(int id, String name, String nameRegional, int tier) {
+ super(id, name, nameRegional, tier);
+ }
+
+ public GT_MetaTileEntity_ChiselBus(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, getSlots(aTier), aDescription, aTextures);
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex < getSlots(this.mTier);
+ }
+
+ public static int getSlots(int aTier) {
+ return (1 + aTier) * 16 + 1;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_ChiselBus(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public boolean allowSelectCircuit() {
+ return false;
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "Item Input Bus for Industrial Chisel", getSlots(this.mTier) - 1 + " + 1 " + " Slots",
+ "Added by: " + EnumChatFormatting.AQUA
+ + "Quetz4l"
+ + " - "
+ + EnumChatFormatting.RED
+ + "[GT++]"
+ + EnumChatFormatting.RESET };
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ int slotIndex = 0;
+ final Scrollable scrollable = new Scrollable().setVerticalScroll();
+ for (int row = 0; row * 4 < inventoryHandler.getSlots() - 1; row++) {
+ int columnsToMake = Math.min(inventoryHandler.getSlots() - row * 4, 4);
+ for (int column = 0; column < columnsToMake; column++) {
+ scrollable.widget(
+ new SlotWidget(inventoryHandler, slotIndex++).setPos(column * 18, row * 18)
+ .setSize(18, 18));
+
+ }
+ }
+
+ builder.widget(
+ scrollable.setSize(18 * 4 + 4, 18 * 4)
+ .setPos(52, 7)); // main slots
+ builder.widget(
+ new SlotWidget(inventoryHandler, slotIndex).setPos(18, 18)
+ .setSize(18, 18)); // slot for target
+ }
+
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_AirIntake.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_AirIntake.java
new file mode 100644
index 0000000000..bab504910e
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_AirIntake.java
@@ -0,0 +1,128 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.FluidUtils;
+
+public class GT_MetaTileEntity_Hatch_AirIntake extends GT_MetaTileEntity_Hatch_FluidGenerator {
+
+ public GT_MetaTileEntity_Hatch_AirIntake(final int aID, final String aName, final String aNameRegional,
+ final int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_Hatch_AirIntake(final String aName, final int aTier, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_AirIntake(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public String[] getCustomTooltip() {
+ String[] aTooltip = new String[3];
+ aTooltip[0] = "DO NOT OBSTRUCT THE INPUT!";
+ aTooltip[1] = "Draws in Air from the surrounding environment";
+ aTooltip[2] = "Creates " + getAmountOfFluidToGenerate() + "L of Air every " + getMaxTickTime() + " ticks";
+ return aTooltip;
+ }
+
+ @Override
+ public Fluid getFluidToGenerate() {
+ return FluidUtils.getAir(1)
+ .getFluid();
+ }
+
+ @Override
+ public int getAmountOfFluidToGenerate() {
+ return 1000;
+ }
+
+ @Override
+ public int getMaxTickTime() {
+ return 4;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 128000;
+ }
+
+ @Override
+ public boolean doesHatchMeetConditionsToGenerate() {
+ return this.getBaseMetaTileEntity()
+ .getAirAtSide(
+ this.getBaseMetaTileEntity()
+ .getFrontFacing());
+ }
+
+ @Override
+ public void generateParticles(World aWorld, String name) {
+ if (this.getBaseMetaTileEntity()
+ .isServerSide()) {
+ return;
+ }
+ final float ran1 = GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat();
+ float ran2 = 0.0f;
+ float ran3 = 0.0f;
+ ran2 = GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat();
+ ran3 = GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat();
+
+ final IGregTechTileEntity aMuffler = this.getBaseMetaTileEntity();
+ final ForgeDirection aDir = aMuffler.getFrontFacing();
+ final float xPos = aDir.offsetX * 0.76f + aMuffler.getXCoord() + 0.25f;
+ float yPos = aDir.offsetY * 0.76f + aMuffler.getYCoord() + 0.65f;
+ final float zPos = aDir.offsetZ * 0.76f + aMuffler.getZCoord() + 0.25f;
+ float ySpd = aDir.offsetY * 0.1f + 0.2f + 0.1f * GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat();
+ float xSpd;
+ float zSpd;
+ if (aDir.offsetY == -1) {
+ // Logger.INFO("Y = -1");
+ final float temp = GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat() * 2.0f * CORE.PI;
+ xSpd = (float) Math.sin(temp) * 0.1f;
+ zSpd = (float) Math.cos(temp) * 0.1f;
+ ySpd = -ySpd;
+ yPos = yPos - 0.8f;
+ } else {
+ xSpd = aDir.offsetX * (0.1f + 0.2f * GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat());
+ zSpd = aDir.offsetZ * (0.1f + 0.2f * GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat());
+
+ xSpd = -xSpd;
+ zSpd = -zSpd;
+ }
+
+ aWorld.spawnParticle(
+ name,
+ (double) (xPos + ran1 * 0.5f),
+ (double) (yPos + GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat() * 0.5f),
+ (double) (zPos + GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat() * 0.5f),
+ (double) xSpd,
+ (double) -ySpd,
+ (double) zSpd);
+ aWorld.spawnParticle(
+ name,
+ (double) (xPos + ran2 * 0.5f),
+ (double) (yPos + GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat() * 0.5f),
+ (double) (zPos + GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat() * 0.5f),
+ (double) xSpd,
+ (double) -ySpd,
+ (double) zSpd);
+ aWorld.spawnParticle(
+ name,
+ (double) (xPos + ran3 * 0.5f),
+ (double) (yPos + GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat() * 0.5f),
+ (double) (zPos + GT_MetaTileEntity_Hatch_AirIntake.floatGen.nextFloat() * 0.5f),
+ (double) xSpd,
+ (double) -ySpd,
+ (double) zSpd);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_AirIntake_Extreme.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_AirIntake_Extreme.java
new file mode 100644
index 0000000000..007310fc06
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_AirIntake_Extreme.java
@@ -0,0 +1,37 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+
+public class GT_MetaTileEntity_Hatch_AirIntake_Extreme extends GT_MetaTileEntity_Hatch_AirIntake {
+
+ public GT_MetaTileEntity_Hatch_AirIntake_Extreme(final int aID, final String aName, final String aNameRegional,
+ final int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_Hatch_AirIntake_Extreme(final String aName, final int aTier, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_AirIntake_Extreme(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public int getAmountOfFluidToGenerate() {
+ return 8000;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 256000;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_DynamoBuffer.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_DynamoBuffer.java
new file mode 100644
index 0000000000..f375900800
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_DynamoBuffer.java
@@ -0,0 +1,67 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class GT_MetaTileEntity_Hatch_DynamoBuffer extends GT_MetaTileEntity_Hatch_Dynamo {
+
+ public GT_MetaTileEntity_Hatch_DynamoBuffer(final int aID, final String aName, final String aNameRegional,
+ final int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_Hatch_DynamoBuffer(final String aName, final int aTier, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(final ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TexturesGtBlock.OVERLAYS_ENERGY_OUT_MULTI_BUFFER[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(final ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TexturesGtBlock.OVERLAYS_ENERGY_OUT_MULTI_BUFFER[this.mTier] };
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return 0L;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 512L + GT_Values.V[this.mTier + 1] * 2048L;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_DynamoBuffer(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ String[] g;
+ g = new String[] { "Dynamo with internal storage and additional Amp capacity",
+ "Does not accept more than " + (this.maxEUOutput() * this.maxAmperesIn()) + "EU/t as input",
+ CORE.GT_Tooltip.get() };
+
+ return g;
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return 4;
+ }
+
+ @Override
+ public long maxAmperesOut() {
+ return 4;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_ElementalDataOrbHolder.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_ElementalDataOrbHolder.java
new file mode 100644
index 0000000000..336c6eb011
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_ElementalDataOrbHolder.java
@@ -0,0 +1,229 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import java.util.ArrayList;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.SlotGroup;
+
+import gregtech.api.enums.ItemList;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.IConfigurationCircuitSupport;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.objects.GT_RenderedTexture;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class GT_MetaTileEntity_Hatch_ElementalDataOrbHolder extends GT_MetaTileEntity_Hatch
+ implements IConfigurationCircuitSupport {
+
+ public GT_MetaTileEntity_Hatch_ElementalDataOrbHolder(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 17,
+ new String[] { "Holds Data Orbs for the Elemental Duplicator", "Can insert/extract the circuit slot",
+ "A circuit must be used to select a slot (1-16)", CORE.GT_Tooltip.get() });
+ }
+
+ public GT_MetaTileEntity_Hatch_ElementalDataOrbHolder(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 17, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Hatch_ElementalDataOrbHolder(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 17, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Hatch_Data_Orb) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Hatch_Data_Orb) };
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_ElementalDataOrbHolder(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ fillStacksIntoFirstSlots();
+ }
+ }
+
+ public void updateSlots() {
+ for (int i = 0; i < mInventory.length - 1; i++)
+ if (mInventory[i] != null && mInventory[i].stackSize <= 0) mInventory[i] = null;
+ fillStacksIntoFirstSlots();
+ }
+
+ protected void fillStacksIntoFirstSlots() {
+ for (int i = 0; i < mInventory.length - 1; i++) {
+ if (mInventory[i] != null && mInventory[i].stackSize <= 0) {
+ mInventory[i] = null;
+ }
+ }
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {}
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ Logger.INFO("Checking if we can pull " + aStack.getDisplayName() + " from slot " + aIndex);
+ if (aIndex == mInventory.length - 1 && ItemUtils.isControlCircuit(aStack)
+ && side == getBaseMetaTileEntity().getFrontFacing()) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ Logger.INFO("Checking if we can put " + aStack.getDisplayName() + " into slot " + aIndex);
+ if (aIndex == mInventory.length - 1 && ItemUtils.isControlCircuit(aStack)
+ && side == getBaseMetaTileEntity().getFrontFacing()) {
+ return true;
+ }
+ return false;
+ }
+
+ public ArrayList<ItemStack> getInventory() {
+ ArrayList<ItemStack> aContents = new ArrayList<>();
+ for (int i = getBaseMetaTileEntity().getSizeInventory() - 2; i >= 0; i--) {
+ if (getBaseMetaTileEntity().getStackInSlot(i) != null)
+ aContents.add(getBaseMetaTileEntity().getStackInSlot(i));
+ }
+ return aContents;
+ }
+
+ public ItemStack getOrbByCircuit() {
+ ItemStack aCirc = getBaseMetaTileEntity().getStackInSlot(getCircuitSlot());
+ if (aCirc != null && ItemUtils.isControlCircuit(aCirc)) {
+ int slot = aCirc.getItemDamage() - 1; // slots are 0 indexed but there's no 0 circuit
+ if (slot < getBaseMetaTileEntity().getSizeInventory() - 1) {
+ return getBaseMetaTileEntity().getStackInSlot(slot);
+ } else {
+ return null;
+ }
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public boolean canInsertItem(int aIndex, ItemStack aStack, int ordinalSide) {
+ if (aIndex == mInventory.length - 1 && ItemUtils.isControlCircuit(aStack)
+ && ordinalSide == getBaseMetaTileEntity().getFrontFacing()
+ .ordinal()) {
+ Logger.INFO("Putting " + aStack.getDisplayName() + " into slot " + aIndex);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean canExtractItem(int aIndex, ItemStack aStack, int ordinalSide) {
+ if (aIndex == mInventory.length - 1 && ItemUtils.isControlCircuit(aStack)) {
+ Logger.INFO("Pulling " + aStack.getDisplayName() + " from slot " + aIndex);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean allowSelectCircuit() {
+ return true;
+ }
+
+ @Override
+ public int getCircuitSlot() {
+ return getSlots(mTier);
+ }
+
+ @Override
+ public int getCircuitSlotX() {
+ return 153;
+ }
+
+ @Override
+ public int getCircuitSlotY() {
+ return 63;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 4)
+ .startFromSlot(0)
+ .endAtSlot(15)
+ .background(getGUITextureSet().getItemSlot(), GT_UITextures.OVERLAY_SLOT_DATA_ORB)
+ .applyForWidget(
+ widget -> widget.setFilter(stack -> ItemList.Tool_DataOrb.isStackEqual(stack, false, true)))
+ .build()
+ .setPos(52, 7));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_FluidGenerator.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_FluidGenerator.java
new file mode 100644
index 0000000000..b4e213e829
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_FluidGenerator.java
@@ -0,0 +1,255 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.objects.XSTR;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.FluidUtils;
+
+public abstract class GT_MetaTileEntity_Hatch_FluidGenerator extends GT_MetaTileEntity_Hatch_Input {
+
+ protected static XSTR floatGen = new XSTR();
+ public int mProgresstime = 0, mMaxProgresstime = 0;
+
+ public GT_MetaTileEntity_Hatch_FluidGenerator(final int aID, final String aName, final String aNameRegional,
+ final int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_Hatch_FluidGenerator(final String aName, final int aTier, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public abstract String[] getCustomTooltip();
+
+ public abstract Fluid getFluidToGenerate();
+
+ public abstract int getAmountOfFluidToGenerate();
+
+ public abstract int getMaxTickTime();
+
+ @Override
+ public synchronized String[] getDescription() {
+ mDescriptionArray[1] = "Capacity: " + GT_Utility.formatNumbers(getCapacity()) + "L";
+ final String[] hatchTierString = new String[] { "Hatch Tier: " + GT_Utility.getColoredTierNameFromTier(mTier) };
+
+ String[] aCustomTips = getCustomTooltip();
+ final String[] desc = new String[mDescriptionArray.length + aCustomTips.length + 2];
+ System.arraycopy(mDescriptionArray, 0, desc, 0, mDescriptionArray.length);
+ System.arraycopy(hatchTierString, 0, desc, mDescriptionArray.length, 1);
+ System.arraycopy(aCustomTips, 0, desc, mDescriptionArray.length + 1, aCustomTips.length);
+ desc[mDescriptionArray.length + aCustomTips.length] = CORE.GT_Tooltip.get();
+ return desc;
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(final ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture,
+ new GT_RenderedTexture((IIconContainer) Textures.BlockIcons.OVERLAY_MUFFLER) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(final ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture,
+ new GT_RenderedTexture((IIconContainer) Textures.BlockIcons.OVERLAY_MUFFLER) };
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(final ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(final EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(final int aIndex) {
+ return false;
+ }
+
+ @Override
+ public abstract MetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity);
+
+ public boolean allowPullStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ return false;
+ }
+
+ public boolean allowPutStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void onPostTick(final IGregTechTileEntity aBaseMetaTileEntity, final long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (!aBaseMetaTileEntity.isAllowedToWork()) {
+ aBaseMetaTileEntity.setActive(false);
+ mProgresstime = 0;
+ mMaxProgresstime = 0;
+ } else {
+ aBaseMetaTileEntity.setActive(true);
+ mMaxProgresstime = getMaxTickTime();
+ if (++mProgresstime >= mMaxProgresstime) {
+ if (this.canTankBeFilled()) {
+ addFluidToHatch(aTick);
+ }
+ mProgresstime = 0;
+ }
+ }
+ }
+
+ @Override
+ public int getProgresstime() {
+ return mProgresstime;
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return mMaxProgresstime;
+ }
+
+ @Override
+ public int increaseProgress(int aProgress) {
+ mProgresstime += aProgress;
+ return mMaxProgresstime - mProgresstime;
+ }
+
+ public abstract void generateParticles(final World aWorld, final String name);
+
+ @Override
+ public int getTankPressure() {
+ return 100;
+ }
+
+ @Override
+ public abstract int getCapacity();
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+ public abstract boolean doesHatchMeetConditionsToGenerate();
+
+ public boolean addFluidToHatch(long aTick) {
+ if (!doesHatchMeetConditionsToGenerate()) {
+ return false;
+ }
+ int aFillAmount = this.fill(FluidUtils.getFluidStack(getFluidToGenerate(), getAmountOfFluidToGenerate()), true);
+ if (aFillAmount > 0) {
+ if (this.getBaseMetaTileEntity()
+ .isClientSide()) {
+ generateParticles(
+ this.getBaseMetaTileEntity()
+ .getWorld(),
+ "cloud");
+ }
+ }
+ return aFillAmount > 0;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return true;
+ }
+
+ @Override
+ public int fill(FluidStack aFluid, boolean doFill) {
+ if (aFluid == null || aFluid.getFluid()
+ .getID() <= 0 || aFluid.amount <= 0 || aFluid.getFluid() != getFluidToGenerate() || !canTankBeFilled()) {
+ return 0;
+ }
+
+ if (getFillableStack() == null || getFillableStack().getFluid()
+ .getID() <= 0) {
+ if (aFluid.amount <= getCapacity()) {
+ if (doFill) {
+ setFillableStack(aFluid.copy());
+ getBaseMetaTileEntity().markDirty();
+ }
+ return aFluid.amount;
+ }
+ if (doFill) {
+ setFillableStack(aFluid.copy());
+ getFillableStack().amount = getCapacity();
+ getBaseMetaTileEntity().markDirty();
+ }
+ return getCapacity();
+ }
+
+ if (!getFillableStack().isFluidEqual(aFluid)) return 0;
+
+ int space = getCapacity() - getFillableStack().amount;
+ if (aFluid.amount <= space) {
+ if (doFill) {
+ getFillableStack().amount += aFluid.amount;
+ getBaseMetaTileEntity().markDirty();
+ }
+ return aFluid.amount;
+ }
+ if (doFill) getFillableStack().amount = getCapacity();
+ return space;
+ }
+
+ @Override
+ public boolean canFill(ForgeDirection aSide, Fluid aFluid) {
+ return false;
+ }
+
+ @Override
+ public int fill(ForgeDirection arg0, FluidStack arg1, boolean arg2) {
+ return 0;
+ }
+
+ @Override
+ public int fill_default(ForgeDirection aSide, FluidStack aFluid, boolean doFill) {
+ return 0;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("mProgresstime", mProgresstime);
+ aNBT.setInteger("mMaxProgresstime", mMaxProgresstime);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ mProgresstime = aNBT.getInteger("mProgresstime");
+ mMaxProgresstime = aNBT.getInteger("mMaxProgresstime");
+ super.loadNBTData(aNBT);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBattery.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBattery.java
new file mode 100644
index 0000000000..c55ddda47d
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_InputBattery.java
@@ -0,0 +1,235 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import static gregtech.api.enums.GT_Values.V;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.xmod.gregtech.api.gui.widget.ElectricSlotWidget;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class GT_MetaTileEntity_Hatch_InputBattery extends GT_MetaTileEntity_Hatch {
+
+ public final RecipeMap<?> mRecipeMap = null;
+
+ public GT_MetaTileEntity_Hatch_InputBattery(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, getSlots(aTier), "Chargeable Item Bus for Multiblocks");
+ }
+
+ public GT_MetaTileEntity_Hatch_InputBattery(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aTier < 1 ? 1 : aTier == 1 ? 4 : aTier == 2 ? 4 : 16, aDescription, aTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ int mSlots = 0;
+ if (this.mTier == 2) {
+ mSlots = 4;
+ } else if (this.mTier == 4) {
+ mSlots = 16;
+ } else {
+ mSlots = 16;
+ }
+ return ArrayUtils.addAll(this.mDescriptionArray, "Capacity: " + mSlots + " slots", CORE.GT_Tooltip.get());
+ }
+
+ @Override
+ public boolean isEnetInput() {
+ return true;
+ }
+
+ @Override
+ public boolean isInputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return 0;
+ }
+
+ @Override
+ public long maxEUInput() {
+ return V[mTier];
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 512 + V[mTier + 1] * 16;
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return 4;
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Hatch_Charger) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Hatch_Charger) };
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_InputBattery(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ fillStacksIntoFirstSlots();
+ }
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (aBaseMetaTileEntity.getMetaTileEntity() instanceof MetaTileEntity mMetaTileEntity) {
+ if (mMetaTileEntity.rechargerSlotCount() > 0 && aBaseMetaTileEntity.getStoredEU() > 0) {
+ for (int i = mMetaTileEntity.rechargerSlotStartIndex(),
+ k = mMetaTileEntity.rechargerSlotCount() + i; i < k; i++) {
+ if (aBaseMetaTileEntity.getStoredEU() > 0 && mMetaTileEntity.mInventory[i] != null) {
+ for (int u = 0; u < 10; u++) {
+ aBaseMetaTileEntity.decreaseStoredEnergyUnits(
+ GT_ModHandler.chargeElectricItem(
+ mMetaTileEntity.mInventory[i],
+ (int) Math.min(V[this.mTier] * 15, aBaseMetaTileEntity.getStoredEU()),
+ (int) Math.min(Integer.MAX_VALUE, GT_Values.V[u]),
+ false,
+ false),
+ true);
+ if (mMetaTileEntity.mInventory[i].stackSize <= 0) {
+ mMetaTileEntity.mInventory[i] = null;
+ }
+ }
+ }
+ }
+ } else {}
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+ }
+
+ public void updateSlots() {
+ for (int i = 0; i < mInventory.length; i++)
+ if (mInventory[i] != null && mInventory[i].stackSize <= 0) mInventory[i] = null;
+ fillStacksIntoFirstSlots();
+ }
+
+ protected void fillStacksIntoFirstSlots() {
+ for (int i = 0; i < mInventory.length; i++)
+ for (int j = i + 1; j < mInventory.length; j++) if (mInventory[j] != null
+ && (mInventory[i] == null || GT_Utility.areStacksEqual(mInventory[i], mInventory[j]))) {
+ GT_Utility.moveStackFromSlotAToSlotB(
+ getBaseMetaTileEntity(),
+ getBaseMetaTileEntity(),
+ j,
+ i,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ }
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == getBaseMetaTileEntity().getFrontFacing()
+ && (mRecipeMap == null || mRecipeMap.containsInput(aStack));
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == getBaseMetaTileEntity().getFrontFacing()
+ && (mRecipeMap == null || mRecipeMap.containsInput(aStack));
+ }
+
+ @Override
+ public int rechargerSlotStartIndex() {
+ return 0;
+ }
+
+ @Override
+ public int rechargerSlotCount() {
+ return switch (mTier) {
+ case 2 -> 4;
+ case 4 -> 16;
+ default -> 16;
+ };
+ }
+
+ @Override
+ public int dechargerSlotStartIndex() {
+ return 0;
+ }
+
+ @Override
+ public int dechargerSlotCount() {
+ return 0;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ if (mTier == 2) {
+ for (int i = 0; i < 4; i++) {
+ builder
+ .widget(new ElectricSlotWidget(inventoryHandler, i).setPos(70 + (i % 2) * 18, 25 + (i / 2) * 18));
+ }
+ } else {
+ for (int i = 0; i < 16; i++) {
+ builder.widget(new ElectricSlotWidget(inventoryHandler, i).setPos(52 + (i % 4) * 18, 7 + (i / 4) * 18));
+ }
+ }
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Muffler_Adv.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Muffler_Adv.java
new file mode 100644
index 0000000000..a3261af6f6
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Muffler_Adv.java
@@ -0,0 +1,370 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.GT_Mod;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GUITextureSet;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_MultiBlockBase;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.util.GT_Config;
+import gregtech.common.GT_Pollution;
+import gtPlusPlus.core.item.general.ItemAirFilter;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.gregtech.PollutionUtils;
+import gtPlusPlus.xmod.gregtech.api.gui.GTPP_UITextures;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class GT_MetaTileEntity_Hatch_Muffler_Adv extends GT_MetaTileEntity_Hatch_Muffler implements IAddGregtechLogo {
+
+ protected int SLOT_FILTER = 0;
+
+ @Override
+ public void onConfigLoad(GT_Config aConfig) {
+ super.onConfigLoad(aConfig);
+ try {
+ int a1 = GT_Mod.gregtechproxy.mPollutionSmogLimit;
+ if (a1 > 0) {
+ mPollutionSmogLimit = a1;
+ }
+ } catch (Throwable t) {
+ mPollutionSmogLimit = 500000;
+ }
+ }
+
+ private int mPollutionSmogLimit = 500000;
+
+ public GT_MetaTileEntity_Hatch_Muffler_Adv(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, 1, new String[] { "" });
+ }
+
+ public GT_MetaTileEntity_Hatch_Muffler_Adv(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures);
+ }
+
+ final String[] mDescription = new String[] { "Outputs pollution from a multiblock", "DO NOT OBSTRUCT THE OUTPUT!",
+ "Requires 3 Air Blocks in front of the exhaust face",
+ mTier < 5 ? "Requires an Air Filter"
+ : "Requires an Air Filter " + EnumChatFormatting.WHITE + "[Tier 2]" + EnumChatFormatting.GRAY,
+ "Can take Air Filters from an input bus of the multiblock",
+ "Reduces Pollution to " + calculatePollutionReduction(100, true) + "%",
+ "Recovers " + (100 - calculatePollutionReduction(100, true)) + "% of CO2/CO/SO2", CORE.GT_Tooltip.get() };
+
+ @Override
+ public String[] getDescription() {
+ return mDescription;
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Hatch_Muffler_Adv) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Hatch_Muffler_Adv) };
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return aIndex == SLOT_FILTER;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return (aIndex == this.SLOT_FILTER && isAirFilter(aStack));
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Muffler_Adv(this.mName, this.mTier, mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public boolean polluteEnvironment(MetaTileEntity parentTileEntity) {
+ if (!airCheck()) return false; // Muffler obstructed.
+
+ int emission = 10000;
+ if (damageAirFilter(parentTileEntity)) {
+ // damageAirFilter already checks that we have a valid filter.
+ emission = calculatePollutionReduction(emission, true);
+ } else {
+ // Revert to reduction of the basic muffler.
+ emission = super.calculatePollutionReduction(emission);
+ }
+ GT_Pollution.addPollution(getBaseMetaTileEntity(), emission);
+ return true;
+ }
+
+ @Override
+ public int calculatePollutionReduction(int aPollution) {
+ // This is called by EBF to calculate exhaust gas amounts, we need to check the filter.
+ return calculatePollutionReduction(aPollution, false);
+ }
+
+ /**
+ * Calculates pollution reduction.
+ *
+ * @param aPollution Amount of pollution to be reduced.
+ * @param ignoreFilter If this is true, assumes that a valid filter is present without checking (for example, to
+ * build tooltips).
+ * @return Amount of pollution after reduction.
+ */
+ protected int calculatePollutionReduction(int aPollution, boolean ignoreFilter) {
+ if (!ignoreFilter && !hasAirFilter()) {
+ // Without a filter, downgrade to basic muffler reduction.
+ return super.calculatePollutionReduction(aPollution);
+ }
+
+ // Special case to be always better than a basic muffler.
+ if (mTier < 2) return (int) (aPollution * 0.95);
+ if (mTier > 8) return 0;
+
+ return (int) (aPollution * Math.pow(0.64D, mTier - 1));
+ }
+
+ /**
+ *
+ * @return True if enough blocks in front of the muffler are air.
+ */
+ private boolean airCheck() {
+ IGregTechTileEntity bmte = getBaseMetaTileEntity();
+ ForgeDirection facing = bmte.getFrontFacing();
+ return bmte.getAirAtSide(facing) && bmte.getAirAtSideAndDistance(facing, 1)
+ && bmte.getAirAtSideAndDistance(facing, 2);
+ }
+
+ /**
+ * Try to damage an air filter. Will first try to find a valid filter in the hatch's own inventory, then in the
+ * input buses of the parent multiblock. If the filter is destroyed, will try to replace it from the parent
+ * multiblock's input buses again.
+ *
+ * @param parentTileEntity Which multiblock this hatch is a part of. If this is null, only checks inventory of the
+ * muffler.
+ * @return True if the filter has been successfully damaged.
+ */
+ private boolean damageAirFilter(MetaTileEntity parentTileEntity) {
+ if (!findAirFilter(parentTileEntity)) return false; // No filter available.
+
+ ItemStack filter = mInventory[SLOT_FILTER];
+ if (filter == null) return false; // This should never happen if findAirFilter() above succeeded.
+
+ long currentDamage = ItemAirFilter.getFilterDamage(filter);
+ if (currentDamage < ItemAirFilter.getFilterMaxDamage(filter) - 1) {
+ // Damage filter by one step.
+ ItemAirFilter.setFilterDamage(filter, currentDamage + 1);
+ return true;
+ } else {
+ // Destroy the filter.
+ mInventory[SLOT_FILTER] = null;
+
+ // Try to find a new one.
+ findAirFilter(parentTileEntity);
+
+ // Regardless of whether we have a new filter or not, *this* operation succeeded.
+ return true;
+ }
+ }
+
+ /**
+ * Try to find a valid air filter in the input buses of the parent multiblock.
+ *
+ * @param parentTileEntity Which multiblock this hatch is a part of. If this is null, only checks inventory of the
+ * muffler.
+ * @return True if the inventory of the muffler already contains an air filter, or if one was retrieved from the
+ * parent multiblock.
+ */
+ private boolean findAirFilter(MetaTileEntity parentTileEntity) {
+ if (hasAirFilter()) return true; // Has a filter in inventory.
+ if (mInventory[SLOT_FILTER] != null) return false; // Has a non-filter item in inventory.
+ if (parentTileEntity == null) return false; // Unknown parent multiblock.
+
+ if (parentTileEntity instanceof GT_MetaTileEntity_MultiBlockBase GTMultiBase) {
+ for (var inputBus : GTMultiBase.mInputBusses) {
+ for (ItemStack stack : inputBus.mInventory) {
+ if (isAirFilter(stack)) {
+ ItemStack stackCopy = stack.copy();
+ if (GTMultiBase.depleteInput(stack)) {
+ mInventory[SLOT_FILTER] = stackCopy;
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ *
+ * @return True if the item currently in the inventory is an air filter valid for this tier of muffler hatch.
+ */
+ private boolean hasAirFilter() {
+ return isAirFilter(mInventory[SLOT_FILTER]);
+ }
+
+ /**
+ *
+ * @param filter
+ * @return True if the argument is an air filter valid for this tier of muffler hatch.
+ */
+ public boolean isAirFilter(ItemStack filter) {
+ if (filter == null) return false;
+ if (filter.getItem() instanceof ItemAirFilter) {
+ if (mTier < 5) {
+ // Accept any filter.
+ return true;
+ } else {
+ // Accept only T2 filter.
+ return filter.getItemDamage() == 1;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+
+ if (aBaseMetaTileEntity.isClientSide()) {
+ if (this.getBaseMetaTileEntity()
+ .isActive()) {
+ String aParticleName;
+ if ((aTick % 2) == 0) {
+ aParticleName = "cloud";
+ } else {
+ aParticleName = "smoke";
+ }
+ this.pollutionParticles(
+ this.getBaseMetaTileEntity()
+ .getWorld(),
+ aParticleName);
+ }
+ }
+ }
+
+ @Override
+ public void pollutionParticles(World aWorld, String name) {
+ float ran1 = CORE.RANDOM.nextFloat();
+ float ran2 = 0.0F;
+ float ran3 = 0.0F;
+ boolean chk1 = ran1 * 100.0F < (float) this.calculatePollutionReduction(100);
+ boolean chk2;
+ boolean chk3;
+ int aPollutionAmount = PollutionUtils.getPollution(getBaseMetaTileEntity());
+ if (aPollutionAmount >= mPollutionSmogLimit) {
+ ran2 = CORE.RANDOM.nextFloat();
+ ran3 = CORE.RANDOM.nextFloat();
+ chk2 = ran2 * 100.0F < (float) this.calculatePollutionReduction(100);
+ chk3 = ran3 * 100.0F < (float) this.calculatePollutionReduction(100);
+ if (!chk1 && !chk2 && !chk3) {
+ return;
+ }
+ } else {
+ if (!chk1) {
+ return;
+ }
+
+ chk3 = false;
+ chk2 = false;
+ }
+
+ IGregTechTileEntity aMuffler = this.getBaseMetaTileEntity();
+ ForgeDirection aDir = aMuffler.getFrontFacing();
+ float xPos = (float) aDir.offsetX * 0.76F + (float) aMuffler.getXCoord() + 0.25F;
+ float yPos = (float) aDir.offsetY * 0.76F + (float) aMuffler.getYCoord() + 0.25F;
+ float zPos = (float) aDir.offsetZ * 0.76F + (float) aMuffler.getZCoord() + 0.25F;
+ float ySpd = (float) aDir.offsetY * 0.1F + 0.2F + 0.1F * CORE.RANDOM.nextFloat();
+ float xSpd;
+ float zSpd;
+ if (aDir.offsetY == -1) {
+ float temp = CORE.RANDOM.nextFloat() * 2.0F * CORE.PI;
+ xSpd = (float) Math.sin((double) temp) * 0.1F;
+ zSpd = (float) Math.cos((double) temp) * 0.1F;
+ } else {
+ xSpd = (float) aDir.offsetX * (0.1F + 0.2F * CORE.RANDOM.nextFloat());
+ zSpd = (float) aDir.offsetZ * (0.1F + 0.2F * CORE.RANDOM.nextFloat());
+ }
+
+ if (chk1) {
+ aWorld.spawnParticle(
+ name,
+ (double) (xPos + ran1 * 0.5F),
+ (double) (yPos + CORE.RANDOM.nextFloat() * 0.5F),
+ (double) (zPos + CORE.RANDOM.nextFloat() * 0.5F),
+ (double) xSpd,
+ (double) ySpd,
+ (double) zSpd);
+ }
+
+ if (chk2) {
+ aWorld.spawnParticle(
+ name,
+ (double) (xPos + ran2 * 0.5F),
+ (double) (yPos + CORE.RANDOM.nextFloat() * 0.5F),
+ (double) (zPos + CORE.RANDOM.nextFloat() * 0.5F),
+ (double) xSpd,
+ (double) ySpd,
+ (double) zSpd);
+ }
+
+ if (chk3) {
+ aWorld.spawnParticle(
+ name,
+ (double) (xPos + ran3 * 0.5F),
+ (double) (yPos + CORE.RANDOM.nextFloat() * 0.5F),
+ (double) (zPos + CORE.RANDOM.nextFloat() * 0.5F),
+ (double) xSpd,
+ (double) ySpd,
+ (double) zSpd);
+ }
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addGregTechLogo(ModularWindow.Builder builder) {}
+
+ @Override
+ public GUITextureSet getGUITextureSet() {
+ return new GUITextureSet().setMainBackground(GTPP_UITextures.BACKGROUND_YELLOW)
+ .setItemSlot(GTPP_UITextures.SLOT_ITEM_YELLOW)
+ .setTitleTab(
+ GTPP_UITextures.TAB_TITLE_YELLOW,
+ GTPP_UITextures.TAB_TITLE_DARK_YELLOW,
+ GTPP_UITextures.TAB_TITLE_ANGULAR_YELLOW);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new SlotWidget(inventoryHandler, 0).setFilter(stack -> stack.getItem() instanceof ItemAirFilter)
+ .setBackground(getGUITextureSet().getItemSlot())
+ .setPos(79, 34));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Naquadah.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Naquadah.java
new file mode 100644
index 0000000000..ad94907d4c
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Naquadah.java
@@ -0,0 +1,203 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import java.lang.reflect.Field;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.reflect.ReflectionUtils;
+
+public class GT_MetaTileEntity_Hatch_Naquadah extends GT_MetaTileEntity_Hatch_Input {
+
+ public final FluidStack[] mFluidsToUse = new FluidStack[3];
+ public final int mFluidCapacity;
+
+ public GT_MetaTileEntity_Hatch_Naquadah(final int aID, final String aName, final String aNameRegional) {
+ super(aID, aName, aNameRegional, 6);
+ mFluidCapacity = 32000;
+ initHatch();
+ }
+
+ public GT_MetaTileEntity_Hatch_Naquadah(final String aName, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, 6, aDescription[0], aTextures);
+ mFluidCapacity = 32000;
+ initHatch();
+ }
+
+ private void initHatch() {
+ if (mFluidsToUse[0] == null) {
+ mFluidsToUse[0] = Materials.Naquadah.getMolten(1);
+ }
+ if (mFluidsToUse[1] == null) {
+ mFluidsToUse[1] = Materials.NaquadahEnriched.getMolten(1);
+ }
+ if (mFluidsToUse[2] == null) {
+ mFluidsToUse[2] = Materials.Naquadria.getMolten(1);
+ }
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(final ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture,
+ new GT_RenderedTexture((IIconContainer) Textures.BlockIcons.NAQUADAH_REACTOR_FLUID_SIDE_ACTIVE) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(final ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture,
+ new GT_RenderedTexture((IIconContainer) Textures.BlockIcons.NAQUADAH_REACTOR_FLUID_SIDE) };
+ }
+
+ public boolean allowPutStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ if (side == aBaseMetaTileEntity.getFrontFacing() && aIndex == 0) {
+ for (FluidStack f : mFluidsToUse) {
+ if (f != null) {
+ if (GT_Utility.getFluidForFilledItem(aStack, true)
+ .getFluid() == f.getFluid()) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(final FluidStack aFluid) {
+ for (FluidStack f : mFluidsToUse) {
+ if (f != null) {
+ if (aFluid.getFluid() == f.getFluid()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public int getCapacity() {
+ return this.mFluidCapacity;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Naquadah(this.mName, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ if (aDescCache[0] == null || aDescCache[0].contains(".name") || aDescCache[0].contains("fluid.")) {
+ aDescCache[0] = formatFluidString(this.mFluidsToUse[0]);
+ }
+ if (aDescCache[1] == null || aDescCache[1].contains(".name") || aDescCache[1].contains("fluid.")) {
+ aDescCache[1] = formatFluidString(this.mFluidsToUse[1]);
+ }
+ if (aDescCache[2] == null || aDescCache[2].contains(".name") || aDescCache[2].contains("fluid.")) {
+ aDescCache[2] = formatFluidString(this.mFluidsToUse[2]);
+ }
+ String aNaq = aDescCache[0];
+ String aEnrNaq = aDescCache[1];
+ String aNaquad = aDescCache[2];
+ String[] s2 = new String[] { "Fluid Input for Multiblocks", "Capacity: " + getCapacity() + "L",
+ "Accepted Fluid: " + aNaq, "Accepted Fluid: " + aEnrNaq, "Accepted Fluid: " + aNaquad,
+ CORE.GT_Tooltip.get() };
+ return s2;
+ }
+
+ private static String[] aDescCache = new String[3];
+
+ private String formatFluidString(FluidStack f) {
+ FluidStack mLockedStack = f;
+ Integer mLockedTemp = 0;;
+ String mTempMod = "" + EnumChatFormatting.RESET;
+ mLockedTemp = mLockedStack.getFluid()
+ .getTemperature();
+ if (mLockedTemp != null) {
+ if (mLockedTemp <= -3000) {
+ mTempMod = "" + EnumChatFormatting.DARK_PURPLE;
+ } else if (mLockedTemp >= -2999 && mLockedTemp <= -500) {
+ mTempMod = "" + EnumChatFormatting.DARK_BLUE;
+ } else if (mLockedTemp >= -499 && mLockedTemp <= -50) {
+ mTempMod = "" + EnumChatFormatting.BLUE;
+ } else if (mLockedTemp >= 30 && mLockedTemp <= 300) {
+ mTempMod = "" + EnumChatFormatting.AQUA;
+ } else if (mLockedTemp >= 301 && mLockedTemp <= 800) {
+ mTempMod = "" + EnumChatFormatting.YELLOW;
+ } else if (mLockedTemp >= 801 && mLockedTemp <= 1500) {
+ mTempMod = "" + EnumChatFormatting.GOLD;
+ } else if (mLockedTemp >= 1501) {
+ mTempMod = "" + EnumChatFormatting.RED;
+ }
+ }
+ return mTempMod + mLockedStack.getLocalizedName();
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return false;
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ // TODO Auto-generated method stub
+ return super.getTextureSet(aTextures);
+ }
+
+ private Field F1, F2;
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int aColorIndex, boolean aActive, boolean aRedstone) {
+ byte a1 = 0, a2 = 0;
+ try {
+ if (F1 == null) {
+ F1 = ReflectionUtils.getField(getClass(), "actualTexture");
+ }
+ if (F2 == null) {
+ F2 = ReflectionUtils.getField(getClass(), "mTexturePage");
+ }
+
+ if (F1 != null) {
+ a1 = F1.getByte(this);
+ }
+ if (F2 != null) {
+ a2 = F2.getByte(this);
+ }
+ } catch (IllegalArgumentException | IllegalAccessException n) {}
+
+ int textureIndex = a1 | a2 << 7;
+ byte texturePointer = (byte) (a1 & 127);
+
+ if (side == ForgeDirection.UP || side == ForgeDirection.DOWN) {
+ ITexture g = textureIndex > 0 ? BlockIcons.casingTexturePages[a2][texturePointer]
+ : BlockIcons.MACHINE_CASINGS[this.mTier][aColorIndex + 1];
+
+ return new ITexture[] { g,
+ new GT_RenderedTexture((IIconContainer) Textures.BlockIcons.NAQUADAH_REACTOR_FLUID_TOP_ACTIVE) };
+ }
+
+ return side != facing
+ ? (textureIndex > 0 ? new ITexture[] { BlockIcons.casingTexturePages[a2][texturePointer] }
+ : new ITexture[] { BlockIcons.MACHINE_CASINGS[this.mTier][aColorIndex + 1] })
+ : (textureIndex > 0
+ ? (aActive ? this.getTexturesActive(BlockIcons.casingTexturePages[a2][texturePointer])
+ : this.getTexturesInactive(BlockIcons.casingTexturePages[a2][texturePointer]))
+ : (aActive ? this.getTexturesActive(BlockIcons.MACHINE_CASINGS[this.mTier][aColorIndex + 1])
+ : this.getTexturesInactive(BlockIcons.MACHINE_CASINGS[this.mTier][aColorIndex + 1])));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_OutputBattery.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_OutputBattery.java
new file mode 100644
index 0000000000..58dc7ec380
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_OutputBattery.java
@@ -0,0 +1,222 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import static gregtech.api.enums.GT_Values.V;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.xmod.gregtech.api.gui.widget.ElectricSlotWidget;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class GT_MetaTileEntity_Hatch_OutputBattery extends GT_MetaTileEntity_Hatch {
+
+ public GT_MetaTileEntity_Hatch_OutputBattery(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, getSlots(aTier), "Dischargeable Item Bus for Multiblocks");
+ }
+
+ public GT_MetaTileEntity_Hatch_OutputBattery(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aTier < 1 ? 1 : aTier == 1 ? 4 : aTier == 2 ? 9 : 16, aDescription, aTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ int mSlots = 0;
+ if (this.mTier == 2) {
+ mSlots = 4;
+ } else if (this.mTier == 4) {
+ mSlots = 16;
+ } else {
+ mSlots = 16;
+ }
+ return ArrayUtils.addAll(this.mDescriptionArray, "Capacity: " + mSlots + " slots", CORE.GT_Tooltip.get());
+ }
+
+ @Override
+ public boolean isEnetOutput() {
+ return true;
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return 0;
+ }
+
+ @Override
+ public long maxEUOutput() {
+ return V[mTier];
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 512 + V[mTier + 1] * 8;
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Hatch_Discharger) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Hatch_Discharger) };
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_OutputBattery(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == aBaseMetaTileEntity.getFrontFacing();
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == aBaseMetaTileEntity.getFrontFacing();
+ }
+
+ public void updateSlots() {
+ for (int i = 0; i < mInventory.length; i++)
+ if (mInventory[i] != null && mInventory[i].stackSize <= 0) mInventory[i] = null;
+ fillStacksIntoFirstSlots();
+ }
+
+ protected void fillStacksIntoFirstSlots() {
+ for (int i = 0; i < mInventory.length; i++)
+ for (int j = i + 1; j < mInventory.length; j++) if (mInventory[j] != null
+ && (mInventory[i] == null || GT_Utility.areStacksEqual(mInventory[i], mInventory[j]))) {
+ GT_Utility.moveStackFromSlotAToSlotB(
+ getBaseMetaTileEntity(),
+ getBaseMetaTileEntity(),
+ j,
+ i,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ }
+ }
+
+ @Override
+ public int rechargerSlotStartIndex() {
+ return 0;
+ }
+
+ @Override
+ public int rechargerSlotCount() {
+ return 0;
+ }
+
+ @Override
+ public int dechargerSlotStartIndex() {
+ return 0;
+ }
+
+ @Override
+ public int dechargerSlotCount() {
+ return mTier == 2 ? 4 : 16;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ fillStacksIntoFirstSlots();
+ }
+
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (aBaseMetaTileEntity.getMetaTileEntity() instanceof MetaTileEntity mMetaTileEntity) {
+ if (mMetaTileEntity.dechargerSlotCount() > 0
+ && mMetaTileEntity.getEUVar() < aBaseMetaTileEntity.getEUCapacity()) {
+ for (int i = mMetaTileEntity.dechargerSlotStartIndex(),
+ k = mMetaTileEntity.dechargerSlotCount() + i; i < k; i++) {
+ if (mMetaTileEntity.mInventory[i] != null
+ && mMetaTileEntity.getEUVar() < aBaseMetaTileEntity.getEUCapacity()) {
+ aBaseMetaTileEntity.increaseStoredEnergyUnits(
+ GT_ModHandler.dischargeElectricItem(
+ mMetaTileEntity.mInventory[i],
+ (int) Math.min(
+ V[mTier] * 15,
+ aBaseMetaTileEntity.getEUCapacity() - aBaseMetaTileEntity.getStoredEU()),
+ (int) Math.min(Integer.MAX_VALUE, mMetaTileEntity.getInputTier()),
+ true,
+ false,
+ false),
+ true);
+ if (mMetaTileEntity.mInventory[i].stackSize <= 0) mMetaTileEntity.mInventory[i] = null;
+ }
+ }
+ }
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ if (mTier == 2) {
+ for (int i = 0; i < 4; i++) {
+ builder
+ .widget(new ElectricSlotWidget(inventoryHandler, i).setPos(70 + (i % 2) * 18, 25 + (i / 2) * 18));
+ }
+ } else {
+ for (int i = 0; i < 16; i++) {
+ builder.widget(new ElectricSlotWidget(inventoryHandler, i).setPos(52 + (i % 4) * 18, 7 + (i / 4) * 18));
+ }
+ }
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Reservoir.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Reservoir.java
new file mode 100644
index 0000000000..bfe8290240
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Reservoir.java
@@ -0,0 +1,75 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.world.World;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.objects.GT_RenderedTexture;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class GT_MetaTileEntity_Hatch_Reservoir extends GT_MetaTileEntity_Hatch_FluidGenerator {
+
+ public GT_MetaTileEntity_Hatch_Reservoir(final int aID, final String aName, final String aNameRegional,
+ final int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_Hatch_Reservoir(final String aName, final int aTier, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Reservoir(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public String[] getCustomTooltip() {
+ String[] aTooltip = new String[2];
+ aTooltip[0] = "Infinite water supply hatch";
+ aTooltip[1] = "Fills to max capacity every 5 seconds";
+ return aTooltip;
+ }
+
+ @Override
+ public Fluid getFluidToGenerate() {
+ return FluidRegistry.WATER;
+ }
+
+ @Override
+ public int getAmountOfFluidToGenerate() {
+ return 2_000_000_000;
+ }
+
+ @Override
+ public int getMaxTickTime() {
+ return 100;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 2_000_000_000;
+ }
+
+ @Override
+ public boolean doesHatchMeetConditionsToGenerate() {
+ return true;
+ }
+
+ @Override
+ public void generateParticles(World aWorld, String name) {}
+
+ @Override
+ public ITexture[] getTexturesActive(final ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Water) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(final ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Water) };
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Solidifier.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Solidifier.java
new file mode 100644
index 0000000000..94c28877d8
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Solidifier.java
@@ -0,0 +1,72 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.util.GT_Utility;
+
+public class GT_MetaTileEntity_Hatch_Solidifier extends GT_MetaTileEntity_Hatch_Input {
+
+ static final int moldSlot = 2;
+
+ public GT_MetaTileEntity_Hatch_Solidifier(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] {
+ "Fluid Input with Mold for " + EnumChatFormatting.YELLOW
+ + "Large Processing Factory"
+ + EnumChatFormatting.RESET,
+ "#22 Circuit is imprinted in Hatch", "Capacity: " + GT_Utility.formatNumbers(getCapacity()) + "L",
+ "Added by: " + EnumChatFormatting.AQUA
+ + "Quetz4l"
+ + " - "
+ + EnumChatFormatting.RED
+ + "[GT++]"
+ + EnumChatFormatting.RESET };
+ }
+
+ public GT_MetaTileEntity_Hatch_Solidifier(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, getSlots(aTier), aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Solidifier(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ public ItemStack getMold() {
+ return this.getStackInSlot(moldSlot);
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ builder.widget(
+ new SlotWidget(inventoryHandler, moldSlot).setPos(125, 35)
+ .setSize(18, 18));
+ }
+
+ @Override
+ public void onBlockDestroyed() {
+ super.onBlockDestroyed();
+ }
+
+ // for a drop-down form when the hatch is destroyed
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ if (aIndex == moldSlot) return true;
+ else return super.isValidSlot(aIndex);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Steam_BusInput.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Steam_BusInput.java
new file mode 100644
index 0000000000..5cc1e64d13
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Steam_BusInput.java
@@ -0,0 +1,279 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import static gregtech.api.enums.Textures.BlockIcons.ITEM_IN_SIGN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE_IN;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.lib.CORE;
+
+public class GT_MetaTileEntity_Hatch_Steam_BusInput extends GT_MetaTileEntity_Hatch {
+
+ public RecipeMap<?> mRecipeMap = null;
+ public boolean disableSort;
+
+ public GT_MetaTileEntity_Hatch_Steam_BusInput(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ getSlots(aTier),
+ new String[] { "Item Input for Steam Multiblocks",
+ "Shift + right click with screwdriver to toggle automatic item shuffling", "Capacity: 4 stacks",
+ "Does not work with non-steam multiblocks", CORE.GT_Tooltip.get() });
+ }
+
+ public GT_MetaTileEntity_Hatch_Steam_BusInput(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Hatch_Steam_BusInput(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return GT_Mod.gregtechproxy.mRenderIndicatorsOnHatch
+ ? new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_IN), TextureFactory.of(ITEM_IN_SIGN) }
+ : new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_IN) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return GT_Mod.gregtechproxy.mRenderIndicatorsOnHatch
+ ? new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_IN), TextureFactory.of(ITEM_IN_SIGN) }
+ : new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_IN) };
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Steam_BusInput(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ fillStacksIntoFirstSlots();
+ }
+ }
+
+ public void updateSlots() {
+ for (int i = 0; i < mInventory.length; i++)
+ if (mInventory[i] != null && mInventory[i].stackSize <= 0) mInventory[i] = null;
+ fillStacksIntoFirstSlots();
+ }
+
+ protected void fillStacksIntoFirstSlots() {
+ if (disableSort) {
+ for (int i = 0; i < mInventory.length; i++)
+ if (mInventory[i] != null && mInventory[i].stackSize <= 0) mInventory[i] = null;
+ } else {
+ for (int i = 0; i < mInventory.length; i++)
+ for (int j = i + 1; j < mInventory.length; j++) if (mInventory[j] != null
+ && (mInventory[i] == null || GT_Utility.areStacksEqual(mInventory[i], mInventory[j])))
+ GT_Utility.moveStackFromSlotAToSlotB(
+ getBaseMetaTileEntity(),
+ getBaseMetaTileEntity(),
+ j,
+ i,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ }
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("disableSort", disableSort);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ disableSort = aNBT.getBoolean("disableSort");
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) {
+ disableSort = !disableSort;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ GT_Utility.trans("200.1", "Automatic Item Shuffling: ")
+ + (disableSort ? GT_Utility.trans("087", "Disabled") : GT_Utility.trans("088", "Enabled")));
+ }
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == getBaseMetaTileEntity().getFrontFacing()
+ && (mRecipeMap == null || mRecipeMap.containsInput(aStack));
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[14][17][];
+ 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;
+ }
+
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE) };
+ }
+
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE) };
+ }
+
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE) };
+ }
+
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE) };
+ }
+
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP : Textures.BlockIcons.MACHINE_BRONZE_TOP) };
+ }
+
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP : Textures.BlockIcons.MACHINE_BRONZE_TOP) };
+ }
+
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM : Textures.BlockIcons.MACHINE_BRONZE_BOTTOM) };
+ }
+
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM : Textures.BlockIcons.MACHINE_BRONZE_BOTTOM) };
+ }
+
+ public ITexture[] getBottomFacingPipeActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM : Textures.BlockIcons.MACHINE_BRONZE_BOTTOM),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getBottomFacingPipeInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM : Textures.BlockIcons.MACHINE_BRONZE_BOTTOM),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getTopFacingPipeActive(byte aColor) {
+ return new ITexture[] {
+ new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP : Textures.BlockIcons.MACHINE_BRONZE_TOP),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getTopFacingPipeInactive(byte aColor) {
+ return new ITexture[] {
+ new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP : Textures.BlockIcons.MACHINE_BRONZE_TOP),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getSideFacingPipeActive(byte aColor) {
+ return new ITexture[] {
+ new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getSideFacingPipeInactive(byte aColor) {
+ return new ITexture[] {
+ new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ getBaseMetaTileEntity().add2by2Slots(builder);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Steam_BusOutput.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Steam_BusOutput.java
new file mode 100644
index 0000000000..1d4dbc8987
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Steam_BusOutput.java
@@ -0,0 +1,215 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import static gregtech.api.enums.Textures.BlockIcons.ITEM_OUT_SIGN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE_OUT;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.render.TextureFactory;
+import gtPlusPlus.core.lib.CORE;
+
+public class GT_MetaTileEntity_Hatch_Steam_BusOutput extends GT_MetaTileEntity_Hatch {
+
+ public GT_MetaTileEntity_Hatch_Steam_BusOutput(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 4,
+ new String[] { "Item Output for Steam Multiblocks", "Does not automatically export items",
+ "Capacity: 4 stacks", "Does not work with non-steam multiblocks", CORE.GT_Tooltip.get() });
+ }
+
+ public GT_MetaTileEntity_Hatch_Steam_BusOutput(String aName, int aTier, String aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Hatch_Steam_BusOutput(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return GT_Mod.gregtechproxy.mRenderIndicatorsOnHatch
+ ? new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_OUT), TextureFactory.of(ITEM_OUT_SIGN) }
+ : new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_OUT) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return GT_Mod.gregtechproxy.mRenderIndicatorsOnHatch
+ ? new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_OUT), TextureFactory.of(ITEM_OUT_SIGN) }
+ : new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_OUT) };
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Steam_BusOutput(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == aBaseMetaTileEntity.getFrontFacing();
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[14][17][];
+ 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;
+ }
+
+ public ITexture[] getSideFacingActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE) };
+ }
+
+ public ITexture[] getSideFacingInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE) };
+ }
+
+ public ITexture[] getFrontFacingActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE) };
+ }
+
+ public ITexture[] getFrontFacingInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE) };
+ }
+
+ public ITexture[] getTopFacingActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP : Textures.BlockIcons.MACHINE_BRONZE_TOP) };
+ }
+
+ public ITexture[] getTopFacingInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP : Textures.BlockIcons.MACHINE_BRONZE_TOP) };
+ }
+
+ public ITexture[] getBottomFacingActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM : Textures.BlockIcons.MACHINE_BRONZE_BOTTOM) };
+ }
+
+ public ITexture[] getBottomFacingInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM : Textures.BlockIcons.MACHINE_BRONZE_BOTTOM) };
+ }
+
+ public ITexture[] getBottomFacingPipeActive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM : Textures.BlockIcons.MACHINE_BRONZE_BOTTOM),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getBottomFacingPipeInactive(byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_BOTTOM : Textures.BlockIcons.MACHINE_BRONZE_BOTTOM),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getTopFacingPipeActive(byte aColor) {
+ return new ITexture[] {
+ new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP : Textures.BlockIcons.MACHINE_BRONZE_TOP),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getTopFacingPipeInactive(byte aColor) {
+ return new ITexture[] {
+ new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_TOP : Textures.BlockIcons.MACHINE_BRONZE_TOP),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getSideFacingPipeActive(byte aColor) {
+ return new ITexture[] {
+ new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ public ITexture[] getSideFacingPipeInactive(byte aColor) {
+ return new ITexture[] {
+ new GT_RenderedTexture(
+ mTier == 1 ? Textures.BlockIcons.MACHINE_BRONZEBRICKS_SIDE : Textures.BlockIcons.MACHINE_BRONZE_SIDE),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_PIPE_OUT) };
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ getBaseMetaTileEntity().add2by2Slots(builder);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Turbine.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Turbine.java
new file mode 100644
index 0000000000..ed3101f309
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_Turbine.java
@@ -0,0 +1,435 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_ST5;
+import static gregtech.api.enums.Textures.BlockIcons.LARGETURBINE_ST_ACTIVE5;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.minecraft.BlockPos;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.PlayerUtils;
+import gtPlusPlus.xmod.gregtech.common.tileentities.machines.multi.production.turbines.GregtechMetaTileEntity_LargerTurbineBase;
+
+@SuppressWarnings("deprecation")
+public class GT_MetaTileEntity_Hatch_Turbine extends GT_MetaTileEntity_Hatch {
+
+ public boolean mHasController = false;
+ public boolean mUsingAnimation = true;
+ private String mControllerLocation;
+ public int mEUt = 0;
+
+ public GT_MetaTileEntity_Hatch_Turbine(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, 16, "Turbine Rotor holder for XL Turbines");
+ }
+
+ public GT_MetaTileEntity_Hatch_Turbine(String aName, int aTier, String aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription, aTextures);
+ }
+
+ public GT_MetaTileEntity_Hatch_Turbine(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 1, aDescription[0], aTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return ArrayUtils.addAll(
+ this.mDescriptionArray,
+ "Right Click with a soldering iron to reset controller link",
+ "Right Click with a wrench to remove turbine",
+ "Right Click with a screwdriver for technical information",
+ "Sneak + Right Click with a wrench to rotate",
+ "Sneak + Right Click with a screwdriver to disable animations",
+ CORE.GT_Tooltip.get());
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, getFrontFacingTurbineTexture() };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, getFrontFacingTurbineTexture() };
+ }
+
+ public int getEU() {
+ return this.mEUt;
+ }
+
+ public void setEU(int aEU) {
+ this.mEUt = aEU;
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return facing.offsetY == 0;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return false;
+ }
+
+ public boolean hasTurbine() {
+ ItemStack aStack = this.mInventory[0];
+ boolean aIsValid = GregtechMetaTileEntity_LargerTurbineBase.isValidTurbine(aStack);
+ return aIsValid;
+ }
+
+ public ItemStack getTurbine() {
+ if (hasTurbine()) {
+ return this.mInventory[0];
+ }
+ return null;
+ }
+
+ public boolean canWork() {
+ return hasTurbine();
+ }
+
+ public boolean insertTurbine(ItemStack aTurbine) {
+ if (GregtechMetaTileEntity_LargerTurbineBase.isValidTurbine(aTurbine)) {
+ this.mInventory[0] = aTurbine;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Turbine(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public int getInventoryStackLimit() {
+ return 1;
+ }
+
+ public void damageTurbine(int aEUt, int damageFactorLow, float damageFactorHigh) {
+ damageTurbine((long) aEUt, damageFactorLow, damageFactorHigh);
+ }
+
+ public void damageTurbine(long aEUt, int damageFactorLow, float damageFactorHigh) {
+ if (hasTurbine() && MathUtils.randInt(0, 1) == 0) {
+ ItemStack aTurbine = getTurbine();
+ ((GT_MetaGenerated_Tool) aTurbine.getItem()).doDamage(
+ aTurbine,
+ (long) getDamageToComponent(aTurbine)
+ * (long) Math.min((float) aEUt / (float) damageFactorLow, Math.pow(aEUt, damageFactorHigh)));
+ }
+ }
+
+ private int getDamageToComponent(ItemStack aStack) {
+ return 1;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("mHasController", mHasController);
+ aNBT.setBoolean("mUsingAnimation", mUsingAnimation);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ mHasController = aNBT.getBoolean("mHasController");
+ mUsingAnimation = aNBT.getBoolean("mUsingAnimation");
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (this.mHasController) {
+ if (aTick % 20 == 0) {
+ if (isControllerActive()) {
+ this.getBaseMetaTileEntity()
+ .setActive(true);
+ } else {
+ this.getBaseMetaTileEntity()
+ .setActive(false);
+ }
+ }
+ } else if (!this.mHasController && this.mControllerLocation != null) {
+ // Weird Invalid State
+ if (setController(BlockPos.generateBlockPos(mControllerLocation))) {
+ // Valid
+ }
+ } else {
+ // No Controller
+ }
+ if (this.mInventory[0] != null && this.mInventory[0].stackSize <= 0) this.mInventory[0] = null;
+ }
+
+ public boolean isControllerActive() {
+ GregtechMetaTileEntity_LargerTurbineBase x = getController();
+ if (x != null) {
+ // Logger.INFO("Checking Status of Controller. Running? "+(x.mEUt > 0));
+ return x.lEUt > 0;
+ }
+ // Logger.INFO("Status of Controller failed, controller is null.");
+ return false;
+ }
+
+ public GregtechMetaTileEntity_LargerTurbineBase getController() {
+ if (this.mHasController && this.mControllerLocation != null && this.mControllerLocation.length() > 0) {
+ BlockPos p = BlockPos.generateBlockPos(mControllerLocation);
+ if (p != null) {
+ // Logger.INFO(p.getLocationString());
+ IGregTechTileEntity tTileEntity = getBaseMetaTileEntity()
+ .getIGregTechTileEntity(p.xPos, p.yPos, p.zPos);
+ if (tTileEntity != null
+ && tTileEntity.getMetaTileEntity() instanceof GregtechMetaTileEntity_LargerTurbineBase) {
+ return (GregtechMetaTileEntity_LargerTurbineBase) tTileEntity.getMetaTileEntity();
+ } else {
+ if (tTileEntity == null) {
+ Logger.INFO("Controller MTE is null, somehow?");
+ } else {
+ Logger.INFO("Controller is a different MTE to expected");
+ }
+ }
+ }
+ }
+ // Logger.INFO("Failed to Get Controller.");
+ return null;
+ }
+
+ public boolean canSetNewController() {
+ if ((mControllerLocation != null && mControllerLocation.length() > 0) || this.mHasController) {
+ return false;
+ }
+ return true;
+ }
+
+ public boolean setController(BlockPos aPos) {
+ clearController();
+ if (canSetNewController()) {
+ mControllerLocation = aPos.getUniqueIdentifier();
+ mHasController = true;
+ Logger.INFO("Successfully injected controller into this Turbine Assembly Hatch.");
+ }
+ return mHasController;
+ }
+
+ public void clearController() {
+ this.mControllerLocation = null;
+ this.mHasController = false;
+ }
+
+ public boolean usingAnimations() {
+ return mUsingAnimation;
+ }
+
+ private ITexture getFrontFacingTurbineTexture() {
+ if (!mHasController) {
+ return this.getBaseMetaTileEntity()
+ .isActive() ? new GT_RenderedTexture(LARGETURBINE_ST_ACTIVE5)
+ : new GT_RenderedTexture(LARGETURBINE_ST5);
+ } else {
+ if (usingAnimations()) {
+ if (isControllerActive()) {
+ return getController().frontFaceActive;
+ }
+ }
+ return getController().frontFace;
+ }
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return 0;
+ }
+
+ @Override
+ public boolean isItemValidForSlot(int aIndex, ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public int[] getAccessibleSlotsFromSide(int ordinalSide) {
+ return new int[] {};
+ }
+
+ @Override
+ public boolean canInsertItem(int aIndex, ItemStack aStack, int ordinalSide) {
+ return false;
+ }
+
+ public void setActive(boolean b) {
+ this.getBaseMetaTileEntity()
+ .setActive(b);
+ }
+
+ @Override
+ public boolean allowCoverOnSide(ForgeDirection side, GT_ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (!aPlayer.isSneaking()) {
+ PlayerUtils.messagePlayer(aPlayer, "Using Animations? " + usingAnimations());
+ PlayerUtils.messagePlayer(aPlayer, "Has Controller? " + this.mHasController);
+ if (mHasController) {
+ PlayerUtils.messagePlayer(
+ aPlayer,
+ "Controller Location: " + BlockPos.generateBlockPos(mControllerLocation)
+ .getLocationString());
+ PlayerUtils.messagePlayer(aPlayer, "Controller Active? " + this.isControllerActive());
+ }
+ PlayerUtils.messagePlayer(
+ aPlayer,
+ "Active? " + this.getBaseMetaTileEntity()
+ .isActive());
+ PlayerUtils.messagePlayer(aPlayer, "Has Turbine inserted? " + this.hasTurbine());
+ if (this.hasTurbine()) {
+ Materials aMat = GT_MetaGenerated_Tool.getPrimaryMaterial(getTurbine());
+ String aSize = GregtechMetaTileEntity_LargerTurbineBase
+ .getTurbineSizeString(GregtechMetaTileEntity_LargerTurbineBase.getTurbineSize(getTurbine()));
+ PlayerUtils.messagePlayer(aPlayer, "Using: " + aMat.mLocalizedName + " " + aSize);
+ }
+ } else {
+ this.mUsingAnimation = !mUsingAnimation;
+ if (this.mUsingAnimation) {
+ PlayerUtils.messagePlayer(aPlayer, "Using Animated Turbine Texture.");
+ } else {
+ PlayerUtils.messagePlayer(aPlayer, "Using Static Turbine Texture.");
+ }
+ }
+ }
+
+ @Override
+ public boolean onWrenchRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer, float aX,
+ float aY, float aZ) {
+ if (this.getBaseMetaTileEntity()
+ .isServerSide() && !aPlayer.isSneaking()) {
+ ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+ if (tCurrentItem != null) {
+ if (tCurrentItem.getItem() instanceof GT_MetaGenerated_Tool) {
+ return onToolClick(tCurrentItem, aPlayer, wrenchingSide);
+ }
+ }
+ }
+ return super.onWrenchRightClick(side, wrenchingSide, aPlayer, aX, aY, aZ);
+ }
+
+ @Override
+ public boolean onSolderingToolRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ if (this.getBaseMetaTileEntity()
+ .isServerSide()) {
+ ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+ if (tCurrentItem != null) {
+ if (tCurrentItem.getItem() instanceof GT_MetaGenerated_Tool) {
+ return onToolClick(tCurrentItem, aPlayer, wrenchingSide);
+ }
+ }
+ }
+ return false;
+ }
+
+ public boolean onToolClick(ItemStack tCurrentItem, EntityPlayer aPlayer, ForgeDirection side) {
+ if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sWrenchList)) {
+ boolean aHasTurbine = this.hasTurbine();
+ if (aPlayer.inventory.getFirstEmptyStack() >= 0 && aHasTurbine) {
+ if (PlayerUtils.isCreative(aPlayer)
+ || GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) {
+ aPlayer.inventory.addItemStackToInventory((this.getTurbine()));
+ this.mInventory[0] = null;
+ GT_Utility.sendChatToPlayer(aPlayer, "Removed turbine with wrench.");
+ return true;
+ }
+ } else {
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ aHasTurbine ? "Cannot remove turbine, no free inventory space." : "No turbine to remove.");
+ }
+ } else if (GT_Utility.isStackInList(tCurrentItem, GregTech_API.sSolderingToolList)) {
+ if (mControllerLocation != null && mControllerLocation.length() > 0) {
+ if (setController(BlockPos.generateBlockPos(mControllerLocation))) {
+ if (PlayerUtils.isCreative(aPlayer)
+ || GT_ModHandler.damageOrDechargeItem(tCurrentItem, 1, 1000, aPlayer)) {
+ String tChat = "Trying to Reset linked Controller";
+ IGregTechTileEntity g = this.getBaseMetaTileEntity();
+ GT_Utility.sendChatToPlayer(aPlayer, tChat);
+ GT_Utility.sendSoundToPlayers(
+ g.getWorld(),
+ SoundResource.IC2_TOOLS_RUBBER_TRAMPOLINE,
+ 1.0F,
+ -1,
+ g.getXCoord(),
+ g.getYCoord(),
+ g.getZCoord());
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new SlotWidget(inventoryHandler, 0).setFilter(GregtechMetaTileEntity_LargerTurbineBase::isValidTurbine)
+ .setAccess(false, true)
+ .setPos(79, 34));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_TurbineProvider.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_TurbineProvider.java
new file mode 100644
index 0000000000..e9626a310c
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_Hatch_TurbineProvider.java
@@ -0,0 +1,221 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_LargeTurbine;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.PlayerUtils;
+import gtPlusPlus.core.util.sys.KeyboardUtils;
+import gtPlusPlus.xmod.gregtech.common.tileentities.machines.multi.production.turbines.GregtechMetaTileEntity_LargerTurbineBase;
+
+public class GT_MetaTileEntity_Hatch_TurbineProvider extends GT_MetaTileEntity_Hatch_InputBus {
+
+ public GT_MetaTileEntity_Hatch_TurbineProvider(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public GT_MetaTileEntity_Hatch_TurbineProvider(String aName, int aTier, String[] aDescription,
+ ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_TurbineProvider(
+ this.mName,
+ this.mTier,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "An automation port for Large Turbines",
+ "Will attempt once per 1200 ticks to fill the turbine slot of it's parent turbine",
+ "You may adjust this with a screwdriver", "Hold shift to adjust in finer amounts",
+ "Hold control to adjust direction", "Left Click with Screwdriver to reset",
+ "This module assumes the entire turbine is in the same Chunk", CORE.GT_Tooltip.get() };
+ }
+
+ private GT_MetaTileEntity_LargeTurbine mParent = null;
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+ if (aTimer % mRefreshTime == 0 && this.getBaseMetaTileEntity()
+ .isServerSide()) {
+ tryRefillTurbine();
+ }
+ }
+
+ private void tryFindParentTurbine() {
+ Logger.INFO("This turbine housing has no parent, searching world.");
+ IGregTechTileEntity T = this.getBaseMetaTileEntity();
+ World W = T.getWorld();
+ Chunk C = W.getChunkFromBlockCoords(T.getXCoord(), T.getZCoord());
+ for (Object o : C.chunkTileEntityMap.values()) {
+ if (o instanceof IGregTechTileEntity G) {
+ final IMetaTileEntity aMetaTileEntity = G.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ continue;
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_LargeTurbine aTurb) {
+ for (GT_MetaTileEntity_Hatch_InputBus ee : aTurb.mInputBusses) {
+ if (ee.equals(this)) {
+ mParent = aTurb;
+ Logger.INFO("Found a Parent to attach to this housing.");
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void tryRefillTurbine() {
+ if (mParent == null) {
+ tryFindParentTurbine();
+ }
+ if (mParent != null && mParent.mInventory[1] == null) {
+ for (ItemStack aStack : this.mInventory) {
+ if (isItemStackTurbine(aStack)) {
+ setGUIItemStack(aStack);
+ }
+ }
+ }
+ }
+
+ protected boolean setGUIItemStack(ItemStack aNewGuiSlotContents) {
+ boolean result = false;
+ if (mParent.mInventory[1] == null) {
+ mParent.mInventory[1] = aNewGuiSlotContents != null ? aNewGuiSlotContents.copy() : null;
+ mParent.depleteInput(aNewGuiSlotContents);
+ mParent.updateSlots();
+ this.updateSlots();
+ result = true;
+ }
+ return result;
+ }
+
+ public boolean isItemStackTurbine(ItemStack aStack) {
+ if (aStack.getItem() instanceof GT_MetaGenerated_Tool) {
+ if (aStack.getItemDamage() >= 170 && aStack.getItemDamage() <= 176) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean isItemStackScrewdriver(ItemStack aStack) {
+ if (aStack.getItem() instanceof GT_MetaGenerated_Tool) {
+ if (aStack.getItemDamage() == 22 || aStack.getItemDamage() == 150) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return isItemStackTurbine(aStack);
+ }
+
+ private int mRefreshTime = 1200;
+ private boolean mDescending = true;
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mRefreshTime", mRefreshTime);
+ aNBT.setBoolean("mDescending", mDescending);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ mRefreshTime = aNBT.getInteger("mRefreshTime");
+ mDescending = aNBT.getBoolean("mDescending");
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (aPlayer != null) {
+ if (KeyboardUtils.isCtrlKeyDown()) {
+ mDescending = !mDescending;
+ PlayerUtils.messagePlayer(aPlayer, "Direction: " + (mDescending ? "DOWN" : "UP"));
+ } else {
+ int aAmount = 0;
+ if (KeyboardUtils.isShiftKeyDown()) {
+ aAmount = 10;
+ } else {
+ aAmount = 100;
+ }
+ if (mDescending) {
+ mRefreshTime -= aAmount;
+ if (mRefreshTime < 0) {
+ mRefreshTime = 1200;
+ }
+ } else {
+ mRefreshTime += aAmount;
+ if (mRefreshTime > 1200) {
+ mRefreshTime = 0;
+ }
+ }
+ PlayerUtils.messagePlayer(aPlayer, "Set check time to be every " + mRefreshTime + " ticks.");
+ }
+ }
+ }
+
+ @Override
+ public void onLeftclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ boolean aDidScrewdriver = false;
+ if (aPlayer != null) {
+ if (aPlayer.getHeldItem() != null) {
+ if (isItemStackScrewdriver(aPlayer.getHeldItem())) {
+ aDidScrewdriver = true;
+ mRefreshTime = 1200;
+ PlayerUtils.messagePlayer(aPlayer, "Reset check time to " + mRefreshTime + " ticks.");
+ }
+ }
+ }
+ if (!aDidScrewdriver) {
+ super.onLeftclick(aBaseMetaTileEntity, aPlayer);
+ }
+ }
+
+ @Override
+ public boolean allowSelectCircuit() {
+ return false;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new SlotWidget(inventoryHandler, 0).setFilter(GregtechMetaTileEntity_LargerTurbineBase::isValidTurbine)
+ .setAccess(false, true)
+ .setPos(79, 34));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_SuperBus_Input.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_SuperBus_Input.java
new file mode 100644
index 0000000000..5794e6adf8
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_SuperBus_Input.java
@@ -0,0 +1,65 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.Scrollable;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gtPlusPlus.core.lib.CORE;
+
+public class GT_MetaTileEntity_SuperBus_Input extends GT_MetaTileEntity_Hatch_InputBus {
+
+ public GT_MetaTileEntity_SuperBus_Input(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, getSlots(aTier) + 1);
+ }
+
+ public GT_MetaTileEntity_SuperBus_Input(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, getSlots(aTier) + 1, aDescription, aTextures);
+ }
+
+ /**
+ * Returns a factor of 16 based on tier.
+ *
+ * @param aTier The tier of this bus.
+ * @return (1 + aTier) * 16
+ */
+ public static int getSlots(int aTier) {
+ return (1 + aTier) * 16;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_SuperBus_Input(this.mName, this.mTier, mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "Item Input for Multiblocks", "" + getSlots(this.mTier) + " Slots",
+ CORE.GT_Tooltip.get() };
+ }
+
+ @Override
+ public int getCircuitSlot() {
+ return getSlots(mTier);
+ }
+
+ @Override
+ public void addUIWidgets(Builder builder, UIBuildContext buildContext) {
+ final Scrollable scrollable = new Scrollable().setVerticalScroll();
+ for (int row = 0; row * 4 < inventoryHandler.getSlots() - 1; row++) {
+ int columnsToMake = Math.min(inventoryHandler.getSlots() - row * 4, 4);
+ for (int column = 0; column < columnsToMake; column++) {
+ scrollable.widget(
+ new SlotWidget(inventoryHandler, row * 4 + column).setPos(column * 18, row * 18)
+ .setSize(18, 18));
+ }
+ }
+ builder.widget(
+ scrollable.setSize(18 * 4 + 4, 18 * 4)
+ .setPos(52, 7));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_SuperBus_Output.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_SuperBus_Output.java
new file mode 100644
index 0000000000..aee6235ab9
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GT_MetaTileEntity_SuperBus_Output.java
@@ -0,0 +1,105 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.inventory.IInventory;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow.Builder;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.Scrollable;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_OutputBus;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.lib.CORE;
+
+public class GT_MetaTileEntity_SuperBus_Output extends GT_MetaTileEntity_Hatch_OutputBus {
+
+ public GT_MetaTileEntity_SuperBus_Output(int id, String name, String nameRegional, int tier) {
+ super(id, name, nameRegional, tier, getSlots(tier));
+ }
+
+ public GT_MetaTileEntity_SuperBus_Output(String name, int tier, String[] description, ITexture[][][] textures) {
+ super(name, tier, getSlots(tier), description, textures);
+ }
+
+ /**
+ * Returns a factor of 16 based on tier.
+ *
+ * @param aTier The tier of this bus.
+ * @return (1 + aTier) * 16
+ */
+ public static int getSlots(int aTier) {
+ return (1 + aTier) * 16;
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_SuperBus_Output(this.mName, this.mTier, mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ this.fillStacksIntoFirstSlots();
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTimer);
+ }
+
+ public void updateSlots() {
+ for (int i = 0; i < this.mInventory.length; ++i) {
+ if (this.mInventory[i] != null && this.mInventory[i].stackSize <= 0) {
+ this.mInventory[i] = null;
+ }
+ }
+ this.fillStacksIntoFirstSlots();
+ }
+
+ protected void fillStacksIntoFirstSlots() {
+ for (int i = 0; i < this.mInventory.length; ++i) {
+ for (int j = i + 1; j < this.mInventory.length; ++j) {
+ if (this.mInventory[j] != null && (this.mInventory[i] == null
+ || GT_Utility.areStacksEqual(this.mInventory[i], this.mInventory[j]))) {
+ GT_Utility.moveStackFromSlotAToSlotB(
+ (IInventory) this.getBaseMetaTileEntity(),
+ (IInventory) this.getBaseMetaTileEntity(),
+ j,
+ i,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ }
+ }
+ }
+ }
+
+ @Override
+ public String[] getDescription() {
+ String[] aDesc = new String[] { "Item Output for Multiblocks", "" + getSlots(this.mTier) + " Slots",
+ CORE.GT_Tooltip.get() };
+ return aDesc;
+ }
+
+ @Override
+ public void addUIWidgets(Builder builder, UIBuildContext buildContext) {
+ final Scrollable scrollable = new Scrollable().setVerticalScroll();
+ for (int row = 0; row * 4 < inventoryHandler.getSlots() - 1; row++) {
+ int columnsToMake = Math.min(inventoryHandler.getSlots() - row * 4, 4);
+ for (int column = 0; column < columnsToMake; column++) {
+ scrollable.widget(
+ new SlotWidget(inventoryHandler, row * 4 + column).setPos(column * 18, row * 18)
+ .setSize(18, 18));
+ }
+ }
+ builder.widget(
+ scrollable.setSize(18 * 4 + 4, 18 * 4)
+ .setPos(52, 7));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaPipeEntityFluid.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaPipeEntityFluid.java
new file mode 100644
index 0000000000..e9f9a2dda4
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaPipeEntityFluid.java
@@ -0,0 +1,117 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SubTag;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Fluid;
+import gregtech.api.render.TextureFactory;
+import gtPlusPlus.xmod.gregtech.api.enums.GregtechOrePrefixes.GT_Materials;
+
+public class GregtechMetaPipeEntityFluid extends GT_MetaPipeEntity_Fluid {
+
+ public final GT_Materials mMaterial;
+
+ public GregtechMetaPipeEntityFluid(int aID, String aName, String aNameRegional, float aThickNess,
+ GT_Materials aMaterial, int aCapacity, int aHeatResistance, boolean aGasProof) {
+ this(aID, aName, aNameRegional, aThickNess, aMaterial, aCapacity, aHeatResistance, aGasProof, 1);
+ }
+
+ public GregtechMetaPipeEntityFluid(final String aName, final float aThickNess, final GT_Materials aMaterial,
+ final int aCapacity, final int aHeatResistance, final boolean aGasProof) {
+ this(aName, aThickNess, aMaterial, aCapacity, aHeatResistance, aGasProof, 1);
+ }
+
+ public GregtechMetaPipeEntityFluid(int aID, String aName, String aNameRegional, float aThickNess,
+ GT_Materials aMaterial, int aCapacity, int aHeatResistance, boolean aGasProof, int aFluidTypes) {
+ super(aID, aName, aNameRegional, aThickNess, null, aCapacity, aHeatResistance, aGasProof, aFluidTypes);
+ this.mLastReceivedFrom = 0;
+ this.oLastReceivedFrom = 0;
+ this.mMaterial = aMaterial;
+ }
+
+ public GregtechMetaPipeEntityFluid(String aName, float aThickNess, GT_Materials aMaterial, int aCapacity,
+ int aHeatResistance, boolean aGasProof, int aFluidTypes) {
+ super(aName, aThickNess, null, aCapacity, aHeatResistance, aGasProof, aFluidTypes);
+ this.mLastReceivedFrom = 0;
+ this.oLastReceivedFrom = 0;
+ this.mMaterial = aMaterial;
+ }
+
+ @Override
+ public byte getTileEntityBaseType() {
+ return this.mMaterial == null ? 4
+ : (byte) ((this.mMaterial.contains(SubTag.WOOD) ? 12 : 4)
+ + Math.max(0, Math.min(3, this.mMaterial.mToolQuality)));
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GregtechMetaPipeEntityFluid(
+ this.mName,
+ this.mThickNess,
+ this.mMaterial,
+ this.mCapacity,
+ this.mHeatResistance,
+ this.mGasProof);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, int aConnections,
+ int aColorIndex, boolean aConnected, boolean aRedstone) {
+ float tThickNess = getThickNess();
+ if (mDisableInput == 0)
+ return new ITexture[] { aConnected ? getBaseTexture(tThickNess, mPipeAmount, mMaterial, aColorIndex)
+ : TextureFactory.of(
+ mMaterial.mIconSet.mTextures[OrePrefixes.pipe.mTextureIndex],
+ Dyes.getModulation(aColorIndex, mMaterial.mRGBa)) };
+ int tMask = 0;
+ int[][] sRestrictionArray = { { 2, 3, 5, 4 }, { 2, 3, 5, 4 }, { 1, 0, 5, 4 }, { 1, 0, 4, 5 }, { 1, 0, 2, 3 },
+ { 1, 0, 2, 3 } };
+ if (side != ForgeDirection.UNKNOWN) {
+ for (int i = 0; i < 4; i++)
+ if (isInputDisabledAtSide(ForgeDirection.getOrientation(sRestrictionArray[side.ordinal()][i])))
+ tMask |= 1 << i;
+ // Full block size renderer flips side 5 and 2 textures, flip restrictor textures to compensate
+ if (side == ForgeDirection.EAST || side == ForgeDirection.UP)
+ if (tMask > 3 && tMask < 12) tMask = (tMask ^ 12);
+ }
+ return new ITexture[] { aConnected ? getBaseTexture(tThickNess, mPipeAmount, mMaterial, aColorIndex)
+ : TextureFactory.of(
+ mMaterial.mIconSet.mTextures[OrePrefixes.pipe.mTextureIndex],
+ Dyes.getModulation(aColorIndex, mMaterial.mRGBa)),
+ getRestrictorTexture(tMask) };
+ }
+
+ protected static ITexture getBaseTexture(float aThickNess, int aPipeAmount, GT_Materials aMaterial,
+ int aColorIndex) {
+ if (aPipeAmount >= 9) return TextureFactory.of(
+ aMaterial.mIconSet.mTextures[OrePrefixes.pipeNonuple.mTextureIndex],
+ Dyes.getModulation(aColorIndex, aMaterial.mRGBa));
+ if (aPipeAmount >= 4) return TextureFactory.of(
+ aMaterial.mIconSet.mTextures[OrePrefixes.pipeQuadruple.mTextureIndex],
+ Dyes.getModulation(aColorIndex, aMaterial.mRGBa));
+ if (aThickNess < 0.124F) return TextureFactory.of(
+ aMaterial.mIconSet.mTextures[OrePrefixes.pipe.mTextureIndex],
+ Dyes.getModulation(aColorIndex, aMaterial.mRGBa));
+ if (aThickNess < 0.374F) return TextureFactory.of(
+ aMaterial.mIconSet.mTextures[OrePrefixes.pipeTiny.mTextureIndex],
+ Dyes.getModulation(aColorIndex, aMaterial.mRGBa));
+ if (aThickNess < 0.499F) return TextureFactory.of(
+ aMaterial.mIconSet.mTextures[OrePrefixes.pipeSmall.mTextureIndex],
+ Dyes.getModulation(aColorIndex, aMaterial.mRGBa));
+ if (aThickNess < 0.749F) return TextureFactory.of(
+ aMaterial.mIconSet.mTextures[OrePrefixes.pipeMedium.mTextureIndex],
+ Dyes.getModulation(aColorIndex, aMaterial.mRGBa));
+ if (aThickNess < 0.874F) return TextureFactory.of(
+ aMaterial.mIconSet.mTextures[OrePrefixes.pipeLarge.mTextureIndex],
+ Dyes.getModulation(aColorIndex, aMaterial.mRGBa));
+ return TextureFactory.of(
+ aMaterial.mIconSet.mTextures[OrePrefixes.pipeHuge.mTextureIndex],
+ Dyes.getModulation(aColorIndex, aMaterial.mRGBa));
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaPipeEntity_Cable.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaPipeEntity_Cable.java
new file mode 100644
index 0000000000..9b1408ba51
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaPipeEntity_Cable.java
@@ -0,0 +1,156 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.TextureSet;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntityCable;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaPipeEntity_Cable;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.util.GT_Utility;
+
+public class GregtechMetaPipeEntity_Cable extends GT_MetaPipeEntity_Cable implements IMetaTileEntityCable {
+
+ private static Textures.BlockIcons INSULATION_MEDIUM_PLUS;
+
+ static {
+ try {
+ INSULATION_MEDIUM_PLUS = (Textures.BlockIcons) GT_Utility
+ .getField(Textures.BlockIcons.class, "INSULATION_MEDIUM_PLUS")
+ .get(null);
+ } catch (IllegalAccessException | NullPointerException e) {
+ throw new Error(e);
+ }
+ }
+
+ private short[] vRGB = null;
+
+ public GregtechMetaPipeEntity_Cable(final int aID, final String aName, final String aNameRegional,
+ final float aThickNess, final Materials aMaterial, final long aCableLossPerMeter, final long aAmperage,
+ final long aVoltage, final boolean aInsulated, final boolean aCanShock, final short[] aRGB) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aThickNess,
+ aMaterial,
+ aCableLossPerMeter,
+ aAmperage,
+ aVoltage,
+ aInsulated,
+ aCanShock);
+ this.vRGB = aRGB == null || aRGB.length != 4 ? Materials.Iron.mRGBa : aRGB;
+ }
+
+ public GregtechMetaPipeEntity_Cable(final String aName, final float aThickNess, final Materials aMaterial,
+ final long aCableLossPerMeter, final long aAmperage, final long aVoltage, final boolean aInsulated,
+ final boolean aCanShock, final short[] aRGB) {
+ super(aName, aThickNess, aMaterial, aCableLossPerMeter, aAmperage, aVoltage, aInsulated, aCanShock);
+ this.vRGB = aRGB == null || aRGB.length != 4 ? Materials.Iron.mRGBa : aRGB;
+ }
+
+ public GregtechMetaPipeEntity_Cable(final int aID, final String aName, final String aNameRegional,
+ final float aThickNess, final long aCableLossPerMeter, final long aAmperage, final long aVoltage,
+ final boolean aInsulated, final boolean aCanShock, final short[] aRGB) {
+ this(
+ aID,
+ aName,
+ aNameRegional,
+ aThickNess,
+ null,
+ aCableLossPerMeter,
+ aAmperage,
+ aVoltage,
+ aInsulated,
+ aCanShock,
+ aRGB);
+ }
+
+ public GregtechMetaPipeEntity_Cable(final String aName, final float aThickNess, final long aCableLossPerMeter,
+ final long aAmperage, final long aVoltage, final boolean aInsulated, final boolean aCanShock,
+ final short[] aRGB) {
+ this(aName, aThickNess, null, aCableLossPerMeter, aAmperage, aVoltage, aInsulated, aCanShock, aRGB);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GregtechMetaPipeEntity_Cable(
+ this.mName,
+ this.mThickNess,
+ this.mMaterial,
+ this.mCableLossPerMeter,
+ this.mAmperage,
+ this.mVoltage,
+ this.mInsulated,
+ this.mCanShock,
+ this.vRGB);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, int aConnections,
+ int aColorIndex, boolean aConnected, boolean aRedstone) {
+ return getTextureGTNH(aBaseMetaTileEntity, side, aConnections, aColorIndex, aConnected, aRedstone);
+ }
+
+ private ITexture[] getTextureGTNH(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection aSide, int aConnections,
+ int aColorIndex, boolean aConnected, boolean aRedstone) {
+
+ Materials wireMaterial = mMaterial;
+ if (wireMaterial == null) {
+ wireMaterial = Materials.Iron;
+ }
+
+ if (!mInsulated) return new ITexture[] { new GT_RenderedTexture(
+ wireMaterial.mIconSet.mTextures[TextureSet.INDEX_wire],
+ Dyes.getModulation(aColorIndex, vRGB)) };
+ if (aConnected) {
+ float tThickNess = getThickNess();
+ if (tThickNess < 0.124F) return new ITexture[] { new GT_RenderedTexture(
+ Textures.BlockIcons.INSULATION_FULL,
+ Dyes.getModulation(aColorIndex, Dyes.CABLE_INSULATION.mRGBa)) };
+ if (tThickNess < 0.374F) // 0.375 x1
+ return new ITexture[] {
+ new GT_RenderedTexture(wireMaterial.mIconSet.mTextures[TextureSet.INDEX_wire], vRGB),
+ new GT_RenderedTexture(
+ Textures.BlockIcons.INSULATION_TINY,
+ Dyes.getModulation(aColorIndex, Dyes.CABLE_INSULATION.mRGBa)) };
+ if (tThickNess < 0.499F) // 0.500 x2
+ return new ITexture[] {
+ new GT_RenderedTexture(wireMaterial.mIconSet.mTextures[TextureSet.INDEX_wire], vRGB),
+ new GT_RenderedTexture(
+ Textures.BlockIcons.INSULATION_SMALL,
+ Dyes.getModulation(aColorIndex, Dyes.CABLE_INSULATION.mRGBa)) };
+ if (tThickNess < 0.624F) // 0.625 x4
+ return new ITexture[] {
+ new GT_RenderedTexture(wireMaterial.mIconSet.mTextures[TextureSet.INDEX_wire], vRGB),
+ new GT_RenderedTexture(
+ Textures.BlockIcons.INSULATION_MEDIUM,
+ Dyes.getModulation(aColorIndex, Dyes.CABLE_INSULATION.mRGBa)) };
+ if (tThickNess < 0.749F) // 0.750 x8
+ return new ITexture[] {
+ new GT_RenderedTexture(wireMaterial.mIconSet.mTextures[TextureSet.INDEX_wire], vRGB),
+ new GT_RenderedTexture(
+ INSULATION_MEDIUM_PLUS,
+ Dyes.getModulation(aColorIndex, Dyes.CABLE_INSULATION.mRGBa)) };
+ if (tThickNess < 0.874F) // 0.825 x12
+ return new ITexture[] {
+ new GT_RenderedTexture(wireMaterial.mIconSet.mTextures[TextureSet.INDEX_wire], vRGB),
+ new GT_RenderedTexture(
+ Textures.BlockIcons.INSULATION_LARGE,
+ Dyes.getModulation(aColorIndex, Dyes.CABLE_INSULATION.mRGBa)) };
+ return new ITexture[] {
+ new GT_RenderedTexture(wireMaterial.mIconSet.mTextures[TextureSet.INDEX_wire], vRGB),
+ new GT_RenderedTexture(
+ Textures.BlockIcons.INSULATION_HUGE,
+ Dyes.getModulation(aColorIndex, Dyes.CABLE_INSULATION.mRGBa)) };
+ }
+ return new ITexture[] { new GT_RenderedTexture(
+ Textures.BlockIcons.INSULATION_FULL,
+ Dyes.getModulation(aColorIndex, Dyes.CABLE_INSULATION.mRGBa)) };
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaTreeFarmerStructural.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaTreeFarmerStructural.java
new file mode 100644
index 0000000000..0aaaa75584
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/GregtechMetaTreeFarmerStructural.java
@@ -0,0 +1,49 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations;
+
+import net.minecraft.nbt.NBTTagCompound;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.objects.GT_RenderedTexture;
+import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.machines.GregtechMetaTreeFarmerBase;
+
+public class GregtechMetaTreeFarmerStructural extends GregtechMetaTreeFarmerBase {
+
+ public GregtechMetaTreeFarmerStructural(final int aID, final String aName, final String aNameRegional,
+ final int aTier) {
+ super(aID, aName, aNameRegional, aTier, 0, "Structural Blocks for the Tree Farmer.");
+ }
+
+ public GregtechMetaTreeFarmerStructural(final String aName, final int aTier, final int aInvSlotCount,
+ final String[] aDescription, final ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GregtechMetaTreeFarmerStructural(
+ this.mName,
+ this.mTier,
+ this.mInventory.length,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public ITexture getOverlayIcon() {
+ return new GT_RenderedTexture(Textures.BlockIcons.VOID);
+ }
+
+ @Override
+ public boolean isValidSlot(final int aIndex) {
+ return false;
+ }
+
+ @Override
+ public void saveNBTData(final NBTTagCompound paramNBTTagCompound) {}
+
+ @Override
+ public void loadNBTData(final NBTTagCompound paramNBTTagCompound) {}
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GT_MetaTileEntity_Hatch_CustomFluidBase.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GT_MetaTileEntity_Hatch_CustomFluidBase.java
new file mode 100644
index 0000000000..6a85c06c1b
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GT_MetaTileEntity_Hatch_CustomFluidBase.java
@@ -0,0 +1,214 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base;
+
+import static gregtech.api.enums.Textures.BlockIcons.FLUID_IN_SIGN;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_PIPE_IN;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidStack;
+
+import com.gtnewhorizons.modularui.common.widget.FluidSlotWidget;
+
+import gregtech.GT_Mod;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.FluidUtils;
+
+public class GT_MetaTileEntity_Hatch_CustomFluidBase extends GT_MetaTileEntity_Hatch {
+
+ public final Fluid mLockedFluid;
+ public final int mFluidCapacity;
+ protected FluidStack mLockedStack = null;
+ protected String mTempMod = null;
+
+ public GT_MetaTileEntity_Hatch_CustomFluidBase(Fluid aFluid, int aAmount, final int aID, final String aName,
+ final String aNameRegional) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ 6,
+ 3,
+ new String[] { "Fluid Input for Multiblocks", "Capacity: " + GT_Utility.formatNumbers(aAmount) + "L" });
+ this.mLockedFluid = aFluid;
+ this.mFluidCapacity = aAmount;
+ }
+
+ public GT_MetaTileEntity_Hatch_CustomFluidBase(Fluid aFluid, int aAmount, final String aName,
+ final String[] aDescription, final ITexture[][][] aTextures) {
+ super(aName, 6, 3, aDescription[0], aTextures);
+ this.mLockedFluid = aFluid;
+ this.mFluidCapacity = aAmount;
+ }
+
+ public boolean allowPutStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ if (side == aBaseMetaTileEntity.getFrontFacing() && aIndex == 0) {
+ FluidStack fs = GT_Utility.getFluidForFilledItem(aStack, true);
+ return fs != null && fs.getFluid() == this.mLockedFluid;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == aBaseMetaTileEntity.getFrontFacing() && aIndex == 1;
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return GT_Mod.gregtechproxy.mRenderIndicatorsOnHatch
+ ? new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_IN), TextureFactory.of(FLUID_IN_SIGN) }
+ : new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_IN) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return GT_Mod.gregtechproxy.mRenderIndicatorsOnHatch
+ ? new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_IN), TextureFactory.of(FLUID_IN_SIGN) }
+ : new ITexture[] { aBaseTexture, TextureFactory.of(OVERLAY_PIPE_IN) };
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ // return true;
+ return false;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysItemStack() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return false;
+ }
+
+ public void updateSlots() {
+ if (mInventory[getInputSlot()] != null && mInventory[getInputSlot()].stackSize <= 0)
+ mInventory[getInputSlot()] = null;
+ }
+
+ @Override
+ public int getTankPressure() {
+ return -100;
+ }
+
+ @Override
+ public int getCapacity() {
+ return this.mFluidCapacity;
+ }
+
+ @Override
+ public String[] getDescription() {
+ if (mLockedStack == null) {
+ mLockedStack = FluidUtils.getFluidStack(mLockedFluid, 1);
+ }
+ int aFluidTemp = 0;
+ boolean isSteam = false;
+ if (mLockedFluid != null) {
+ aFluidTemp = mLockedFluid.getTemperature();
+ mTempMod = mLockedFluid.getName();
+ }
+ if (mTempMod.equalsIgnoreCase("steam")) {
+ isSteam = true;
+ }
+
+ EnumChatFormatting aColour = EnumChatFormatting.BLUE;
+ if (aFluidTemp <= -3000) {
+ aColour = EnumChatFormatting.DARK_PURPLE;
+ } else if (aFluidTemp >= -2999 && aFluidTemp <= -500) {
+ aColour = EnumChatFormatting.DARK_BLUE;
+ } else if (aFluidTemp >= -499 && aFluidTemp <= -50) {
+ aColour = EnumChatFormatting.BLUE;
+ } else if (aFluidTemp >= 30 && aFluidTemp <= 300) {
+ aColour = EnumChatFormatting.AQUA;
+ } else if (aFluidTemp >= 301 && aFluidTemp <= 800) {
+ aColour = EnumChatFormatting.YELLOW;
+ } else if (aFluidTemp >= 801 && aFluidTemp <= 1500) {
+ aColour = EnumChatFormatting.GOLD;
+ } else if (aFluidTemp >= 1501) {
+ aColour = EnumChatFormatting.RED;
+ }
+ String aFluidName = "Accepted Fluid: " + aColour
+ + (mLockedStack != null ? mLockedStack.getLocalizedName() : "Empty")
+ + EnumChatFormatting.RESET;
+ return new String[] { "Fluid Input for " + (isSteam ? "Steam " : "") + "Multiblocks",
+ "Capacity: " + getCapacity() + "L", aFluidName, CORE.GT_Tooltip.get() };
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(final FluidStack aFluid) {
+ return this.mLockedFluid.getName()
+ .equals(
+ aFluid.getFluid()
+ .getName());
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(final IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_CustomFluidBase(
+ this.mLockedFluid,
+ this.mFluidCapacity,
+ this.mName,
+ this.mDescriptionArray,
+ this.mTextures);
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ protected FluidSlotWidget createFluidSlot() {
+ return super.createFluidSlot().setFilter(f -> f == mLockedFluid);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMetaTileEntity.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMetaTileEntity.java
new file mode 100644
index 0000000000..e260347ca5
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMetaTileEntity.java
@@ -0,0 +1,74 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base;
+
+import static gregtech.api.enums.GT_Values.GT;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.metatileentity.MetaTileEntity;
+
+public abstract class GregtechMetaTileEntity extends MetaTileEntity {
+
+ /**
+ * Value between [0 - 9] to describe the Tier of this Machine.
+ */
+ protected byte mTier;
+
+ /**
+ * A simple Description.
+ */
+ protected final String mDescription;
+
+ /**
+ * Contains all Textures used by this Block.
+ */
+ public final ITexture[][][] mTextures;
+
+ public GregtechMetaTileEntity(final int aID, final String aName, final String aNameRegional, final int aTier,
+ final int aInvSlotCount, final String aDescription, final ITexture... aTextures) {
+ super(aID, aName, aNameRegional, aInvSlotCount);
+ this.mTier = (byte) Math.max(0, Math.min(aTier, 9));
+ this.mDescription = aDescription;
+
+ // must always be the last call!
+ if (GT.isClientSide()) {
+ this.mTextures = this.getTextureSet(aTextures);
+ } else {
+ this.mTextures = null;
+ }
+ }
+
+ public GregtechMetaTileEntity(final String aName, final int aTier, final int aInvSlotCount,
+ final String aDescription, final ITexture[][][] aTextures) {
+ super(aName, aInvSlotCount);
+ this.mTier = (byte) aTier;
+ this.mDescription = aDescription;
+ this.mTextures = aTextures;
+ }
+
+ @Override
+ public byte getTileEntityBaseType() {
+ return (byte) (Math.min(3, this.mTier <= 0 ? 0 : 1 + ((this.mTier - 1) / 4)));
+ }
+
+ @Override
+ public long getInputTier() {
+ return this.mTier;
+ }
+
+ @Override
+ public long getOutputTier() {
+ return this.mTier;
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { this.mDescription };
+ }
+
+ /**
+ * Used Client Side to get a Texture Set for this Block. Called after setting the Tier and the Description so that
+ * those two are accessible.
+ *
+ * @param aTextures is the optional Array you can give to the Constructor.
+ */
+ public abstract ITexture[][][] getTextureSet(ITexture[] aTextures);
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMetaTransformerHiAmp.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMetaTransformerHiAmp.java
new file mode 100644
index 0000000000..c6a088fb1c
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMetaTransformerHiAmp.java
@@ -0,0 +1,117 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Transformer;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.PlayerUtils;
+
+public class GregtechMetaTransformerHiAmp extends GT_MetaTileEntity_Transformer {
+
+ private boolean mHalfMode = false;
+
+ public GregtechMetaTransformerHiAmp(int aID, String aName, String aNameRegional, int aTier, String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aDescription);
+ }
+
+ public GregtechMetaTransformerHiAmp(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ @Override
+ public long maxEUStore() {
+ return ((512L + gregtech.api.enums.GT_Values.V[(this.mTier + 1)] * 2L) * 8);
+ }
+
+ @Override
+ public long maxAmperesOut() {
+ if (this.mHalfMode) {
+ return ((getBaseMetaTileEntity().isAllowedToWork()) ? 8L : 2L);
+ }
+ return ((getBaseMetaTileEntity().isAllowedToWork()) ? 16L : 4L);
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ if (this.mHalfMode) {
+ return ((getBaseMetaTileEntity().isAllowedToWork()) ? 2L : 8L);
+ }
+ return ((getBaseMetaTileEntity().isAllowedToWork()) ? 4L : 16L);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(ITexture[] aTextures) {
+ ITexture[][][] rTextures = new ITexture[12][17][];
+ for (byte i = -1; i < 16; i++) {
+ rTextures[0][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_OUT[mTier] };
+ rTextures[1][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_OUT[mTier] };
+ rTextures[2][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_OUT[mTier] };
+ rTextures[3][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_IN_MULTI[mTier + 1] };
+ rTextures[4][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_IN_MULTI[mTier + 1] };
+ rTextures[5][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_IN_MULTI[mTier + 1] };
+ rTextures[6][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_IN[mTier] };
+ rTextures[7][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_IN[mTier] };
+ rTextures[8][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_IN[mTier] };
+ rTextures[9][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_OUT_MULTI[mTier + 1] };
+ rTextures[10][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_OUT_MULTI[mTier + 1] };
+ rTextures[11][i + 1] = new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[mTier][i + 1],
+ Textures.BlockIcons.OVERLAYS_ENERGY_OUT_MULTI[mTier + 1] };
+ }
+ return rTextures;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GregtechMetaTransformerHiAmp(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return ArrayUtils.addAll(
+ this.mDescriptionArray,
+ "Accepts 4A and outputs 16A",
+ "Toggle 2A/8A half-mode with Screwdriver",
+ CORE.GT_Tooltip.get());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setBoolean("mHalfMode", this.mHalfMode);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ this.mHalfMode = aNBT.getBoolean("mHalfMode");
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ this.mHalfMode = !mHalfMode;
+ if (this.mHalfMode) {
+ PlayerUtils.messagePlayer(aPlayer, "Transformer is now running at 2A:8A in/out Ratio.");
+ } else {
+ PlayerUtils.messagePlayer(aPlayer, "Transformer is now running at 4A:16A in/out Ratio.");
+ }
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java
new file mode 100644
index 0000000000..e756a92343
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_MultiBlockBase.java
@@ -0,0 +1,1799 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base;
+
+import static gregtech.api.enums.Mods.TecTech;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
+import java.util.function.BiConsumer;
+import java.util.function.BiPredicate;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.oredict.OreDictionary;
+
+import com.gtnewhorizon.structurelib.StructureLibAPI;
+import com.gtnewhorizon.structurelib.structure.AutoPlaceEnvironment;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import com.gtnewhorizon.structurelib.structure.StructureUtility;
+import com.gtnewhorizons.modularui.api.drawable.ItemDrawable;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+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.TextWidget;
+
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.VoidingMode;
+import gregtech.api.gui.modularui.GT_UITextures;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.IIconContainer;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBus;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Maintenance;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_OutputBus;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.IGT_HatchAdder;
+import gregtech.common.items.GT_MetaGenerated_Tool_01;
+import gregtech.common.tileentities.machines.IDualInputHatch;
+import gtPlusPlus.GTplusplus;
+import gtPlusPlus.GTplusplus.INIT_PHASE;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.minecraft.BlockPos;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+import gtPlusPlus.core.util.minecraft.PlayerUtils;
+import gtPlusPlus.core.util.reflect.ReflectionUtils;
+import gtPlusPlus.preloader.CORE_Preloader;
+import gtPlusPlus.preloader.asm.AsmConfig;
+import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_AirIntake;
+import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_InputBattery;
+import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_OutputBattery;
+import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Steam_BusInput;
+
+// Glee8e - 11/12/21 - 2:15pm
+// Yeah, now I see what's wrong. Someone inherited from GregtechMeta_MultiBlockBase instead of
+// GregtechMeta_MultiBlockBase<GregtechMetaTileEntity_IndustrialDehydrator> as it should have been
+// so any method in GregtechMetaTileEntity_IndustrialDehydrator would see generic field declared in
+// GregtechMeta_MultiBlockBase without generic parameter
+
+public abstract class GregtechMeta_MultiBlockBase<T extends GT_MetaTileEntity_ExtendedPowerMultiBlockBase<T>>
+ extends GT_MetaTileEntity_ExtendedPowerMultiBlockBase<T> {
+
+ public static final boolean DEBUG_DISABLE_CORES_TEMPORARILY = true;
+
+ public GT_Recipe mLastRecipe;
+ protected long mTotalRunTime = 0;
+
+ /**
+ * Don't use this for recipe input check, otherwise you'll get duplicated fluids
+ */
+ public ArrayList<GT_MetaTileEntity_Hatch_AirIntake> mAirIntakes = new ArrayList<>();
+
+ public ArrayList<GT_MetaTileEntity_Hatch_InputBattery> mChargeHatches = new ArrayList<>();
+ public ArrayList<GT_MetaTileEntity_Hatch_OutputBattery> mDischargeHatches = new ArrayList<>();
+ public ArrayList<GT_MetaTileEntity_Hatch> mAllEnergyHatches = new ArrayList<>();
+ public ArrayList<GT_MetaTileEntity_Hatch> mAllDynamoHatches = new ArrayList<>();
+
+ public GregtechMeta_MultiBlockBase(final int aID, final String aName, final String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GregtechMeta_MultiBlockBase(final String aName) {
+ super(aName);
+ }
+
+ private static int toStackCount(Entry<ItemStack, Integer> e) {
+ int tMaxStackSize = e.getKey()
+ .getMaxStackSize();
+ int tStackSize = e.getValue();
+ return (tStackSize + tMaxStackSize - 1) / tMaxStackSize;
+ }
+
+ public long getTotalRuntimeInTicks() {
+ return this.mTotalRunTime;
+ }
+
+ public abstract String getMachineType();
+
+ public String getMachineTooltip() {
+ return "Machine Type: " + EnumChatFormatting.YELLOW + getMachineType() + EnumChatFormatting.RESET;
+ }
+
+ public String[] getExtraInfoData() {
+ return new String[0];
+ }
+
+ @Override
+ public String[] getInfoData() {
+ ArrayList<String> mInfo = new ArrayList<>();
+ if (!this.getMetaName()
+ .equals("")) {
+ mInfo.add(this.getMetaName());
+ }
+
+ String[] extra = getExtraInfoData();
+
+ if (extra == null) {
+ extra = new String[0];
+ }
+ if (extra.length > 0) {
+ for (String s : extra) {
+ mInfo.add(s);
+ }
+ }
+
+ long seconds = (this.mTotalRunTime / 20);
+ int weeks = (int) (TimeUnit.SECONDS.toDays(seconds) / 7);
+ int days = (int) (TimeUnit.SECONDS.toDays(seconds) - 7 * weeks);
+ long hours = TimeUnit.SECONDS.toHours(seconds) - TimeUnit.DAYS.toHours(days)
+ - TimeUnit.DAYS.toHours(7L * weeks);
+ long minutes = TimeUnit.SECONDS.toMinutes(seconds) - (TimeUnit.SECONDS.toHours(seconds) * 60);
+ long second = TimeUnit.SECONDS.toSeconds(seconds) - (TimeUnit.SECONDS.toMinutes(seconds) * 60);
+
+ mInfo.add(getMachineTooltip());
+
+ // Lets borrow the GTNH handling
+
+ mInfo.add(
+ StatCollector.translateToLocal("GTPP.multiblock.progress") + ": "
+ + EnumChatFormatting.GREEN
+ + mProgresstime / 20
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + mMaxProgresstime / 20
+ + EnumChatFormatting.RESET
+ + " s");
+
+ if (!this.mAllEnergyHatches.isEmpty()) {
+ long storedEnergy = getStoredEnergyInAllEnergyHatches();
+ long maxEnergy = getMaxEnergyStorageOfAllEnergyHatches();
+ mInfo.add(StatCollector.translateToLocal("GTPP.multiblock.energy") + ":");
+ mInfo.add(
+ StatCollector.translateToLocal(
+ "" + EnumChatFormatting.GREEN
+ + Long.toString(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + Long.toString(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU"));
+
+ mInfo.add(StatCollector.translateToLocal("GTPP.multiblock.mei") + ":");
+ mInfo.add(
+ StatCollector.translateToLocal(
+ "" + EnumChatFormatting.YELLOW
+ + Long.toString(getMaxInputVoltage())
+ + EnumChatFormatting.RESET
+ + " EU/t(*2A) "
+ + StatCollector.translateToLocal("GTPP.machines.tier")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Values.VN[GT_Utility.getTier(getMaxInputVoltage())]
+ + EnumChatFormatting.RESET));;
+ }
+ if (!this.mAllDynamoHatches.isEmpty()) {
+ long storedEnergy = getStoredEnergyInAllDynamoHatches();
+ long maxEnergy = getMaxEnergyStorageOfAllDynamoHatches();
+ mInfo.add(StatCollector.translateToLocal("GTPP.multiblock.energy") + " In Dynamos:");
+ mInfo.add(
+ StatCollector.translateToLocal(
+ "" + EnumChatFormatting.GREEN
+ + Long.toString(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + Long.toString(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU"));
+ }
+
+ if (-lEUt > 0) {
+ mInfo.add(StatCollector.translateToLocal("GTPP.multiblock.usage") + ":");
+ mInfo.add(
+ StatCollector
+ .translateToLocal("" + EnumChatFormatting.RED + (-lEUt) + EnumChatFormatting.RESET + " EU/t"));
+ } else {
+ mInfo.add(StatCollector.translateToLocal("GTPP.multiblock.generation") + ":");
+ mInfo.add(
+ StatCollector
+ .translateToLocal("" + EnumChatFormatting.GREEN + lEUt + EnumChatFormatting.RESET + " EU/t"));
+ }
+
+ mInfo.add(
+ StatCollector.translateToLocal("GTPP.multiblock.problems") + ": "
+ + EnumChatFormatting.RED
+ + (getIdealStatus() - getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GTPP.multiblock.efficiency")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + Float.toString(mEfficiency / 100.0F)
+ + EnumChatFormatting.RESET
+ + " %");
+
+ if (this.getPollutionPerSecond(null) > 0) {
+ int mPollutionReduction = getPollutionReductionForAllMufflers();
+ mInfo.add(
+ StatCollector.translateToLocal("GTPP.multiblock.pollution") + ": "
+ + EnumChatFormatting.RED
+ + this.getPollutionPerSecond(null)
+ + EnumChatFormatting.RESET
+ + "/sec");
+ mInfo.add(
+ StatCollector.translateToLocal("GTPP.multiblock.pollutionreduced") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %");
+ }
+
+ mInfo.add(
+ StatCollector.translateToLocal("GTPP.CC.parallel") + ": "
+ + EnumChatFormatting.GREEN
+ + (getMaxParallelRecipes())
+ + EnumChatFormatting.RESET);
+
+ mInfo.add(
+ "Total Time Since Built: " + EnumChatFormatting.DARK_GREEN
+ + Integer.toString(weeks)
+ + EnumChatFormatting.RESET
+ + " Weeks, "
+ + EnumChatFormatting.DARK_GREEN
+ + Integer.toString(days)
+ + EnumChatFormatting.RESET
+ + " Days, ");
+ mInfo.add(
+ EnumChatFormatting.DARK_GREEN + Long.toString(hours)
+ + EnumChatFormatting.RESET
+ + " Hours, "
+ + EnumChatFormatting.DARK_GREEN
+ + Long.toString(minutes)
+ + EnumChatFormatting.RESET
+ + " Minutes, "
+ + EnumChatFormatting.DARK_GREEN
+ + Long.toString(second)
+ + EnumChatFormatting.RESET
+ + " Seconds.");
+ mInfo.add("Total Time in ticks: " + EnumChatFormatting.DARK_GREEN + Long.toString(this.mTotalRunTime));
+
+ String[] mInfo2 = mInfo.toArray(new String[mInfo.size()]);
+ return mInfo2;
+ }
+
+ public int getPollutionReductionForAllMufflers() {
+ int mPollutionReduction = 0;
+ for (GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ mPollutionReduction = Math.max(calculatePollutionReductionForHatch(tHatch, 100), mPollutionReduction);
+ }
+ return mPollutionReduction;
+ }
+
+ public long getStoredEnergyInAllEnergyHatches() {
+ long storedEnergy = 0;
+ for (GT_MetaTileEntity_Hatch tHatch : filterValidMTEs(mAllEnergyHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ }
+ return storedEnergy;
+ }
+
+ public long getMaxEnergyStorageOfAllEnergyHatches() {
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch tHatch : filterValidMTEs(mAllEnergyHatches)) {
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+ return maxEnergy;
+ }
+
+ public long getStoredEnergyInAllDynamoHatches() {
+ long storedEnergy = 0;
+ for (GT_MetaTileEntity_Hatch tHatch : filterValidMTEs(mAllDynamoHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ }
+ return storedEnergy;
+ }
+
+ public long getMaxEnergyStorageOfAllDynamoHatches() {
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch tHatch : filterValidMTEs(mAllDynamoHatches)) {
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+ return maxEnergy;
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ private String[] aCachedToolTip;
+
+ /*
+ * private final String aRequiresMuffler = "1x Muffler Hatch"; private final String aRequiresCoreModule =
+ * "1x Core Module"; private final String aRequiresMaint = "1x Maintanence Hatch";
+ */
+
+ public static final String TAG_HIDE_HATCHES = "TAG_HIDE_HATCHES";
+ public static final String TAG_HIDE_MAINT = "TAG_HIDE_MAINT";
+ public static final String TAG_HIDE_POLLUTION = "TAG_HIDE_POLLUTION";
+ public static final String TAG_HIDE_MACHINE_TYPE = "TAG_HIDE_MACHINE_TYPE";
+
+ public abstract int getMaxParallelRecipes();
+
+ @Override
+ public boolean isCorrectMachinePart(final ItemStack paramItemStack) {
+ return true;
+ }
+
+ @Override
+ public int getDamageToComponent(final ItemStack paramItemStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack p0) {
+ return false;
+ }
+
+ /**
+ * A Static {@link Method} object which holds the current status of logging.
+ */
+ public static Method aLogger = null;
+
+ public void log(String s) {
+ if (!AsmConfig.disableAllLogging) {
+ if (CORE_Preloader.DEBUG_MODE) {
+ Logger.INFO(s);
+ } else {
+ Logger.MACHINE_INFO(s);
+ }
+ }
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(GT_Utility.roundUpVoltage(this.getMaxInputVoltage()));
+ logic.setAvailableAmperage(1L);
+ }
+
+ public long getMaxInputEnergy() {
+ long rEnergy = 0;
+ if (mEnergyHatches.size() == 1) // so it only takes 1 amp is only 1 hatch is present so it works like most gt
+ // multies
+ return mEnergyHatches.get(0)
+ .getBaseMetaTileEntity()
+ .getInputVoltage();
+ for (GT_MetaTileEntity_Hatch_Energy tHatch : filterValidMTEs(mEnergyHatches))
+ rEnergy += tHatch.getBaseMetaTileEntity()
+ .getInputVoltage()
+ * tHatch.getBaseMetaTileEntity()
+ .getInputAmperage();
+ return rEnergy;
+ }
+
+ public boolean isMachineRunning() {
+ boolean aRunning = this.getBaseMetaTileEntity()
+ .isActive();
+ // log("Queried Multiblock is currently running: "+aRunning);
+ return aRunning;
+ }
+
+ @Override
+ public void onPostTick(final IGregTechTileEntity aBaseMetaTileEntity, final long aTick) {
+
+ // Time Counter
+ if (aBaseMetaTileEntity.isServerSide()) {
+ this.mTotalRunTime++;
+ }
+
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (this.mUpdate == 1 || this.mStartUpCheck == 1) {
+ this.mChargeHatches.clear();
+ this.mDischargeHatches.clear();
+ this.mAirIntakes.clear();
+ this.mTecTechEnergyHatches.clear();
+ this.mTecTechDynamoHatches.clear();
+ this.mAllEnergyHatches.clear();
+ this.mAllDynamoHatches.clear();
+ }
+ }
+
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public void explodeMultiblock() {
+ MetaTileEntity tTileEntity;
+ for (final Iterator<GT_MetaTileEntity_Hatch_InputBattery> localIterator = this.mChargeHatches
+ .iterator(); localIterator.hasNext(); tTileEntity.getBaseMetaTileEntity()
+ .doExplosion(gregtech.api.enums.GT_Values.V[8])) {
+ tTileEntity = localIterator.next();
+ }
+ tTileEntity = null;
+ for (final Iterator<GT_MetaTileEntity_Hatch_OutputBattery> localIterator = this.mDischargeHatches
+ .iterator(); localIterator.hasNext(); tTileEntity.getBaseMetaTileEntity()
+ .doExplosion(gregtech.api.enums.GT_Values.V[8])) {
+ tTileEntity = localIterator.next();
+ }
+ tTileEntity = null;
+ for (final Iterator<GT_MetaTileEntity_Hatch> localIterator = this.mTecTechDynamoHatches
+ .iterator(); localIterator.hasNext(); tTileEntity.getBaseMetaTileEntity()
+ .doExplosion(gregtech.api.enums.GT_Values.V[8])) {
+ tTileEntity = localIterator.next();
+ }
+ tTileEntity = null;
+ for (final Iterator<GT_MetaTileEntity_Hatch> localIterator = this.mTecTechEnergyHatches
+ .iterator(); localIterator.hasNext(); tTileEntity.getBaseMetaTileEntity()
+ .doExplosion(gregtech.api.enums.GT_Values.V[8])) {
+ tTileEntity = localIterator.next();
+ }
+
+ super.explodeMultiblock();
+ }
+
+ protected boolean setGUIItemStack(ItemStack aNewGuiSlotContents) {
+ boolean result = false;
+ if (this.mInventory[1] == null) {
+ this.mInventory[1] = aNewGuiSlotContents != null ? aNewGuiSlotContents.copy() : null;
+ this.depleteInput(aNewGuiSlotContents);
+ this.updateSlots();
+ result = true;
+ }
+ return result;
+ }
+
+ public ItemStack findItemInInventory(Item aSearchStack) {
+ return findItemInInventory(aSearchStack, 0);
+ }
+
+ public ItemStack findItemInInventory(Item aSearchStack, int aMeta) {
+ return findItemInInventory(ItemUtils.simpleMetaStack(aSearchStack, aMeta, 1));
+ }
+
+ public ItemStack findItemInInventory(ItemStack aSearchStack) {
+ if (aSearchStack != null && this.mInputBusses.size() > 0) {
+ for (GT_MetaTileEntity_Hatch_InputBus bus : this.mInputBusses) {
+ if (bus != null) {
+ for (ItemStack uStack : bus.mInventory) {
+ if (uStack != null) {
+ if (aSearchStack.getClass()
+ .isInstance(uStack.getItem())) {
+ return uStack;
+ }
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Deplete fluid input from a set of restricted hatches. This assumes these hatches can store nothing else but your
+ * expected fluid
+ */
+ protected boolean depleteInputFromRestrictedHatches(Collection<GT_MetaTileEntity_Hatch_CustomFluidBase> aHatches,
+ int aAmount) {
+ for (final GT_MetaTileEntity_Hatch_CustomFluidBase tHatch : filterValidMTEs(aHatches)) {
+ FluidStack tLiquid = tHatch.getFluid();
+ if (tLiquid == null || tLiquid.amount < aAmount) {
+ continue;
+ }
+ tLiquid = tHatch.drain(aAmount, false);
+ if (tLiquid != null && tLiquid.amount >= aAmount) {
+ tLiquid = tHatch.drain(aAmount, true);
+ return tLiquid != null && tLiquid.amount >= aAmount;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void updateSlots() {
+ for (final GT_MetaTileEntity_Hatch_InputBattery tHatch : filterValidMTEs(this.mChargeHatches)) {
+ tHatch.updateSlots();
+ }
+ for (final GT_MetaTileEntity_Hatch_OutputBattery tHatch : filterValidMTEs(this.mDischargeHatches)) {
+ tHatch.updateSlots();
+ }
+ super.updateSlots();
+ }
+
+ /**
+ * Causes a Random Maint. Issue.
+ *
+ * @return {@link boolean} - Returns whether or not an issue was caused, should always be true.
+ */
+ public boolean causeMaintenanceIssue() {
+ boolean b = false;
+ switch (this.getBaseMetaTileEntity()
+ .getRandomNumber(6)) {
+ case 0 -> {
+ this.mWrench = false;
+ b = true;
+ }
+ case 1 -> {
+ this.mScrewdriver = false;
+ b = true;
+ }
+ case 2 -> {
+ this.mSoftHammer = false;
+ b = true;
+ }
+ case 3 -> {
+ this.mHardHammer = false;
+ b = true;
+ }
+ case 4 -> {
+ this.mSolderingTool = false;
+ b = true;
+ }
+ case 5 -> {
+ this.mCrowbar = false;
+ b = true;
+ }
+ }
+ return b;
+ }
+
+ public void fixAllMaintenanceIssue() {
+ this.mCrowbar = true;
+ this.mWrench = true;
+ this.mHardHammer = true;
+ this.mSoftHammer = true;
+ this.mSolderingTool = true;
+ this.mScrewdriver = true;
+ }
+
+ public boolean checkHatch() {
+ return mMaintenanceHatches.size() <= 1
+ && (this.getPollutionPerSecond(null) > 0 ? !mMufflerHatches.isEmpty() : true);
+ }
+
+ @Override
+ public void clearHatches() {
+ super.clearHatches();
+ this.mChargeHatches.clear();
+ this.mDischargeHatches.clear();
+ this.mAirIntakes.clear();
+ this.mTecTechEnergyHatches.clear();
+ this.mTecTechDynamoHatches.clear();
+ this.mAllEnergyHatches.clear();
+ this.mAllDynamoHatches.clear();
+ }
+
+ public <E> boolean addToMachineListInternal(ArrayList<E> aList, final IGregTechTileEntity aTileEntity,
+ final int aBaseCasingIndex) {
+ return addToMachineListInternal(aList, getMetaTileEntity(aTileEntity), aBaseCasingIndex);
+ }
+
+ public <E> boolean addToMachineListInternal(ArrayList<E> aList, final IMetaTileEntity aTileEntity,
+ final int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ }
+
+ // Check type
+ /*
+ * Class <?> aHatchType = ReflectionUtils.getTypeOfGenericObject(aList); if
+ * (!aHatchType.isInstance(aTileEntity)) { return false; }
+ */
+
+ // Try setRecipeMap
+
+ try {
+ if (aTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ resetRecipeMapForHatch((GT_MetaTileEntity_Hatch) aTileEntity, getRecipeMap());
+ }
+ if (aTileEntity instanceof GT_MetaTileEntity_Hatch_InputBus) {
+ resetRecipeMapForHatch((GT_MetaTileEntity_Hatch) aTileEntity, getRecipeMap());
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ }
+
+ if (aList.isEmpty()) {
+ if (aTileEntity instanceof GT_MetaTileEntity_Hatch) {
+ if (GTplusplus.CURRENT_LOAD_PHASE == INIT_PHASE.STARTED) {
+ log(
+ "Adding " + aTileEntity.getInventoryName()
+ + " at "
+ + new BlockPos(aTileEntity.getBaseMetaTileEntity()).getLocationString());
+ }
+ updateTexture(aTileEntity, aBaseCasingIndex);
+ return aList.add((E) aTileEntity);
+ }
+ } else {
+ IGregTechTileEntity aCur = aTileEntity.getBaseMetaTileEntity();
+ if (aList.contains(aTileEntity)) {
+ log(
+ "Found Duplicate " + aTileEntity.getInventoryName()
+ + " @ "
+ + new BlockPos(aCur).getLocationString());
+ return false;
+ }
+ BlockPos aCurPos = new BlockPos(aCur);
+ boolean aExists = false;
+ for (E m : aList) {
+ IGregTechTileEntity b = ((IMetaTileEntity) m).getBaseMetaTileEntity();
+ if (b != null) {
+ BlockPos aPos = new BlockPos(b);
+ if (aPos != null) {
+ if (aCurPos.equals(aPos)) {
+ if (GTplusplus.CURRENT_LOAD_PHASE == INIT_PHASE.STARTED) {
+ log("Found Duplicate " + b.getInventoryName() + " at " + aPos.getLocationString());
+ }
+ return false;
+ }
+ }
+ }
+ }
+ if (aTileEntity instanceof GT_MetaTileEntity_Hatch) {
+ if (GTplusplus.CURRENT_LOAD_PHASE == INIT_PHASE.STARTED) {
+ log("Adding " + aCur.getInventoryName() + " at " + aCurPos.getLocationString());
+ }
+ updateTexture(aTileEntity, aBaseCasingIndex);
+ return aList.add((E) aTileEntity);
+ }
+ }
+ return false;
+ }
+
+ private IMetaTileEntity getMetaTileEntity(final IGregTechTileEntity aTileEntity) {
+ if (aTileEntity == null) {
+ return null;
+ }
+ final IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ return aMetaTileEntity;
+ }
+
+ @Override
+ public boolean addToMachineList(final IGregTechTileEntity aTileEntity, final int aBaseCasingIndex) {
+ return addToMachineList(getMetaTileEntity(aTileEntity), aBaseCasingIndex);
+ }
+
+ public boolean addToMachineList(final IMetaTileEntity aMetaTileEntity, final int aBaseCasingIndex) {
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+
+ // Use this to determine the correct value, then update the hatch texture after.
+ boolean aDidAdd = false;
+
+ // Handle Custom Hatches
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_InputBattery) {
+ log("Found GT_MetaTileEntity_Hatch_InputBattery");
+ aDidAdd = addToMachineListInternal(mChargeHatches, aMetaTileEntity, aBaseCasingIndex);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_OutputBattery) {
+ log("Found GT_MetaTileEntity_Hatch_OutputBattery");
+ aDidAdd = addToMachineListInternal(mDischargeHatches, aMetaTileEntity, aBaseCasingIndex);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_AirIntake) {
+ aDidAdd = addToMachineListInternal(mAirIntakes, aMetaTileEntity, aBaseCasingIndex)
+ && addToMachineListInternal(mInputHatches, aMetaTileEntity, aBaseCasingIndex);
+ }
+
+ // Handle TT Multi-A Energy Hatches
+ else if (TecTech.isModLoaded() && isThisHatchMultiEnergy(aMetaTileEntity)) {
+ log("Found isThisHatchMultiEnergy");
+ aDidAdd = addToMachineListInternal(mTecTechEnergyHatches, aMetaTileEntity, aBaseCasingIndex);
+ updateMasterEnergyHatchList(aMetaTileEntity);
+ }
+
+ // Handle TT Multi-A Dynamos
+ else if (TecTech.isModLoaded() && isThisHatchMultiDynamo(aMetaTileEntity)) {
+ log("Found isThisHatchMultiDynamo");
+ aDidAdd = addToMachineListInternal(mTecTechDynamoHatches, aMetaTileEntity, aBaseCasingIndex);
+ updateMasterDynamoHatchList(aMetaTileEntity);
+ }
+
+ // Handle Fluid Hatches using seperate logic
+ else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input)
+ aDidAdd = addToMachineListInternal(mInputHatches, aMetaTileEntity, aBaseCasingIndex);
+ else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output)
+ aDidAdd = addToMachineListInternal(mOutputHatches, aMetaTileEntity, aBaseCasingIndex);
+
+ // Process Remaining hatches using Vanilla GT Logic
+ else if (aMetaTileEntity instanceof IDualInputHatch hatch) {
+ hatch.updateCraftingIcon(this.getMachineCraftingIcon());
+ aDidAdd = addToMachineListInternal(mDualInputHatches, aMetaTileEntity, aBaseCasingIndex);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_InputBus)
+ aDidAdd = addToMachineListInternal(mInputBusses, aMetaTileEntity, aBaseCasingIndex);
+ else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_OutputBus)
+ aDidAdd = addToMachineListInternal(mOutputBusses, aMetaTileEntity, aBaseCasingIndex);
+ else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Energy) {
+ aDidAdd = addToMachineListInternal(mEnergyHatches, aMetaTileEntity, aBaseCasingIndex);
+ updateMasterEnergyHatchList(aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Dynamo) {
+ aDidAdd = addToMachineListInternal(mDynamoHatches, aMetaTileEntity, aBaseCasingIndex);
+ updateMasterDynamoHatchList(aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Maintenance)
+ aDidAdd = addToMachineListInternal(mMaintenanceHatches, aMetaTileEntity, aBaseCasingIndex);
+ else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Muffler)
+ aDidAdd = addToMachineListInternal(mMufflerHatches, aMetaTileEntity, aBaseCasingIndex);
+
+ // return super.addToMachineList(aTileEntity, aBaseCasingIndex);
+ return aDidAdd;
+ }
+
+ @Override
+ public boolean addMaintenanceToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Maintenance) {
+ return addToMachineList(aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addMufflerToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Muffler) {
+ return addToMachineList(aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addInputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input
+ || aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_InputBus) {
+ return addToMachineList(aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addOutputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output
+ || aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_OutputBus) {
+ return addToMachineList(aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ public boolean addAirIntakeToMachineList(final IGregTechTileEntity aTileEntity, final int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_AirIntake) {
+ return addToMachineList(aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ public boolean addFluidInputToMachineList(final IGregTechTileEntity aTileEntity, final int aBaseCasingIndex) {
+ return addFluidInputToMachineList(getMetaTileEntity(aTileEntity), aBaseCasingIndex);
+ }
+
+ public boolean addFluidInputToMachineList(final IMetaTileEntity aMetaTileEntity, final int aBaseCasingIndex) {
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ return addToMachineList(aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ public boolean clearRecipeMapForAllInputHatches() {
+ return resetRecipeMapForAllInputHatches(null);
+ }
+
+ public boolean resetRecipeMapForAllInputHatches() {
+ return resetRecipeMapForAllInputHatches(this.getRecipeMap());
+ }
+
+ public boolean resetRecipeMapForAllInputHatches(RecipeMap<?> aMap) {
+ int cleared = 0;
+ for (GT_MetaTileEntity_Hatch_Input g : this.mInputHatches) {
+ if (resetRecipeMapForHatch(g, aMap)) {
+ cleared++;
+ }
+ }
+ for (GT_MetaTileEntity_Hatch_InputBus g : this.mInputBusses) {
+ if (resetRecipeMapForHatch(g, aMap)) {
+ cleared++;
+ }
+ }
+ return cleared > 0;
+ }
+
+ public boolean resetRecipeMapForHatch(IGregTechTileEntity aTileEntity, RecipeMap<?> aMap) {
+ try {
+ final IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input
+ || aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_InputBus
+ || aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Steam_BusInput) {
+ return resetRecipeMapForHatch((GT_MetaTileEntity_Hatch) aMetaTileEntity, aMap);
+ } else {
+ return false;
+ }
+ } catch (Throwable t) {
+ t.printStackTrace();
+ return false;
+ }
+ }
+
+ public boolean resetRecipeMapForHatch(GT_MetaTileEntity_Hatch aTileEntity, RecipeMap<?> aMap) {
+ if (aTileEntity == null) {
+ return false;
+ }
+ final IMetaTileEntity aMetaTileEntity = aTileEntity;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input
+ || aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_InputBus
+ || aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Steam_BusInput) {
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ ((GT_MetaTileEntity_Hatch_Input) aMetaTileEntity).mRecipeMap = null;
+ ((GT_MetaTileEntity_Hatch_Input) aMetaTileEntity).mRecipeMap = aMap;
+ if (aMap != null) {
+ log("Remapped Input Hatch to " + aMap.unlocalizedName + ".");
+ } else {
+ log("Cleared Input Hatch.");
+ }
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_InputBus) {
+ ((GT_MetaTileEntity_Hatch_InputBus) aMetaTileEntity).mRecipeMap = null;
+ ((GT_MetaTileEntity_Hatch_InputBus) aMetaTileEntity).mRecipeMap = aMap;
+ if (aMap != null) {
+ log("Remapped Input Bus to " + aMap.unlocalizedName + ".");
+ } else {
+ log("Cleared Input Bus.");
+ }
+ } else {
+ ((GT_MetaTileEntity_Hatch_Steam_BusInput) aMetaTileEntity).mRecipeMap = null;
+ ((GT_MetaTileEntity_Hatch_Steam_BusInput) aMetaTileEntity).mRecipeMap = aMap;
+ if (aMap != null) {
+ log("Remapped Input Bus to " + aMap.unlocalizedName + ".");
+ } else {
+ log("Cleared Input Bus.");
+ }
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ);
+ clearRecipeMapForAllInputHatches();
+ onModeChangeByScrewdriver(side, aPlayer, aX, aY, aZ);
+ resetRecipeMapForAllInputHatches();
+ }
+
+ public void onModeChangeByScrewdriver(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {}
+
+ /**
+ * Enable Texture Casing Support if found in GT 5.09
+ */
+ public boolean updateTexture(final IGregTechTileEntity aTileEntity, int aCasingID) {
+ return updateTexture(getMetaTileEntity(aTileEntity), aCasingID);
+ }
+
+ /**
+ * Enable Texture Casing Support if found in GT 5.09
+ */
+ public boolean updateTexture(final IMetaTileEntity aTileEntity, int aCasingID) {
+ try { // gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch.updateTexture(int)
+
+ final IMetaTileEntity aMetaTileEntity = aTileEntity;
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+ Method mProper = ReflectionUtils.getMethod(GT_MetaTileEntity_Hatch.class, "updateTexture", int.class);
+ if (mProper != null) {
+ if (GT_MetaTileEntity_Hatch.class.isInstance(aMetaTileEntity)) {
+ mProper.setAccessible(true);
+ mProper.invoke(aMetaTileEntity, aCasingID);
+ // log("Good Method Call for updateTexture.");
+ return true;
+ }
+ } else {
+ log("Bad Method Call for updateTexture.");
+ if (GT_MetaTileEntity_Hatch.class.isInstance(aMetaTileEntity)) {
+ if (aCasingID <= Byte.MAX_VALUE) {
+ ((GT_MetaTileEntity_Hatch) aTileEntity).updateTexture(aCasingID);
+ log(
+ "Good Method Call for updateTexture. Used fallback method of setting mMachineBlock as casing id was <= 128.");
+ return true;
+ } else {
+ log("updateTexture returning false. 1.2");
+ }
+ } else {
+ log("updateTexture returning false. 1.3");
+ }
+ }
+ log("updateTexture returning false. 1");
+ return false;
+ } catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
+ log("updateTexture returning false.");
+ log("updateTexture returning false. 2");
+ e.printStackTrace();
+ return false;
+ }
+ }
+
+ /**
+ * TecTech Support
+ */
+
+ /**
+ * This is the array Used to Store the Tectech Multi-Amp Dynamo hatches.
+ */
+ public ArrayList<GT_MetaTileEntity_Hatch> mTecTechDynamoHatches = new ArrayList<>();
+
+ /**
+ * This is the array Used to Store the Tectech Multi-Amp Energy hatches.
+ */
+ public ArrayList<GT_MetaTileEntity_Hatch> mTecTechEnergyHatches = new ArrayList<>();
+
+ /**
+ * TecTech Multi-Amp Dynamo Support
+ *
+ * @param aTileEntity - The Dynamo Hatch
+ * @param aBaseCasingIndex - Casing Texture
+ * @return
+ */
+ public boolean addMultiAmpDynamoToMachineList(final IGregTechTileEntity aTileEntity, final int aBaseCasingIndex) {
+ final IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+ if (isThisHatchMultiDynamo(aTileEntity)) {
+ return addToMachineListInternal(mTecTechDynamoHatches, aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ public boolean isThisHatchMultiDynamo(IGregTechTileEntity aTileEntity) {
+ return isThisHatchMultiDynamo(getMetaTileEntity(aTileEntity));
+ }
+
+ public boolean isThisHatchMultiDynamo(IMetaTileEntity aMetaTileEntity) {
+ Class<?> mDynamoClass;
+ mDynamoClass = ReflectionUtils
+ .getClass("com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_DynamoMulti");
+ if (mDynamoClass != null) {
+ if (mDynamoClass.isInstance(aMetaTileEntity)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addDynamoToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Dynamo || isThisHatchMultiDynamo(aMetaTileEntity)) {
+ return addToMachineList(aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ private boolean updateMasterDynamoHatchList(IMetaTileEntity aMetaTileEntity) {
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch aHatch) {
+ return mAllDynamoHatches.add(aHatch);
+ }
+ return false;
+ }
+
+ /**
+ * TecTech Multi-Amp Energy Hatch Support
+ *
+ * @param aTileEntity - The Energy Hatch
+ * @param aBaseCasingIndex - Casing Texture
+ * @return
+ */
+ public boolean addMultiAmpEnergyToMachineList(final IGregTechTileEntity aTileEntity, final int aBaseCasingIndex) {
+ final IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+ if (isThisHatchMultiEnergy(aMetaTileEntity)) {
+ return addToMachineListInternal(mTecTechEnergyHatches, aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ public boolean isThisHatchMultiEnergy(IGregTechTileEntity aTileEntity) {
+ return isThisHatchMultiEnergy(getMetaTileEntity(aTileEntity));
+ }
+
+ public boolean isThisHatchMultiEnergy(IMetaTileEntity aMetaTileEntity) {
+ Class<?> mDynamoClass;
+ mDynamoClass = ReflectionUtils
+ .getClass("com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti");
+ if (mDynamoClass != null) {
+ if (mDynamoClass.isInstance(aMetaTileEntity)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean addEnergyInputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = getMetaTileEntity(aTileEntity);
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Energy || isThisHatchMultiEnergy(aMetaTileEntity)) {
+ return addToMachineList(aMetaTileEntity, aBaseCasingIndex);
+ }
+ return false;
+ }
+
+ private boolean updateMasterEnergyHatchList(IMetaTileEntity aMetaTileEntity) {
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch aHatch) {
+ return mAllEnergyHatches.add(aHatch);
+ }
+ return false;
+ }
+
+ /**
+ * Pollution Management
+ */
+ public int calculatePollutionReductionForHatch(GT_MetaTileEntity_Hatch_Muffler hatch, int poll) {
+ return hatch.calculatePollutionReduction(poll);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setLong("mTotalRunTime", this.mTotalRunTime);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mTotalRunTime = aNBT.getLong("mTotalRunTime");
+ if (aNBT.hasKey("mVoidExcess")) {
+ // backward compatibility
+ voidingMode = aNBT.getBoolean("mVoidExcess") ? VoidingMode.VOID_ALL : VoidingMode.VOID_NONE;
+ }
+ if (aNBT.hasKey("mUseMultiparallelMode")) {
+ // backward compatibility
+ batchMode = aNBT.getBoolean("mUseMultiparallelMode");
+ }
+ }
+
+ /**
+ * Custom Tool Handling
+ */
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer, ForgeDirection side,
+ float aX, float aY, float aZ) {
+ // Do Things
+ if (this.getBaseMetaTileEntity()
+ .isServerSide()) {
+ // Logger.INFO("Right Clicked Controller.");
+ ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+ if (tCurrentItem != null) {
+ // Logger.INFO("Holding Item.");
+ if (tCurrentItem.getItem() instanceof GT_MetaGenerated_Tool) {
+ // Logger.INFO("Is GT_MetaGenerated_Tool.");
+ int[] aOreID = OreDictionary.getOreIDs(tCurrentItem);
+ for (int id : aOreID) {
+ // Plunger
+ if (OreDictionary.getOreName(id)
+ .equals("craftingToolPlunger")) {
+ // Logger.INFO("Is Plunger.");
+ return onPlungerRightClick(aPlayer, side, aX, aY, aZ);
+ }
+ }
+ }
+ }
+ }
+ // Do Super
+ boolean aSuper = super.onRightclick(aBaseMetaTileEntity, aPlayer, side, aX, aY, aZ);
+ return aSuper;
+ }
+
+ public boolean onPlungerRightClick(EntityPlayer aPlayer, ForgeDirection side, float aX, float aY, float aZ) {
+ int aHatchIndex = 0;
+ PlayerUtils.messagePlayer(aPlayer, "Trying to clear " + mOutputHatches.size() + " output hatches.");
+ for (GT_MetaTileEntity_Hatch_Output hatch : this.mOutputHatches) {
+ if (hatch.mFluid != null) {
+ PlayerUtils.messagePlayer(
+ aPlayer,
+ "Clearing " + hatch.mFluid.amount
+ + "L of "
+ + hatch.mFluid.getLocalizedName()
+ + " from hatch "
+ + aHatchIndex
+ + ".");
+ hatch.mFluid = null;
+ }
+ aHatchIndex++;
+ }
+ return aHatchIndex > 0;
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ if (aPlayer.isSneaking()) {
+ batchMode = !batchMode;
+ if (batchMode) {
+ GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("misc.BatchModeTextOn"));
+ } else {
+ GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("misc.BatchModeTextOff"));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onSolderingToolRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ if (supportsVoidProtection() && wrenchingSide == getBaseMetaTileEntity().getFrontFacing()) {
+ Set<VoidingMode> allowed = getAllowedVoidingModes();
+ setVoidingMode(getVoidingMode().nextInCollection(allowed));
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.gui.button.voiding_mode") + " "
+ + StatCollector.translateToLocal(getVoidingMode().getTransKey()));
+ return true;
+ } else return super.onSolderingToolRightClick(side, wrenchingSide, aPlayer, aX, aY, aZ);
+ }
+
+ @Override
+ public void onServerStart() {
+ super.onServerStart();
+ tryTickWaitTimerDown();
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ tryTickWaitTimerDown();
+ }
+
+ @Override
+ public void onPreTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPreTick(aBaseMetaTileEntity, aTick);
+ tryTickWaitTimerDown();
+ }
+
+ @Override
+ public void onCreated(ItemStack aStack, World aWorld, EntityPlayer aPlayer) {
+ super.onCreated(aStack, aWorld, aPlayer);
+ tryTickWaitTimerDown();
+ }
+
+ private void tryTickWaitTimerDown() {
+ /*
+ * if (mStartUpCheck > 10) { mStartUpCheck = 10; }
+ */
+ }
+
+ // Only support to use meta to tier
+
+ /**
+ * accept meta [0, maxMeta)
+ *
+ * @param maxMeta exclusive
+ */
+ public static <T> IStructureElement<T> addTieredBlock(Block aBlock, BiConsumer<T, Integer> aSetTheMeta,
+ Function<T, Integer> aGetTheMeta, int maxMeta) {
+ return addTieredBlock(aBlock, (t, i) -> {
+ aSetTheMeta.accept(t, i);
+ return true;
+ }, aGetTheMeta, 0, maxMeta);
+ }
+
+ /**
+ *
+ * @param minMeta inclusive
+ * @param maxMeta exclusive
+ */
+ public static <T> IStructureElement<T> addTieredBlock(Block aBlock, BiConsumer<T, Integer> aSetTheMeta,
+ Function<T, Integer> aGetTheMeta, int minMeta, int maxMeta) {
+ return addTieredBlock(aBlock, (t, i) -> {
+ aSetTheMeta.accept(t, i);
+ return true;
+ }, aGetTheMeta, minMeta, maxMeta);
+ }
+
+ /**
+ *
+ * @param minMeta inclusive
+ * @param maxMeta exclusive
+ */
+ public static <T> IStructureElement<T> addTieredBlock(Block aBlock, BiPredicate<T, Integer> aSetTheMeta,
+ Function<T, Integer> aGetTheMeta, int minMeta, int maxMeta) {
+
+ return new IStructureElement<>() {
+
+ @Override
+ public boolean check(T t, World world, int x, int y, int z) {
+ Block tBlock = world.getBlock(x, y, z);
+ if (aBlock == tBlock) {
+ Integer currentMeta = aGetTheMeta.apply(t);
+ int newMeta = tBlock.getDamageValue(world, x, y, z) + 1;
+ if (newMeta > maxMeta || newMeta < minMeta + 1) return false;
+ if (currentMeta == 0) {
+ return aSetTheMeta.test(t, newMeta);
+ } else {
+ return currentMeta == newMeta;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
+ StructureLibAPI.hintParticle(world, x, y, z, aBlock, getMeta(trigger));
+ return true;
+ }
+
+ @Override
+ public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
+ return world.setBlock(x, y, z, aBlock, getMeta(trigger), 3);
+ }
+
+ private int getMeta(ItemStack trigger) {
+ int meta = trigger.stackSize;
+ if (meta <= 0) meta = minMeta;
+ if (meta + minMeta >= maxMeta) meta = maxMeta - 1 - minMeta;
+ return meta + minMeta;
+ }
+
+ @Nullable
+ @Override
+ public BlocksToPlace getBlocksToPlace(T t, World world, int x, int y, int z, ItemStack trigger,
+ AutoPlaceEnvironment env) {
+ return BlocksToPlace.create(aBlock, getMeta(trigger));
+ }
+
+ @Override
+ public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
+ AutoPlaceEnvironment env) {
+ if (world.getBlock(x, y, z) == aBlock) {
+ if (world.getBlockMetadata(x, y, z) == getMeta(trigger)) {
+ return PlaceResult.SKIP;
+ }
+ return PlaceResult.REJECT;
+ }
+ return StructureUtility.survivalPlaceBlock(
+ aBlock,
+ getMeta(trigger),
+ world,
+ x,
+ y,
+ z,
+ env.getSource(),
+ env.getActor(),
+ env.getChatter());
+ }
+ };
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int aColorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { getCasingTexture(), TextureFactory.builder()
+ .addIcon(getActiveOverlay())
+ .extFacing()
+ .build() };
+ return new ITexture[] { getCasingTexture(), TextureFactory.builder()
+ .addIcon(getInactiveOverlay())
+ .extFacing()
+ .build() };
+ }
+ return new ITexture[] { getCasingTexture() };
+ }
+
+ protected IIconContainer getActiveOverlay() {
+ return null;
+ }
+
+ protected IIconContainer getInactiveOverlay() {
+ return null;
+ }
+
+ protected ITexture getCasingTexture() {
+ return Textures.BlockIcons.getCasingTextureForId(getCasingTextureId());
+ }
+
+ protected int getCasingTextureId() {
+ return 0;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ if (doesBindPlayerInventory()) {
+ super.addUIWidgets(builder, buildContext);
+ } else {
+ addNoPlayerInventoryUI(builder, buildContext);
+ }
+ }
+
+ private static final Materials GOOD = Materials.Uranium;
+ private static final Materials BAD = Materials.Plutonium;
+ private static final ConcurrentHashMap<String, ItemStack> mToolStacks = new ConcurrentHashMap<>();
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+
+ protected void addNoPlayerInventoryUI(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.PICTURE_SCREEN_BLACK)
+ .setPos(3, 4)
+ .setSize(152, 159));
+ for (int i = 0; i < 9; i++) {
+ builder.widget(
+ new DrawableWidget().setDrawable(GT_UITextures.BUTTON_STANDARD)
+ .setPos(155, 3 + i * 18)
+ .setSize(18, 18));
+ }
+
+ DynamicPositionedColumn screenElements = new DynamicPositionedColumn();
+ drawTextsNoPlayerInventory(screenElements);
+ builder.widget(screenElements);
+
+ setupToolDisplay();
+
+ builder.widget(
+ new ItemDrawable(() -> mToolStacks.get(mWrench + "WRENCH")).asWidget()
+ .setPos(156, 58))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mWrench, val -> mWrench = val));
+ builder.widget(
+ new ItemDrawable(() -> mToolStacks.get(mCrowbar + "CROWBAR")).asWidget()
+ .setPos(156, 76))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mCrowbar, val -> mCrowbar = val));
+ builder.widget(
+ new ItemDrawable(() -> mToolStacks.get(mHardHammer + "HARDHAMMER")).asWidget()
+ .setPos(156, 94))
+ .widget(
+ new TextWidget("H").setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(167, 103))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mHardHammer, val -> mHardHammer = val));
+ builder.widget(
+ new ItemDrawable(() -> mToolStacks.get(mSoftHammer + "SOFTHAMMER")).asWidget()
+ .setPos(156, 112))
+ .widget(
+ new TextWidget("M").setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(167, 121))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mSoftHammer, val -> mSoftHammer = val));
+ builder.widget(
+ new ItemDrawable(() -> mToolStacks.get(mScrewdriver + "SCREWDRIVER")).asWidget()
+ .setPos(156, 130))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mScrewdriver, val -> mScrewdriver = val));
+ builder.widget(
+ new ItemDrawable(() -> mToolStacks.get(mSolderingTool + "SOLDERING_IRON_LV")).asWidget()
+ .setPos(156, 148))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mSolderingTool, val -> mSolderingTool = val));
+ builder.widget(
+ new ItemDrawable(() -> mToolStacks.get(getBaseMetaTileEntity().isActive() + "GLASS")).asWidget()
+ .setPos(156, 22))
+ .widget(
+ TextWidget.dynamicString(() -> getBaseMetaTileEntity().isActive() ? "On" : "Off")
+ .setSynced(false)
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setPos(157, 31))
+ .widget(
+ new FakeSyncWidget.BooleanSyncer(
+ () -> getBaseMetaTileEntity().isActive(),
+ val -> getBaseMetaTileEntity().setActive(val)));
+ }
+
+ protected void drawTextsNoPlayerInventory(DynamicPositionedColumn screenElements) {
+ screenElements.setSynced(false)
+ .setSpace(0)
+ .setPos(6, 7);
+
+ screenElements
+ .widget(
+ new TextWidget(GT_Utility.trans("138", "Incomplete Structure.")).setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> !mMachine))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> mMachine, val -> mMachine = val))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal("GTPP.machines.input") + " "
+ + StatCollector.translateToLocal("GTPP.machines.tier")
+ + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Values.VOLTAGE_NAMES[(int) getInputTier()])
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine && getInputTier() > 0))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal("GTPP.machines.output") + " "
+ + StatCollector.translateToLocal("GTPP.machines.tier")
+ + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Values.VOLTAGE_NAMES[(int) getOutputTier()])
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine && getOutputTier() > 0))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal("GTPP.multiblock.progress") + ": "
+ + EnumChatFormatting.GREEN
+ + getBaseMetaTileEntity().getProgress() / 20
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + getBaseMetaTileEntity().getMaxProgress() / 20
+ + EnumChatFormatting.RESET
+ + " s")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("GTPP.multiblock.energy") + ":")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal(
+ "" + EnumChatFormatting.GREEN
+ + getStoredEnergyInAllEnergyHatches()
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + getMaxEnergyStorageOfAllEnergyHatches()
+ + EnumChatFormatting.RESET
+ + " EU"))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("GTPP.multiblock.usage") + ":")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine && getLastRecipeEU() > 0 && getLastRecipeDuration() > 0))
+ .widget(
+ TextWidget.dynamicString(
+ () -> StatCollector.translateToLocal(
+ "" + EnumChatFormatting.RED + -getLastRecipeEU() + EnumChatFormatting.RESET + " EU/t/parallel"))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine && getLastRecipeEU() > 0 && getLastRecipeDuration() > 0))
+ .widget(
+ TextWidget.dynamicString(() -> StatCollector.translateToLocal("GTPP.multiblock.generation") + ":")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine && getLastRecipeEU() < 0 && getLastRecipeDuration() > 0))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal(
+ "" + EnumChatFormatting.GREEN
+ + getLastRecipeEU()
+ + EnumChatFormatting.RESET
+ + " EU/t/parallel"))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine && getLastRecipeEU() < 0 && getLastRecipeDuration() > 0))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal("GTPP.multiblock.duration") + ": "
+ + EnumChatFormatting.RED
+ + getLastRecipeDuration()
+ + EnumChatFormatting.RESET
+ + " ticks")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine && getLastRecipeEU() != 0 && getLastRecipeDuration() > 0))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal("GTPP.multiblock.specialvalue") + ": "
+ + EnumChatFormatting.RED
+ + getLastRecipeEU()
+ + EnumChatFormatting.RESET
+ + "")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(
+ widget -> mMachine && getLastRecipeEU() != 0
+ && getLastRecipeDuration() > 0
+ && (mLastRecipe != null ? mLastRecipe.mSpecialValue : 0) > 0))
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("GTPP.multiblock.mei") + ":")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal(
+ "" + EnumChatFormatting.YELLOW
+ + getMaxInputVoltage()
+ + EnumChatFormatting.RESET
+ + " EU/t(*2A) "
+ + StatCollector.translateToLocal("GTPP.machines.tier")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Values.VN[GT_Utility.getTier(getMaxInputVoltage())]
+ + EnumChatFormatting.RESET))
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal("GTPP.multiblock.efficiency") + ": "
+ + EnumChatFormatting.YELLOW
+ + (mEfficiency / 100.0F)
+ + EnumChatFormatting.RESET
+ + " %")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal("GTPP.multiblock.pollution") + ": "
+ + EnumChatFormatting.RED
+ + (getPollutionPerTick(null) * 20)
+ + EnumChatFormatting.RESET
+ + "/sec")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> StatCollector.translateToLocal("GTPP.multiblock.pollutionreduced") + ": "
+ + EnumChatFormatting.GREEN
+ + getPollutionReductionForAllMufflers()
+ + EnumChatFormatting.RESET
+ + " %")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ new TextWidget("Total Time Since Built: ").setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> "" + EnumChatFormatting.DARK_GREEN
+ + getRuntimeWeeksDisplay()
+ + EnumChatFormatting.RESET
+ + " Weeks,")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> "" + EnumChatFormatting.DARK_GREEN
+ + getRuntimeDaysDisplay()
+ + EnumChatFormatting.RESET
+ + " Days,")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> "" + EnumChatFormatting.DARK_GREEN
+ + getRuntimeHoursDisplay()
+ + EnumChatFormatting.RESET
+ + " Hours,")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> "" + EnumChatFormatting.DARK_GREEN
+ + getRuntimeMinutesDisplay()
+ + EnumChatFormatting.RESET
+ + " Minutes,")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine))
+ .widget(
+ TextWidget
+ .dynamicString(
+ () -> "" + EnumChatFormatting.DARK_GREEN
+ + getRuntimeSecondsDisplay()
+ + EnumChatFormatting.RESET
+ + " Seconds")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> mMachine));
+ }
+
+ protected int getLastRecipeEU() {
+ return mLastRecipe != null ? mLastRecipe.mEUt : 0;
+ }
+
+ protected int getLastRecipeDuration() {
+ return mLastRecipe != null ? mLastRecipe.mDuration : 0;
+ }
+
+ protected long getRuntimeSeconds() {
+ return getTotalRuntimeInTicks() / 20;
+ }
+
+ protected long getRuntimeWeeksDisplay() {
+ return TimeUnit.SECONDS.toDays(getRuntimeSeconds()) / 7;
+ }
+
+ protected long getRuntimeDaysDisplay() {
+ return TimeUnit.SECONDS.toDays(getRuntimeSeconds()) - 7 * getRuntimeWeeksDisplay();
+ }
+
+ protected long getRuntimeHoursDisplay() {
+ return TimeUnit.SECONDS.toHours(getRuntimeSeconds()) - TimeUnit.DAYS.toHours(getRuntimeDaysDisplay())
+ - TimeUnit.DAYS.toHours(7 * getRuntimeWeeksDisplay());
+ }
+
+ protected long getRuntimeMinutesDisplay() {
+ return TimeUnit.SECONDS.toMinutes(getRuntimeSeconds()) - (TimeUnit.SECONDS.toHours(getRuntimeSeconds()) * 60);
+ }
+
+ protected long getRuntimeSecondsDisplay() {
+ return TimeUnit.SECONDS.toSeconds(getRuntimeSeconds()) - (TimeUnit.SECONDS.toMinutes(getRuntimeSeconds()) * 60);
+ }
+
+ protected void setupToolDisplay() {
+ if (!mToolStacks.isEmpty()) return;
+
+ mToolStacks.put(
+ true + "WRENCH",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.WRENCH, 1, GOOD, Materials.Tungsten, null));
+ mToolStacks.put(
+ true + "CROWBAR",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.CROWBAR, 1, GOOD, Materials.Tungsten, null));
+ mToolStacks.put(
+ true + "HARDHAMMER",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.HARDHAMMER, 1, GOOD, Materials.Tungsten, null));
+ mToolStacks.put(
+ true + "SOFTHAMMER",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.SOFTMALLET, 1, GOOD, Materials.Tungsten, null));
+ mToolStacks.put(
+ true + "SCREWDRIVER",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.SCREWDRIVER, 1, GOOD, Materials.Tungsten, null));
+ mToolStacks.put(
+ true + "SOLDERING_IRON_LV",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.SOLDERING_IRON_LV, 1, GOOD, Materials.Tungsten, null));
+
+ mToolStacks.put(
+ false + "WRENCH",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.WRENCH, 1, BAD, Materials.Tungsten, null));
+ mToolStacks.put(
+ false + "CROWBAR",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.CROWBAR, 1, BAD, Materials.Tungsten, null));
+ mToolStacks.put(
+ false + "HARDHAMMER",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.HARDHAMMER, 1, BAD, Materials.Tungsten, null));
+ mToolStacks.put(
+ false + "SOFTHAMMER",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.SOFTMALLET, 1, BAD, Materials.Tungsten, null));
+ mToolStacks.put(
+ false + "SCREWDRIVER",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.SCREWDRIVER, 1, BAD, Materials.Tungsten, null));
+ mToolStacks.put(
+ false + "SOLDERING_IRON_LV",
+ GT_MetaGenerated_Tool_01.INSTANCE
+ .getToolWithStats(GT_MetaGenerated_Tool_01.SOLDERING_IRON_LV, 1, BAD, Materials.Tungsten, null));
+
+ ItemStack aGlassPane1 = ItemUtils.getItemStackOfAmountFromOreDict("paneGlassRed", 1);
+ ItemStack aGlassPane2 = ItemUtils.getItemStackOfAmountFromOreDict("paneGlassLime", 1);
+ mToolStacks.put("falseGLASS", aGlassPane1);
+ mToolStacks.put("trueGLASS", aGlassPane2);
+ }
+
+ public enum GTPPHatchElement implements IHatchElement<GregtechMeta_MultiBlockBase<?>> {
+
+ AirIntake(GregtechMeta_MultiBlockBase::addAirIntakeToMachineList, GT_MetaTileEntity_Hatch_AirIntake.class) {
+
+ @Override
+ public long count(GregtechMeta_MultiBlockBase<?> t) {
+ return t.mAirIntakes.size();
+ }
+ },
+ TTDynamo(GregtechMeta_MultiBlockBase::addMultiAmpDynamoToMachineList,
+ "com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_DynamoMulti") {
+
+ @Override
+ public long count(GregtechMeta_MultiBlockBase<?> t) {
+ return t.mTecTechDynamoHatches.size();
+ }
+ },
+ TTEnergy(GregtechMeta_MultiBlockBase::addMultiAmpEnergyToMachineList,
+ "com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti") {
+
+ @Override
+ public long count(GregtechMeta_MultiBlockBase<?> t) {
+ return t.mTecTechEnergyHatches.size();
+ }
+ },;
+
+ @SuppressWarnings("unchecked")
+ private static <T> Class<T> retype(Class<?> clazz) {
+ return (Class<T>) clazz;
+ }
+
+ private final List<? extends Class<? extends IMetaTileEntity>> mMteClasses;
+ private final IGT_HatchAdder<? super GregtechMeta_MultiBlockBase<?>> mAdder;
+
+ @SafeVarargs
+ GTPPHatchElement(IGT_HatchAdder<? super GregtechMeta_MultiBlockBase<?>> aAdder,
+ Class<? extends IMetaTileEntity>... aMteClasses) {
+ this.mMteClasses = Arrays.asList(aMteClasses);
+ this.mAdder = aAdder;
+ }
+
+ GTPPHatchElement(IGT_HatchAdder<? super GregtechMeta_MultiBlockBase<?>> aAdder, String... aClassNames) {
+ this.mMteClasses = Arrays.stream(aClassNames)
+ .map(ReflectionUtils::getClass)
+ .filter(Objects::nonNull)
+ .<Class<? extends IMetaTileEntity>>map(GTPPHatchElement::retype)
+ .collect(Collectors.toList());
+ this.mAdder = aAdder;
+ }
+
+ @Override
+ public List<? extends Class<? extends IMetaTileEntity>> mteClasses() {
+ return mMteClasses;
+ }
+
+ @Override
+ public IGT_HatchAdder<? super GregtechMeta_MultiBlockBase<?>> adder() {
+ return mAdder;
+ }
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_SteamMultiBase.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_SteamMultiBase.java
new file mode 100644
index 0000000000..6e501815f0
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/GregtechMeta_SteamMultiBase.java
@@ -0,0 +1,428 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base;
+
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+import static gregtech.api.util.GT_Utility.formatNumbers;
+import static mcp.mobius.waila.api.SpecialChars.GREEN;
+import static mcp.mobius.waila.api.SpecialChars.RED;
+import static mcp.mobius.waila.api.SpecialChars.RESET;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import net.minecraft.inventory.IInventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import gregtech.GT_Mod;
+import gregtech.api.enums.Textures;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.util.GT_HatchElementBuilder;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.GT_Waila;
+import gregtech.api.util.IGT_HatchAdder;
+import gregtech.api.util.shutdown.ShutDownReasonRegistry;
+import gtPlusPlus.core.util.minecraft.FluidUtils;
+import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Steam_BusInput;
+import gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Steam_BusOutput;
+import mcp.mobius.waila.api.IWailaConfigHandler;
+import mcp.mobius.waila.api.IWailaDataAccessor;
+
+public abstract class GregtechMeta_SteamMultiBase<T extends GregtechMeta_SteamMultiBase<T>>
+ extends GregtechMeta_MultiBlockBase<T> {
+
+ public ArrayList<GT_MetaTileEntity_Hatch_Steam_BusInput> mSteamInputs = new ArrayList<>();
+ public ArrayList<GT_MetaTileEntity_Hatch_Steam_BusOutput> mSteamOutputs = new ArrayList<>();
+ public ArrayList<GT_MetaTileEntity_Hatch_CustomFluidBase> mSteamInputFluids = new ArrayList<>();
+
+ protected static final String TT_steaminputbus = StatCollector.translateToLocal("GTPP.MBTT.SteamInputBus");
+ protected static final String TT_steamoutputbus = StatCollector.translateToLocal("GTPP.MBTT.SteamOutputBus");
+ protected static final String TT_steamhatch = StatCollector.translateToLocal("GTPP.MBTT.SteamHatch");
+
+ public GregtechMeta_SteamMultiBase(String aName) {
+ super(aName);
+ }
+
+ public GregtechMeta_SteamMultiBase(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ @Override
+ public ITexture[] getTexture(final IGregTechTileEntity aBaseMetaTileEntity, final ForgeDirection side,
+ final ForgeDirection facing, final int aColorIndex, final boolean aActive, final boolean aRedstone) {
+ if (side == facing) {
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(getCasingTextureIndex()),
+ aActive ? getFrontOverlayActive() : getFrontOverlay() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(getCasingTextureIndex()) };
+ }
+
+ protected abstract GT_RenderedTexture getFrontOverlay();
+
+ protected abstract GT_RenderedTexture getFrontOverlayActive();
+
+ private int getCasingTextureIndex() {
+ return 10;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic().setMaxParallelSupplier(this::getMaxParallelRecipes);
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(V[1]);
+ // We need to trick the GT_ParallelHelper we have enough amps for all recipe parallels.
+ logic.setAvailableAmperage(getMaxParallelRecipes());
+ logic.setAmperageOC(false);
+ }
+
+ public ArrayList<FluidStack> getAllSteamStacks() {
+ ArrayList<FluidStack> aFluids = new ArrayList<>();
+ FluidStack aSteam = FluidUtils.getSteam(1);
+ for (FluidStack aFluid : this.getStoredFluids()) {
+ if (aFluid.isFluidEqual(aSteam)) {
+ aFluids.add(aFluid);
+ }
+ }
+ return aFluids;
+ }
+
+ public int getTotalSteamStored() {
+ int aSteam = 0;
+ for (FluidStack aFluid : getAllSteamStacks()) {
+ aSteam += aFluid.amount;
+ }
+ return aSteam;
+ }
+
+ public boolean tryConsumeSteam(int aAmount) {
+ if (getTotalSteamStored() <= 0) {
+ return false;
+ } else {
+ return this.depleteInput(FluidUtils.getSteam(aAmount));
+ }
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack arg0) {
+ return 0;
+ }
+
+ @Override
+ public void onPostTick(final IGregTechTileEntity aBaseMetaTileEntity, final long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (this.mUpdate == 1 || this.mStartUpCheck == 1) {
+ this.mSteamInputs.clear();
+ this.mSteamOutputs.clear();
+ this.mSteamInputFluids.clear();
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ /**
+ * Called every tick the Machine runs
+ */
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ fixAllMaintenanceIssue();
+ if (lEUt < 0) {
+ long aSteamVal = ((-lEUt * 10000) / Math.max(1000, mEfficiency));
+ // Logger.INFO("Trying to drain "+aSteamVal+" steam per tick.");
+ if (!tryConsumeSteam((int) aSteamVal)) {
+ stopMachine(ShutDownReasonRegistry.POWER_LOSS);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean addToMachineList(final IGregTechTileEntity aTileEntity, final int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ log("Invalid IGregTechTileEntity");
+ return false;
+ }
+ final IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ log("Invalid IMetaTileEntity");
+ return false;
+ }
+
+ // Use this to determine the correct value, then update the hatch texture after.
+ boolean aDidAdd = false;
+
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_CustomFluidBase) {
+ log("Adding Steam Input Hatch");
+ aDidAdd = addToMachineListInternal(mSteamInputFluids, aMetaTileEntity, aBaseCasingIndex);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Steam_BusInput) {
+ log(
+ "Trying to set recipe map. Type: "
+ + (getRecipeMap() != null ? getRecipeMap().unlocalizedName : "Null"));
+ this.resetRecipeMapForHatch(aTileEntity, getRecipeMap());
+ log("Adding Steam Input Bus");
+ aDidAdd = addToMachineListInternal(mSteamInputs, aMetaTileEntity, aBaseCasingIndex);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Steam_BusOutput) {
+ log("Adding Steam Output Bus");
+ aDidAdd = addToMachineListInternal(mSteamOutputs, aMetaTileEntity, aBaseCasingIndex);
+ }
+
+ return aDidAdd;
+ }
+
+ /*
+ * Handle I/O with custom hatches
+ */
+
+ @Override
+ public boolean depleteInput(FluidStack aLiquid) {
+ if (aLiquid == null) return false;
+ for (GT_MetaTileEntity_Hatch_CustomFluidBase tHatch : filterValidMTEs(mSteamInputFluids)) {
+ FluidStack tLiquid = tHatch.getFluid();
+ if (tLiquid != null && tLiquid.isFluidEqual(aLiquid)) {
+ tLiquid = tHatch.drain(aLiquid.amount, false);
+ if (tLiquid != null && tLiquid.amount >= aLiquid.amount) {
+ tLiquid = tHatch.drain(aLiquid.amount, true);
+ return tLiquid != null && tLiquid.amount >= aLiquid.amount;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean depleteInput(ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack)) return false;
+ FluidStack aLiquid = GT_Utility.getFluidForFilledItem(aStack, true);
+ if (aLiquid != null) return depleteInput(aLiquid);
+ for (GT_MetaTileEntity_Hatch_CustomFluidBase tHatch : filterValidMTEs(mSteamInputFluids)) {
+ if (GT_Utility.areStacksEqual(
+ aStack,
+ tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(0))) {
+ if (tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(0).stackSize >= aStack.stackSize) {
+ tHatch.getBaseMetaTileEntity()
+ .decrStackSize(0, aStack.stackSize);
+ return true;
+ }
+ }
+ }
+ for (GT_MetaTileEntity_Hatch_Steam_BusInput tHatch : filterValidMTEs(mSteamInputs)) {
+ tHatch.mRecipeMap = getRecipeMap();
+ for (int i = tHatch.getBaseMetaTileEntity()
+ .getSizeInventory() - 1; i >= 0; i--) {
+ if (GT_Utility.areStacksEqual(
+ aStack,
+ tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i))) {
+ if (tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(0).stackSize >= aStack.stackSize) {
+ tHatch.getBaseMetaTileEntity()
+ .decrStackSize(0, aStack.stackSize);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public ArrayList<FluidStack> getStoredFluids() {
+ ArrayList<FluidStack> rList = new ArrayList<>();
+ for (GT_MetaTileEntity_Hatch_CustomFluidBase tHatch : filterValidMTEs(mSteamInputFluids)) {
+ if (tHatch.getFillableStack() != null) {
+ rList.add(tHatch.getFillableStack());
+ }
+ }
+ return rList;
+ }
+
+ @Override
+ public ArrayList<ItemStack> getStoredInputs() {
+ ArrayList<ItemStack> rList = new ArrayList<>();
+ for (GT_MetaTileEntity_Hatch_Steam_BusInput tHatch : filterValidMTEs(mSteamInputs)) {
+ tHatch.mRecipeMap = getRecipeMap();
+ for (int i = tHatch.getBaseMetaTileEntity()
+ .getSizeInventory() - 1; i >= 0; i--) {
+ if (tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i) != null) {
+ rList.add(
+ tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i));
+ }
+ }
+ }
+ return rList;
+ }
+
+ @Override
+ public boolean addOutput(ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack)) return false;
+ aStack = GT_Utility.copy(aStack);
+ boolean outputSuccess = true;
+ while (outputSuccess && aStack.stackSize > 0) {
+ outputSuccess = false;
+ ItemStack single = aStack.splitStack(1);
+ for (GT_MetaTileEntity_Hatch_Steam_BusOutput tHatch : filterValidMTEs(mSteamOutputs)) {
+ if (!outputSuccess) {
+ for (int i = tHatch.getSizeInventory() - 1; i >= 0 && !outputSuccess; i--) {
+ if (tHatch.getBaseMetaTileEntity()
+ .addStackToSlot(i, single)) outputSuccess = true;
+ }
+ }
+ }
+ for (GT_MetaTileEntity_Hatch_Output tHatch : filterValidMTEs(mOutputHatches)) {
+ if (!outputSuccess && tHatch.outputsItems()) {
+ if (tHatch.getBaseMetaTileEntity()
+ .addStackToSlot(1, single)) outputSuccess = true;
+ }
+ }
+ }
+ return outputSuccess;
+ }
+
+ @Override
+ public ArrayList<ItemStack> getStoredOutputs() {
+ ArrayList<ItemStack> rList = new ArrayList<>();
+ for (GT_MetaTileEntity_Hatch_Steam_BusOutput tHatch : filterValidMTEs(mSteamOutputs)) {
+ for (int i = tHatch.getBaseMetaTileEntity()
+ .getSizeInventory() - 1; i >= 0; i--) {
+ rList.add(
+ tHatch.getBaseMetaTileEntity()
+ .getStackInSlot(i));
+ }
+ }
+ return rList;
+ }
+
+ @Override
+ public List<ItemStack> getItemOutputSlots(ItemStack[] toOutput) {
+ List<ItemStack> ret = new ArrayList<>();
+ for (final GT_MetaTileEntity_Hatch tBus : filterValidMTEs(mSteamOutputs)) {
+ final IInventory tBusInv = tBus.getBaseMetaTileEntity();
+ for (int i = 0; i < tBusInv.getSizeInventory(); i++) {
+ ret.add(tBus.getStackInSlot(i));
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public void updateSlots() {
+ for (GT_MetaTileEntity_Hatch_CustomFluidBase tHatch : filterValidMTEs(mSteamInputFluids)) tHatch.updateSlots();
+ for (GT_MetaTileEntity_Hatch_Steam_BusInput tHatch : filterValidMTEs(mSteamInputs)) tHatch.updateSlots();
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return false;
+ }
+
+ @Override
+ public void clearHatches() {
+ super.clearHatches();
+ mSteamInputFluids.clear();
+ mSteamInputs.clear();
+ mSteamOutputs.clear();
+ }
+
+ @Override
+ public boolean resetRecipeMapForAllInputHatches(RecipeMap<?> aMap) {
+ boolean ret = super.resetRecipeMapForAllInputHatches(aMap);
+ for (GT_MetaTileEntity_Hatch_Steam_BusInput hatch : mSteamInputs) {
+ if (resetRecipeMapForHatch(hatch, aMap)) {
+ ret = true;
+ }
+ }
+ return ret;
+ }
+
+ @Override
+ public void getWailaBody(ItemStack itemStack, List<String> currentTip, IWailaDataAccessor accessor,
+ IWailaConfigHandler config) {
+ final NBTTagCompound tag = accessor.getNBTData();
+
+ if (tag.getBoolean("incompleteStructure")) {
+ currentTip.add(RED + "** INCOMPLETE STRUCTURE **" + RESET);
+ }
+ currentTip.add(
+ (tag.getBoolean("hasProblems") ? (RED + "** HAS PROBLEMS **") : GREEN + "Running Fine") + RESET
+ + " Efficiency: "
+ + tag.getFloat("efficiency")
+ + "%");
+
+ boolean isActive = tag.getBoolean("isActive");
+ if (isActive) {
+ long actualEnergyUsage = tag.getLong("energyUsage");
+ if (actualEnergyUsage > 0) {
+ currentTip.add(
+ StatCollector.translateToLocalFormatted("GTPP.waila.steam.use", formatNumbers(actualEnergyUsage)));
+ }
+ }
+ currentTip.add(
+ GT_Waila.getMachineProgressString(isActive, tag.getInteger("maxProgress"), tag.getInteger("progress")));
+ // Show ns on the tooltip
+ if (GT_Mod.gregtechproxy.wailaAverageNS && tag.hasKey("averageNS")) {
+ int tAverageTime = tag.getInteger("averageNS");
+ currentTip.add("Average CPU load of ~" + formatNumbers(tAverageTime) + " ns");
+ }
+ super.getMTEWailaBody(itemStack, currentTip, accessor, config);
+ }
+
+ protected static <T extends GregtechMeta_SteamMultiBase<T>> GT_HatchElementBuilder<T> buildSteamInput(
+ Class<T> typeToken) {
+ return buildHatchAdder(typeToken).adder(GregtechMeta_SteamMultiBase::addToMachineList)
+ .hatchIds(31040)
+ .shouldReject(t -> !t.mSteamInputFluids.isEmpty());
+ }
+
+ protected enum SteamHatchElement implements IHatchElement<GregtechMeta_SteamMultiBase<?>> {
+
+ InputBus_Steam {
+
+ @Override
+ public List<? extends Class<? extends IMetaTileEntity>> mteClasses() {
+ return Collections.singletonList(GT_MetaTileEntity_Hatch_Steam_BusInput.class);
+ }
+
+ @Override
+ public long count(GregtechMeta_SteamMultiBase<?> t) {
+ return t.mSteamInputs.size();
+ }
+ },
+ OutputBus_Steam {
+
+ @Override
+ public List<? extends Class<? extends IMetaTileEntity>> mteClasses() {
+ return Collections.singletonList(GT_MetaTileEntity_Hatch_Steam_BusOutput.class);
+ }
+
+ @Override
+ public long count(GregtechMeta_SteamMultiBase<?> t) {
+ return t.mSteamOutputs.size();
+ }
+ },;
+
+ @Override
+ public IGT_HatchAdder<? super GregtechMeta_SteamMultiBase<?>> adder() {
+ return GregtechMeta_SteamMultiBase::addToMachineList;
+ }
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechMetaBoilerBase.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechMetaBoilerBase.java
new file mode 100644
index 0000000000..3f0d8d1ec1
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechMetaBoilerBase.java
@@ -0,0 +1,361 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.generators;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Items;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidHandler;
+
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SoundResource;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_OreDictUnificator;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.util.math.MathUtils;
+
+public abstract class GregtechMetaBoilerBase extends GT_MetaTileEntity_BasicTank {
+
+ public int mTemperature = 20;
+ public int mProcessingEnergy = 0;
+ public int mLossTimer = 0;
+ public FluidStack mSteam = null;
+ public boolean mHadNoWater = false;
+ public long RI = MathUtils.randLong(5L, 30L);
+
+ public GregtechMetaBoilerBase(final int aID, final String aName, final String aNameRegional,
+ final String aDescription, final ITexture... aTextures) {
+ super(aID, aName, aNameRegional, 0, 4, aDescription, aTextures);
+ }
+
+ public GregtechMetaBoilerBase(final String aName, final int aTier, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, aTier, 4, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexture(final IGregTechTileEntity aBaseMetaTileEntity, final ForgeDirection side,
+ final ForgeDirection facing, final int aColorIndex, final boolean aActive, final boolean aRedstone) {
+ ITexture[] tmp = this.mTextures[side.offsetY == 0 ? side != facing ? 2 : ((byte) (aActive ? 4 : 3))
+ : side.ordinal()][aColorIndex + 1];
+ if ((side != facing) && (tmp.length == 2)) {
+ tmp = new ITexture[] { tmp[0] };
+ }
+ return tmp;
+ }
+
+ @Override
+ public boolean isElectric() {
+ return false;
+ }
+
+ @Override
+ public boolean isPneumatic() {
+ return false;
+ }
+
+ @Override
+ public boolean isSteampowered() {
+ return false;
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isFacingValid(final ForgeDirection facing) {
+ return facing.offsetY == 0;
+ }
+
+ @Override
+ public boolean isAccessAllowed(final EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public boolean isValidSlot(final int aIndex) {
+ return true;
+ }
+
+ @Override
+ public int getProgresstime() {
+ return this.mTemperature;
+ }
+
+ @Override
+ public int maxProgresstime() {
+ return 500;
+ }
+
+ @Override
+ public boolean onRightclick(final IGregTechTileEntity aBaseMetaTileEntity, final EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isClientSide()) {
+ return true;
+ }
+ if (aPlayer != null) {
+ if (GT_Utility.areStacksEqual(aPlayer.getCurrentEquippedItem(), new ItemStack(Items.water_bucket, 1))) {
+ this.fill(Materials.Water.getFluid(1000 * aPlayer.getCurrentEquippedItem().stackSize), true);
+ aPlayer.getCurrentEquippedItem()
+ .func_150996_a(Items.bucket);
+ } else {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return true;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysItemStack() {
+ return false;
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return false;
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(final FluidStack aFluid) {
+ return GT_ModHandler.isWater(aFluid);
+ }
+
+ @Override
+ public FluidStack getDrainableStack() {
+ return this.mSteam;
+ }
+
+ @Override
+ public FluidStack setDrainableStack(final FluidStack aFluid) {
+ this.mSteam = aFluid;
+ return this.mSteam;
+ }
+
+ @Override
+ public boolean isDrainableStackSeparate() {
+ return true;
+ }
+
+ @Override
+ public boolean allowCoverOnSide(final ForgeDirection side, final GT_ItemStack aCover) {
+ return GregTech_API.getCoverBehaviorNew(aCover.toStack())
+ .isSimpleCover();
+ }
+
+ @Override
+ public void saveNBTData(final NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mLossTimer", this.mLossTimer);
+ aNBT.setInteger("mTemperature", this.mTemperature);
+ aNBT.setInteger("mProcessingEnergy", this.mProcessingEnergy);
+ if (this.mSteam != null) {
+ try {
+ aNBT.setTag("mSteam", this.mSteam.writeToNBT(new NBTTagCompound()));
+ } catch (final Throwable e) {}
+ }
+ }
+
+ @Override
+ public void loadNBTData(final NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mLossTimer = aNBT.getInteger("mLossTimer");
+ this.mTemperature = aNBT.getInteger("mTemperature");
+ this.mProcessingEnergy = aNBT.getInteger("mProcessingEnergy");
+ this.mSteam = FluidStack.loadFluidStackFromNBT(aNBT.getCompoundTag("mSteam"));
+ }
+
+ @Override
+ public void onPostTick(final IGregTechTileEntity aBaseMetaTileEntity, final long aTick) {
+ if ((aBaseMetaTileEntity.isServerSide()) && (aTick > 20L)) {
+ if (this.mTemperature <= 20) {
+ this.mTemperature = 20;
+ this.mLossTimer = 0;
+ }
+ if (++this.mLossTimer > 40) {
+ this.mTemperature -= 1;
+ this.mLossTimer = 0;
+ }
+ for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
+ if (side != aBaseMetaTileEntity.getFrontFacing()) {
+ final IFluidHandler tTileEntity = aBaseMetaTileEntity.getITankContainerAtSide(side);
+ if (tTileEntity != null) {
+ final FluidStack tDrained = aBaseMetaTileEntity
+ .drain(side, Math.max(1, this.mSteam.amount / 2), false);
+ if (tDrained != null) {
+ final int tFilledAmount = tTileEntity.fill(side.getOpposite(), tDrained, false);
+ if (tFilledAmount > 0) {
+ tTileEntity.fill(
+ side.getOpposite(),
+ aBaseMetaTileEntity.drain(side, tFilledAmount, true),
+ true);
+ }
+ }
+ }
+ }
+ }
+ if ((aTick % 10L) == 0L) {
+ if (this.mTemperature > 100) {
+ if ((this.mFluid == null) || (!GT_ModHandler.isWater(this.mFluid)) || (this.mFluid.amount <= 0)) {
+ this.mHadNoWater = true;
+ } else {
+ if (this.mHadNoWater) {
+ aBaseMetaTileEntity.doExplosion(2048L);
+ return;
+ }
+ this.mFluid.amount -= 1;
+ if (this.mSteam == null) {
+ this.mSteam = GT_ModHandler.getSteam(150L);
+ } else if (GT_ModHandler.isSteam(this.mSteam)) {
+ this.mSteam.amount += 150;
+ } else {
+ this.mSteam = GT_ModHandler.getSteam(150L);
+ }
+ }
+ } else {
+ this.mHadNoWater = false;
+ }
+ }
+ if ((this.mSteam != null) && (this.mSteam.amount > getSteamCapacity())) {
+ this.sendSound((byte) 1);
+ this.mSteam.amount = getSteamCapacity() * 3 / 4;
+ }
+ if ((this.mProcessingEnergy <= 0) && (aBaseMetaTileEntity.isAllowedToWork())
+ && (this.mInventory[2] != null)) {
+ if ((GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.gem.get(Materials.Coal)))
+ || (GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.dust.get(Materials.Coal)))
+ || (GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.dustImpure.get(Materials.Coal)))
+ || (GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.crushed.get(Materials.Coal)))) {
+ this.mProcessingEnergy += 160;
+ aBaseMetaTileEntity.decrStackSize(2, 1);
+ if (aBaseMetaTileEntity.getRandomNumber(3) == 0) {
+ aBaseMetaTileEntity
+ .addStackToSlot(3, GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.DarkAsh, 1L));
+ }
+ } else if (GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.gem.get(Materials.Charcoal))) {
+ this.mProcessingEnergy += 160;
+ aBaseMetaTileEntity.decrStackSize(2, 1);
+ if (aBaseMetaTileEntity.getRandomNumber(3) == 0) {
+ aBaseMetaTileEntity
+ .addStackToSlot(3, GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Ash, 1L));
+ }
+ } else if (GT_OreDictUnificator.isItemStackInstanceOf(this.mInventory[2], "fuelCoke")) {
+ this.mProcessingEnergy += 640;
+ aBaseMetaTileEntity.decrStackSize(2, 1);
+ if (aBaseMetaTileEntity.getRandomNumber(2) == 0) {
+ aBaseMetaTileEntity
+ .addStackToSlot(3, GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.Ash, 1L));
+ }
+ } else if ((GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.gem.get(Materials.Lignite)))
+ || (GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.dust.get(Materials.Lignite)))
+ || (GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.dustImpure.get(Materials.Lignite)))
+ || (GT_OreDictUnificator
+ .isItemStackInstanceOf(this.mInventory[2], OrePrefixes.crushed.get(Materials.Lignite)))) {
+ this.mProcessingEnergy += 40;
+ aBaseMetaTileEntity.decrStackSize(2, 1);
+ if (aBaseMetaTileEntity.getRandomNumber(8) == 0) {
+ aBaseMetaTileEntity.addStackToSlot(
+ 3,
+ GT_OreDictUnificator.get(OrePrefixes.dustTiny, Materials.DarkAsh, 1L));
+ }
+ }
+ }
+ if ((this.mTemperature < 1000) && (this.mProcessingEnergy > 0) && ((aTick % 12L) == 0L)) {
+ this.mProcessingEnergy -= 2;
+ this.mTemperature += 1;
+ }
+ aBaseMetaTileEntity.setActive(this.mProcessingEnergy > 0);
+ }
+ }
+
+ @Override
+ // Since this type of machine can have different water and steam capacities, we need to override getTankInfo() to
+ // support returning those different capacities.
+ public FluidTankInfo[] getTankInfo(ForgeDirection aSide) {
+ return new FluidTankInfo[] { new FluidTankInfo(this.mFluid, getCapacity()),
+ new FluidTankInfo(this.mSteam, getSteamCapacity()) };
+ }
+
+ @Override
+ public boolean allowPullStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ return (aIndex == 1) || (aIndex == 3);
+ }
+
+ @Override
+ public boolean allowPutStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ return aIndex == 2;
+ }
+
+ @Override
+ public void doSound(final byte aIndex, final double aX, final double aY, final double aZ) {
+ if (aIndex == 1) {
+ GT_Utility.doSoundAtClient(SoundResource.RANDOM_FIZZ, 2, 1.0F, aX, aY, aZ);
+ for (int l = 0; l < 8; l++) {
+ this.getBaseMetaTileEntity()
+ .getWorld()
+ .spawnParticle(
+ "largesmoke",
+ (aX - 0.5D) + Math.random(),
+ aY,
+ (aZ - 0.5D) + Math.random(),
+ 0.0D,
+ 0.0D,
+ 0.0D);
+ }
+ }
+ }
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ // This type of machine can have different water and steam capacities.
+ public int getSteamCapacity() {
+ return 32000;
+ }
+
+ @Override
+ public int getTankPressure() {
+ return 100;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechMetaSolarGenerator.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechMetaSolarGenerator.java
new file mode 100644
index 0000000000..5e0588acfd
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechMetaSolarGenerator.java
@@ -0,0 +1,241 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.generators;
+
+import static gregtech.api.enums.GT_Values.V;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+
+public abstract class GregtechMetaSolarGenerator extends GT_MetaTileEntity_BasicTank {
+
+ public int mEfficiency;
+ public int mProcessingEnergy = 0;
+ public int mSolarCharge = 20;
+ public int mLossTimer = 0;
+ public static int sEnergyPerTick = 16;
+
+ public GregtechMetaSolarGenerator(final int aID, final String aName, final String aNameRegional, final int aTier,
+ final String aDescription, final ITexture... aTextures) {
+ super(aID, aName, aNameRegional, aTier, 3, aDescription, aTextures);
+ }
+
+ public GregtechMetaSolarGenerator(final String aName, final int aTier, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(final ITexture[] aTextures) {
+ final ITexture[][][] rTextures = new ITexture[10][17][];
+ for (byte i = -1; i < 16; i++) {
+ rTextures[0][i + 1] = this.getFront(i);
+ rTextures[1][i + 1] = this.getBack(i);
+ rTextures[2][i + 1] = this.getBottom(i);
+ rTextures[3][i + 1] = this.getTop(i);
+ rTextures[4][i + 1] = this.getSides(i);
+ rTextures[5][i + 1] = this.getFrontActive(i);
+ rTextures[6][i + 1] = this.getBackActive(i);
+ rTextures[7][i + 1] = this.getBottomActive(i);
+ rTextures[8][i + 1] = this.getTopActive(i);
+ rTextures[9][i + 1] = this.getSidesActive(i);
+ }
+ return rTextures;
+ }
+
+ @Override
+ public ITexture[] getTexture(final IGregTechTileEntity aBaseMetaTileEntity, final ForgeDirection side,
+ final ForgeDirection facing, final int aColorIndex, final boolean aActive, final boolean aRedstone) {
+ return this.mTextures[(aActive ? 5 : 0) + (side == facing ? 0
+ : side == facing.getOpposite() ? 1
+ : side == ForgeDirection.DOWN ? 2 : side == ForgeDirection.UP ? 3 : 4)][aColorIndex + 1];
+ }
+
+ @Override
+ public String[] getDescription() {
+ return ArrayUtils.add(this.mDescriptionArray, "Efficiency: " + this.getEfficiency() + "%");
+ }
+
+ @Override
+ public boolean onRightclick(final IGregTechTileEntity aBaseMetaTileEntity, final EntityPlayer aPlayer) {
+ if (aBaseMetaTileEntity.isClientSide()) {
+ return true;
+ }
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ public ITexture[] getFront(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getBack(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getBottom(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getTop(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getSides(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getFrontActive(final byte aColor) {
+ return this.getFront(aColor);
+ }
+
+ public ITexture[] getBackActive(final byte aColor) {
+ return this.getBack(aColor);
+ }
+
+ public ITexture[] getBottomActive(final byte aColor) {
+ return this.getBottom(aColor);
+ }
+
+ public ITexture[] getTopActive(final byte aColor) {
+ return this.getTop(aColor);
+ }
+
+ public ITexture[] getSidesActive(final byte aColor) {
+ return this.getSides(aColor);
+ }
+
+ @Override
+ public boolean isFacingValid(final ForgeDirection side) {
+ return side.offsetY == 0;
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isValidSlot(final int aIndex) {
+ return aIndex < 2;
+ }
+
+ @Override
+ public boolean isEnetOutput() {
+ return true;
+ }
+
+ @Override
+ public boolean isOutputFacing(final ForgeDirection side) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(final EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public long maxEUOutput() {
+ return this.getBaseMetaTileEntity()
+ .isAllowedToWork() ? V[this.mTier] : 0;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return Math.max(this.getEUVar(), (V[this.mTier] * 40) + this.getMinimumStoredEU());
+ }
+
+ @Override
+ public void onPostTick(final IGregTechTileEntity aBaseMetaTileEntity, final long aTick) {
+ if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.isAllowedToWork()
+ && (aTick > 20L)
+ && (aBaseMetaTileEntity.getUniversalEnergyStored()
+ < (this.maxEUOutput() + aBaseMetaTileEntity.getEUCapacity()))) {
+
+ if (this.mSolarCharge <= 20) {
+ this.mSolarCharge = 20;
+ this.mLossTimer = 0;
+ }
+ if (++this.mLossTimer > 45) {
+ this.mSolarCharge -= 1;
+ this.mLossTimer = 0;
+ }
+
+ if ((aTick % 25L) == 0L) {
+ if (this.mSolarCharge > 100) {
+ if ((this.mProcessingEnergy > 0) && (aBaseMetaTileEntity.isAllowedToWork())
+ && ((aTick % 256L) == 0L)
+ && (!aBaseMetaTileEntity.getWorld()
+ .isThundering()
+ && (aBaseMetaTileEntity.getUniversalEnergyStored()
+ < ((this.maxEUOutput() * 20) + this.getMinimumStoredEU())))) {
+ this.getBaseMetaTileEntity()
+ .increaseStoredEnergyUnits((sEnergyPerTick * this.getEfficiency()) / 10, false);
+ }
+ }
+ }
+
+ if ((this.mSolarCharge < 500) && (this.mProcessingEnergy > 0) && ((aTick % 12L) == 0L)) {
+ this.mProcessingEnergy -= 1;
+ this.mSolarCharge += 1;
+ }
+
+ if ((this.mProcessingEnergy <= 0) && (aBaseMetaTileEntity.isAllowedToWork())
+ && ((aTick % 256L) == 0L)
+ && (!aBaseMetaTileEntity.getWorld()
+ .isThundering())) {
+ final boolean bRain = aBaseMetaTileEntity.getWorld()
+ .isRaining() && (aBaseMetaTileEntity.getBiome().rainfall > 0.0F);
+ this.mProcessingEnergy += (bRain && (aBaseMetaTileEntity.getWorld().skylightSubtracted >= 4))
+ || !aBaseMetaTileEntity.getSkyAtSide(ForgeDirection.UP) ? 0
+ : !bRain && aBaseMetaTileEntity.getWorld()
+ .isDaytime() ? 8 : 1;
+ }
+
+ if (aBaseMetaTileEntity.isServerSide()) {
+ aBaseMetaTileEntity.setActive(
+ aBaseMetaTileEntity.isAllowedToWork() && (aBaseMetaTileEntity.getUniversalEnergyStored()
+ >= (this.maxEUOutput() + this.getMinimumStoredEU())));
+ }
+ }
+ }
+
+ public abstract int getEfficiency();
+
+ @Override
+ public boolean doesFillContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return false;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return false;
+ }
+
+ @Override
+ public boolean displaysItemStack() {
+ return false;
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return false;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechRocketFuelGeneratorBase.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechRocketFuelGeneratorBase.java
new file mode 100644
index 0000000000..83745f393a
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/generators/GregtechRocketFuelGeneratorBase.java
@@ -0,0 +1,338 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.generators;
+
+import static gregtech.api.enums.GT_Values.V;
+
+import java.util.Collection;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.init.Blocks;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.RecipeMapWorkable;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicTank;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.math.MathUtils;
+import gtPlusPlus.core.util.minecraft.gregtech.PollutionUtils;
+
+public abstract class GregtechRocketFuelGeneratorBase extends GT_MetaTileEntity_BasicTank implements RecipeMapWorkable {
+
+ protected int pollMin, pollMax;
+
+ public GregtechRocketFuelGeneratorBase(final int aID, final String aName, final String aNameRegional,
+ final int aTier, final String aDescription, final ITexture... aTextures) {
+ super(aID, aName, aNameRegional, aTier, 3, aDescription, aTextures);
+ pollMin = (int) (CORE.ConfigSwitches.baseMinPollutionPerSecondRocketFuelGenerator
+ * CORE.ConfigSwitches.pollutionReleasedByTierRocketFuelGenerator[mTier]);
+ pollMax = (int) (CORE.ConfigSwitches.baseMaxPollutionPerSecondRocketFuelGenerator
+ * CORE.ConfigSwitches.pollutionReleasedByTierRocketFuelGenerator[mTier]);
+ }
+
+ public GregtechRocketFuelGeneratorBase(final String aName, final int aTier, final String[] aDescription,
+ final ITexture[][][] aTextures) {
+ super(aName, aTier, 3, aDescription, aTextures);
+ pollMin = (int) (CORE.ConfigSwitches.baseMinPollutionPerSecondRocketFuelGenerator
+ * CORE.ConfigSwitches.pollutionReleasedByTierRocketFuelGenerator[mTier]);
+ pollMax = (int) (CORE.ConfigSwitches.baseMaxPollutionPerSecondRocketFuelGenerator
+ * CORE.ConfigSwitches.pollutionReleasedByTierRocketFuelGenerator[mTier]);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(final ITexture[] aTextures) {
+ final ITexture[][][] rTextures = new ITexture[10][17][];
+ for (byte i = -1; i < 16; i++) {
+ rTextures[0][i + 1] = this.getFront(i);
+ rTextures[1][i + 1] = this.getBack(i);
+ rTextures[2][i + 1] = this.getBottom(i);
+ rTextures[3][i + 1] = this.getTop(i);
+ rTextures[4][i + 1] = this.getSides(i);
+ rTextures[5][i + 1] = this.getFrontActive(i);
+ rTextures[6][i + 1] = this.getBackActive(i);
+ rTextures[7][i + 1] = this.getBottomActive(i);
+ rTextures[8][i + 1] = this.getTopActive(i);
+ rTextures[9][i + 1] = this.getSidesActive(i);
+ }
+ return rTextures;
+ }
+
+ @Override
+ public ITexture[] getTexture(final IGregTechTileEntity aBaseMetaTileEntity, final ForgeDirection side,
+ final ForgeDirection facing, final int aColorIndex, final boolean aActive, final boolean aRedstone) {
+ return this.mTextures[(aActive ? 5 : 0) + (side == facing ? 0
+ : side == facing.getOpposite() ? 1
+ : side == ForgeDirection.DOWN ? 2 : side == ForgeDirection.UP ? 3 : 4)][aColorIndex + 1];
+ }
+
+ @Override
+ public String[] getDescription() {
+ String aPollution = "Causes between " + pollMin + " and " + pollMax + " Pollution per second";
+ return ArrayUtils.addAll(
+ this.mDescriptionArray,
+ "Fuel Efficiency: " + this.getEfficiency() + "%",
+ aPollution,
+ CORE.GT_Tooltip.get());
+ }
+
+ @Override
+ public boolean onRightclick(final IGregTechTileEntity aBaseMetaTileEntity, final EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ public ITexture[] getFront(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getBack(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getBottom(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getTop(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getSides(final byte aColor) {
+ return new ITexture[] { Textures.BlockIcons.MACHINE_CASINGS[this.mTier][aColor + 1] };
+ }
+
+ public ITexture[] getFrontActive(final byte aColor) {
+ return this.getFront(aColor);
+ }
+
+ public ITexture[] getBackActive(final byte aColor) {
+ return this.getBack(aColor);
+ }
+
+ public ITexture[] getBottomActive(final byte aColor) {
+ return this.getBottom(aColor);
+ }
+
+ public ITexture[] getTopActive(final byte aColor) {
+ return this.getTop(aColor);
+ }
+
+ public ITexture[] getSidesActive(final byte aColor) {
+ return this.getSides(aColor);
+ }
+
+ @Override
+ public boolean isFacingValid(final ForgeDirection side) {
+ return side.offsetY == 0;
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isValidSlot(final int aIndex) {
+ return aIndex < 2;
+ }
+
+ @Override
+ public boolean isEnetOutput() {
+ return true;
+ }
+
+ @Override
+ public boolean isOutputFacing(final ForgeDirection side) {
+ return this.getBaseMetaTileEntity()
+ .getFrontFacing() == side;
+ }
+
+ @Override
+ public boolean isAccessAllowed(final EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public long maxEUOutput() {
+ return V[this.mTier];
+ }
+
+ @Override
+ public long maxEUStore() {
+ return Math.max(this.getEUVar(), (V[this.mTier] * 500) + this.getMinimumStoredEU());
+ }
+
+ @Override
+ public boolean doesFillContainers() {
+ return false;
+ }
+
+ @Override
+ public boolean doesEmptyContainers() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return false;
+ }
+
+ @Override
+ public boolean displaysItemStack() {
+ return true;
+ }
+
+ @Override
+ public boolean displaysStackSize() {
+ return false;
+ }
+
+ @Override
+ public boolean isFluidInputAllowed(final FluidStack aFluid) {
+ return this.getFuelValue(aFluid) > 0;
+ }
+
+ @Override
+ public void onPostTick(final IGregTechTileEntity aBaseMetaTileEntity, final long aTick) {
+
+ if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.isAllowedToWork() && ((aTick % 10) == 0)) {
+ if (this.mFluid == null) {
+ if (aBaseMetaTileEntity.getUniversalEnergyStored() < (this.maxEUOutput() + this.getMinimumStoredEU())) {
+ this.mInventory[this.getStackDisplaySlot()] = null;
+ } else {
+ if (this.mInventory[this.getStackDisplaySlot()] == null) {
+ this.mInventory[this.getStackDisplaySlot()] = new ItemStack(Blocks.fire, 1);
+ }
+ this.mInventory[this.getStackDisplaySlot()].setStackDisplayName(
+ "Generating: " + (aBaseMetaTileEntity.getUniversalEnergyStored() - this.getMinimumStoredEU())
+ + " EU");
+ }
+ } else {
+ final int tFuelValue = this.getFuelValue(this.mFluid),
+ tConsumed = this.consumedFluidPerOperation(this.mFluid);
+ if ((tFuelValue > 0) && (tConsumed > 0) && (this.mFluid.amount >= tConsumed)) {
+ final long tFluidAmountToUse = Math.min(
+ this.mFluid.amount / tConsumed,
+ (((this.maxEUOutput() * 20) + this.getMinimumStoredEU())
+ - aBaseMetaTileEntity.getUniversalEnergyStored()) / tFuelValue);
+ if ((tFluidAmountToUse > 0)
+ && aBaseMetaTileEntity.increaseStoredEnergyUnits(tFluidAmountToUse * tFuelValue, true)) {
+ int aSafeFloor = (int) Math.max(((tFluidAmountToUse * tConsumed) / 3), 1);
+ this.mFluid.amount -= (int) aSafeFloor;
+ PollutionUtils.addPollution(getBaseMetaTileEntity(), 10 * getPollution());
+ }
+ }
+ }
+ if ((this.mInventory[this.getInputSlot()] != null)
+ && (aBaseMetaTileEntity.getUniversalEnergyStored()
+ < ((this.maxEUOutput() * 20) + this.getMinimumStoredEU()))
+ && (GT_Utility.getFluidForFilledItem(this.mInventory[this.getInputSlot()], true) == null)) {
+ final int tFuelValue = this.getFuelValue(this.mInventory[this.getInputSlot()]);
+ if (tFuelValue > 0) {
+ final ItemStack tEmptyContainer = this.getEmptyContainer(this.mInventory[this.getInputSlot()]);
+ if (aBaseMetaTileEntity.addStackToSlot(this.getOutputSlot(), tEmptyContainer)) {
+ aBaseMetaTileEntity.increaseStoredEnergyUnits(tFuelValue, true);
+ aBaseMetaTileEntity.decrStackSize(this.getInputSlot(), 1);
+ PollutionUtils.addPollution(getBaseMetaTileEntity(), getPollution() / 2);
+ }
+ }
+ }
+ }
+
+ if (aBaseMetaTileEntity.isServerSide()) {
+ aBaseMetaTileEntity.setActive(
+ aBaseMetaTileEntity.isAllowedToWork() && (aBaseMetaTileEntity.getUniversalEnergyStored()
+ >= (this.maxEUOutput() + this.getMinimumStoredEU())));
+ }
+ }
+
+ public int getPollution() {
+ return MathUtils.randInt(pollMin, pollMax);
+ }
+
+ @Override
+ public abstract RecipeMap<?> getRecipeMap();
+
+ public abstract int getEfficiency();
+
+ public int consumedFluidPerOperation(final FluidStack aLiquid) {
+ return 1;
+ }
+
+ public int getFuelValue(final FluidStack aLiquid) {
+ if ((aLiquid == null) || (this.getRecipeMap() == null)) {
+ return 0;
+ }
+ FluidStack tLiquid;
+ final Collection<GT_Recipe> tRecipeList = this.getRecipeMap()
+ .getAllRecipes();
+ for (final GT_Recipe tFuel : tRecipeList) {
+ if ((tLiquid = tFuel.mFluidInputs[0]) != null) {
+ if (aLiquid.isFluidEqual(tLiquid)) {
+ int aperOp = this.consumedFluidPerOperation(tLiquid);
+ return (int) (((long) tFuel.mSpecialValue * this.getEfficiency() * aperOp) / 100);
+ }
+ }
+ }
+ return 0;
+ }
+
+ public int getFuelValue(final ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack) || (this.getRecipeMap() == null)) {
+ return 0;
+ }
+ final GT_Recipe tFuel = this.getRecipeMap()
+ .findRecipe(this.getBaseMetaTileEntity(), false, Long.MAX_VALUE, null, aStack);
+ if (tFuel != null) {
+ return (int) ((tFuel.mSpecialValue * 1000L * this.getEfficiency()) / 100);
+ }
+ return 0;
+ }
+
+ public ItemStack getEmptyContainer(final ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack) || (this.getRecipeMap() == null)) {
+ return null;
+ }
+ final GT_Recipe tFuel = this.getRecipeMap()
+ .findRecipe(this.getBaseMetaTileEntity(), false, Long.MAX_VALUE, null, aStack);
+ if (tFuel != null) {
+ return GT_Utility.copy(tFuel.getOutput(0));
+ }
+ return GT_Utility.getContainerItem(aStack, true);
+ }
+
+ @Override
+ public boolean allowPutStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ return super.allowPutStack(aBaseMetaTileEntity, aIndex, side, aStack) && ((this.getFuelValue(aStack) > 0)
+ || (this.getFuelValue(GT_Utility.getFluidForFilledItem(aStack, true)) > 0));
+ }
+
+ @Override
+ public int getCapacity() {
+ return 32000;
+ }
+
+ @Override
+ public int getTankPressure() {
+ return -100;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/machines/GregtechMetaTreeFarmerBase.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/machines/GregtechMetaTreeFarmerBase.java
new file mode 100644
index 0000000000..fe3253244a
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/base/machines/GregtechMetaTreeFarmerBase.java
@@ -0,0 +1,180 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.base.machines;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_TieredMachineBlock;
+import gregtech.api.objects.GT_RenderedTexture;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public abstract class GregtechMetaTreeFarmerBase extends GT_MetaTileEntity_TieredMachineBlock {
+
+ public GregtechMetaTreeFarmerBase(final int aID, final String aName, final String aNameRegional, final int aTier,
+ final int aInvSlotCount, final String aDescription) {
+ super(aID, aName, aNameRegional, aTier, aInvSlotCount, aDescription);
+ }
+
+ public GregtechMetaTreeFarmerBase(final String aName, final int aTier, final int aInvSlotCount,
+ final String[] aDescription, final ITexture[][][] aTextures) {
+ super(aName, aTier, aInvSlotCount, aDescription, aTextures);
+ }
+
+ @Override
+ public ITexture[][][] getTextureSet(final ITexture[] aTextures) {
+ final ITexture[][][] rTextures = new ITexture[10][17][];
+ for (byte i = -1; i < 16; i++) {
+ rTextures[0][i + 1] = this.getFront(i);
+ rTextures[1][i + 1] = this.getBack(i);
+ rTextures[2][i + 1] = this.getBottom(i);
+ rTextures[3][i + 1] = this.getTop(i);
+ rTextures[4][i + 1] = this.getSides(i);
+ rTextures[5][i + 1] = this.getFrontActive(i);
+ rTextures[6][i + 1] = this.getBackActive(i);
+ rTextures[7][i + 1] = this.getBottomActive(i);
+ rTextures[8][i + 1] = this.getTopActive(i);
+ rTextures[9][i + 1] = this.getSidesActive(i);
+ }
+ return rTextures;
+ }
+
+ @Override
+ public ITexture[] getTexture(final IGregTechTileEntity aBaseMetaTileEntity, final ForgeDirection side,
+ final ForgeDirection facing, final int aColorIndex, final boolean aActive, final boolean aRedstone) {
+ return this.mTextures[(aActive ? 5 : 0) + (side == facing ? 0
+ : side == facing.getOpposite() ? 1
+ : side == ForgeDirection.DOWN ? 2 : side == ForgeDirection.UP ? 3 : 4)][aColorIndex + 1];
+ }
+
+ @Override
+ public boolean isSimpleMachine() {
+ return false;
+ }
+
+ @Override
+ public boolean isValidSlot(final int aIndex) {
+ return false;
+ }
+
+ @Override
+ public boolean isFacingValid(final ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isEnetInput() {
+ return false;
+ }
+
+ @Override
+ public boolean isEnetOutput() {
+ return false;
+ }
+
+ @Override
+ public boolean isInputFacing(final ForgeDirection side) {
+ return !this.isOutputFacing(side);
+ }
+
+ @Override
+ public boolean isOutputFacing(final ForgeDirection side) {
+ return this.getBaseMetaTileEntity()
+ .getBackFacing() == side;
+ }
+
+ @Override
+ public boolean isTeleporterCompatible() {
+ return false;
+ }
+
+ @Override
+ public long getMinimumStoredEU() {
+ return 0;
+ }
+
+ @Override
+ public long maxEUStore() {
+ return 0;
+ }
+
+ @Override
+ public long maxEUInput() {
+ return 0;
+ }
+
+ @Override
+ public long maxEUOutput() {
+ return 0;
+ }
+
+ @Override
+ public long maxAmperesIn() {
+ return 0;
+ }
+
+ @Override
+ public long maxAmperesOut() {
+ return 0;
+ }
+
+ @Override
+ public boolean isAccessAllowed(final EntityPlayer aPlayer) {
+ return false;
+ }
+
+ public abstract ITexture getOverlayIcon();
+
+ @Override
+ public boolean allowPullStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public boolean allowPutStack(final IGregTechTileEntity aBaseMetaTileEntity, final int aIndex,
+ final ForgeDirection side, final ItemStack aStack) {
+ return false;
+ }
+
+ public ITexture[] getFront(final byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(TexturesGtBlock.Casing_Machine_Farm_Manager) };
+ }
+
+ public ITexture[] getBack(final byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(TexturesGtBlock.Casing_Machine_Farm_Manager) };
+ }
+
+ public ITexture[] getBottom(final byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(TexturesGtBlock.Casing_Machine_Acacia_Log) };
+ }
+
+ public ITexture[] getTop(final byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(TexturesGtBlock.Casing_Machine_Podzol) };
+ }
+
+ public ITexture[] getSides(final byte aColor) {
+ return new ITexture[] { new GT_RenderedTexture(TexturesGtBlock.Casing_Machine_Farm_Manager) };
+ }
+
+ public ITexture[] getFrontActive(final byte aColor) {
+ return this.getFront(aColor);
+ }
+
+ public ITexture[] getBackActive(final byte aColor) {
+ return this.getBack(aColor);
+ }
+
+ public ITexture[] getBottomActive(final byte aColor) {
+ return this.getBottom(aColor);
+ }
+
+ public ITexture[] getTopActive(final byte aColor) {
+ return this.getTop(aColor);
+ }
+
+ public ITexture[] getSidesActive(final byte aColor) {
+ return this.getSides(aColor);
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_Catalysts.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_Catalysts.java
new file mode 100644
index 0000000000..b53e540044
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_Catalysts.java
@@ -0,0 +1,71 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.nbthandlers;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.objects.GT_RenderedTexture;
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class GT_MetaTileEntity_Hatch_Catalysts extends GT_MetaTileEntity_Hatch_NbtConsumable {
+
+ public GT_MetaTileEntity_Hatch_Catalysts(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, 0, 16, "Dedicated Catalyst Storage", false);
+ }
+
+ public GT_MetaTileEntity_Hatch_Catalysts(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, 0, 16, aDescription, false, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Bus_Catalyst) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Bus_Catalyst) };
+ }
+
+ @Override
+ public String[] getDescription() {
+ return ArrayUtils.add(this.mDescriptionArray, CORE.GT_Tooltip.get());
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_Catalysts(mName, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public String getNameGUI() {
+ return "Catalyst Container";
+ }
+
+ @Override
+ public AutoMap<ItemStack> getItemsValidForUsageSlots() {
+ return new AutoMap<>();
+ }
+
+ @Override
+ public boolean isItemValidForUsageSlot(ItemStack aStack) {
+ return ItemUtils.isCatalyst(aStack);
+ }
+
+ @Override
+ public int getInputSlotCount() {
+ return 16;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_MillingBalls.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_MillingBalls.java
new file mode 100644
index 0000000000..e3134f5812
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_MillingBalls.java
@@ -0,0 +1,71 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.nbthandlers;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.apache.commons.lang3.ArrayUtils;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.objects.GT_RenderedTexture;
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.core.lib.CORE;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class GT_MetaTileEntity_Hatch_MillingBalls extends GT_MetaTileEntity_Hatch_NbtConsumable {
+
+ public GT_MetaTileEntity_Hatch_MillingBalls(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional, 6, 4, "Dedicated Milling Ball Storage", false);
+ }
+
+ public GT_MetaTileEntity_Hatch_MillingBalls(String aName, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, 6, 4, aDescription, false, aTextures);
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Bus_Milling_Balls) };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, new GT_RenderedTexture(TexturesGtBlock.Overlay_Bus_Milling_Balls) };
+ }
+
+ @Override
+ public String[] getDescription() {
+ return ArrayUtils.add(this.mDescriptionArray, CORE.GT_Tooltip.get());
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new GT_MetaTileEntity_Hatch_MillingBalls(mName, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public String getNameGUI() {
+ return "Ball Housing";
+ }
+
+ @Override
+ public AutoMap<ItemStack> getItemsValidForUsageSlots() {
+ return new AutoMap<>();
+ }
+
+ @Override
+ public boolean isItemValidForUsageSlot(ItemStack aStack) {
+ return ItemUtils.isMillingBall(aStack);
+ }
+
+ @Override
+ public int getInputSlotCount() {
+ return 4;
+ }
+}
diff --git a/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_NbtConsumable.java b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_NbtConsumable.java
new file mode 100644
index 0000000000..e81c9ed554
--- /dev/null
+++ b/src/main/java/gtPlusPlus/xmod/gregtech/api/metatileentity/implementations/nbthandlers/GT_MetaTileEntity_Hatch_NbtConsumable.java
@@ -0,0 +1,353 @@
+package gtPlusPlus.xmod.gregtech.api.metatileentity.implementations.nbthandlers;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.DrawableWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotGroup;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.modularui.IAddGregtechLogo;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.api.objects.Logger;
+import gtPlusPlus.api.objects.data.AutoMap;
+import gtPlusPlus.core.util.minecraft.ItemUtils;
+
+public abstract class GT_MetaTileEntity_Hatch_NbtConsumable extends GT_MetaTileEntity_Hatch
+ implements IAddGregtechLogo {
+
+ private final int mInputslotCount;
+ private final int mTotalSlotCount;
+ private final boolean mAllowDuplicateUsageTypes;
+
+ public GT_MetaTileEntity_Hatch_NbtConsumable(int aID, String aName, String aNameRegional, int aTier,
+ int aInputSlots, String aDescription, boolean aAllowDuplicateTypes) {
+ super(aID, aName, aNameRegional, aTier, aInputSlots * 2, aDescription);
+ mInputslotCount = getInputSlotCount();
+ mTotalSlotCount = getInputSlotCount() * 2;
+ mAllowDuplicateUsageTypes = aAllowDuplicateTypes;
+ }
+
+ public GT_MetaTileEntity_Hatch_NbtConsumable(String aName, int aTier, int aInputSlots, String[] aDescription,
+ boolean aAllowDuplicateTypes, ITexture[][][] aTextures) {
+ super(aName, aTier, aInputSlots * 2, aDescription, aTextures);
+ mInputslotCount = getInputSlotCount();
+ mTotalSlotCount = getInputSlotCount() * 2;
+ mAllowDuplicateUsageTypes = aAllowDuplicateTypes;
+ }
+
+ @Override
+ public abstract ITexture[] getTexturesActive(ITexture aBaseTexture);
+
+ @Override
+ public abstract ITexture[] getTexturesInactive(ITexture aBaseTexture);
+
+ public abstract int getInputSlotCount();
+
+ @Override
+ public final boolean isSimpleMachine() {
+ return true;
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public final boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public final boolean isValidSlot(int aIndex) {
+ return true;
+ }
+
+ @Override
+ public abstract MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity);
+
+ @Override
+ public final boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ public abstract String getNameGUI();
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTimer) {
+ validateUsageSlots();
+ if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ fillStacksIntoFirstSlots();
+ tryFillUsageSlots();
+ }
+ }
+
+ public final void updateSlots() {
+ for (int i = 0; i < mInventory.length; i++) {
+ if (mInventory[i] != null && mInventory[i].stackSize <= 0) {
+ mInventory[i] = null;
+ }
+ // Only moves items in the first four slots
+ if (i <= getSlotID_LastInput()) {
+ fillStacksIntoFirstSlots();
+ }
+ }
+ }
+
+ protected void validateUsageSlots() {
+ for (int i = getSlotID_FirstUsage(); i <= getSlotID_LastUsage(); i++) {
+ if (mInventory[i] != null && mInventory[i].stackSize < 1) {
+ mInventory[i] = null;
+ this.markDirty();
+ }
+ }
+ }
+
+ // Only moves items in the first four slots
+ protected final void fillStacksIntoFirstSlots() {
+ for (int i = 0; i <= getSlotID_LastInput(); i++) {
+ for (int j = i + 1; j <= getSlotID_LastInput(); j++) {
+ if (mInventory[j] != null
+ && (mInventory[i] == null || GT_Utility.areStacksEqual(mInventory[i], mInventory[j]))) {
+ GT_Utility.moveStackFromSlotAToSlotB(
+ getBaseMetaTileEntity(),
+ getBaseMetaTileEntity(),
+ j,
+ i,
+ (byte) 64,
+ (byte) 1,
+ (byte) 64,
+ (byte) 1);
+ }
+ }
+ }
+ }
+
+ public final void tryFillUsageSlots() {
+ int aSlotSpace = (mInputslotCount - getContentUsageSlots().size());
+ if (aSlotSpace > 0) {
+ Logger.INFO("We have empty usage slots. " + aSlotSpace);
+ for (int i = getSlotID_FirstInput(); i <= getSlotID_LastInput(); i++) {
+ ItemStack aStackToTryMove = mInventory[i];
+ if (aStackToTryMove != null && isItemValidForUsageSlot(aStackToTryMove)) {
+ Logger.INFO("Trying to move stack from input slot " + i);
+ if (moveItemFromStockToUsageSlots(aStackToTryMove)) {
+ Logger.INFO("Updating Slots.");
+ updateSlots();
+ }
+ }
+ }
+ }
+ }
+
+ private int getSlotID_FirstInput() {
+ return 0;
+ }
+
+ private int getSlotID_LastInput() {
+ return mInputslotCount - 1;
+ }
+
+ private int getSlotID_FirstUsage() {
+ return mInputslotCount;
+ }
+
+ private int getSlotID_LastUsage() {
+ return mTotalSlotCount - 1;
+ }
+
+ public final AutoMap<ItemStack> getContentUsageSlots() {
+ AutoMap<ItemStack> aItems = new AutoMap<>();
+ for (int i = mInputslotCount; i < mTotalSlotCount; i++) {
+ if (mInventory[i] != null) {
+ aItems.add(mInventory[i]);
+ }
+ }
+ return aItems;
+ }
+
+ public final boolean moveItemFromStockToUsageSlots(ItemStack aStack) {
+ return moveItemFromStockToUsageSlots(aStack, mAllowDuplicateUsageTypes);
+ }
+
+ public final boolean moveItemFromStockToUsageSlots(ItemStack aStack, boolean aAllowMultiOfSameTypeInUsageSlots) {
+ if (aStack != null) {
+ if (aStack.stackSize > 0) {
+
+ if (!isItemValidForUsageSlot(aStack)) {
+ Logger.INFO("Stack not valid: " + ItemUtils.getItemName(aStack));
+ return false;
+ }
+
+ // Copy the input stack into a new object
+ ItemStack aStackToMove = aStack.copy();
+ // Set stack size of stack to move to 1.
+ aStackToMove.stackSize = 1;
+ // Did we set a stack in the usage slots?
+ boolean aDidSet = false;
+ // Did we find another of this item already in the usage slots?
+ boolean aFoundMatching = false;
+ // Continue processing with our new stack
+ // First check for duplicates
+ for (int i = getSlotID_FirstUsage(); i <= getSlotID_LastUsage(); i++) {
+ if (mInventory[i] != null) {
+ if (GT_Utility.areStacksEqual(aStackToMove, mInventory[i], true)) {
+ Logger.INFO("Found matching stack in slot " + i + ".");
+ aFoundMatching = true;
+ break;
+ }
+ }
+ }
+ // Then Move stack to Usage slots
+ for (int i = getSlotID_FirstUsage(); i <= getSlotID_LastUsage(); i++) {
+ if (mInventory[i] == null) {
+ if ((aFoundMatching && aAllowMultiOfSameTypeInUsageSlots) || !aFoundMatching) {
+ mInventory[i] = aStackToMove;
+ aDidSet = true;
+ Logger.INFO("Moving new stack to usage slots.");
+ break;
+ }
+ }
+ }
+ if (aDidSet) {
+ Logger.INFO("Depleting input stack size by 1.");
+ // Depleted one from the original input stack
+ aStack.stackSize--;
+ }
+ return aDidSet;
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public final boolean allowPullStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public final boolean allowPutStack(IGregTechTileEntity aBaseMetaTileEntity, int aIndex, ForgeDirection side,
+ ItemStack aStack) {
+ return side == getBaseMetaTileEntity().getFrontFacing() && isItemValidForUsageSlot(aStack)
+ && aIndex < mInputslotCount;
+ }
+
+ /**
+ * Items that get compared when checking for Usage Slot validity. Can return an empty map if
+ * isItemValidForUsageSlot() is overridden.
+ *
+ * @return
+ */
+ public abstract AutoMap<ItemStack> getItemsValidForUsageSlots();
+
+ /**
+ * Checks if the given item is valid for Usage Slots. Can be overridden for easier handling if you already have
+ * methods to check this.
+ *
+ * @param aStack
+ * @return
+ */
+ public boolean isItemValidForUsageSlot(ItemStack aStack) {
+ if (aStack != null) {
+ for (ItemStack aValid : getItemsValidForUsageSlots()) {
+ if (GT_Utility.areStacksEqual(aStack, aValid, true)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addGregTechLogo(ModularWindow.Builder builder) {
+ switch (mTotalSlotCount) {
+ case 8, 18 -> builder.widget(
+ new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
+ .setSize(17, 17)
+ .setPos(152, 63));
+ case 32 -> builder.widget(
+ new DrawableWidget().setDrawable(getGUITextureSet().getGregTechLogo())
+ .setSize(17, 17)
+ .setPos(79, 35));
+ }
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ switch (mTotalSlotCount) {
+ case 8 -> {
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 2)
+ .startFromSlot(0)
+ .endAtSlot(3)
+ .build()
+ .setPos(25, 25));
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 2)
+ .startFromSlot(4)
+ .endAtSlot(7)
+ .canInsert(false)
+ .build()
+ .setPos(115, 25));
+ builder.widget(
+ new TextWidget("Stock").setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(25, 16))
+ .widget(
+ new TextWidget("Active").setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(115, 16));
+ }
+ case 18 -> {
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(0)
+ .endAtSlot(8)
+ .build()
+ .setPos(25, 19));
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 3)
+ .startFromSlot(9)
+ .endAtSlot(17)
+ .canInsert(false)
+ .build()
+ .setPos(97, 19));
+ builder.widget(
+ new TextWidget("Stock").setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(25, 14))
+ .widget(
+ new TextWidget("Active").setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setPos(15, 14));
+ }
+ case 32 -> {
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 4)
+ .startFromSlot(0)
+ .endAtSlot(15)
+ .build()
+ .setPos(7, 7));
+ builder.widget(
+ SlotGroup.ofItemHandler(inventoryHandler, 4)
+ .startFromSlot(16)
+ .endAtSlot(31)
+ .canInsert(false)
+ .build()
+ .setPos(96, 7));
+ }
+ }
+ }
+}