aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/goodgenerator/blocks/tileEntity
diff options
context:
space:
mode:
authorRaven Szewczyk <git@eigenraven.me>2024-05-25 14:13:58 +0100
committerRaven Szewczyk <git@eigenraven.me>2024-05-25 14:13:58 +0100
commit91b1909427bb0cab0f72505c325b07f8fb39c62e (patch)
treed6570897b7150afd4f3cb1470202af11e3e9ece3 /src/main/java/goodgenerator/blocks/tileEntity
parent40efa0d238677418071b658b11b0a1a7c9e0d864 (diff)
downloadGT5-Unofficial-91b1909427bb0cab0f72505c325b07f8fb39c62e.tar.gz
GT5-Unofficial-91b1909427bb0cab0f72505c325b07f8fb39c62e.tar.bz2
GT5-Unofficial-91b1909427bb0cab0f72505c325b07f8fb39c62e.zip
Move GoodGen sources
Diffstat (limited to 'src/main/java/goodgenerator/blocks/tileEntity')
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/ComponentAssemblyLine.java403
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/CoolantTower.java225
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/EssentiaHatch.java244
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/EssentiaOutputHatch.java179
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/EssentiaOutputHatch_ME.java150
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/ExtremeHeatExchanger.java416
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/FuelRefineFactory.java376
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/DieselGenerator.java214
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronAccelerator.java48
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronSensor.java277
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/YOTTAHatch.java470
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/LargeEssentiaGenerator.java511
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/LargeEssentiaSmeltery.java558
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer1.java170
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer2.java171
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer3.java172
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer4.java227
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer5.java231
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/MultiNqGenerator.java471
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/NeutronActivator.java515
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/PreciseAssembler.java491
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/SupercriticalFluidTurbine.java184
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/UniversalChemicalFuelEngine.java393
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/YottaFluidTank.java709
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/base/GT_MetaTileEntity_LargeTurbineBase.java345
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/base/GT_MetaTileEntity_TooltipMultiBlockBase_EM.java62
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputer.java733
-rw-r--r--src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputerPP.java53
28 files changed, 8998 insertions, 0 deletions
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/ComponentAssemblyLine.java b/src/main/java/goodgenerator/blocks/tileEntity/ComponentAssemblyLine.java
new file mode 100644
index 0000000000..618477d09c
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/ComponentAssemblyLine.java
@@ -0,0 +1,403 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.GT_HatchElement.*;
+import static gregtech.api.enums.Textures.BlockIcons.*;
+
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.apache.commons.lang3.tuple.Pair;
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import goodgenerator.api.recipe.GoodGeneratorRecipeMaps;
+import goodgenerator.loader.Loaders;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+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.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_ExtendedPowerMultiBlockBase;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_StructureUtility;
+import gregtech.api.util.GT_Utility;
+
+public class ComponentAssemblyLine extends GT_MetaTileEntity_ExtendedPowerMultiBlockBase<ComponentAssemblyLine>
+ implements ISurvivalConstructable {
+
+ private int casingTier;
+ protected static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final IStructureDefinition<ComponentAssemblyLine> STRUCTURE_DEFINITION = StructureDefinition
+ .<ComponentAssemblyLine>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ new String[][] {
+ { " ", " III ", " HHI~IHH ", "HH III HH", "H H", "H H", "H JJJ H",
+ "H JJJ H", "H N N H", "HHHHHHHHH" },
+ { " ", " ELHHHLE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "HC CH", "AC CA", "AC CA", "A D D A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " BBB ", " EL LE ", "E GGDGG E", "HGG D GGH", "AG C GA", "AG GA", "AG GA",
+ "AG HHH GA", "AG GA", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "HC CH", "AC CA", "AC CA", "A D D A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " BBB ", " EL LE ", "E GGDGG E", "HGG D GGH", "HG C GH", "HG GH", "HG GH",
+ "HG HHH GH", "HG GH", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "HC CH", "AC CA", "AC CA", "A D D A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " BBB ", " EL LE ", "E GGDGG E", "HGG D GGH", "AG C GA", "AG GA", "AG GA",
+ "AG HHH GA", "AG GA", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "HC CH", "AC CA", "AC CA", "A D D A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " BBB ", " EL LE ", "E GGDGG E", "HGG D GGH", "HG C GH", "HG GH", "HG GH",
+ "HG HHH GH", "HG GH", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "HC CH", "AC CA", "AC CA", "A D D A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " BBB ", " EL LE ", "E GGDGG E", "HGG D GGH", "AG C GA", "AG GA", "AG GA",
+ "AG HHH GA", "AG GA", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "HC CH", "AC CA", "AC CA", "A D D A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " BBB ", " EL LE ", "E GGDGG E", "HGG D GGH", "HG C GH", "HG GH", "HG GH",
+ "HG HHH GH", "HG GH", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "HC CH", "AC CA", "AC CA", "A D D A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " BBB ", " EL LE ", "E GGDGG E", "HGG D GGH", "AG C GA", "AG GA", "AG GA",
+ "AG HHH GA", "AG GA", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A n n A", "MHHHHHHHM" },
+ { " HBH ", " EL LE ", "E E", "HC CH", "AC CA", "AC CA", "A D D A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " ", " ELHHHLE ", "E E", "H H", "A A", "A A", "A A",
+ "A HHH A", "A A", "MHHHHHHHM" },
+ { " ", " ", " HHHHHHH ", "HH HH", "H H", "H H", "H H",
+ "H H", "H KKK H", "HHHHHHHHH" } })
+ .addElement(
+ 'A',
+ ofChain(
+ ofBlockUnlocalizedName("bartworks", "BW_GlasBlocks", 5),
+ ofBlockUnlocalizedName("bartworks", "BW_GlasBlocks", 13),
+ ofBlockUnlocalizedName("bartworks", "BW_GlasBlocks", 14),
+ ofBlockUnlocalizedName("bartworks", "BW_GlasBlocks", 15),
+ ofBlockUnlocalizedName("bartworks", "BW_GlasBlocks2", 0)))
+ .addElement('H', ofBlock(GregTech_API.sBlockCasings8, 7))
+ .addElement('C', ofBlock(GregTech_API.sBlockCasings2, 5))
+ .addElement('D', ofBlock(GregTech_API.sBlockCasings2, 9))
+ .addElement('G', ofBlock(GregTech_API.sBlockCasings9, 0))
+ .addElement('E', ofBlock(GregTech_API.sBlockCasings9, 1))
+ .addElement('F', ofBlock(GregTech_API.sBlockCasings4, 1))
+ .addElement(
+ 'B',
+ ofBlocksTiered(
+ (block, meta) -> block == Loaders.componentAssemblylineCasing ? meta : -1,
+ IntStream.range(0, 14)
+ .mapToObj(i -> Pair.of(Loaders.componentAssemblylineCasing, i))
+ .collect(Collectors.toList()),
+ -2,
+ (t, meta) -> t.casingTier = meta,
+ t -> t.casingTier))
+ .addElement(
+ 'J',
+ GT_StructureUtility.buildHatchAdder(ComponentAssemblyLine.class)
+ .atLeast(InputBus)
+ .dot(1)
+ .casingIndex(183)
+ .buildAndChain(GregTech_API.sBlockCasings8, 7))
+ .addElement(
+ 'N',
+ GT_StructureUtility.buildHatchAdder(ComponentAssemblyLine.class)
+ .atLeast(InputBus)
+ .dot(1)
+ .casingIndex(183)
+ .buildAndChain(GT_StructureUtility.ofFrame(Materials.TungstenSteel)))
+ .addElement(
+ 'K',
+ GT_StructureUtility.buildHatchAdder(ComponentAssemblyLine.class)
+ .atLeast(OutputBus)
+ .dot(2)
+ .casingIndex(183)
+ .buildAndChain(GregTech_API.sBlockCasings8, 7))
+ .addElement(
+ 'L',
+ GT_StructureUtility.buildHatchAdder(ComponentAssemblyLine.class)
+ .atLeast(Energy, ExoticEnergy)
+ .dot(3)
+ .casingIndex(183)
+ .buildAndChain(GregTech_API.sBlockCasings8, 7))
+ .addElement(
+ 'I',
+ GT_StructureUtility.buildHatchAdder(ComponentAssemblyLine.class)
+ .atLeast(Maintenance)
+ .dot(4)
+ .casingIndex(183)
+ .buildAndChain(GregTech_API.sBlockCasings8, 7))
+ .addElement(
+ 'M',
+ GT_StructureUtility.buildHatchAdder(ComponentAssemblyLine.class)
+ .atLeast(InputHatch)
+ .dot(5)
+ .casingIndex(183)
+ .buildAndChain(GregTech_API.sBlockCasings8, 7))
+ .addElement('n', GT_StructureUtility.ofFrame(Materials.TungstenSteel))
+ .build();
+
+ public ComponentAssemblyLine(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public ComponentAssemblyLine(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 4, 2, 0);
+ }
+
+ @Override
+ public IStructureDefinition<ComponentAssemblyLine> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("High-Capacity Component Assembler")
+ .addInfo("Controller block for the Component Assembly Line.")
+ .addInfo("Assembles basic components (motors, pumps, etc.) in large batches.")
+ .addInfo(
+ "The " + EnumChatFormatting.BOLD
+ + EnumChatFormatting.YELLOW
+ + "Component Assembly Line Casing "
+ + EnumChatFormatting.RESET
+ + EnumChatFormatting.GRAY
+ + "limits the recipes the machine can perform. See the NEI pages for details.")
+ .addInfo(
+ "Supports " + EnumChatFormatting.BLUE
+ + "Tec"
+ + EnumChatFormatting.DARK_BLUE
+ + "Tech"
+ + EnumChatFormatting.GRAY
+ + " laser and multi-amp hatches!")
+ .addInfo("Supports overclocking beyond MAX!")
+ .addInfo(EnumChatFormatting.ITALIC + "Much more efficient than other competing brands!")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .beginStructureBlock(9, 10, 33, false)
+ .addStructureInfo("This structure is too complex! See schematic for details.")
+ .addOtherStructurePart("Borosilicate Glass", "Can be UV tier or higher")
+ .addInputBus("Start of conveyor belt", 1)
+ .addOutputBus("End of conveyor belt", 2)
+ .addEnergyHatch("Second-top layer", 3)
+ .addMaintenanceHatch("Around the controller", 4)
+ .addInputHatch("Bottom left and right corners", 5)
+ .toolTipFinisher(
+ EnumChatFormatting.AQUA + "MadMan310"
+ + EnumChatFormatting.GRAY
+ + " via "
+ + EnumChatFormatting.GREEN
+ + "Good Generator");
+
+ return tt;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new ComponentAssemblyLine(mName);
+ }
+
+ /**
+ * Changes and adds new information to the default info data for the scanner.
+ */
+ @Override
+ public String[] getInfoData() {
+ String[] origin = super.getInfoData();
+ String[] ret = new String[origin.length + 1];
+ System.arraycopy(origin, 0, ret, 0, origin.length);
+ ret[origin.length] = StatCollector.translateToLocal("scanner.info.CASS.tier")
+ + (casingTier >= 0 ? GT_Values.VN[casingTier + 1] : "None!");
+ return ret;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(183),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(183), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_PROCESSING_ARRAY_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(183) };
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult validateRecipe(@NotNull GT_Recipe recipe) {
+ if (recipe.mSpecialValue > casingTier + 1) {
+ return CheckRecipeResultRegistry.insufficientMachineTier(recipe.mSpecialValue);
+ }
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+ };
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(getMaxInputEu());
+ logic.setAvailableAmperage(1);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ int realBudget = elementBudget >= 200 ? elementBudget : Math.min(200, elementBudget * 5);
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 4, 2, 0, realBudget, env, false, true);
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ casingTier = -2;
+ return checkPiece(STRUCTURE_PIECE_MAIN, 4, 2, 0);
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ inputSeparation = !inputSeparation;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ StatCollector.translateToLocal("GT5U.machines.separatebus") + " " + inputSeparation);
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ, ItemStack aTool) {
+ if (aPlayer.isSneaking()) {
+ batchMode = !batchMode;
+ if (batchMode) {
+ GT_Utility.sendChatToPlayer(aPlayer, "Batch recipes.");
+ } else {
+ GT_Utility.sendChatToPlayer(aPlayer, "Don't batch recipes.");
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean supportsInputSeparation() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return GoodGeneratorRecipeMaps.componentAssemblyLineRecipes;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("casingTier", casingTier);
+ }
+
+ @Override
+ public void loadNBTData(final NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ casingTier = aNBT.getInteger("casingTier");
+ if (!aNBT.hasKey(INPUT_SEPARATION_NBT_KEY)) {
+ inputSeparation = aNBT.getBoolean("mSeparate");
+ }
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/CoolantTower.java b/src/main/java/goodgenerator/blocks/tileEntity/CoolantTower.java
new file mode 100644
index 0000000000..ae3395ffb9
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/CoolantTower.java
@@ -0,0 +1,225 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.Textures.BlockIcons.*;
+import static gregtech.api.util.GT_StructureUtility.*;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.github.technus.tectech.thing.metaTileEntity.multi.base.GT_MetaTileEntity_MultiblockBase_EM;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_MultiInput;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class CoolantTower extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ protected IStructureDefinition<CoolantTower> multiDefinition = null;
+ private final int CASING_INDEX = 1542;
+
+ public CoolantTower(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public CoolantTower(String name) {
+ super(name);
+ }
+
+ @Override
+ public IStructureDefinition<? extends GT_MetaTileEntity_MultiblockBase_EM> getStructure_EM() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<CoolantTower>builder()
+ .addShape(
+ mName,
+ transpose(
+ new String[][] {
+ { " ", " ", " BBB ", " B B ", " B B ", " B B ",
+ " B B ", " B B ", " BBB ", " ", " " },
+ { " ", " ", " BBB ", " BBBBB ", " BB BB ", " BB BB ",
+ " BB BB ", " BBBBB ", " BBB ", " ", " " },
+ { " ", " ", " ", " BBB ", " B B ", " B B ",
+ " B B ", " BBB ", " ", " ", " " },
+ { " ", " ", " ", " BBB ", " B B ", " B B ",
+ " B B ", " BBB ", " ", " ", " " },
+ { " ", " ", " ", " BBB ", " B B ", " B B ",
+ " B B ", " BBB ", " ", " ", " " },
+ { " ", " ", " BBB ", " BBBBB ", " BB BB ", " BB BB ",
+ " BB BB ", " BBBBB ", " BBB ", " ", " " },
+ { " ", " ", " BBB ", " B B ", " B B ", " B B ",
+ " B B ", " B B ", " BBB ", " ", " " },
+ { " ", " ", " BBB ", " B B ", " B B ", " B B ",
+ " B B ", " B B ", " BBB ", " ", " " },
+ { " ", " BBB ", " BBBBB ", " BB BB ", " BB BB ", " BB BB ",
+ " BB BB ", " BB BB ", " BBBBB ", " BBB ", " " },
+ { " ", " BBB ", " B B ", " B B ", " B B ", " B B ",
+ " B B ", " B B ", " B B ", " BBB ", " " },
+ { " ", " BBBBB ", " BB BB ", " BB BB ", " B B ", " B B ",
+ " B B ", " BB BB ", " BB BB ", " BBBBB ", " " },
+ { " HH~HH ", " HBBBBBH ", " HB BH ", "HB BH", "HB BH", "HB BH",
+ "HB BH", "HB BH", " HB BH ", " HBBBBBH ", " HHHHH " },
+ { " CCCCC ", " C C ", " C C ", "C C", "C C", "C C",
+ "C C", "C C", " C C ", " C C ", " CCCCC " }, }))
+ .addElement('B', ofBlockAnyMeta(GregTech_API.sBlockConcretes, 8))
+ .addElement('C', ofFrame(Materials.TungstenCarbide))
+ .addElement(
+ 'H',
+ buildHatchAdder(CoolantTower.class).atLeast(GT_HatchElement.InputHatch, GT_HatchElement.OutputHatch)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .buildAndChain(ofBlockAnyMeta(GregTech_API.sBlockConcretes, 8)))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mWrench = true;
+ mScrewdriver = true;
+ mSoftHammer = true;
+ mHardHammer = true;
+ mSolderingTool = true;
+ mCrowbar = true;
+ return structureCheck_EM(mName, 5, 11, 0);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Coolant Tower")
+ .addInfo("Controller block for the Coolant Tower.")
+ .addInfo("Turn Steam back to Distilled Water.")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addController("Mid of the second layer.")
+ .addInputHatch("Input Hatch", 1)
+ .addOutputHatch("Output Hatch", 1)
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ structureBuild_EM(mName, 5, 11, 0, stackSize, hintsOnly);
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("CoolantTower.hint", 3);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new CoolantTower(mName);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aTick % 72000 == 0) {
+ mWrench = true;
+ mScrewdriver = true;
+ mSoftHammer = true;
+ mHardHammer = true;
+ mSolderingTool = true;
+ mCrowbar = true;
+ }
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ protected @NotNull CheckRecipeResult checkProcessing_EM() {
+ this.mMaxProgresstime = 20;
+ int steam = 0;
+
+ for (GT_MetaTileEntity_Hatch_Input tHatch : filterValidMTEs(mInputHatches)) {
+ steam += maybeDrainHatch(tHatch);
+ }
+ addOutput(GT_ModHandler.getDistilledWater(steam / 160));
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ private int maybeDrainHatch(GT_MetaTileEntity_Hatch_Input tHatch) {
+ if (tHatch instanceof GT_MetaTileEntity_Hatch_MultiInput) {
+ int drained = 0;
+ for (FluidStack maybeSteam : ((GT_MetaTileEntity_Hatch_MultiInput) tHatch).getStoredFluid()) {
+ drained += maybeDrainSteam(tHatch, maybeSteam);
+ }
+ return drained;
+ }
+ return maybeDrainSteam(tHatch, tHatch.getFillableStack());
+ }
+
+ private int maybeDrainSteam(GT_MetaTileEntity_Hatch_Input tHatch, FluidStack maybeSteam) {
+ if (maybeSteam == null) return 0;
+ if (!GT_Utility.areFluidsEqual(maybeSteam, GT_ModHandler.getSteam(1))) return 0;
+ FluidStack defoSteam = tHatch.drain(ForgeDirection.UNKNOWN, maybeSteam, true);
+ return defoSteam.amount;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { casingTexturePages[12][6], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[12][6], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[12][6] };
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(mName, stackSize, 5, 11, 0, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/EssentiaHatch.java b/src/main/java/goodgenerator/blocks/tileEntity/EssentiaHatch.java
new file mode 100644
index 0000000000..f9eab80f03
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/EssentiaHatch.java
@@ -0,0 +1,244 @@
+package goodgenerator.blocks.tileEntity;
+
+import java.util.ArrayList;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.network.NetworkManager;
+import net.minecraft.network.Packet;
+import net.minecraft.network.play.server.S35PacketUpdateTileEntity;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import goodgenerator.crossmod.thaumcraft.LargeEssentiaEnergyData;
+import thaumcraft.api.ThaumcraftApiHelper;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
+import thaumcraft.api.aspects.IAspectContainer;
+import thaumcraft.api.aspects.IEssentiaTransport;
+
+public class EssentiaHatch extends TileEntity implements IAspectContainer, IEssentiaTransport {
+
+ private Aspect mLocked;
+ private AspectList current = new AspectList();
+ public int mState = 0;
+
+ public void setLockedAspect(Aspect aAspect) {
+ this.mLocked = aAspect;
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound tagCompound) {
+ super.readFromNBT(tagCompound);
+
+ this.mLocked = Aspect.getAspect(tagCompound.getString("mLocked"));
+ this.mState = tagCompound.getInteger("mState");
+ current = new AspectList();
+ NBTTagList tlist = tagCompound.getTagList("Aspects", 10);
+ for (int j = 0; j < tlist.tagCount(); ++j) {
+ NBTTagCompound rs = tlist.getCompoundTagAt(j);
+ if (rs.hasKey("key")) {
+ current.add(Aspect.getAspect(rs.getString("key")), rs.getInteger("amount"));
+ }
+ }
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound tagCompound) {
+ super.writeToNBT(tagCompound);
+
+ tagCompound.setString("mLocked", this.mLocked == null ? "" : this.mLocked.getTag());
+ tagCompound.setInteger("mState", mState);
+ NBTTagList tlist = new NBTTagList();
+ Aspect[] aspectA = current.getAspects();
+ for (Aspect aspect : aspectA) {
+ if (aspect != null) {
+ NBTTagCompound f = new NBTTagCompound();
+ f.setString("key", aspect.getTag());
+ f.setInteger("amount", current.getAmount(aspect));
+ tlist.appendTag(f);
+ }
+ }
+ tagCompound.setTag("Aspects", tlist);
+ }
+
+ public final Packet getDescriptionPacket() {
+ NBTTagCompound nbt = new NBTTagCompound();
+ writeToNBT(nbt);
+ return new S35PacketUpdateTileEntity(this.xCoord, this.yCoord, this.zCoord, 0, nbt);
+ }
+
+ public void onDataPacket(NetworkManager net, S35PacketUpdateTileEntity pkt) {
+ NBTTagCompound nbt = pkt.func_148857_g();
+ readFromNBT(nbt);
+ }
+
+ public void markDirty() {
+ super.markDirty();
+ if (this.worldObj.isRemote) {
+ return;
+ }
+ this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord);
+ }
+
+ @Override
+ public void updateEntity() {
+ fillfrompipe();
+ }
+
+ public void fillfrompipe() {
+ if (getEssentiaAmount(null) >= 1000) return;
+ TileEntity[] te = new TileEntity[ForgeDirection.VALID_DIRECTIONS.length];
+ for (int i = 0; i < ForgeDirection.VALID_DIRECTIONS.length; i++) {
+ te[i] = ThaumcraftApiHelper.getConnectableTile(
+ this.worldObj,
+ this.xCoord,
+ this.yCoord,
+ this.zCoord,
+ ForgeDirection.VALID_DIRECTIONS[i]);
+ if (te[i] != null) {
+ IEssentiaTransport pipe = (IEssentiaTransport) te[i];
+ if (!pipe.canOutputTo(ForgeDirection.VALID_DIRECTIONS[i])) {
+ continue;
+ }
+ if ((pipe.getEssentiaType(ForgeDirection.VALID_DIRECTIONS[i].getOpposite()) != null)
+ && (pipe.getSuctionAmount(ForgeDirection.VALID_DIRECTIONS[i])
+ < getSuctionAmount(ForgeDirection.VALID_DIRECTIONS[i]))) {
+ Aspect readyInput = pipe.getEssentiaType(ForgeDirection.VALID_DIRECTIONS[i].getOpposite());
+ int type = LargeEssentiaEnergyData.getAspectTypeIndex(readyInput);
+ if (type != -1 && (mState & (1 << type)) == 0) continue;
+ if (readyInput.equals(mLocked)) {
+ addToContainer(mLocked, pipe.takeEssentia(mLocked, 1, ForgeDirection.VALID_DIRECTIONS[i]));
+ }
+ if (mLocked == null) addToContainer(
+ pipe.getEssentiaType(ForgeDirection.VALID_DIRECTIONS[i]),
+ pipe.takeEssentia(
+ pipe.getEssentiaType(ForgeDirection.VALID_DIRECTIONS[i]),
+ 1,
+ ForgeDirection.VALID_DIRECTIONS[i]));
+ }
+ }
+ }
+ }
+
+ @Override
+ public AspectList getAspects() {
+ return current;
+ }
+
+ @Override
+ public void setAspects(AspectList aspectList) {
+ this.current.add(aspectList);
+ }
+
+ @Override
+ public boolean doesContainerAccept(Aspect aspect) {
+ int type = LargeEssentiaEnergyData.getAspectTypeIndex(aspect);
+ if (type != -1 && (mState & (1 << type)) == 0) return false;
+ return (mLocked == null || mLocked.equals(aspect)) && getEssentiaAmount(null) <= 1000;
+ }
+
+ @Override
+ public int addToContainer(Aspect aspect, int i) {
+ int type = LargeEssentiaEnergyData.getAspectTypeIndex(aspect);
+ if (type != -1 && (mState & (1 << type)) == 0) return i;
+ int ready = Math.min(1000 - getEssentiaAmount(null), i);
+ if ((mLocked == null || mLocked.equals(aspect)) && ready > 0) {
+ current.add(aspect, ready);
+ this.markDirty();
+ return i - ready;
+ }
+ this.markDirty();
+ return i;
+ }
+
+ @Override
+ public boolean takeFromContainer(Aspect aspect, int i) {
+ return false;
+ }
+
+ @Override
+ public boolean takeFromContainer(AspectList aspectList) {
+ return false;
+ }
+
+ @Override
+ public boolean doesContainerContainAmount(Aspect aspect, int i) {
+ return current.aspects.containsKey(aspect) && i <= current.getAmount(aspect);
+ }
+
+ @Override
+ public boolean doesContainerContain(AspectList aspectList) {
+ ArrayList<Boolean> ret = new ArrayList<Boolean>();
+ for (Aspect a : aspectList.aspects.keySet()) ret.add(current.aspects.containsKey(a));
+ return !ret.contains(false);
+ }
+
+ @Override
+ public int containerContains(Aspect aspect) {
+ return current.aspects.containsKey(aspect) ? current.getAmount(aspect) : 0;
+ }
+
+ @Override
+ public boolean isConnectable(ForgeDirection forgeDirection) {
+ return true;
+ }
+
+ @Override
+ public boolean canInputFrom(ForgeDirection forgeDirection) {
+ return true;
+ }
+
+ @Override
+ public boolean canOutputTo(ForgeDirection forgeDirection) {
+ return false;
+ }
+
+ @Override
+ public void setSuction(Aspect aspect, int i) {}
+
+ @Override
+ public Aspect getSuctionType(ForgeDirection forgeDirection) {
+ return this.mLocked;
+ }
+
+ @Override
+ public int getSuctionAmount(ForgeDirection forgeDirection) {
+ return 256;
+ }
+
+ @Override
+ public int takeEssentia(Aspect aspect, int i, ForgeDirection forgeDirection) {
+ return 0;
+ }
+
+ @Override
+ public int addEssentia(Aspect aspect, int i, ForgeDirection forgeDirection) {
+ return i - addToContainer(aspect, i);
+ }
+
+ @Override
+ public Aspect getEssentiaType(ForgeDirection forgeDirection) {
+ if (current == null || current.size() < 1) return null;
+ return current.getAspects()[0];
+ }
+
+ @Override
+ public int getEssentiaAmount(ForgeDirection forgeDirection) {
+ int ret = 0;
+ for (final Aspect A : current.aspects.keySet()) {
+ ret += current.getAmount(A);
+ }
+ return ret;
+ }
+
+ @Override
+ public int getMinimumSuction() {
+ return Integer.MAX_VALUE;
+ }
+
+ @Override
+ public boolean renderExtendedTube() {
+ return true;
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/EssentiaOutputHatch.java b/src/main/java/goodgenerator/blocks/tileEntity/EssentiaOutputHatch.java
new file mode 100644
index 0000000000..93cec4672c
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/EssentiaOutputHatch.java
@@ -0,0 +1,179 @@
+package goodgenerator.blocks.tileEntity;
+
+import java.util.Map;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import thaumcraft.api.TileThaumcraft;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
+import thaumcraft.api.aspects.IAspectContainer;
+import thaumcraft.api.aspects.IEssentiaTransport;
+
+public class EssentiaOutputHatch extends TileThaumcraft implements IAspectContainer, IEssentiaTransport {
+
+ public static final int CAPACITY = 256;
+ protected AspectList mAspects = new AspectList();
+
+ public void clear() {
+ this.mAspects.aspects.clear();
+ }
+
+ @Override
+ public void markDirty() {
+ super.markDirty();
+ if (this.worldObj.isRemote) return;
+ this.worldObj.markBlockForUpdate(this.xCoord, this.yCoord, this.zCoord);
+ }
+
+ @Override
+ public void readFromNBT(NBTTagCompound nbttagcompound) {
+ super.readFromNBT(nbttagcompound);
+ this.mAspects.aspects.clear();
+ NBTTagList tlist = nbttagcompound.getTagList("Aspects", 10);
+ for (int j = 0; j < tlist.tagCount(); ++j) {
+ NBTTagCompound rs = tlist.getCompoundTagAt(j);
+ if (rs.hasKey("key")) mAspects.add(Aspect.getAspect(rs.getString("key")), rs.getInteger("amount"));
+ }
+ }
+
+ @Override
+ public void writeToNBT(NBTTagCompound nbttagcompound) {
+ super.writeToNBT(nbttagcompound);
+ Aspect[] aspectA = this.mAspects.getAspects();
+ NBTTagList nbtTagList = new NBTTagList();
+ for (Aspect aspect : aspectA) {
+ if (aspect != null) {
+ NBTTagCompound f = new NBTTagCompound();
+ f.setString("key", aspect.getTag());
+ f.setInteger("amount", this.mAspects.getAmount(aspect));
+ nbtTagList.appendTag(f);
+ }
+ }
+ nbttagcompound.setTag("Aspects", nbtTagList);
+ }
+
+ private int remainingCapacity() {
+ return CAPACITY - this.getEssentiaAmount(null);
+ }
+
+ @Override
+ public AspectList getAspects() {
+ return this.mAspects;
+ }
+
+ @Override
+ public void setAspects(AspectList aspectList) {
+ for (Map.Entry<Aspect, Integer> entry : aspectList.aspects.entrySet()) {
+ this.addEssentia(entry.getKey(), entry.getValue(), null);
+ }
+ }
+
+ @Override
+ public boolean doesContainerAccept(Aspect var1) {
+ return true;
+ }
+
+ @Override
+ public int addToContainer(Aspect aspect, int amount) {
+ int remaining = 0;
+ if (amount > this.remainingCapacity()) {
+ remaining = amount - this.remainingCapacity();
+ this.mAspects.add(aspect, this.remainingCapacity());
+ } else this.mAspects.add(aspect, amount);
+ this.markDirty();
+ return remaining;
+ }
+
+ @Override
+ public boolean takeFromContainer(Aspect aspect, int amount) {
+ if (this.mAspects != null && this.mAspects.getAmount(aspect) >= amount) {
+ this.mAspects.remove(aspect, amount);
+ this.markDirty();
+ return true;
+ } else return false;
+ }
+
+ @Override
+ public boolean takeFromContainer(AspectList aspects) {
+ return true;
+ }
+
+ @Override
+ public boolean doesContainerContainAmount(Aspect aspect, int amount) {
+ return this.mAspects.getAmount(aspect) >= amount;
+ }
+
+ @Override
+ public boolean doesContainerContain(AspectList aspectList) {
+ for (Map.Entry<Aspect, Integer> entry : aspectList.aspects.entrySet()) {
+ if (this.mAspects.getAmount(entry.getKey()) < entry.getValue()) return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int containerContains(Aspect aspect) {
+ return this.mAspects.getAmount(aspect);
+ }
+
+ @Override
+ public boolean isConnectable(ForgeDirection var1) {
+ return true;
+ }
+
+ @Override
+ public boolean canInputFrom(ForgeDirection var1) {
+ return false;
+ }
+
+ @Override
+ public boolean canOutputTo(ForgeDirection var1) {
+ return true;
+ }
+
+ @Override
+ public void setSuction(Aspect var1, int var2) {}
+
+ @Override
+ public Aspect getSuctionType(ForgeDirection var1) {
+ return null;
+ }
+
+ @Override
+ public int getSuctionAmount(ForgeDirection var1) {
+ return 0;
+ }
+
+ @Override
+ public int takeEssentia(Aspect aspect, int amount, ForgeDirection var3) {
+ return this.takeFromContainer(aspect, amount) ? amount : 0;
+ }
+
+ @Override
+ public int addEssentia(Aspect aspect, int amount, ForgeDirection direction) {
+ return amount - addToContainer(aspect, amount);
+ }
+
+ @Override
+ public Aspect getEssentiaType(ForgeDirection var1) {
+ return this.mAspects.size() > 0 ? this.mAspects.getAspects()[0] : null;
+ }
+
+ @Override
+ public int getEssentiaAmount(ForgeDirection var1) {
+ return this.mAspects.visSize();
+ }
+
+ @Override
+ public int getMinimumSuction() {
+ return 0;
+ }
+
+ @Override
+ public boolean renderExtendedTube() {
+ return true;
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/EssentiaOutputHatch_ME.java b/src/main/java/goodgenerator/blocks/tileEntity/EssentiaOutputHatch_ME.java
new file mode 100644
index 0000000000..b576b44e7f
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/EssentiaOutputHatch_ME.java
@@ -0,0 +1,150 @@
+package goodgenerator.blocks.tileEntity;
+
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import appeng.api.config.Actionable;
+import appeng.api.networking.GridFlags;
+import appeng.api.networking.IGrid;
+import appeng.api.networking.IGridNode;
+import appeng.api.networking.security.IActionHost;
+import appeng.api.networking.security.MachineSource;
+import appeng.api.util.AECableType;
+import appeng.api.util.DimensionalCoord;
+import appeng.me.helpers.AENetworkProxy;
+import appeng.me.helpers.IGridProxyable;
+import appeng.tile.TileEvent;
+import appeng.tile.events.TileEventType;
+import goodgenerator.util.ItemRefer;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
+import thaumicenergistics.api.grid.IEssentiaGrid;
+import thaumicenergistics.api.grid.IMEEssentiaMonitor;
+
+public class EssentiaOutputHatch_ME extends EssentiaOutputHatch implements IActionHost, IGridProxyable {
+
+ private AENetworkProxy gridProxy = null;
+ private IMEEssentiaMonitor monitor = null;
+ private MachineSource asMachineSource = new MachineSource(this);
+
+ @Override
+ public void updateEntity() {
+ getProxy();
+ super.updateEntity();
+ }
+
+ @Override
+ public void invalidate() {
+ super.invalidate();
+ this.invalidateAE();
+ }
+
+ @Override
+ public void onChunkUnload() {
+ super.onChunkUnload();
+ this.onChunkUnloadAE();
+ }
+
+ @TileEvent(TileEventType.WORLD_NBT_READ)
+ public void readFromNBT_AENetwork(final NBTTagCompound data) {
+ AENetworkProxy gp = getProxy();
+ if (gp != null) getProxy().readFromNBT(data);
+ }
+
+ @TileEvent(TileEventType.WORLD_NBT_WRITE)
+ public void writeToNBT_AENetwork(final NBTTagCompound data) {
+ AENetworkProxy gp = getProxy();
+ if (gp != null) gp.writeToNBT(data);
+ }
+
+ void onChunkUnloadAE() {
+ AENetworkProxy gp = getProxy();
+ if (gp != null) gp.onChunkUnload();
+ }
+
+ void invalidateAE() {
+ AENetworkProxy gp = getProxy();
+ if (gp != null) gp.invalidate();
+ }
+
+ @Override
+ public IGridNode getGridNode(ForgeDirection forgeDirection) {
+ AENetworkProxy gp = getProxy();
+ return gp != null ? gp.getNode() : null;
+ }
+
+ @Override
+ public void gridChanged() {}
+
+ @Override
+ public AECableType getCableConnectionType(ForgeDirection forgeDirection) {
+ return AECableType.SMART;
+ }
+
+ @Override
+ public void securityBreak() {}
+
+ @Override
+ public AENetworkProxy getProxy() {
+ if (gridProxy == null) {
+ gridProxy = new AENetworkProxy(this, "proxy", ItemRefer.Essentia_Output_Hatch_ME.get(1), true);
+ gridProxy.onReady();
+ gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL);
+ }
+ return this.gridProxy;
+ }
+
+ @Override
+ public DimensionalCoord getLocation() {
+ return new DimensionalCoord(this.worldObj, this.xCoord, this.yCoord, this.zCoord);
+ }
+
+ @Override
+ public IGridNode getActionableNode() {
+ AENetworkProxy gp = getProxy();
+ return gp != null ? gp.getNode() : null;
+ }
+
+ @Override
+ public boolean takeFromContainer(AspectList aspects) {
+ return false;
+ }
+
+ @Override
+ public boolean takeFromContainer(Aspect aspect, int amount) {
+ return false;
+ }
+
+ @Override
+ public int addEssentia(Aspect aspect, int amount, ForgeDirection side) {
+ return this.addEssentia(aspect, amount, side, Actionable.MODULATE);
+ }
+
+ public int addEssentia(Aspect aspect, int amount, ForgeDirection side, Actionable mode) {
+ long rejectedAmount = amount;
+ if (this.getEssentiaMonitor()) {
+ rejectedAmount = this.monitor.injectEssentia(aspect, amount, mode, this.getMachineSource(), true);
+ }
+
+ long acceptedAmount = (long) amount - rejectedAmount;
+ return (int) acceptedAmount;
+ }
+
+ protected boolean getEssentiaMonitor() {
+ IMEEssentiaMonitor essentiaMonitor = null;
+ IGrid grid = null;
+ IGridNode node = this.getProxy()
+ .getNode();
+
+ if (node != null) {
+ grid = node.getGrid();
+ if (grid != null) essentiaMonitor = grid.getCache(IEssentiaGrid.class);
+ }
+ this.monitor = essentiaMonitor;
+ return (this.monitor != null);
+ }
+
+ public MachineSource getMachineSource() {
+ return this.asMachineSource;
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/ExtremeHeatExchanger.java b/src/main/java/goodgenerator/blocks/tileEntity/ExtremeHeatExchanger.java
new file mode 100644
index 0000000000..af1fd82030
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/ExtremeHeatExchanger.java
@@ -0,0 +1,416 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.Textures.BlockIcons.*;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.Constants;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.Fluid;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import goodgenerator.api.recipe.ExtremeHeatExchangerRecipe;
+import goodgenerator.api.recipe.GoodGeneratorRecipeMaps;
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_HatchElement;
+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.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.IGT_HatchAdder;
+
+public class ExtremeHeatExchanger extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ protected IStructureDefinition<ExtremeHeatExchanger> multiDefinition = null;
+
+ public static double penalty_per_config = 0.015d;
+ protected int casingAmount = 0;
+ protected GT_MetaTileEntity_Hatch_Input mHotFluidHatch;
+ protected GT_MetaTileEntity_Hatch_Output mCooledFluidHatch;
+ private boolean transformed = false;
+ private String hotName;
+ private ExtremeHeatExchangerRecipe tRunningRecipe;
+
+ public ExtremeHeatExchanger(String name) {
+ super(name);
+ }
+
+ public ExtremeHeatExchanger(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ @Override
+ public IStructureDefinition<ExtremeHeatExchanger> getStructure_EM() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<ExtremeHeatExchanger>builder()
+ .addShape(
+ mName,
+ transpose(
+ new String[][] {
+ // spotless:off
+ { " CCC ", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", " CCC " },
+ { " CCC ", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", " CCC " },
+ { " CFC ", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", " CEC " },
+ { " CCC ", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", " CCC " },
+ { " CCC ", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", "GWWWG", "GPPPG", " CCC " },
+ { " C~C ", "BBBBB", "BBBBB", "BBBBB", "BBBBB", "BBBBB", "BBBBB", "BBBBB", "BBBBB", "BBBBB", " CCC " },
+ //spotless:on
+ }))
+ .addElement(
+ 'B',
+ ofChain(
+ buildHatchAdder(ExtremeHeatExchanger.class)
+ .atLeast(GT_HatchElement.InputHatch, GT_HatchElement.Maintenance)
+ .casingIndex(48)
+ .dot(1)
+ .build(),
+ onElementPass(x -> x.casingAmount++, ofBlock(GregTech_API.sBlockCasings4, 0))))
+ .addElement(
+ 'T',
+ ofChain(
+ buildHatchAdder(ExtremeHeatExchanger.class)
+ .atLeast(GT_HatchElement.OutputHatch, GT_HatchElement.Maintenance)
+ .casingIndex(48)
+ .dot(2)
+ .build(),
+ onElementPass(x -> x.casingAmount++, ofBlock(GregTech_API.sBlockCasings4, 0))))
+ .addElement('F', EHEHatches.HotInputHatch.newAny(48, 3))
+ .addElement('E', EHEHatches.ColdOutputHatch.newAny(48, 4))
+ .addElement(
+ 'C',
+ ofChain(
+ buildHatchAdder(ExtremeHeatExchanger.class).atLeast(GT_HatchElement.Maintenance)
+ .casingIndex(48)
+ .dot(5)
+ .build(),
+ onElementPass(x -> x.casingAmount++, ofBlock(GregTech_API.sBlockCasings4, 0))))
+ .addElement('G', Glasses.chainAllGlasses())
+ .addElement('P', ofBlock(GregTech_API.sBlockCasings2, 15))
+ .addElement('W', ofBlock(Loaders.pressureResistantWalls, 0))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ public boolean addHotFluidInputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ mHotFluidHatch = (GT_MetaTileEntity_Hatch_Input) aMetaTileEntity;
+ return true;
+ }
+ return false;
+ }
+
+ public boolean addColdFluidOutputToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ mCooledFluidHatch = (GT_MetaTileEntity_Hatch_Output) aMetaTileEntity;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ transformed = aNBT.getBoolean("transformed");
+ if (aNBT.hasKey("hotName", Constants.NBT.TAG_STRING)) {
+ String loadedHotName = aNBT.getString("hotName");
+ Fluid hotFluid = FluidRegistry.getFluid(loadedHotName);
+ if (hotFluid != null) {
+ hotName = loadedHotName;
+ tRunningRecipe = (ExtremeHeatExchangerRecipe) GoodGeneratorRecipeMaps.extremeHeatExchangerFuels
+ .getBackend()
+ .findFuel(hotFluid);
+ }
+ } else {
+ hotName = null;
+ tRunningRecipe = null;
+ }
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setBoolean("transformed", transformed);
+ if (hotName != null) aNBT.setString("hotName", hotName);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return GoodGeneratorRecipeMaps.extremeHeatExchangerFuels;
+ }
+
+ @Override
+ protected void clearHatches_EM() {
+ super.clearHatches_EM();
+ mCooledFluidHatch = null;
+ mHotFluidHatch = null;
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ this.casingAmount = 0;
+ return structureCheck_EM(mName, 2, 5, 0) && mMaintenanceHatches.size() == 1 && casingAmount >= 25;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Heat Exchanger/Plasma Heat Exchanger")
+ .addInfo("Controller block for the Extreme Heat Exchanger.")
+ .addInfo("Accept Hot fluid like lava, hot coolant or plasma.")
+ .addInfo("Output SC Steam/SH Steam/Steam.")
+ .addInfo("Check NEI for more info.")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addController("Front bottom")
+ .addOtherStructurePart("Input Hatch", "distilled water", 1)
+ .addOtherStructurePart("Output Hatch", "SC Steam/SH Steam/Steam", 2)
+ .addOtherStructurePart("Input Hatch", "Hot fluid or plasma", 3)
+ .addOtherStructurePart("Output Hatch", "Cold fluid", 4)
+ .addMaintenanceHatch("Any Casing", 1, 2, 5)
+ .addCasingInfoMin("Robust Tungstensteel Machine Casings", 25, false)
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public @NotNull CheckRecipeResult checkProcessing_EM() {
+ tRunningRecipe = null;
+ if (mHotFluidHatch.getFluid() == null) return CheckRecipeResultRegistry.SUCCESSFUL;
+ ExtremeHeatExchangerRecipe tRecipe = (ExtremeHeatExchangerRecipe) GoodGeneratorRecipeMaps.extremeHeatExchangerFuels
+ .getBackend()
+ .findFuel(mHotFluidHatch.getFluid());
+ if (tRecipe == null) return CheckRecipeResultRegistry.NO_RECIPE;
+ tRunningRecipe = tRecipe;
+ this.hotName = mHotFluidHatch.getFluid()
+ .getFluid()
+ .getName();
+ int tMaxConsume = tRecipe.getMaxHotFluidConsume();
+ int transformed_threshold = tRecipe.mSpecialValue;
+ int tRealConsume = Math.min(tMaxConsume, mHotFluidHatch.getFluid().amount);
+ double penalty = 0.0d;
+ double efficiency = 1d;
+ int shs_reduction_per_config = 150;
+
+ if (mInventory[1] != null && mInventory[1].getUnlocalizedName()
+ .startsWith("gt.integrated_circuit")) {
+ int circuit_config = mInventory[1].getItemDamage();
+ if (circuit_config >= 1 && circuit_config <= 25) {
+ penalty = (circuit_config - 1) * penalty_per_config;
+ transformed_threshold -= (shs_reduction_per_config * (circuit_config - 1));
+ }
+ }
+ efficiency -= penalty;
+
+ if (transformed_threshold <= 0) transformed_threshold = 1;
+
+ transformed = tRealConsume >= transformed_threshold;
+
+ this.mMaxProgresstime = 20;
+ this.mEUt = (int) (tRecipe.getEUt() * efficiency * ((double) tRealConsume / (double) tMaxConsume));
+ mHotFluidHatch.drain(tRealConsume, true);
+ mCooledFluidHatch.fill(new FluidStack(tRecipe.getCooledFluid(), tRealConsume), true);
+ this.mEfficiencyIncrease = 160;
+
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ if (this.mEUt > 0 && tRunningRecipe != null) {
+ Fluid tReadySteam = transformed ? tRunningRecipe.getHeatedSteam() : tRunningRecipe.getNormalSteam();
+ int waterAmount = (int) (this.mEUt / getUnitSteamPower(tReadySteam.getName())) / 160;
+ if (waterAmount < 0) return false;
+ if (depleteInput(GT_ModHandler.getDistilledWater(waterAmount))) {
+ addOutput(new FluidStack(tReadySteam, waterAmount * 160));
+ } else {
+ GT_Log.exp.println(this.mName + " had no more Distilled water!");
+ mHotFluidHatch.getBaseMetaTileEntity()
+ .doExplosion(V[8]);
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public double getUnitSteamPower(String steam) {
+ switch (steam) {
+ case "steam":
+ return 0.5;
+ case "ic2superheatedsteam":
+ return 1;
+ case "supercriticalsteam":
+ return 100;
+ default:
+ return -1;
+ }
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ structureBuild_EM(mName, 2, 5, 0, stackSize, hintsOnly);
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("ExtremeHeatExchanger.hint", 6);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new ExtremeHeatExchanger(mName);
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int tThreshold = tRunningRecipe != null ? tRunningRecipe.mSpecialValue : 0;
+ return new String[] {
+ StatCollector.translateToLocal("GT5U.multiblock.Progress") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(mProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(mMaxProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s",
+ StatCollector.translateToLocal("GT5U.multiblock.problems") + ": "
+ + EnumChatFormatting.RED
+ + (getIdealStatus() - getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " "
+ + StatCollector.translateToLocal("GT5U.multiblock.efficiency")
+ + ": "
+ + EnumChatFormatting.YELLOW
+ + mEfficiency / 100.0F
+ + EnumChatFormatting.RESET
+ + " %",
+ StatCollector.translateToLocal("scanner.info.XHE.0") + " "
+ + (transformed ? EnumChatFormatting.RED : EnumChatFormatting.YELLOW)
+ + GT_Utility.formatNumbers(this.mEUt)
+ + EnumChatFormatting.RESET
+ + " EU/t",
+ StatCollector.translateToLocal("scanner.info.XHE.1") + " "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(tThreshold)
+ + EnumChatFormatting.RESET
+ + " L/s" };
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][48], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_ACTIVE)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_ACTIVE_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][48], TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_HEAT_EXCHANGER_GLOW)
+ .extFacing()
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[0][48] };
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(mName, stackSize, 2, 5, 0, elementBudget, env, false, true);
+ }
+
+ private enum EHEHatches implements IHatchElement<ExtremeHeatExchanger> {
+
+ HotInputHatch(ExtremeHeatExchanger::addHotFluidInputToMachineList, GT_MetaTileEntity_Hatch_Input.class) {
+
+ @Override
+ public long count(ExtremeHeatExchanger t) {
+ if (t.mHotFluidHatch == null) return 0;
+ return 1;
+ }
+ },
+ ColdOutputHatch(ExtremeHeatExchanger::addColdFluidOutputToMachineList, GT_MetaTileEntity_Hatch_Output.class) {
+
+ @Override
+ public long count(ExtremeHeatExchanger t) {
+ if (t.mCooledFluidHatch == null) return 0;
+ return 1;
+ }
+ };
+
+ private final List<Class<? extends IMetaTileEntity>> mteClasses;
+ private final IGT_HatchAdder<ExtremeHeatExchanger> adder;
+
+ EHEHatches(IGT_HatchAdder<ExtremeHeatExchanger> adder, Class<? extends IMetaTileEntity>... mteClasses) {
+ this.mteClasses = Collections.unmodifiableList(Arrays.asList(mteClasses));
+ this.adder = adder;
+ }
+
+ @Override
+ public List<? extends Class<? extends IMetaTileEntity>> mteClasses() {
+ return mteClasses;
+ }
+
+ public IGT_HatchAdder<? super ExtremeHeatExchanger> adder() {
+ return adder;
+ }
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/FuelRefineFactory.java b/src/main/java/goodgenerator/blocks/tileEntity/FuelRefineFactory.java
new file mode 100644
index 0000000000..85c4bffbab
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/FuelRefineFactory.java
@@ -0,0 +1,376 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti;
+import com.gtnewhorizon.structurelib.StructureLibAPI;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.AutoPlaceEnvironment;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizon.structurelib.structure.StructureUtility;
+
+import goodgenerator.api.recipe.GoodGeneratorRecipeMaps;
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.enums.GT_HatchElement;
+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.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+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_Output;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_Recipe;
+
+public class FuelRefineFactory extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ private IStructureDefinition<FuelRefineFactory> multiDefinition = null;
+ private int Tier = -1;
+ private int[] cnt = new int[] { 0, 0, 0, 0 };
+ private static final Block[] coils = new Block[] { Loaders.FRF_Coil_1, Loaders.FRF_Coil_2, Loaders.FRF_Coil_3,
+ Loaders.FRF_Coil_4 };
+
+ public FuelRefineFactory(String name) {
+ super(name);
+ turnOffMaintenance();
+ useLongPower = true;
+ }
+
+ public FuelRefineFactory(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ turnOffMaintenance();
+ useLongPower = true;
+ }
+
+ @Override
+ public void onFirstTick_EM(IGregTechTileEntity aBaseMetaTileEntity) {
+ if (!hasMaintenanceChecks) turnOffMaintenance();
+ }
+
+ @Override
+ public boolean doRandomMaintenanceDamage() {
+ return true;
+ }
+
+ @Override
+ public void construct(ItemStack itemStack, boolean hintsOnly) {
+ structureBuild_EM(mName, 7, 12, 1, itemStack, hintsOnly);
+ }
+
+ @Override
+ public IStructureDefinition<FuelRefineFactory> getStructure_EM() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<FuelRefineFactory>builder()
+ .addShape(
+ mName,
+ transpose(
+ new String[][] { { " ", " CCC ", " " },
+ { " XGX ", " CCFFFCC ", " XGX " },
+ { " CC CC ", " CFFCCCFFC ", " CC CC " },
+ { " C C ", " CFCC CCFC ", " C C " },
+ { " C C ", " CFC CFC ", " C C " },
+ { " C C ", " CFC CFC ", " C C " },
+ { " X X ", "CFC CFC", " X X " },
+ { " G G ", "CFC CFC", " G G " },
+ { " X X ", "CFC CFC", " X X " },
+ { " C C ", " CFC CFC ", " C C " },
+ { " C C ", " CFC CFC ", " C C " },
+ { " C C ", " CFCC CCFC ", " C C " },
+ { " CC CC ", " CFFC~CFFC ", " CC CC " },
+ { " XGX ", " CCFFFCC ", " XGX " },
+ { " ", " CCC ", " " } }))
+ .addElement(
+ 'X',
+ buildHatchAdder(FuelRefineFactory.class)
+ .atLeast(
+ GT_HatchElement.Maintenance,
+ GT_HatchElement.InputHatch,
+ GT_HatchElement.InputBus,
+ GT_HatchElement.OutputHatch,
+ HatchElement.EnergyMulti.or(GT_HatchElement.Energy))
+ .casingIndex(179)
+ .dot(1)
+ .buildAndChain(ofBlock(Loaders.FRF_Casings, 0)))
+ .addElement('C', ofBlock(Loaders.FRF_Casings, 0))
+ .addElement('G', ofBlock(Loaders.fieldRestrictingGlass, 0))
+ .addElement(
+ 'F',
+ ofChain(
+ onElementPass(x -> ++x.cnt[0], ofFieldCoil(0)),
+ onElementPass(x -> ++x.cnt[1], ofFieldCoil(1)),
+ onElementPass(x -> ++x.cnt[2], ofFieldCoil(2)),
+ onElementPass(x -> ++x.cnt[3], ofFieldCoil(3))))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ public static <T> IStructureElement<T> ofFieldCoil(int aIndex) {
+ return new IStructureElement<T>() {
+
+ @Override
+ public boolean check(T t, World world, int x, int y, int z) {
+ Block block = world.getBlock(x, y, z);
+ return block.equals(coils[aIndex]);
+ }
+
+ @Override
+ public boolean spawnHint(T t, World world, int x, int y, int z, ItemStack trigger) {
+ StructureLibAPI.hintParticle(world, x, y, z, coils[getIndex(trigger)], 0);
+ return true;
+ }
+
+ private int getIndex(ItemStack trigger) {
+ int s = trigger.stackSize;
+ if (s > 4 || s <= 0) s = 4;
+ return s - 1;
+ }
+
+ @Override
+ public boolean placeBlock(T t, World world, int x, int y, int z, ItemStack trigger) {
+ return world.setBlock(x, y, z, coils[getIndex(trigger)], 0, 3);
+ }
+
+ @Override
+ public BlocksToPlace getBlocksToPlace(T t, World world, int x, int y, int z, ItemStack trigger,
+ AutoPlaceEnvironment env) {
+ return BlocksToPlace.create(coils[getIndex(trigger)], 0);
+ }
+
+ @Override
+ public PlaceResult survivalPlaceBlock(T t, World world, int x, int y, int z, ItemStack trigger,
+ AutoPlaceEnvironment env) {
+ if (check(t, world, x, y, z)) return PlaceResult.SKIP;
+ return StructureUtility.survivalPlaceBlock(
+ coils[getIndex(trigger)],
+ 0,
+ world,
+ x,
+ y,
+ z,
+ env.getSource(),
+ env.getActor(),
+ env.getChatter());
+ }
+ };
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Naquadah Fuel Refinery")
+ .addInfo("Controller block for the Naquadah Fuel Refinery")
+ .addInfo("But at what cost?")
+ .addInfo("Produces naquadah fuels.")
+ .addInfo("Needs field restriction coils to control the fatal radiation.")
+ .addInfo("Use higher tier coils to unlock more fuel types and reduce the processing times.")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .beginStructureBlock(3, 15, 15, false)
+ .addInputHatch("The casings adjoin the field restriction glass.")
+ .addInputBus("The casings adjoin the field restriction glass.", 1)
+ .addOutputHatch("The casings adjoin the field restriction glass.", 1)
+ .addEnergyHatch("The casings adjoin the field restriction glass.", 1)
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ this.Tier = aNBT.getInteger("mTier");
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("mTier", this.Tier);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack itemStack) {
+ return DescTextLocalization.addText("FuelRefineFactory.hint", 8);
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ cnt[0] = 0;
+ cnt[1] = 0;
+ cnt[2] = 0;
+ cnt[3] = 0;
+ return structureCheck_EM(mName, 7, 12, 1) && getTier() != -1;
+ }
+
+ public int getTier() {
+ for (int i = 0; i < 4; i++) {
+ if (cnt[i] == 32) {
+ Tier = i + 1;
+ return i;
+ }
+ }
+ Tier = -1;
+ return -1;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return GoodGeneratorRecipeMaps.naquadahFuelRefineFactoryRecipes;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult validateRecipe(@NotNull GT_Recipe recipe) {
+ if (recipe.mSpecialValue > Tier) {
+ return CheckRecipeResultRegistry.insufficientMachineTier(recipe.mSpecialValue);
+ }
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @NotNull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@NotNull GT_Recipe recipe) {
+ int overclockAmount = Tier - recipe.mSpecialValue;
+ return super.createOverclockCalculator(recipe).limitOverclockCount(overclockAmount);
+ }
+ }.setOverclock(1, 1); // Set Overclock to be 2/2
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(getMaxInputEu());
+ logic.setAvailableAmperage(1);
+ }
+
+ public final boolean addToFRFList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ return false;
+ } else {
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ return this.mInputHatches.add((GT_MetaTileEntity_Hatch_Input) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output) {
+ return this.mOutputHatches.add((GT_MetaTileEntity_Hatch_Output) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_InputBus) {
+ return this.mInputBusses.add((GT_MetaTileEntity_Hatch_InputBus) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Energy) {
+ return this.mEnergyHatches.add((GT_MetaTileEntity_Hatch_Energy) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_EnergyMulti) {
+ return this.eEnergyMulti.add((GT_MetaTileEntity_Hatch_EnergyMulti) aMetaTileEntity);
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new FuelRefineFactory(this.mName);
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getPollutionPerTick(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ String[] infoData = new String[super.getInfoData().length + 1];
+ System.arraycopy(super.getInfoData(), 0, infoData, 0, super.getInfoData().length);
+ infoData[super.getInfoData().length] = StatCollector.translateToLocal("scanner.info.FRF") + " " + this.Tier;
+ return infoData;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ @SuppressWarnings("ALL")
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(179),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE), TextureFactory.builder()
+ .addIcon(Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(179),
+ new GT_RenderedTexture(Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE), TextureFactory.builder()
+ .addIcon(Textures.BlockIcons.OVERLAY_FRONT_ASSEMBLY_LINE_GLOW)
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(179) };
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(mName, stackSize, 7, 12, 1, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/DieselGenerator.java b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/DieselGenerator.java
new file mode 100644
index 0000000000..4d54be44d1
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/DieselGenerator.java
@@ -0,0 +1,214 @@
+package goodgenerator.blocks.tileEntity.GTMetaTileEntity;
+
+import static gregtech.api.enums.Textures.BlockIcons.*;
+import static gregtech.api.enums.Textures.BlockIcons.DIESEL_GENERATOR_SIDE_ACTIVE_GLOW;
+
+import net.minecraft.item.ItemStack;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import cpw.mods.fml.common.registry.GameRegistry;
+import gregtech.GT_Mod;
+import gregtech.api.enums.ItemList;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicGenerator;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Log;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Utility;
+
+public class DieselGenerator extends GT_MetaTileEntity_BasicGenerator {
+
+ public int mEfficiency;
+
+ public DieselGenerator(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ new String[] { "Requires liquid Fuel",
+ "Causes " + (int) (GT_Mod.gregtechproxy.mPollutionBaseDieselGeneratorPerSecond * (1.1 - aTier * 0.1))
+ + " Pollution per second" });
+ mEfficiency = 100 - aTier * 10;
+ }
+
+ public DieselGenerator(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ mEfficiency = 100 - aTier * 10;
+ }
+
+ @Override
+ public boolean isOutputFacing(ForgeDirection side) {
+ return side == getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new DieselGenerator(this.mName, this.mTier, this.mDescriptionArray, this.mTextures);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.dieselFuels;
+ }
+
+ @Override
+ public int getCapacity() {
+ return 16000;
+ }
+
+ @Override
+ public int getEfficiency() {
+ return this.mEfficiency;
+ }
+
+ @Override
+ public int getFuelValue(ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack) || getRecipeMap() == null) return 0;
+ long rValue = Math.max(GT_ModHandler.getFuelCanValue(aStack) * 6 / 5, super.getFuelValue(aStack));
+ if (ItemList.Fuel_Can_Plastic_Filled.isStackEqual(aStack, false, true)) {
+ rValue = Math.max(rValue, GameRegistry.getFuelValue(aStack) * 3L);
+ }
+ if (rValue > Integer.MAX_VALUE) {
+ throw new ArithmeticException("Integer LOOPBACK!");
+ }
+ return (int) rValue;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aTick % 100 == 0 && mFluid != null && mFluid.amount > this.getCapacity()) {
+ GT_Log.err.println(
+ "Dupe Abuse: " + aBaseMetaTileEntity.getOwnerName()
+ + " Coords: "
+ + aBaseMetaTileEntity.getXCoord()
+ + " "
+ + aBaseMetaTileEntity.getYCoord()
+ + " "
+ + aBaseMetaTileEntity.getZCoord());
+ aBaseMetaTileEntity.setToFire();
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public ITexture[] getFront(byte aColor) {
+ return new ITexture[] { super.getFront(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_FRONT),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_FRONT_GLOW)
+ .glow()
+ .build()),
+ OVERLAYS_ENERGY_OUT[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getBack(byte aColor) {
+ return new ITexture[] { super.getBack(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_BACK),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_BACK_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottom(byte aColor) {
+ return new ITexture[] { super.getBottom(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_BOTTOM),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_BOTTOM_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTop(byte aColor) {
+ return new ITexture[] { super.getTop(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_TOP),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_TOP_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSides(byte aColor) {
+ return new ITexture[] { super.getSides(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_SIDE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_SIDE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getFrontActive(byte aColor) {
+ return new ITexture[] { super.getFrontActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build()),
+ OVERLAYS_ENERGY_OUT[this.mTier] };
+ }
+
+ @Override
+ public ITexture[] getBackActive(byte aColor) {
+ return new ITexture[] { super.getBackActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_BACK_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_BACK_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getBottomActive(byte aColor) {
+ return new ITexture[] { super.getBottomActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_BOTTOM_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_BOTTOM_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getTopActive(byte aColor) {
+ return new ITexture[] { super.getTopActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_TOP_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_TOP_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public ITexture[] getSidesActive(byte aColor) {
+ return new ITexture[] { super.getSidesActive(aColor)[0],
+ TextureFactory.of(
+ TextureFactory.of(DIESEL_GENERATOR_SIDE_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(DIESEL_GENERATOR_SIDE_ACTIVE_GLOW)
+ .glow()
+ .build()) };
+ }
+
+ @Override
+ public int getPollution() {
+ return (int) (GT_Mod.gregtechproxy.mPollutionBaseDieselGeneratorPerSecond * (1.1 - mTier * 0.1));
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronAccelerator.java b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronAccelerator.java
new file mode 100644
index 0000000000..730374db66
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronAccelerator.java
@@ -0,0 +1,48 @@
+package goodgenerator.blocks.tileEntity.GTMetaTileEntity;
+
+import static gregtech.api.enums.GT_Values.V;
+
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.MetaTileEntity;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+
+public class NeutronAccelerator extends GT_MetaTileEntity_Hatch_Energy {
+
+ public NeutronAccelerator(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier);
+ }
+
+ public NeutronAccelerator(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, aDescription, aTextures);
+ }
+
+ public int getMaxEUConsume() {
+ return (int) (V[mTier] * 8 / 10);
+ }
+
+ @Override
+ public MetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new NeutronAccelerator(mName, mTier, this.getDescription(), mTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "Input EU to Accelerate the Neutron!", "Max EU input: " + this.maxEUInput(),
+ "Max EU consumption: " + this.getMaxEUConsume(),
+ "Every EU can be transformed into 10~20 eV Neutron Kinetic Energy." };
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (aBaseMetaTileEntity.getStoredEU() >= getMaxEUConsume() && aBaseMetaTileEntity.isAllowedToWork()) {
+ setEUVar(aBaseMetaTileEntity.getStoredEU() - getMaxEUConsume());
+ aBaseMetaTileEntity.setActive(true);
+ } else {
+ aBaseMetaTileEntity.setActive(false);
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronSensor.java b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronSensor.java
new file mode 100644
index 0000000000..86bcbeece9
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/NeutronSensor.java
@@ -0,0 +1,277 @@
+package goodgenerator.blocks.tileEntity.GTMetaTileEntity;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.gtnewhorizons.modularui.api.math.Alignment;
+import com.gtnewhorizons.modularui.api.math.Color;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget;
+
+import crazypants.enderio.Log;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UIInfos;
+import gregtech.api.gui.modularui.GT_UITextures;
+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.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.gui.modularui.widget.CoverCycleButtonWidget;
+
+public class NeutronSensor extends GT_MetaTileEntity_Hatch {
+
+ private static final IIconContainer textureFont = new Textures.BlockIcons.CustomIcon("icons/NeutronSensorFont");
+ private static final IIconContainer textureFont_Glow = new Textures.BlockIcons.CustomIcon(
+ "icons/NeutronSensorFont_GLOW");
+
+ protected int threshold = 0;
+ protected boolean inverted = false;
+ boolean isOn = false;
+
+ public NeutronSensor(int aID, String aName, String aNameRegional, int aTier) {
+ super(aID, aName, aNameRegional, aTier, 0, "Detect Neutron Kinetic Energy.");
+ }
+
+ public NeutronSensor(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 0, aDescription, aTextures);
+ }
+
+ @Override
+ public String[] getDescription() {
+ return new String[] { "Can be installed in Neutron Activator.",
+ "Output Redstone Signal according to the Neutron Kinetic Energy.",
+ "Right click to open the GUI and setting." };
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ if (aNBT.hasKey("mBoxContext")) {
+ // Convert legacy settings
+ setThresholdFromString(aNBT.getString("mBoxContext"));
+ } else {
+ threshold = aNBT.getInteger("mThreshold");
+ inverted = aNBT.getBoolean("mInverted");
+ }
+ super.loadNBTData(aNBT);
+ }
+
+ /**
+ * Used to convert legacy setting where the sensor would use a string like ">200keV" to set its threshold. This
+ * method updates the {@link #threshold} and {@link #inverted} fields based on the input string. The string is
+ * assumed to be in format "(operator)(value)[suffix](ev)", where:
+ * <ul>
+ * <li>(operator) is one of "<", ">", "<=", ">=", "==", or "!="</li>
+ * <li>(value) is a numeric value (sequence of decimal digits)</li>
+ * <li>(suffix) is "k", "K", "m", or "M" (optional)</li>
+ * <li>(ev) is the string "ev", case-insensitive.</li>
+ * </ul>
+ * Note that operators "==" and "!=" can not be converted exactly, as the new threshold supports only a binary
+ * comparison (less than, or greater than or equal). Thus "==" is interpreted in the same way as "<=", and "!=" as
+ * ">". This shouldn't be a big problem for real setups, because one should probably not be testing for strict
+ * equality here anyway. The possible reasonable conditions "==0eV" and "!=0eV" will continue working as before.
+ *
+ * @param text String to convert.
+ */
+ private void setThresholdFromString(String text) {
+ Matcher matcher = Pattern.compile("^(<|>|<=|>=|==|!=)([0-9]*)(|k|m)(ev)$", Pattern.CASE_INSENSITIVE)
+ .matcher(text);
+
+ if (!matcher.matches()) {
+ Log.error("Failed to parse Neutron Sensor setting: \"" + text + "\"!");
+ return;
+ }
+
+ String operator = matcher.group(1);
+ String value = matcher.group(2);
+ String suffix = matcher.group(3);
+
+ int newThreshold = Integer.parseInt(value);
+
+ switch (suffix) {
+ case "k":
+ case "K":
+ newThreshold *= 1000;
+ break;
+ case "m":
+ case "M":
+ newThreshold *= 1_000_000;
+ break;
+ }
+
+ switch (operator) {
+ case "<":
+ threshold = newThreshold;
+ inverted = true;
+ break;
+ case ">":
+ threshold = newThreshold + 1;
+ inverted = false;
+ break;
+ case "<=":
+ threshold = newThreshold + 1;
+ inverted = true;
+ break;
+ case ">=":
+ threshold = newThreshold;
+ inverted = false;
+ break;
+ case "==": // Interpret as <= to keep "==0eV" working as before.
+ threshold = newThreshold + 1;
+ inverted = true;
+ break;
+ case "!=": // Interpret as > to keep "!=0eV" working as before.
+ threshold = newThreshold + 1;
+ inverted = false;
+ break;
+ }
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("mThreshold", threshold);
+ aNBT.setBoolean("mInverted", inverted);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void initDefaultModes(NBTTagCompound aNBT) {
+ getBaseMetaTileEntity().setActive(true);
+ }
+
+ @Override
+ public boolean isValidSlot(int aIndex) {
+ return false;
+ }
+
+ @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, ForgeDirection side,
+ float aX, float aY, float aZ) {
+ GT_UIInfos.openGTTileEntityUI(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ /**
+ * Updates redstone output strength based on the eV of the multiblock.
+ *
+ * @param eV Amount of eV to compare.
+ */
+ public void updateRedstoneOutput(int eV) {
+ isOn = (eV >= threshold) ^ inverted;
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(textureFont), TextureFactory.builder()
+ .addIcon(textureFont_Glow)
+ .glow()
+ .build() };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(textureFont) };
+ }
+
+ @Override
+ public boolean allowGeneralRedstoneOutput() {
+ return true;
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (isOn) {
+ for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
+ aBaseMetaTileEntity.setInternalOutputRedstoneSignal(side, (byte) 15);
+ }
+ } else {
+ for (final ForgeDirection side : ForgeDirection.VALID_DIRECTIONS) {
+ aBaseMetaTileEntity.setInternalOutputRedstoneSignal(side, (byte) 0);
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new NeutronSensor(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @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 boolean useModularUI() {
+ return true;
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ final String INVERTED = GT_Utility.trans("INVERTED", "Inverted");
+ final String NORMAL = GT_Utility.trans("NORMAL", "Normal");
+
+ builder.widget(
+ new CoverCycleButtonWidget().setToggle(() -> inverted, (val) -> inverted = val)
+ .setTextureGetter(
+ (state) -> state == 1 ? GT_UITextures.OVERLAY_BUTTON_REDSTONE_ON
+ : GT_UITextures.OVERLAY_BUTTON_REDSTONE_OFF)
+ .addTooltip(0, NORMAL)
+ .addTooltip(1, INVERTED)
+ .setPos(10, 8))
+ .widget(
+ new TextWidget().setStringSupplier(() -> inverted ? INVERTED : NORMAL)
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setTextAlignment(Alignment.CenterLeft)
+ .setPos(28, 12))
+ .widget(
+ new NumericWidget().setBounds(0, 1200000000)
+ .setGetter(() -> threshold)
+ .setSetter((value) -> threshold = (int) value)
+ .setScrollValues(1000, 1, 1_000_000)
+ .setTextColor(Color.WHITE.dark(1))
+ .setTextAlignment(Alignment.CenterLeft)
+ .setFocusOnGuiOpen(true)
+ .setBackground(GT_UITextures.BACKGROUND_TEXT_FIELD.withOffset(-1, -1, 2, 2))
+ .setPos(10, 28)
+ .setSize(77, 12))
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("gui.NeutronSensor.4"))
+ .setDefaultColor(COLOR_TEXT_GRAY.get())
+ .setTextAlignment(Alignment.CenterLeft)
+ .setPos(90, 30));
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/YOTTAHatch.java b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/YOTTAHatch.java
new file mode 100644
index 0000000000..f905e82f8c
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/GTMetaTileEntity/YOTTAHatch.java
@@ -0,0 +1,470 @@
+package goodgenerator.blocks.tileEntity.GTMetaTileEntity;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+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 net.minecraftforge.fluids.FluidTankInfo;
+
+import appeng.api.config.AccessRestriction;
+import appeng.api.config.Actionable;
+import appeng.api.networking.GridFlags;
+import appeng.api.networking.IGrid;
+import appeng.api.networking.IGridNode;
+import appeng.api.networking.events.MENetworkCellArrayUpdate;
+import appeng.api.networking.events.MENetworkStorageEvent;
+import appeng.api.networking.security.BaseActionSource;
+import appeng.api.networking.security.IActionHost;
+import appeng.api.networking.storage.IStorageGrid;
+import appeng.api.storage.ICellContainer;
+import appeng.api.storage.IMEInventory;
+import appeng.api.storage.IMEInventoryHandler;
+import appeng.api.storage.StorageChannel;
+import appeng.api.storage.data.IAEFluidStack;
+import appeng.api.storage.data.IItemList;
+import appeng.api.util.AECableType;
+import appeng.api.util.DimensionalCoord;
+import appeng.me.helpers.AENetworkProxy;
+import appeng.me.helpers.IGridProxyable;
+import goodgenerator.blocks.tileEntity.YottaFluidTank;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.StackUtils;
+import gregtech.api.enums.Textures;
+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.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Utility;
+
+public class YOTTAHatch extends GT_MetaTileEntity_Hatch implements IGridProxyable, IActionHost, ICellContainer,
+ IMEInventory<IAEFluidStack>, IMEInventoryHandler<IAEFluidStack> {
+
+ private static final IIconContainer textureFont = new Textures.BlockIcons.CustomIcon("icons/YOTTAHatch");
+
+ private YottaFluidTank host;
+ private AENetworkProxy gridProxy = null;
+ private int priority;
+ private byte tickRate = 20;
+ private FluidStack lastFluid = null;
+ private BigInteger lastAmt = BigInteger.ZERO;
+ private AccessRestriction readMode = AccessRestriction.READ_WRITE;
+ private final AccessRestriction[] AEModes = new AccessRestriction[] { AccessRestriction.NO_ACCESS,
+ AccessRestriction.READ, AccessRestriction.WRITE, AccessRestriction.READ_WRITE };
+
+ private static final BigInteger MAX_LONG_BIGINT = BigInteger.valueOf(Long.MAX_VALUE);
+
+ public YOTTAHatch(int aID, String aName, String aNameRegional, int aTier) {
+ super(
+ aID,
+ aName,
+ aNameRegional,
+ aTier,
+ 0,
+ new String[] { "Special I/O port for AE2FC.", "Directly connected YOTTank with AE fluid storage system.",
+ "Use screwdriver to set storage priority", "Use soldering iron to set read/write mode" });
+ }
+
+ public YOTTAHatch(String aName, int aTier, String[] aDescription, ITexture[][][] aTextures) {
+ super(aName, aTier, 0, aDescription, aTextures);
+ }
+
+ public void setTank(YottaFluidTank te) {
+ this.host = te;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mAEPriority", this.priority);
+ aNBT.setInteger("mAEMode", this.readMode.ordinal());
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.priority = aNBT.getInteger("mAEPriority");
+ this.readMode = AEModes[aNBT.getInteger("mAEMode")];
+ }
+
+ @Override
+ public boolean isFacingValid(ForgeDirection facing) {
+ return true;
+ }
+
+ @Override
+ public boolean isAccessAllowed(EntityPlayer aPlayer) {
+ return true;
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ,
+ ItemStack toolStack) {
+ if (aPlayer.isSneaking()) this.priority -= 10;
+ else this.priority += 10;
+ GT_Utility
+ .sendChatToPlayer(aPlayer, String.format(StatCollector.translateToLocal("yothatch.chat.0"), this.priority));
+ }
+
+ @Override
+ public boolean onSolderingToolRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ, ItemStack toolStack) {
+ this.readMode = AEModes[(readMode.ordinal() + 1) % 4];
+ GT_Utility
+ .sendChatToPlayer(aPlayer, String.format(StatCollector.translateToLocal("yothatch.chat.1"), this.readMode));
+ return true;
+ }
+
+ @Override
+ public IGridNode getGridNode(ForgeDirection forgeDirection) {
+ AENetworkProxy gp = getProxy();
+ return gp != null ? gp.getNode() : null;
+ }
+
+ @Override
+ public AECableType getCableConnectionType(ForgeDirection forgeDirection) {
+ return AECableType.SMART;
+ }
+
+ @Override
+ public void securityBreak() {}
+
+ @Override
+ public AENetworkProxy getProxy() {
+ if (gridProxy == null) {
+ gridProxy = new AENetworkProxy(this, "proxy", Loaders.YFH, true);
+ gridProxy.onReady();
+ gridProxy.setFlags(GridFlags.REQUIRE_CHANNEL);
+ }
+ return this.gridProxy;
+ }
+
+ @Override
+ public DimensionalCoord getLocation() {
+ IGregTechTileEntity gtm = this.getBaseMetaTileEntity();
+ return new DimensionalCoord(gtm.getWorld(), gtm.getXCoord(), gtm.getYCoord(), gtm.getZCoord());
+ }
+
+ @Override
+ public IItemList<IAEFluidStack> getAvailableItems(IItemList<IAEFluidStack> out) {
+ if (host == null || host.getBaseMetaTileEntity() == null
+ || !host.getBaseMetaTileEntity()
+ .isActive())
+ return out;
+ if (host.mFluid == null || host.mStorageCurrent.signum() <= 0) return out;
+ long ready;
+ if (host.mStorageCurrent.compareTo(MAX_LONG_BIGINT) >= 0) {
+ ready = Long.MAX_VALUE;
+ } else ready = host.mStorageCurrent.longValue();
+ out.add(StackUtils.createAEFluidStack(host.mFluid.getFluid(), ready));
+ return out;
+ }
+
+ @Override
+ public IAEFluidStack injectItems(IAEFluidStack input, Actionable type, BaseActionSource src) {
+ long amt = fill(null, input, false);
+ if (amt == input.getStackSize()) {
+ if (type.equals(Actionable.MODULATE)) fill(null, input, true);
+ return null;
+ }
+ return input;
+ }
+
+ @Override
+ public IAEFluidStack extractItems(IAEFluidStack request, Actionable mode, BaseActionSource src) {
+ IAEFluidStack ready = drain(null, request, false);
+ if (ready != null) {
+ if (mode.equals(Actionable.MODULATE)) drain(null, ready, true);
+ return ready;
+ } else return null;
+ }
+
+ @Override
+ public StorageChannel getChannel() {
+ return StorageChannel.FLUIDS;
+ }
+
+ @Override
+ public void onFirstTick(IGregTechTileEntity aBaseMetaTileEntity) {
+ super.onFirstTick(aBaseMetaTileEntity);
+ getProxy();
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (shouldTick(aTick)) {
+ if (isChanged()) {
+ IGridNode node = getGridNode(null);
+ if (node != null) {
+ IGrid grid = node.getGrid();
+ if (grid != null) {
+ grid.postEvent(new MENetworkCellArrayUpdate());
+ IStorageGrid storageGrid = grid.getCache(IStorageGrid.class);
+ if (storageGrid == null) {
+ node.getGrid()
+ .postEvent(new MENetworkStorageEvent(null, StorageChannel.FLUIDS));
+ } else {
+ node.getGrid()
+ .postEvent(
+ new MENetworkStorageEvent(storageGrid.getFluidInventory(), StorageChannel.FLUIDS));
+ }
+ node.getGrid()
+ .postEvent(new MENetworkCellArrayUpdate());
+ }
+ }
+ faster();
+ update();
+ } else {
+ slower();
+ }
+ }
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public int getCapacity() {
+ if (host == null || host.getBaseMetaTileEntity() == null
+ || !host.getBaseMetaTileEntity()
+ .isActive())
+ return 0;
+ if (host.mStorage.compareTo(YottaFluidTank.MAX_INT_BIGINT) >= 0) {
+ return Integer.MAX_VALUE;
+ } else return host.mStorage.intValue();
+ }
+
+ @Override
+ public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
+ if (host == null || host.getBaseMetaTileEntity() == null
+ || !host.getBaseMetaTileEntity()
+ .isActive())
+ return 0;
+ if (host.mLockedFluid != null && !host.mLockedFluid.isFluidEqual(resource)) return 0;
+ if (host.mFluid == null || host.mFluid.isFluidEqual(resource)) {
+ if (host.mFluid == null) {
+ host.mFluid = resource.copy();
+ host.mFluid.amount = 1;
+ }
+
+ if (host.addFluid(resource.amount, doFill)) {
+ return resource.amount;
+ } else {
+ final int returned;
+ if (host.getIsVoidExcessEnabled()) {
+ returned = resource.amount;
+ } else {
+ final BigInteger delta = host.mStorage.subtract(host.mStorageCurrent);
+ returned = delta.intValueExact();
+ }
+ host.mStorageCurrent = host.mStorage;
+ return returned;
+ }
+ }
+ return 0;
+ }
+
+ public long fill(@SuppressWarnings("unused") ForgeDirection from, IAEFluidStack resource, boolean doFill) {
+ if (host == null || host.getBaseMetaTileEntity() == null
+ || !host.getBaseMetaTileEntity()
+ .isActive())
+ return 0;
+ if (host.mLockedFluid != null && host.mLockedFluid.getFluid() != resource.getFluid()) return 0;
+ if (host.mFluid == null || host.mFluid.getFluid() == resource.getFluid()) {
+ if (host.mFluid == null) {
+ host.mFluid = resource.getFluidStack(); // makes a copy internally
+ host.mFluid.amount = 1;
+ }
+
+ if (host.addFluid(resource.getStackSize(), doFill)) {
+ return resource.getStackSize();
+ } else {
+ final long returned;
+ if (host.getIsVoidExcessEnabled()) {
+ returned = resource.getStackSize();
+ } else {
+ final BigInteger delta = host.mStorage.subtract(host.mStorageCurrent);
+ returned = delta.longValueExact();
+ }
+ host.mStorageCurrent = host.mStorage;
+ return returned;
+ }
+ }
+ return 0;
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
+ if (host == null || host.getBaseMetaTileEntity() == null
+ || !host.getBaseMetaTileEntity()
+ .isActive())
+ return null;
+ if (host.mFluid == null || host.mFluid.getFluid() != resource.getFluid()) return null;
+ int ready;
+ if (host.mStorageCurrent.compareTo(YottaFluidTank.MAX_INT_BIGINT) >= 0) {
+ ready = Integer.MAX_VALUE;
+ } else ready = host.mStorageCurrent.intValue();
+ ready = Math.min(ready, resource.amount);
+ if (doDrain) {
+ host.reduceFluid(ready);
+ }
+ return new FluidStack(resource.getFluid(), ready);
+ }
+
+ public IAEFluidStack drain(@SuppressWarnings("unused") ForgeDirection from, IAEFluidStack resource,
+ boolean doDrain) {
+ if (host == null || host.getBaseMetaTileEntity() == null
+ || !host.getBaseMetaTileEntity()
+ .isActive())
+ return null;
+ if (host.mFluid == null || host.mFluid.getFluid() != resource.getFluid()) return null;
+ long ready;
+ if (host.mStorageCurrent.compareTo(MAX_LONG_BIGINT) > 0) {
+ ready = Long.MAX_VALUE;
+ } else ready = host.mStorageCurrent.longValue();
+ ready = Math.min(ready, resource.getStackSize());
+ if (doDrain) {
+ host.reduceFluid(ready);
+ }
+ IAEFluidStack copy = resource.copy();
+ copy.setStackSize(ready);
+ return copy;
+ }
+
+ @Override
+ public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
+ if (host == null || host.getBaseMetaTileEntity() == null
+ || !host.getBaseMetaTileEntity()
+ .isActive())
+ return null;
+ if (host.mFluid == null) return null;
+ final FluidStack drainStack = host.mFluid.copy();
+ drainStack.amount = maxDrain;
+ return this.drain(from, drainStack, doDrain);
+ }
+
+ private static final FluidTankInfo[] EMPTY_TANK_INFO = new FluidTankInfo[] { new FluidTankInfo(null, 0) };
+
+ @Override
+ public FluidTankInfo[] getTankInfo(ForgeDirection from) {
+ if (host == null || host.getBaseMetaTileEntity() == null
+ || !host.getBaseMetaTileEntity()
+ .isActive())
+ return EMPTY_TANK_INFO;
+
+ return host.getTankInfo(from);
+ }
+
+ @Override
+ public boolean canTankBeFilled() {
+ return true;
+ }
+
+ @Override
+ public boolean canTankBeEmptied() {
+ return true;
+ }
+
+ @Override
+ public ITexture[] getTexturesActive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(textureFont), };
+ }
+
+ @Override
+ public ITexture[] getTexturesInactive(ITexture aBaseTexture) {
+ return new ITexture[] { aBaseTexture, TextureFactory.of(textureFont), };
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new YOTTAHatch(mName, mTier, mDescriptionArray, mTextures);
+ }
+
+ @Override
+ public IGridNode getActionableNode() {
+ AENetworkProxy gp = getProxy();
+ return gp != null ? gp.getNode() : null;
+ }
+
+ @Override
+ public AccessRestriction getAccess() {
+ return this.readMode;
+ }
+
+ @Override
+ public boolean isPrioritized(IAEFluidStack input) {
+ return true;
+ }
+
+ @Override
+ public boolean canAccept(IAEFluidStack input) {
+ FluidStack rInput = input.getFluidStack();
+ return fill(null, rInput, false) > 0;
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public List<IMEInventoryHandler> getCellArray(StorageChannel channel) {
+ List<IMEInventoryHandler> list = new ArrayList<>();
+ if (channel == StorageChannel.FLUIDS) {
+ list.add(this);
+ }
+ return list;
+ }
+
+ @Override
+ public int getPriority() {
+ return this.priority;
+ }
+
+ @Override
+ public int getSlot() {
+ return 0;
+ }
+
+ @Override
+ public boolean validForPass(int i) {
+ return true;
+ }
+
+ @Override
+ public void blinkCell(int slot) {}
+
+ @Override
+ public void saveChanges(IMEInventory cellInventory) {
+ // This is handled by host itself.
+ }
+
+ private boolean isChanged() {
+ if (this.host == null) return false;
+ return !this.lastAmt.equals(this.host.mStorageCurrent) || this.lastFluid != this.host.mFluid;
+ }
+
+ private void update() {
+ if (this.host == null) return;
+ this.lastAmt = this.host.mStorageCurrent;
+ this.lastFluid = this.host.mFluid;
+ }
+
+ private void faster() {
+ if (this.tickRate > 15) {
+ this.tickRate -= 5;
+ }
+ }
+
+ private void slower() {
+ if (this.tickRate < 100) {
+ this.tickRate += 5;
+ }
+ }
+
+ private boolean shouldTick(long tick) {
+ if (this.host == null) return false;
+ return tick % this.tickRate == 0;
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/LargeEssentiaGenerator.java b/src/main/java/goodgenerator/blocks/tileEntity/LargeEssentiaGenerator.java
new file mode 100644
index 0000000000..b590378922
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/LargeEssentiaGenerator.java
@@ -0,0 +1,511 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import java.util.ArrayList;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.github.bartimaeusnek.bartworks.system.material.WerkstoffLoader;
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_DynamoMulti;
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_DynamoTunnel;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.crossmod.thaumcraft.LargeEssentiaEnergyData;
+import goodgenerator.items.MyMaterial;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import goodgenerator.util.ItemRefer;
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.Materials;
+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_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.objects.XSTR;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
+import thaumcraft.common.config.ConfigBlocks;
+
+public class LargeEssentiaGenerator extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ private IStructureDefinition<LargeEssentiaGenerator> multiDefinition = null;
+ protected int mStableValue = 0;
+ protected int mTierLimit = -1;
+ protected long mLeftEnergy;
+ private int mUpgrade = 1;
+ final XSTR R = new XSTR();
+ protected ArrayList<EssentiaHatch> mEssentiaHatch = new ArrayList<>();
+
+ public LargeEssentiaGenerator(String name) {
+ super(name);
+ }
+
+ public LargeEssentiaGenerator(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ @Override
+ public void construct(ItemStack itemStack, boolean hintsOnly) {
+ structureBuild_EM(mName, 4, 0, 4, itemStack, hintsOnly);
+ }
+
+ @Override
+ protected void clearHatches_EM() {
+ super.clearHatches_EM();
+ mEssentiaHatch.clear();
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mStableValue = 0;
+ return structureCheck_EM(mName, 4, 0, 4) && (mDynamoHatches.size() + eDynamoMulti.size()) == 1
+ && checkHatchTier()
+ && checkNoLaser()
+ && updateEssentiaHatchState();
+ }
+
+ private boolean checkNoLaser() {
+ for (GT_MetaTileEntity_Hatch_DynamoMulti tHatch : eDynamoMulti) {
+ if (tHatch instanceof GT_MetaTileEntity_Hatch_DynamoTunnel) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean checkHatchTier() {
+ for (GT_MetaTileEntity_Hatch_Input tHatch : mInputHatches) {
+ if (tHatch.mTier > mTierLimit) return false;
+ }
+ for (GT_MetaTileEntity_Hatch_Dynamo tHatch : mDynamoHatches) {
+ if (tHatch.mTier > mTierLimit) return false;
+ }
+ for (GT_MetaTileEntity_Hatch_DynamoMulti tHatch : eDynamoMulti) {
+ if (tHatch.mTier > mTierLimit) return false;
+ }
+ return true;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ this.mStableValue = aNBT.getInteger("mStableValue");
+ this.mLeftEnergy = aNBT.getLong("mLeftEnergy");
+ this.mUpgrade = aNBT.getInteger("mUpgrade");
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setInteger("mStableValue", this.mStableValue);
+ aNBT.setLong("mLeftEnergy", this.mLeftEnergy);
+ aNBT.setInteger("mUpgrade", this.mUpgrade);
+ }
+
+ public boolean updateEssentiaHatchState() {
+ for (EssentiaHatch hatch : mEssentiaHatch) {
+ hatch.mState = mUpgrade;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean onRightclick(IGregTechTileEntity aBaseMetaTileEntity, EntityPlayer aPlayer) {
+ if (this.getBaseMetaTileEntity()
+ .isServerSide()) {
+ ItemStack tCurrentItem = aPlayer.inventory.getCurrentItem();
+ if (tCurrentItem != null && tCurrentItem.getItem()
+ .equals(
+ ItemRefer.Essentia_Upgrade_Empty.get(1)
+ .getItem())) {
+ int tMeta = tCurrentItem.getItemDamage();
+ if ((mUpgrade & (1 << tMeta)) == 0 && tMeta != 0) {
+ tCurrentItem.stackSize--;
+ mUpgrade = mUpgrade | (1 << tMeta);
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ tCurrentItem.getDisplayName() + StatCollector.translateToLocal("largeessentiagenerator.chat"));
+ }
+ updateEssentiaHatchState();
+ return true;
+ }
+ }
+ super.onRightclick(aBaseMetaTileEntity, aPlayer);
+ return true;
+ }
+
+ @Override
+ public IStructureDefinition<LargeEssentiaGenerator> getStructure_EM() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<LargeEssentiaGenerator>builder()
+ .addShape(
+ mName,
+ transpose(
+ new String[][] {
+ { "A A", " ", " ", " ", " ~ ", " ", " ",
+ " ", "A A" },
+ { "T C T", " CEC ", " CEEEC ", " CEEEEEC ", "CEEEEEEEC", " CEEEEEC ", " CEEEC ",
+ " CEC ", "T C T" },
+ { "T TXT T", " TCXCT ", " TCCXCCT ", "TCCCXCCCT", "XXXXXXXXX", "TCCCXCCCT", " TCCXCCT ",
+ " TCXCT ", "T TXT T" } }))
+ .addElement('A', ofBlock(ConfigBlocks.blockCosmeticOpaque, 1))
+ .addElement('T', ofBlock(ConfigBlocks.blockCosmeticSolid, 7))
+ .addElement('C', ofBlock(Loaders.magicCasing, 0)) //
+ .addElement('E', ofChain(onElementPass(x -> {
+ ++x.mStableValue;
+ x.mTierLimit = Math.max(x.mTierLimit, 4);
+ }, ofBlock(Loaders.essentiaCell, 0)), onElementPass(x -> {
+ x.mStableValue += 2;
+ x.mTierLimit = Math.max(x.mTierLimit, 5);
+ }, ofBlock(Loaders.essentiaCell, 1)), onElementPass(x -> {
+ x.mStableValue += 5;
+ x.mTierLimit = Math.max(x.mTierLimit, 6);
+ }, ofBlock(Loaders.essentiaCell, 2)), onElementPass(x -> {
+ x.mStableValue += 10;
+ x.mTierLimit = Math.max(x.mTierLimit, 8);
+ }, ofBlock(Loaders.essentiaCell, 3))))
+ .addElement(
+ 'X',
+ ofChain(
+ buildHatchAdder(LargeEssentiaGenerator.class)
+ .atLeast(
+ HatchElement.DynamoMulti.or(GT_HatchElement.Dynamo),
+ GT_HatchElement.Maintenance,
+ GT_HatchElement.InputHatch)
+ .casingIndex(1536)
+ .dot(1)
+ .build(),
+ ofBlock(Loaders.magicCasing, 0),
+ ofSpecificTileAdder(
+ LargeEssentiaGenerator::addEssentiaHatch,
+ EssentiaHatch.class,
+ Loaders.magicCasing,
+ 0)))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ public final boolean addEssentiaHatch(EssentiaHatch aTileEntity) {
+ return this.mEssentiaHatch.add(aTileEntity);
+ }
+
+ @Override
+ public @NotNull CheckRecipeResult checkProcessing_EM() {
+ this.mEfficiency = 10000;
+ this.mMaxProgresstime = 1;
+ setEssentiaToEUVoltageAndAmp(getVoltageLimit(), getAmpLimit());
+ return CheckRecipeResultRegistry.GENERATING;
+ }
+
+ public int getVoltageLimit() {
+ long voltage = 0;
+ for (GT_MetaTileEntity_Hatch tHatch : this.eDynamoMulti) {
+ voltage += tHatch.maxEUOutput();
+ }
+ for (GT_MetaTileEntity_Hatch tHatch : this.mDynamoHatches) {
+ voltage += tHatch.maxEUOutput();
+ }
+ if (voltage > Integer.MAX_VALUE) voltage = Integer.MAX_VALUE;
+ return (int) voltage;
+ }
+
+ public int getAmpLimit() {
+ long amp = 0;
+ for (GT_MetaTileEntity_Hatch tHatch : this.eDynamoMulti) {
+ amp += tHatch.maxAmperesOut();
+ }
+ for (GT_MetaTileEntity_Hatch tHatch : this.mDynamoHatches) {
+ amp += tHatch.maxAmperesOut();
+ }
+ if (amp > Integer.MAX_VALUE) amp = Integer.MAX_VALUE;
+ return (int) amp;
+ }
+
+ public long getPerAspectEnergy(Aspect aspect) {
+ int type = LargeEssentiaEnergyData.getAspectTypeIndex(aspect);
+ if (!isValidEssentia(aspect)) return 0;
+ switch (type) {
+ case 0:
+ return normalEssentia(aspect);
+ case 1:
+ return airEssentia(aspect);
+ case 2:
+ return thermalEssentia(aspect);
+ case 3:
+ return unstableEssentia(aspect);
+ case 4:
+ return victusEssentia(aspect);
+ case 5:
+ return taintedEssentia(aspect);
+ case 6:
+ return mechanicEssentia(aspect);
+ case 7:
+ return spiritEssentia(aspect);
+ case 8:
+ return radiationEssentia(aspect);
+ case 9:
+ return electricEssentia(aspect);
+ default:
+ return 0;
+ }
+ }
+
+ public long normalEssentia(Aspect aspect) {
+ return LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ }
+
+ public long airEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = 0;
+ int ceoInput = (int) LargeEssentiaEnergyData.getAspectCeo(aspect) * 8;
+ if (depleteInput(Materials.LiquidAir.getFluid(ceoInput))) {
+ ceoOutput = 1.5D;
+ } else if (depleteInput(Materials.Air.getGas(ceoInput))) {
+ ceoOutput = 1.0D;
+ }
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public long thermalEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = 0;
+ int ceoInput = (int) LargeEssentiaEnergyData.getAspectCeo(aspect) * 2;
+ if (depleteInput(Materials.SuperCoolant.getFluid(ceoInput))) {
+ ceoOutput = 9.0D;
+ } else if (depleteInput(FluidRegistry.getFluidStack("cryotheum", ceoInput))) {
+ ceoOutput = 5.0D;
+ } else if (depleteInput(FluidRegistry.getFluidStack("ic2coolant", ceoInput))) {
+ ceoOutput = 1.5D;
+ } else if (depleteInput(Materials.Ice.getSolid(ceoInput))) {
+ ceoOutput = 1.2D;
+ } else if (depleteInput(FluidRegistry.getFluidStack("ic2distilledwater", ceoInput))) {
+ ceoOutput = 1.0D;
+ } else if (depleteInput(Materials.Water.getFluid(ceoInput))) {
+ ceoOutput = 0.5D;
+ }
+
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public long unstableEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = 0;
+ int ceoInput = (int) LargeEssentiaEnergyData.getAspectCeo(aspect) * 4;
+ if (depleteInput(WerkstoffLoader.Xenon.getFluidOrGas(ceoInput))) {
+ ceoOutput = 4.0D;
+ } else if (depleteInput(WerkstoffLoader.Krypton.getFluidOrGas(ceoInput))) {
+ ceoOutput = 3.0D;
+ } else if (depleteInput(Materials.Argon.getFluid(ceoInput))) {
+ ceoOutput = 2.5D;
+ } else if (depleteInput(WerkstoffLoader.Neon.getFluidOrGas(ceoInput))) {
+ ceoOutput = 2.2D;
+ } else if (depleteInput(Materials.Helium.getFluid(ceoInput))) {
+ ceoOutput = 2.0D;
+ } else if (depleteInput(Materials.Nitrogen.getFluid(ceoInput))) {
+ ceoOutput = 1.0D;
+ }
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public long victusEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = 1.0D;
+ int ceoInput = (int) LargeEssentiaEnergyData.getAspectCeo(aspect) * 18;
+ if (depleteInput(FluidRegistry.getFluidStack("xpjuice", ceoInput))) {
+ ceoOutput = 2.0D;
+ } else if (depleteInput(FluidRegistry.getFluidStack("lifeessence", ceoInput))) {
+ ceoOutput = 6.0D;
+ }
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public long taintedEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = 1.0D;
+ int ceoInput = (int) LargeEssentiaEnergyData.getAspectCeo(aspect) * 3;
+ int chance = 2000;
+ if (depleteInput(FluidRegistry.getFluidStack("fluidpure", ceoInput))) {
+ ceoOutput = 60.0D;
+ chance = 0;
+ } else if (depleteInput(FluidRegistry.getFluidStack("fluiddeath", ceoInput))) {
+ ceoOutput = Math.pow(25000D / baseValue, 4);
+ chance = 4000;
+ }
+
+ if (R.nextInt(10000) < chance) {
+ World world = getBaseMetaTileEntity().getWorld();
+ int tX = R.nextInt(4);
+ int tZ = R.nextInt(4);
+ if (world.isAirBlock(tX, 0, tZ)) world.setBlock(tX, 0, tZ, ConfigBlocks.blockFluxGas, R.nextInt(8), 3);
+ }
+
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public long mechanicEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = 0;
+ int ceoInput = (int) LargeEssentiaEnergyData.getAspectCeo(aspect) * 20;
+ if (depleteInput(Materials.Lubricant.getFluid(ceoInput))) {
+ ceoOutput = 1.0D;
+ }
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public long spiritEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = 1.0D;
+ int ceoInput = (int) LargeEssentiaEnergyData.getAspectCeo(aspect) * 2;
+ if (depleteInput(FluidRegistry.getFluidStack("witchery:fluidspirit", ceoInput))) {
+ ceoOutput = 10D * (1 + mStableValue / 100D);
+ } else if (depleteInput(FluidRegistry.getFluidStack("witchery:hollowtears", ceoInput))) {
+ ceoOutput = 15D * (1 + 100D / mStableValue);
+ }
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public long radiationEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = 1.0D;
+ int ceoInput = (int) LargeEssentiaEnergyData.getAspectCeo(aspect) * 6;
+ if (depleteInput(Materials.Caesium.getMolten(ceoInput))) {
+ ceoOutput = 2.0D;
+ } else if (depleteInput(Materials.Uranium235.getMolten(ceoInput))) {
+ ceoOutput = 3.0D;
+ } else if (depleteInput(Materials.Naquadah.getMolten(ceoInput))) {
+ ceoOutput = 4.0D;
+ } else if (depleteInput(MyMaterial.atomicSeparationCatalyst.getMolten(ceoInput))) {
+ ceoOutput = 16.0D;
+ }
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public long electricEssentia(Aspect aspect) {
+ long baseValue = LargeEssentiaEnergyData.getAspectFuelValue(aspect);
+ double ceoOutput = Math.pow(3.0, GT_Utility.getTier(getVoltageLimit()));
+ return (long) (baseValue * ceoOutput);
+ }
+
+ public void setEssentiaToEUVoltageAndAmp(long voltageLimit, long ampLimit) {
+ long EUt = mLeftEnergy;
+ long EUVoltage = voltageLimit, EUAmp = 1;
+
+ for (EssentiaHatch hatch : this.mEssentiaHatch) {
+ AspectList aspects = hatch.getAspects();
+ for (Aspect aspect : aspects.aspects.keySet()) {
+ if (!isValidEssentia(aspect)) continue;
+ while (EUt <= (voltageLimit * ampLimit) && aspects.getAmount(aspect) > 0) {
+ long addedEU = getPerAspectEnergy(aspect) * mStableValue / 25;
+ if (addedEU == 0) break;
+ EUt += addedEU;
+ aspects.reduce(aspect, 1);
+ if (aspects.getAmount(aspect) == 0) aspects.remove(aspect);
+ }
+ }
+ }
+
+ if (EUt <= voltageLimit) {
+ EUVoltage = EUt;
+ EUAmp = 1;
+ mLeftEnergy = 0;
+ } else {
+ while (EUVoltage * (EUAmp + 1) <= EUt && EUAmp + 1 <= ampLimit) {
+ EUAmp++;
+ }
+ mLeftEnergy = EUt - (EUVoltage * EUAmp);
+ }
+
+ this.mEUt = (int) EUVoltage;
+ this.eAmpereFlow = (int) EUAmp;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack itemStack) {
+ return DescTextLocalization.addText("LargeEssentiaGenerator.hint", 6);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new LargeEssentiaGenerator(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Essentia Generator")
+ .addInfo("Controller block for the Large Essentia Generator")
+ .addInfo("Maybe some Thaumaturges are upset by it. . .")
+ .addInfo("Transform Essentia into energy!")
+ .addInfo("The Diffusion Cell determines the highest hatch tier that the LEG can accept.")
+ .addInfo("Supports normal Dynamo Hatches or TecTech ones for up to 64A, but no Laser Hatches.")
+ .addInfo("You can find more information about this generator in the Thaumonomicon.")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addMaintenanceHatch("Hint block with dot 1", 1)
+ .addInputHatch("Hint block with dot 1", 1)
+ .addDynamoHatch("Hint block with dot 1", 1)
+ .addOtherStructurePart("Essentia Input Hatch", "Essentia Input", 1)
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ @SuppressWarnings("ALL")
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1536),
+ new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_DRAGONEGG), TextureFactory.builder()
+ .addIcon(Textures.BlockIcons.MACHINE_CASING_DRAGONEGG_GLOW)
+ .glow()
+ .build() };
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1536),
+ new GT_RenderedTexture(Textures.BlockIcons.MACHINE_CASING_DRAGONEGG) };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1536) };
+ }
+
+ public boolean isValidEssentia(Aspect aspect) {
+ int type = LargeEssentiaEnergyData.getAspectTypeIndex(aspect);
+ return type != -1 && (mUpgrade & (1 << type)) != 0;
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(mName, stackSize, 4, 0, 4, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/LargeEssentiaSmeltery.java b/src/main/java/goodgenerator/blocks/tileEntity/LargeEssentiaSmeltery.java
new file mode 100644
index 0000000000..039bd76c51
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/LargeEssentiaSmeltery.java
@@ -0,0 +1,558 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.Mods.ThaumicBases;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti;
+import com.github.technus.tectech.thing.metaTileEntity.multi.base.GT_MetaTileEntity_MultiblockBase_EM;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.Textures;
+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.metatileentity.implementations.GT_MetaTileEntity_Hatch_Energy;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.objects.XSTR;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import thaumcraft.api.aspects.Aspect;
+import thaumcraft.api.aspects.AspectList;
+import thaumcraft.api.visnet.VisNetHandler;
+import thaumcraft.common.config.ConfigBlocks;
+import thaumcraft.common.lib.crafting.ThaumcraftCraftingManager;
+
+public class LargeEssentiaSmeltery extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ private static final IIconContainer textureFontOn = new Textures.BlockIcons.CustomIcon(
+ "icons/LargeEssentiaSmeltery_On");
+ private static final IIconContainer textureFontOn_Glow = new Textures.BlockIcons.CustomIcon(
+ "icons/LargeEssentiaSmeltery_On_GLOW");
+ private static final IIconContainer textureFontOff = new Textures.BlockIcons.CustomIcon(
+ "icons/LargeEssentiaSmeltery_Off");
+ private static final IIconContainer textureFontOff_Glow = new Textures.BlockIcons.CustomIcon(
+ "icons/LargeEssentiaSmeltery_Off_GLOW");
+ private static final String STRUCTURE_PIECE_FIRST = "first";
+ private static final String STRUCTURE_PIECE_LATER = "later";
+ private static final String STRUCTURE_PIECE_LAST = "last";
+ private static final int CASING_INDEX = 1536;
+ private static final int MAX_STRUCTURE_LENGTH = 8;
+ private static final int DEFAULT_STRUCTURE_LENGTH = 3;
+ private static final int MAX_CONFIGURABLE_LENGTH = MAX_STRUCTURE_LENGTH - DEFAULT_STRUCTURE_LENGTH;
+
+ private static final int RECIPE_DURATION = 32;
+ private static final int RECIPE_EUT = 480;
+ private static final float NODE_COST_MULTIPLIER = 1.15f;
+
+ public AspectList mOutputAspects = new AspectList();
+ protected int mCasing = 0;
+ protected double mParallel = 0;
+ protected int nodePower = 0;
+ protected int nodePurificationEfficiency = 0;
+ protected int nodeIncrease = 0;
+
+ private IStructureDefinition<LargeEssentiaSmeltery> multiDefinition = null;
+ private ArrayList<EssentiaOutputHatch> mEssentiaOutputHatches = new ArrayList<>();
+ private int pTier = 0;
+ private XSTR xstr = new XSTR();
+
+ public LargeEssentiaSmeltery(String name) {
+ super(name);
+ }
+
+ public LargeEssentiaSmeltery(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ @Override
+ public void construct(ItemStack itemStack, boolean hintsOnly) {
+ structureBuild_EM(STRUCTURE_PIECE_FIRST, 2, 2, 0, itemStack, hintsOnly);
+ // default
+ structureBuild_EM(STRUCTURE_PIECE_LATER, 2, 2, -1, itemStack, hintsOnly);
+ structureBuild_EM(STRUCTURE_PIECE_LATER, 2, 2, -2, itemStack, hintsOnly);
+ int len = itemStack.stackSize;
+ if (len > MAX_CONFIGURABLE_LENGTH) len = MAX_CONFIGURABLE_LENGTH;
+ structureBuild_EM(STRUCTURE_PIECE_LAST, 2, 2, -len - 3, itemStack, hintsOnly);
+ while (len > 0) {
+ structureBuild_EM(STRUCTURE_PIECE_LATER, 2, 2, -len - 2, itemStack, hintsOnly);
+ len--;
+ }
+ }
+
+ @Override
+ protected void clearHatches_EM() {
+ super.clearHatches_EM();
+ mEssentiaOutputHatches.clear();
+ }
+
+ @Override
+ protected boolean checkMachine_EM(IGregTechTileEntity iGregTechTileEntity, ItemStack itemStack) {
+ this.mCasing = 0;
+ this.mParallel = 0;
+ this.pTier = 0;
+ this.nodePower = 0;
+ this.nodePurificationEfficiency = 0;
+ this.nodeIncrease = 0;
+
+ if (!structureCheck_EM(STRUCTURE_PIECE_FIRST, 2, 2, 0)) return false;
+ if (!structureCheck_EM(STRUCTURE_PIECE_LATER, 2, 2, -1)) return false;
+ if (!structureCheck_EM(STRUCTURE_PIECE_LATER, 2, 2, -2)) return false;
+ int len = 2;
+ while (structureCheck_EM(STRUCTURE_PIECE_LATER, 2, 2, -len - 1)) len++;
+ if (len > MAX_STRUCTURE_LENGTH - 1 || len < DEFAULT_STRUCTURE_LENGTH) return false;
+ if (!structureCheck_EM(STRUCTURE_PIECE_LAST, 2, 2, -len - 1)) return false;
+ if (this.mCasing >= 24 && this.mMaintenanceHatches.size() == 1
+ && this.mInputBusses.size() >= 1
+ && this.mEssentiaOutputHatches.size() >= 1) {
+ this.mParallel = Math.floor(this.mParallel += 1 << this.pTier);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public IStructureDefinition<? extends GT_MetaTileEntity_MultiblockBase_EM> getStructure_EM() {
+ if (this.multiDefinition == null) {
+ this.multiDefinition = StructureDefinition.<LargeEssentiaSmeltery>builder()
+ .addShape(
+ "first",
+ transpose(new String[][] { { " A " }, { " AAA " }, { "AA~AA" }, { " AAA " }, { " A " } }))
+ .addShape(
+ "later",
+ transpose(new String[][] { { " ABA " }, { "AECEA" }, { "D---D" }, { "AEFEA" }, { " AAA " } }))
+ .addShape(
+ "last",
+ transpose(new String[][] { { " A " }, { " AAA " }, { "AAAAA" }, { " AAA " }, { " A " } }))
+ .addElement('C', ofBlock(Loaders.essentiaFilterCasing, 0))
+ .addElement('D', ofBlock(ConfigBlocks.blockCosmeticOpaque, 2))
+ .addElement(
+ 'F',
+ ThaumicBases.isModLoaded() ? ofBlock(Block.getBlockFromName("thaumicbases:advAlchFurnace"), 0)
+ : ofBlock(ConfigBlocks.blockStoneDevice, 0))
+ .addElement(
+ 'E',
+ ofChain(
+ onElementPass(x -> x.onEssentiaCellFound(0), ofBlock(Loaders.essentiaCell, 0)),
+ onElementPass(x -> x.onEssentiaCellFound(1), ofBlock(Loaders.essentiaCell, 1)),
+ onElementPass(x -> x.onEssentiaCellFound(2), ofBlock(Loaders.essentiaCell, 2)),
+ onElementPass(x -> x.onEssentiaCellFound(3), ofBlock(Loaders.essentiaCell, 3))))
+ .addElement(
+ 'A',
+ ofChain(
+ buildHatchAdder(LargeEssentiaSmeltery.class)
+ .atLeast(GT_HatchElement.Maintenance, GT_HatchElement.Energy, GT_HatchElement.InputBus)
+ .casingIndex(CASING_INDEX)
+ .dot(1)
+ .build(),
+ ofSpecificTileAdder(
+ LargeEssentiaSmeltery::addEssentiaOutputHatchToMachineList,
+ EssentiaOutputHatch.class,
+ Loaders.essentiaOutputHatch,
+ 0),
+ onElementPass(LargeEssentiaSmeltery::onCasingFound, ofBlock(Loaders.magicCasing, 0))))
+ .addElement('B', GT_HatchElement.Muffler.newAny(CASING_INDEX, 2))
+ .build();
+ }
+ return this.multiDefinition;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Essentia Smeltery")
+ .addInfo("Controller block for the Large Essentia Smeltery")
+ .addInfo("Necessary evil.")
+ .addInfo("Advanced Essentia smelting technology.")
+ .addInfo("Max parallel dictated by structure size and Essentia Diffusion Cell tier")
+ .addInfo("Energy Hatch tier: HV+")
+ .addInfo("You can find more information about this machine in the Thaumonomicon.")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addController("Front center")
+ .addCasingInfo("Magic Casing", 24)
+ .addMaintenanceHatch("Hint block with dot 1")
+ .addInputBus("Hint block with dot 1")
+ .addInputHatch("Hint block with dot 1")
+ .addEnergyHatch("Hint block with dot 1")
+ .addOtherStructurePart("Essentia Output Hatch", "Hint block with dot 1")
+ .addMufflerHatch("Hint block with dot 2")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack itemStack) {
+ return DescTextLocalization.addText("LargeEssentiaSmeltery.hint", 8);
+ }
+
+ @Override
+ public String[] getInfoData() {
+ String[] info = super.getInfoData();
+ info[8] = "Node Power: " + EnumChatFormatting.RED
+ + this.nodePower
+ + EnumChatFormatting.RESET
+ + " Purification Efficiency: "
+ + EnumChatFormatting.AQUA
+ + this.nodePurificationEfficiency
+ + "%"
+ + EnumChatFormatting.RESET
+ + " Speed Up: "
+ + EnumChatFormatting.GRAY
+ + this.nodeIncrease
+ + "%"
+ + EnumChatFormatting.RESET;
+ return info;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX),
+ TextureFactory.of(textureFontOn), TextureFactory.builder()
+ .addIcon(textureFontOn_Glow)
+ .glow()
+ .build() };
+ else return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX),
+ TextureFactory.of(textureFontOff), TextureFactory.builder()
+ .addIcon(textureFontOff_Glow)
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(CASING_INDEX) };
+ }
+
+ protected void onCasingFound() {
+ this.mCasing++;
+ }
+
+ protected void onEssentiaCellFound(int tier) {
+ this.mParallel += (1 << tier) * 0.25f;
+ this.pTier = Math.max(this.pTier, tier);
+ }
+
+ private boolean addEnergyHatchToMachineList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ return false;
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Energy) {
+ if (((GT_MetaTileEntity_Hatch_Energy) aMetaTileEntity).mTier < 3) return false;
+ ((GT_MetaTileEntity_Hatch_Energy) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.mEnergyHatches.add((GT_MetaTileEntity_Hatch_Energy) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_EnergyMulti) {
+ ((GT_MetaTileEntity_Hatch_EnergyMulti) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.eEnergyMulti.add(((GT_MetaTileEntity_Hatch_EnergyMulti) aMetaTileEntity));
+ } else {
+ return false;
+ }
+ }
+ }
+
+ private boolean addEssentiaOutputHatchToMachineList(EssentiaOutputHatch aTileEntity) {
+ if (aTileEntity instanceof EssentiaOutputHatch) {
+ return this.mEssentiaOutputHatches.add((EssentiaOutputHatch) aTileEntity);
+ }
+ return false;
+ }
+
+ @Override
+ protected void runMachine(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (!this.isFullPower()) return;
+ super.runMachine(aBaseMetaTileEntity, aTick);
+ }
+
+ @Override
+ public @NotNull CheckRecipeResult checkProcessing_EM() {
+ if (!isFullPower()) return SimpleCheckRecipeResult.ofFailure("node_too_small");
+
+ ArrayList<ItemStack> tInputList = getStoredInputs();
+
+ if (tInputList.size() == 0) return CheckRecipeResultRegistry.NO_RECIPE;
+
+ int p = (int) this.mParallel;
+ for (int i = tInputList.size() - 1; i >= 0; i--) {
+ ItemStack itemStack = tInputList.get(i);
+ int stackSize = itemStack.stackSize;
+ int sur = p - stackSize;
+
+ if (sur > 0) {
+ p -= stackSize;
+ this.mOutputAspects.add(getEssentia(itemStack, stackSize));
+ if (!depleteInput(itemStack)) itemStack.stackSize = 0;
+ } else if (sur == 0) {
+ this.mOutputAspects.add(getEssentia(itemStack, stackSize));
+ if (!depleteInput(itemStack)) itemStack.stackSize = 0;
+ break;
+ } else {
+ this.mOutputAspects.add(getEssentia(itemStack, p));
+ itemStack.stackSize -= p;
+ break;
+ }
+ }
+
+ this.mEfficiency = 10000 - (this.getIdealStatus() - this.getRepairStatus()) * 1000;
+ this.mEfficiencyIncrease = 10000;
+
+ final World WORLD = this.getBaseMetaTileEntity()
+ .getWorld();
+ int x = this.getBaseMetaTileEntity()
+ .getXCoord();
+ int y = this.getBaseMetaTileEntity()
+ .getYCoord();
+ int z = this.getBaseMetaTileEntity()
+ .getZCoord();
+
+ this.drainNodePower(WORLD, x, y, z);
+ this.nodePower -= expectedPower();
+
+ calculatePerfectOverclockedNessMulti(
+ RECIPE_EUT,
+ (int) Math.ceil(this.mOutputAspects.visSize() * RECIPE_DURATION * (1 - this.nodeIncrease * 0.005)),
+ 1,
+ Math.min(Integer.MAX_VALUE, getMaxInputEnergy_EM()));
+
+ this.updateSlots();
+ if (this.mEUt > 0) this.mEUt = -this.mEUt;
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ private AspectList getEssentia(ItemStack itemStack, int amount) {
+ AspectList aspectList = new AspectList();
+ AspectList aspects = ThaumcraftCraftingManager.getObjectTags(itemStack);
+ aspects = ThaumcraftCraftingManager.getBonusTags(itemStack, aspects);
+ if (aspects != null && aspects.size() != 0 && aspects.getAspects()[0] != null) {
+ for (int i = 0; i < amount; i++) aspectList.add(aspects);
+ } else aspectList.add(Aspect.ENTROPY, amount);
+ return aspectList;
+ }
+
+ private void fillEssentiaOutputHatch() {
+ for (EssentiaOutputHatch outputHatch : this.mEssentiaOutputHatches) {
+ for (Map.Entry<Aspect, Integer> entry : this.mOutputAspects.copy().aspects.entrySet()) {
+ Aspect aspect = entry.getKey();
+ int amount = entry.getValue();
+ this.mOutputAspects.remove(aspect, outputHatch.addEssentia(aspect, amount, null));
+ }
+ }
+ this.mOutputAspects.aspects.clear();
+ }
+
+ private int expectedPower() {
+ return (int) (Math.pow(this.getMaxEnergyInputTier_EM(), 2) * NODE_COST_MULTIPLIER);
+ }
+
+ private boolean isFullPower() {
+ return this.nodePower > expectedPower();
+ }
+
+ private void generateFluxGas(World world, int x, int y, int z) {
+ world.setBlock(x, y, z, ConfigBlocks.blockFluxGas, 8, 3);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setDouble("mParallel", this.mParallel);
+ aNBT.setDouble("nodePower", this.nodePower);
+ aNBT.setDouble("nodePurificationEfficiency", this.nodePurificationEfficiency);
+ aNBT.setDouble("nodeIncrease", this.nodeIncrease);
+
+ Aspect[] aspectA = this.mOutputAspects.getAspects();
+ NBTTagList nbtTagList = new NBTTagList();
+ for (Aspect aspect : aspectA) {
+ if (aspect != null) {
+ NBTTagCompound f = new NBTTagCompound();
+ f.setString("key", aspect.getTag());
+ f.setInteger("amount", this.mOutputAspects.getAmount(aspect));
+ nbtTagList.appendTag(f);
+ }
+ }
+ aNBT.setTag("Aspects", nbtTagList);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ this.mParallel = aNBT.getDouble("mParallel");
+ this.nodePower = aNBT.getInteger("nodePower");
+ this.nodePurificationEfficiency = aNBT.getInteger("nodePurificationEfficiency");
+ this.nodeIncrease = aNBT.getInteger("nodeIncrease");
+
+ this.mOutputAspects.aspects.clear();
+ NBTTagList tlist = aNBT.getTagList("Aspects", 10);
+ for (int j = 0; j < tlist.tagCount(); ++j) {
+ NBTTagCompound rs = tlist.getCompoundTagAt(j);
+ if (rs.hasKey("key"))
+ this.mOutputAspects.add(Aspect.getAspect(rs.getString("key")), rs.getInteger("amount"));
+ }
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ protected void addClassicOutputs_EM() {
+ super.addClassicOutputs_EM();
+ fillEssentiaOutputHatch();
+ }
+
+ @Override
+ public void stopMachine() {
+ super.stopMachine();
+ this.mOutputAspects.aspects.clear();
+ }
+
+ private void drainNodePower(World world, int x, int y, int z) {
+ int power = this.expectedPower();
+ if (this.nodePower < power * 10) {
+ this.nodePower += VisNetHandler.drainVis(world, x, y, z, Aspect.WATER, power);
+ this.nodePower += VisNetHandler.drainVis(world, x, y, z, Aspect.FIRE, power);
+ }
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ if (aTick % 5 == 0 && this.mMachine) {
+ final World WORLD = this.getBaseMetaTileEntity()
+ .getWorld();
+ int x = this.getBaseMetaTileEntity()
+ .getXCoord();
+ int y = this.getBaseMetaTileEntity()
+ .getYCoord();
+ int z = this.getBaseMetaTileEntity()
+ .getZCoord();
+
+ this.drainNodePower(WORLD, x, y, z);
+
+ this.nodePurificationEfficiency = Math.max(0, this.nodePurificationEfficiency - 1);
+ if (this.nodePurificationEfficiency < 100) {
+ this.nodePurificationEfficiency = (int) Math.min(
+ 100,
+ this.nodePurificationEfficiency
+ + Math.ceil(VisNetHandler.drainVis(WORLD, x, y, z, Aspect.ORDER, 200) * 0.05));
+ }
+
+ this.nodeIncrease = Math.min(100, VisNetHandler.drainVis(WORLD, x, y, z, Aspect.ENTROPY, 125));
+ }
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ this.nodePurificationEfficiency = Math.max(0, this.nodePurificationEfficiency - 1);
+ if (xstr.nextInt(20) == 0) {
+ if (xstr.nextInt(100) < Math.max(100 - this.nodePurificationEfficiency, 0)) {
+ final World WORLD = this.getBaseMetaTileEntity()
+ .getWorld();
+ GT_MetaTileEntity_Hatch_Muffler mufflerHatch = this.mMufflerHatches
+ .get(xstr.nextInt(this.mMufflerHatches.size()));
+ int x = mufflerHatch.getBaseMetaTileEntity()
+ .getXCoord();
+ int y = mufflerHatch.getBaseMetaTileEntity()
+ .getYCoord();
+ int z = mufflerHatch.getBaseMetaTileEntity()
+ .getZCoord();
+
+ ForgeDirection facing = mufflerHatch.getBaseMetaTileEntity()
+ .getFrontFacing();
+ switch (facing) {
+ case SOUTH:
+ z += 1;
+ break;
+ case NORTH:
+ z -= 1;
+ break;
+ case WEST:
+ x -= 1;
+ break;
+ case EAST:
+ x += 1;
+ break;
+ default:
+ y += 1;
+ }
+ generateFluxGas(WORLD, x, y, z);
+ }
+ }
+ return super.onRunningTick(aStack);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack itemStack) {
+ return true;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return 22 * (100 - this.nodePurificationEfficiency);
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack itemStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack itemStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack itemStack) {
+ return false;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity iGregTechTileEntity) {
+ return new LargeEssentiaSmeltery(this.mName);
+ }
+
+ @Override
+ protected void maintenance_EM() {
+ super.maintenance_EM();
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ int built = survivialBuildPiece(STRUCTURE_PIECE_FIRST, stackSize, 2, 2, 0, elementBudget, env, false, true);
+ if (built >= 0) return built;
+ int length = stackSize.stackSize + 2;
+ if (length > MAX_CONFIGURABLE_LENGTH) length = MAX_CONFIGURABLE_LENGTH + 2;
+ for (int i = 1; i <= length; i++) {
+ built = survivialBuildPiece(STRUCTURE_PIECE_LATER, stackSize, 2, 2, -i, elementBudget, env, false, true);
+ if (built >= 0) return built;
+ }
+ return survivialBuildPiece(STRUCTURE_PIECE_LAST, stackSize, 2, 2, -length - 1, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer1.java b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer1.java
new file mode 100644
index 0000000000..cad1cb001c
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer1.java
@@ -0,0 +1,170 @@
+package goodgenerator.blocks.tileEntity;
+
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION1;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION1_GLOW;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+
+import com.github.bartimaeusnek.bartworks.common.loaders.ItemRegistry;
+
+import goodgenerator.blocks.tileEntity.base.LargeFusionComputer;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class LargeFusionComputer1 extends LargeFusionComputer {
+
+ private static final ITexture textureOverlay = TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION1)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION1_GLOW)
+ .extFacing()
+ .glow()
+ .build());
+
+ public LargeFusionComputer1(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ public LargeFusionComputer1(String name) {
+ super(name);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fusion Reactor")
+ .addInfo("Millions of nuclear.")
+ .addInfo("Controller block for the Compact Fusion Reactor MK-I Prototype.")
+ .addInfo(
+ EnumChatFormatting.AQUA + GT_Utility.formatNumbers(getSingleHatchPower())
+ + EnumChatFormatting.GRAY
+ + " EU/t and "
+ + EnumChatFormatting.AQUA
+ + GT_Utility.formatNumbers(capableStartupCanonical() / 32 / M)
+ + "M"
+ + EnumChatFormatting.GRAY
+ + " EU capacity per Energy Hatch")
+ .addInfo("If the recipe has a startup cost greater than the")
+ .addInfo("number of energy hatches * cap, you can't do it")
+ .addInfo(
+ "If the recipe requires a voltage tier over " + GT_Utility.getColoredTierNameFromTier((byte) tier())
+ + EnumChatFormatting.GRAY
+ + " , you can't do it either")
+ .addInfo("Make sure the whole structure is built in the 3x3")
+ .addInfo("chunk area of the ring center (not controller).")
+ .addInfo("It can run 64x recipes at most.")
+ .addInfo(
+ "Support" + EnumChatFormatting.BLUE
+ + " Tec"
+ + EnumChatFormatting.DARK_BLUE
+ + "Tech"
+ + EnumChatFormatting.GRAY
+ + " Energy/Laser Hatches!")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addCasingInfo("LuV Machine Casing", 1664)
+ .addCasingInfo("Ameliorated Superconduct Coil", 560)
+ .addCasingInfo("Naquadah Alloy Frame Boxes", 128)
+ .addCasingInfo("Rhodium-Plated Palladium Reinforced Borosilicate Glass Block", 63)
+ .addEnergyHatch("1-32, Hint block with dot 2", 2)
+ .addInputHatch("1-16, Hint block with dot 1", 1)
+ .addOutputHatch("1-16, Hint block with dot 1", 1)
+ .addStructureInfo("Supports Crafting Input Buffer")
+ .addStructureInfo(
+ "ALL Hatches must be " + GT_Utility.getColoredTierNameFromTier((byte) hatchTier())
+ + EnumChatFormatting.GRAY
+ + " or better")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public int tier() {
+ return 6;
+ }
+
+ @Override
+ public long capableStartupCanonical() {
+ return 160_000_000;
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings1;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 6;
+ }
+
+ @Override
+ public Block getCoilBlock() {
+ return Loaders.compactFusionCoil;
+ }
+
+ @Override
+ public int getCoilMeta() {
+ return 0;
+ }
+
+ @Override
+ public Block getGlassBlock() {
+ return ItemRegistry.bw_realglas;
+ }
+
+ @Override
+ public int getGlassMeta() {
+ return 3;
+ }
+
+ @Override
+ public int hatchTier() {
+ return 6;
+ }
+
+ @Override
+ public Materials getFrameBox() {
+ return Materials.NaquadahAlloy;
+ }
+
+ @Override
+ public int getMaxPara() {
+ return 64;
+ }
+
+ @Override
+ public int extraPara(int startEnergy) {
+ return 1;
+ }
+
+ @Override
+ public ITexture getTextureOverlay() {
+ return textureOverlay;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("LargeFusion1.hint", 9);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new LargeFusionComputer1(mName);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer2.java b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer2.java
new file mode 100644
index 0000000000..7a72e7842f
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer2.java
@@ -0,0 +1,171 @@
+package goodgenerator.blocks.tileEntity;
+
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION2;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION2_GLOW;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+
+import com.github.bartimaeusnek.bartworks.common.loaders.ItemRegistry;
+
+import goodgenerator.blocks.tileEntity.base.LargeFusionComputer;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class LargeFusionComputer2 extends LargeFusionComputer {
+
+ private static final ITexture textureOverlay = TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION2)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION2_GLOW)
+ .extFacing()
+ .glow()
+ .build());
+
+ public LargeFusionComputer2(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ public LargeFusionComputer2(String name) {
+ super(name);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fusion Reactor")
+ .addInfo("Millions of nuclear.")
+ .addInfo("Controller block for the Compact Fusion Reactor MK-II.")
+ .addInfo(
+ EnumChatFormatting.AQUA + GT_Utility.formatNumbers(getSingleHatchPower())
+ + EnumChatFormatting.GRAY
+ + " EU/t and "
+ + EnumChatFormatting.AQUA
+ + GT_Utility.formatNumbers(capableStartupCanonical() / 32 / M)
+ + "M"
+ + EnumChatFormatting.GRAY
+ + " EU capacity per Energy Hatch")
+ .addInfo("If the recipe has a startup cost greater than the")
+ .addInfo("number of energy hatches * cap, you can't do it")
+ .addInfo(
+ "If the recipe requires a voltage tier over " + GT_Utility.getColoredTierNameFromTier((byte) tier())
+ + EnumChatFormatting.GRAY
+ + " , you can't do it either")
+ .addInfo("Make sure the whole structure is built in the 3x3")
+ .addInfo("chunk area of the ring center (not controller).")
+ .addInfo("Startup < 160,000,000 EU: 128x Parallel")
+ .addInfo("Startup >= 160,000,000 EU: 64x Parallel")
+ .addInfo(
+ "Support" + EnumChatFormatting.BLUE
+ + " Tec"
+ + EnumChatFormatting.DARK_BLUE
+ + "Tech"
+ + EnumChatFormatting.GRAY
+ + " Energy/Laser Hatches!")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addCasingInfo("Fusion Machine Casing", 1664)
+ .addCasingInfo("Compact Fusion Coil", 560)
+ .addCasingInfo("Duranium Frame Box", 128)
+ .addCasingInfo("Iridium Reinforced Borosilicate Glass Block", 63)
+ .addEnergyHatch("1-32, Hint block with dot 2", 2)
+ .addInputHatch("1-16, Hint block with dot 1", 1)
+ .addOutputHatch("1-16, Hint block with dot 1", 1)
+ .addStructureInfo("Supports Crafting Input Buffer")
+ .addStructureInfo(
+ "ALL Hatches must be " + GT_Utility.getColoredTierNameFromTier((byte) hatchTier())
+ + EnumChatFormatting.GRAY
+ + " or better")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public int tier() {
+ return 7;
+ }
+
+ @Override
+ public long capableStartupCanonical() {
+ return 320_000_000;
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 6;
+ }
+
+ @Override
+ public Block getCoilBlock() {
+ return Loaders.compactFusionCoil;
+ }
+
+ @Override
+ public int getCoilMeta() {
+ return 1;
+ }
+
+ @Override
+ public Block getGlassBlock() {
+ return ItemRegistry.bw_realglas;
+ }
+
+ @Override
+ public int getGlassMeta() {
+ return 4;
+ }
+
+ @Override
+ public int hatchTier() {
+ return 7;
+ }
+
+ @Override
+ public Materials getFrameBox() {
+ return Materials.Duranium;
+ }
+
+ @Override
+ public int getMaxPara() {
+ return 64;
+ }
+
+ @Override
+ public int extraPara(int startEnergy) {
+ return startEnergy < 160000000 ? 2 : 1;
+ }
+
+ @Override
+ public ITexture getTextureOverlay() {
+ return textureOverlay;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("LargeFusion2.hint", 9);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new LargeFusionComputer2(mName);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer3.java b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer3.java
new file mode 100644
index 0000000000..4a4f9832d0
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer3.java
@@ -0,0 +1,172 @@
+package goodgenerator.blocks.tileEntity;
+
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION3;
+import static gregtech.api.enums.Textures.BlockIcons.OVERLAY_FUSION3_GLOW;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+
+import com.github.bartimaeusnek.bartworks.common.loaders.ItemRegistry;
+
+import goodgenerator.blocks.tileEntity.base.LargeFusionComputer;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.Materials;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class LargeFusionComputer3 extends LargeFusionComputer {
+
+ private static final ITexture textureOverlay = TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION3)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FUSION3_GLOW)
+ .extFacing()
+ .glow()
+ .build());
+
+ public LargeFusionComputer3(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ public LargeFusionComputer3(String name) {
+ super(name);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fusion Reactor")
+ .addInfo("Millions of nuclear.")
+ .addInfo("Controller block for the Compact Fusion Reactor MK-III.")
+ .addInfo(
+ EnumChatFormatting.AQUA + GT_Utility.formatNumbers(getSingleHatchPower())
+ + EnumChatFormatting.GRAY
+ + " EU/t and "
+ + EnumChatFormatting.AQUA
+ + GT_Utility.formatNumbers(capableStartupCanonical() / 32 / M)
+ + "M"
+ + EnumChatFormatting.GRAY
+ + " EU capacity per Energy Hatch")
+ .addInfo("If the recipe has a startup cost greater than the")
+ .addInfo("number of energy hatches * cap, you can't do it")
+ .addInfo(
+ "If the recipe requires a voltage tier over " + GT_Utility.getColoredTierNameFromTier((byte) tier())
+ + EnumChatFormatting.GRAY
+ + " , you can't do it either")
+ .addInfo("Make sure the whole structure is built in the 3x3")
+ .addInfo("chunk area of the ring center (not controller).")
+ .addInfo("Startup < 160,000,000 EU: 192x Parallel")
+ .addInfo("Startup < 320,000,000 EU: 128x Parallel")
+ .addInfo("Startup >= 320,000,000 EU: 64x Parallel")
+ .addInfo(
+ "Support" + EnumChatFormatting.BLUE
+ + " Tec"
+ + EnumChatFormatting.DARK_BLUE
+ + "Tech"
+ + EnumChatFormatting.GRAY
+ + " Energy/Laser Hatches!")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addCasingInfo("Fusion Machine Casing MK II", 1664)
+ .addCasingInfo("Advanced Compact Fusion Coil", 560)
+ .addCasingInfo("Neutronium Frame Box", 128)
+ .addCasingInfo("Osmium Reinforced Borosilicate Glass Block", 63)
+ .addEnergyHatch("1-32, Hint block with dot 2", 2)
+ .addInputHatch("1-16, Hint block with dot 1", 1)
+ .addOutputHatch("1-16, Hint block with dot 1", 1)
+ .addStructureInfo("Supports Crafting Input Buffer")
+ .addStructureInfo(
+ "ALL Hatches must be " + GT_Utility.getColoredTierNameFromTier((byte) hatchTier())
+ + EnumChatFormatting.GRAY
+ + " or better")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public int tier() {
+ return 8;
+ }
+
+ @Override
+ public long capableStartupCanonical() {
+ return 640_000_000;
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return GregTech_API.sBlockCasings4;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 8;
+ }
+
+ @Override
+ public Block getCoilBlock() {
+ return Loaders.compactFusionCoil;
+ }
+
+ @Override
+ public int getCoilMeta() {
+ return 2;
+ }
+
+ @Override
+ public Block getGlassBlock() {
+ return ItemRegistry.bw_realglas;
+ }
+
+ @Override
+ public int getGlassMeta() {
+ return 5;
+ }
+
+ @Override
+ public int hatchTier() {
+ return 8;
+ }
+
+ @Override
+ public Materials getFrameBox() {
+ return Materials.Neutronium;
+ }
+
+ @Override
+ public int getMaxPara() {
+ return 64;
+ }
+
+ @Override
+ public int extraPara(int startEnergy) {
+ return (startEnergy < 160000000 ? 3 : (startEnergy < 320000000 ? 2 : 1));
+ }
+
+ @Override
+ public ITexture getTextureOverlay() {
+ return textureOverlay;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("LargeFusion3.hint", 9);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new LargeFusionComputer3(mName);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer4.java b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer4.java
new file mode 100644
index 0000000000..96a9662475
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer4.java
@@ -0,0 +1,227 @@
+package goodgenerator.blocks.tileEntity;
+
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.github.bartimaeusnek.bartworks.common.loaders.ItemRegistry;
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti;
+
+import goodgenerator.blocks.tileEntity.base.LargeFusionComputerPP;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.TAE;
+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_Hatch_Energy;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.tileentities.machines.IDualInputHatch;
+import gtPlusPlus.core.block.ModBlocks;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class LargeFusionComputer4 extends LargeFusionComputerPP {
+
+ public LargeFusionComputer4(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ public LargeFusionComputer4(String name) {
+ super(name);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fusion Reactor")
+ .addInfo("Galaxy Collapse.")
+ .addInfo("Controller block for the Compact Fusion Reactor MK-IV Prototype.")
+ .addInfo(
+ EnumChatFormatting.AQUA + GT_Utility.formatNumbers(getSingleHatchPower())
+ + EnumChatFormatting.GRAY
+ + " EU/t and "
+ + EnumChatFormatting.AQUA
+ + GT_Utility.formatNumbers(capableStartupCanonical() / 32 / M)
+ + "M"
+ + EnumChatFormatting.GRAY
+ + " EU capacity per Energy Hatch")
+ .addInfo("If the recipe has a startup cost greater than the")
+ .addInfo("number of energy hatches * cap, you can't do it")
+ .addInfo(
+ "If the recipe requires a voltage tier over " + GT_Utility.getColoredTierNameFromTier((byte) tier())
+ + EnumChatFormatting.GRAY
+ + " , you can't do it either")
+ .addInfo("Make sure the whole structure is built in the 3x3")
+ .addInfo("chunk area of the ring center (not controller).")
+ .addInfo("Performs 4/4 overclock.")
+ .addInfo("Startup < 160,000,000 EU: 256x Parallel")
+ .addInfo("Startup < 320,000,000 EU: 192x Parallel")
+ .addInfo("Startup < 640,000,000 EU: 128x Parallel")
+ .addInfo("Startup >= 640,000,000 EU: 64x Parallel")
+ .addInfo(
+ "Support" + EnumChatFormatting.BLUE
+ + " Tec"
+ + EnumChatFormatting.DARK_BLUE
+ + "Tech"
+ + EnumChatFormatting.GRAY
+ + " Energy/Laser Hatches!")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addCasingInfo("Fusion Machine Casing MK III", 1664)
+ .addCasingInfo("Compact Fusion Coil MK-II Prototype", 560)
+ .addCasingInfo("Infinity Catalyst Frame Box", 128)
+ .addCasingInfo("Neutronium Reinforced Borosilicate Glass Block", 63)
+ .addEnergyHatch("1-32, Hint block with dot 2", 2)
+ .addInputHatch("1-16, Hint block with dot 1", 1)
+ .addOutputHatch("1-16, Hint block with dot 1", 1)
+ .addStructureInfo("Supports Crafting Input Buffer")
+ .addStructureInfo(
+ "ALL Hatches must be " + GT_Utility.getColoredTierNameFromTier((byte) hatchTier())
+ + EnumChatFormatting.GRAY
+ + " or better")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public int tier() {
+ return 9;
+ }
+
+ @Override
+ public long capableStartupCanonical() {
+ return 5_120_000_000L;
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return ModBlocks.blockCasings3Misc;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 12;
+ }
+
+ @Override
+ public Block getCoilBlock() {
+ return Loaders.compactFusionCoil;
+ }
+
+ @Override
+ public int getCoilMeta() {
+ return 3;
+ }
+
+ @Override
+ public Block getGlassBlock() {
+ return ItemRegistry.bw_realglas;
+ }
+
+ @Override
+ public int getGlassMeta() {
+ return 13;
+ }
+
+ @Override
+ public int hatchTier() {
+ return 9;
+ }
+
+ @Override
+ public Materials getFrameBox() {
+ return Materials.InfinityCatalyst;
+ }
+
+ @Override
+ public ITexture getTextureOverlay() {
+ if (this.mMaxProgresstime > 0) return TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(TexturesGtBlock.Casing_Machine_Screen_3)
+ .extFacing()
+ .build());
+ else return TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(TexturesGtBlock.Casing_Machine_Screen_1)
+ .extFacing()
+ .build());
+ }
+
+ @Override
+ public int getMaxPara() {
+ return 64;
+ }
+
+ @Override
+ public int extraPara(int startEnergy) {
+ if (startEnergy < 160000000) return 4;
+ if (startEnergy < 320000000) return 3;
+ if (startEnergy < 640000000) return 2;
+ return 1;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("LargeFusion4.hint", 9);
+ }
+
+ @Override
+ public boolean turnCasingActive(boolean status) {
+ if (this.mEnergyHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Energy hatch : this.mEnergyHatches) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(2, 14) : 53);
+ }
+ }
+ if (this.eEnergyMulti != null) {
+ for (GT_MetaTileEntity_Hatch_EnergyMulti hatch : this.eEnergyMulti) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(2, 14) : 53);
+ }
+ }
+ if (this.mOutputHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Output hatch : this.mOutputHatches) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(2, 14) : 53);
+ }
+ }
+ if (this.mInputHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Input hatch : this.mInputHatches) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(2, 14) : 53);
+ }
+ }
+ if (this.mDualInputHatches != null) {
+ for (IDualInputHatch hatch : this.mDualInputHatches) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(2, 14) : 53);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) return new ITexture[] { TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS)
+ .extFacing()
+ .build(), getTextureOverlay() };
+ if (!aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(52) };
+ return new ITexture[] { TextureFactory.builder()
+ .addIcon(TexturesGtBlock.TEXTURE_CASING_FUSION_CASING_ULTRA)
+ .extFacing()
+ .build() };
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new LargeFusionComputer4(mName);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer5.java b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer5.java
new file mode 100644
index 0000000000..aa4766a01a
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/LargeFusionComputer5.java
@@ -0,0 +1,231 @@
+package goodgenerator.blocks.tileEntity;
+
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.Textures.BlockIcons.MACHINE_CASING_FUSION_GLASS;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.github.bartimaeusnek.bartworks.common.loaders.ItemRegistry;
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti;
+
+import goodgenerator.blocks.tileEntity.base.LargeFusionComputerPP;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.TAE;
+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_Hatch_Energy;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.tileentities.machines.IDualInputHatch;
+import gtPlusPlus.core.block.ModBlocks;
+import gtPlusPlus.xmod.gregtech.common.blocks.textures.TexturesGtBlock;
+
+public class LargeFusionComputer5 extends LargeFusionComputerPP {
+
+ public LargeFusionComputer5(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ public LargeFusionComputer5(String name) {
+ super(name);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fusion Reactor")
+ .addInfo("Galaxy Collapse.")
+ .addInfo("Controller block for the Compact Fusion Reactor MK-V.")
+ .addInfo(
+ EnumChatFormatting.AQUA + GT_Utility.formatNumbers(getSingleHatchPower())
+ + EnumChatFormatting.GRAY
+ + " EU/t and "
+ + EnumChatFormatting.AQUA
+ + GT_Utility.formatNumbers(capableStartupCanonical() / 32 / M)
+ + "M"
+ + EnumChatFormatting.GRAY
+ + " EU capacity per Energy Hatch")
+ .addInfo("If the recipe has a startup cost greater than the")
+ .addInfo("number of energy hatches * cap, you can't do it")
+ .addInfo(
+ "If the recipe requires a voltage tier over " + GT_Utility.getColoredTierNameFromTier((byte) tier())
+ + EnumChatFormatting.GRAY
+ + " , you can't do it either")
+ .addInfo("Make sure the whole structure is built in the 3x3")
+ .addInfo("chunk area of the ring center (not controller).")
+ .addInfo("Performs 4/4 overclock.")
+ .addInfo("Startup < 160,000,000 EU: 320x Parallel")
+ .addInfo("Startup < 320,000,000 EU: 256x Parallel")
+ .addInfo("Startup < 640,000,000 EU: 192x Parallel")
+ .addInfo("Startup < 1,200,000,000 EU: 128x Parallel")
+ .addInfo("Startup >= 1,200,000,000 EU: 64x Parallel")
+ .addInfo(
+ "Support" + EnumChatFormatting.BLUE
+ + " Tec"
+ + EnumChatFormatting.DARK_BLUE
+ + "Tech"
+ + EnumChatFormatting.GRAY
+ + " Energy/Laser Hatches!")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addCasingInfo("Fusion Machine Casing MK IV", 1664)
+ .addCasingInfo("Compact Fusion Coil MK-II Finaltype", 560)
+ .addCasingInfo("Infinity Frame Box", 128)
+ .addCasingInfo("Cosmic Neutronium Reinforced Borosilicate Glass Block", 63)
+ .addEnergyHatch("1-32, Hint block with dot 2", 2)
+ .addInputHatch("1-16, Hint block with dot 1", 1)
+ .addOutputHatch("1-16, Hint block with dot 1", 1)
+ .addStructureInfo("Supports Crafting Input Buffer")
+ .addStructureInfo(
+ "ALL Hatches must be " + GT_Utility.getColoredTierNameFromTier((byte) hatchTier())
+ + EnumChatFormatting.GRAY
+ + " or better")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public int tier() {
+ return 10;
+ }
+
+ @Override
+ public long capableStartupCanonical() {
+ return 20_480_000_000L;
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return ModBlocks.blockCasings6Misc;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 0;
+ }
+
+ @Override
+ public Block getCoilBlock() {
+ return Loaders.compactFusionCoil;
+ }
+
+ @Override
+ public int getCoilMeta() {
+ return 4;
+ }
+
+ @Override
+ public Block getGlassBlock() {
+ return ItemRegistry.bw_realglas;
+ }
+
+ @Override
+ public int getGlassMeta() {
+ return 14;
+ }
+
+ @Override
+ public int hatchTier() {
+ return 10;
+ }
+
+ @Override
+ public Materials getFrameBox() {
+ return Materials.Infinity;
+ }
+
+ @Override
+ public ITexture getTextureOverlay() {
+ if (this.getBaseMetaTileEntity()
+ .isActive())
+ return TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(TexturesGtBlock.Casing_Machine_Screen_Rainbow)
+ .extFacing()
+ .build());
+ else return TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(TexturesGtBlock.Casing_Machine_Screen_1)
+ .extFacing()
+ .build());
+ }
+
+ @Override
+ public int getMaxPara() {
+ return 64;
+ }
+
+ @Override
+ public int extraPara(int startEnergy) {
+ if (startEnergy < 160000000) return 5;
+ if (startEnergy < 320000000) return 4;
+ if (startEnergy < 640000000) return 3;
+ if (startEnergy < 1200000000) return 2;
+ return 1;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("LargeFusion5.hint", 9);
+ }
+
+ @Override
+ public boolean turnCasingActive(boolean status) {
+ if (this.mEnergyHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Energy hatch : this.mEnergyHatches) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(3, 6) : 53);
+ }
+ }
+ if (this.eEnergyMulti != null) {
+ for (GT_MetaTileEntity_Hatch_EnergyMulti hatch : this.eEnergyMulti) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(3, 6) : 53);
+ }
+ }
+ if (this.mOutputHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Output hatch : this.mOutputHatches) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(3, 6) : 53);
+ }
+ }
+ if (this.mInputHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Input hatch : this.mInputHatches) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(3, 6) : 53);
+ }
+ }
+ if (this.mDualInputHatches != null) {
+ for (IDualInputHatch hatch : this.mDualInputHatches) {
+ hatch.updateTexture(status ? TAE.getIndexFromPage(3, 6) : 53);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) return new ITexture[] { TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS)
+ .extFacing()
+ .build(), getTextureOverlay() };
+ if (!aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(52) };
+ return new ITexture[] { TextureFactory.builder()
+ .addIcon(TexturesGtBlock.TEXTURE_CASING_FUSION_CASING_HYPER)
+ .extFacing()
+ .build() };
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new LargeFusionComputer5(mName);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/MultiNqGenerator.java b/src/main/java/goodgenerator/blocks/tileEntity/MultiNqGenerator.java
new file mode 100644
index 0000000000..cd53c48974
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/MultiNqGenerator.java
@@ -0,0 +1,471 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.main.GG_Config_Loader.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.github.bartimaeusnek.bartworks.util.Pair;
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_DynamoMulti;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import goodgenerator.api.recipe.GoodGeneratorRecipeMaps;
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.items.MyMaterial;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.CrackRecipeAdder;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.MaterialsUEVplus;
+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_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Maintenance;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.objects.GT_RenderedTexture;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+
+public class MultiNqGenerator extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ protected IStructureDefinition<MultiNqGenerator> multiDefinition = null;
+ protected long leftEnergy = 0;
+ protected long trueOutput = 0;
+ protected int trueEff = 0;
+ protected FluidStack lockedFluid = null;
+ protected int times = 1;
+ protected int basicOutput;
+
+ private static final List<Pair<FluidStack, Integer>> excitedLiquid;
+
+ private static final List<Pair<FluidStack, Integer>> coolant;
+
+ static {
+ excitedLiquid = Arrays.asList(
+ new Pair<>(MaterialsUEVplus.Space.getMolten(20L), ExcitedLiquidCoe[0]),
+ new Pair<>(MyMaterial.atomicSeparationCatalyst.getMolten(20), ExcitedLiquidCoe[1]),
+ new Pair<>(Materials.Naquadah.getMolten(20L), ExcitedLiquidCoe[2]),
+ new Pair<>(Materials.Uranium235.getMolten(180L), ExcitedLiquidCoe[3]),
+ new Pair<>(Materials.Caesium.getMolten(180L), ExcitedLiquidCoe[4]));
+ coolant = Arrays.asList(
+ new Pair<>(MaterialsUEVplus.Time.getMolten(20L), CoolantEfficiency[0]),
+ new Pair<>(FluidRegistry.getFluidStack("cryotheum", 1000), CoolantEfficiency[1]),
+ new Pair<>(Materials.SuperCoolant.getFluid(1000L), CoolantEfficiency[2]),
+ new Pair<>(FluidRegistry.getFluidStack("ic2coolant", 1000), CoolantEfficiency[3]));
+ }
+
+ @Override
+ public void construct(ItemStack itemStack, boolean hintsOnly) {
+ structureBuild_EM(mName, 3, 7, 0, itemStack, hintsOnly);
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack itemStack) {
+ return DescTextLocalization.addText("MultiNqGenerator.hint", 8);
+ }
+
+ public final boolean addToGeneratorList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ return false;
+ } else {
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ return this.mInputHatches.add((GT_MetaTileEntity_Hatch_Input) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output) {
+ return this.mOutputHatches.add((GT_MetaTileEntity_Hatch_Output) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Dynamo) {
+ return this.mDynamoHatches.add((GT_MetaTileEntity_Hatch_Dynamo) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Maintenance) {
+ return this.mMaintenanceHatches.add((GT_MetaTileEntity_Hatch_Maintenance) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_DynamoMulti) {
+ return this.eDynamoMulti.add((GT_MetaTileEntity_Hatch_DynamoMulti) aMetaTileEntity);
+ } else {
+ return false;
+ }
+ }
+ }
+ }
+
+ @Override
+ public IStructureDefinition<MultiNqGenerator> getStructure_EM() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<MultiNqGenerator>builder()
+ .addShape(
+ mName,
+ transpose(
+ new String[][] {
+ { "AAAAAAA", "AAAAAAA", "AAAAAAA", "AAAAAAA", "AAAAAAA", "AAAAAAA", "AAAAAAA" },
+ { "N N", " ", " CCC ", " CPC ", " CCC ", " ", "N N" },
+ { "N N", " ", " CCC ", " CPC ", " CCC ", " ", "N N" },
+ { "N N", " ", " CCC ", " CPC ", " CCC ", " ", "N N" },
+ { "N N", " ", " CCC ", " CPC ", " CCC ", " ", "N N" },
+ { "AAAAAAA", "A A", "A CCC A", "A CPC A", "A CCC A", "A A", "AAAAAAA" },
+ { "ANNNNNA", "N N", "N CCC N", "N CPC N", "N CCC N", "N N", "ANNNNNA" },
+ { "XXX~XXX", "XXXXXXX", "XXXXXXX", "XXXXXXX", "XXXXXXX", "XXXXXXX", "XXXXXXX" }, }))
+ .addElement(
+ 'X',
+ ofChain(
+ buildHatchAdder(MultiNqGenerator.class)
+ .atLeast(
+ HatchElement.DynamoMulti.or(GT_HatchElement.Dynamo),
+ GT_HatchElement.InputHatch,
+ GT_HatchElement.OutputHatch,
+ GT_HatchElement.Maintenance)
+ .casingIndex(44)
+ .dot(1)
+ .build(),
+ ofBlock(GregTech_API.sBlockCasings3, 12)))
+ .addElement('A', ofBlock(GregTech_API.sBlockCasings3, 12))
+ .addElement('N', ofBlock(Loaders.radiationProtectionSteelFrame, 0))
+ .addElement('C', ofBlock(Loaders.MAR_Casing, 0))
+ .addElement('P', ofBlock(GregTech_API.sBlockCasings2, 15))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ public MultiNqGenerator(String name) {
+ super(name);
+ }
+
+ public MultiNqGenerator(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ this.times = aNBT.getInteger("mTimes");
+ this.leftEnergy = aNBT.getLong("mLeftEnergy");
+ this.basicOutput = aNBT.getInteger("mbasicOutput");
+ if (FluidRegistry.getFluid(aNBT.getString("mLockedFluidName")) != null) this.lockedFluid = new FluidStack(
+ FluidRegistry.getFluid(aNBT.getString("mLockedFluidName")),
+ aNBT.getInteger("mLockedFluidAmount"));
+ else this.lockedFluid = null;
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("mTimes", this.times);
+ aNBT.setLong("mLeftEnergy", this.leftEnergy);
+ aNBT.setInteger("mbasicOutput", this.basicOutput);
+ if (lockedFluid != null) {
+ aNBT.setString(
+ "mLockedFluidName",
+ this.lockedFluid.getFluid()
+ .getName());
+ aNBT.setInteger("mLockedFluidAmount", this.lockedFluid.amount);
+ }
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return GoodGeneratorRecipeMaps.naquadahReactorFuels;
+ }
+
+ @Override
+ protected boolean filtersFluid() {
+ return false;
+ }
+
+ @Override
+ public @NotNull CheckRecipeResult checkProcessing_EM() {
+
+ ArrayList<FluidStack> tFluids = getStoredFluids();
+ for (int i = 0; i < tFluids.size() - 1; i++) {
+ for (int j = i + 1; j < tFluids.size(); j++) {
+ if (GT_Utility.areFluidsEqual(tFluids.get(i), tFluids.get(j))) {
+ if ((tFluids.get(i)).amount >= (tFluids.get(j)).amount) {
+ tFluids.remove(j--);
+ } else {
+ tFluids.remove(i--);
+ break;
+ }
+ }
+ }
+ }
+
+ GT_Recipe tRecipe = GoodGeneratorRecipeMaps.naquadahReactorFuels
+ .findRecipe(this.getBaseMetaTileEntity(), true, 1 << 30, tFluids.toArray(new FluidStack[0]));
+ if (tRecipe != null) {
+ Pair<FluidStack, Integer> excitedInfo = getExcited(tFluids.toArray(new FluidStack[0]), false);
+ int pall = excitedInfo == null ? 1 : excitedInfo.getValue();
+ if (consumeFuel(
+ CrackRecipeAdder.copyFluidWithAmount(tRecipe.mFluidInputs[0], pall),
+ tFluids.toArray(new FluidStack[0]))) {
+ mOutputFluids = new FluidStack[] {
+ CrackRecipeAdder.copyFluidWithAmount(tRecipe.mFluidOutputs[0], pall) };
+ basicOutput = tRecipe.mSpecialValue;
+ times = pall;
+ lockedFluid = excitedInfo == null ? null : excitedInfo.getKey();
+ mMaxProgresstime = tRecipe.mDuration;
+ return CheckRecipeResultRegistry.GENERATING;
+ }
+ }
+
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack stack) {
+ if (this.getBaseMetaTileEntity()
+ .isServerSide()) {
+ if (mMaxProgresstime != 0 && mProgresstime % 20 == 0) {
+ // If there's no startRecipeProcessing, ME input hatch wouldn't work
+ startRecipeProcessing();
+ FluidStack[] input = getStoredFluids().toArray(new FluidStack[0]);
+ int time = 1;
+ if (LiquidAirConsumptionPerSecond != 0
+ && !consumeFuel(Materials.LiquidAir.getFluid(LiquidAirConsumptionPerSecond), input)) {
+ this.mEUt = 0;
+ this.trueEff = 0;
+ this.trueOutput = 0;
+ endRecipeProcessing();
+ return true;
+ }
+ int eff = consumeCoolant(input);
+ if (consumeFuel(lockedFluid, input)) time = times;
+ this.mEUt = basicOutput * eff * time / 100;
+ this.trueEff = eff;
+ this.trueOutput = (long) basicOutput * (long) eff * (long) time / 100;
+ endRecipeProcessing();
+ }
+ addAutoEnergy(trueOutput);
+ }
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ String[] info = super.getInfoData();
+ info[4] = "Probably makes: " + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(Math.abs(this.trueOutput))
+ + EnumChatFormatting.RESET
+ + " EU/t";
+ info[6] = "Problems: " + EnumChatFormatting.RED
+ + (this.getIdealStatus() - this.getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " Efficiency: "
+ + EnumChatFormatting.YELLOW
+ + trueEff
+ + EnumChatFormatting.RESET
+ + " %";
+ return info;
+ }
+
+ public boolean consumeFuel(FluidStack target, FluidStack[] input) {
+ if (target == null) return false;
+ for (FluidStack inFluid : input) {
+ if (inFluid != null && inFluid.isFluidEqual(target) && inFluid.amount >= target.amount) {
+ inFluid.amount -= target.amount;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public Pair<FluidStack, Integer> getExcited(FluidStack[] input, boolean isConsume) {
+ for (Pair<FluidStack, Integer> fluidPair : excitedLiquid) {
+ FluidStack tFluid = fluidPair.getKey();
+ for (FluidStack inFluid : input) {
+ if (inFluid != null && inFluid.isFluidEqual(tFluid) && inFluid.amount >= tFluid.amount) {
+ if (isConsume) inFluid.amount -= tFluid.amount;
+ return fluidPair;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Finds valid coolant from given inputs and consumes if found.
+ *
+ * @param input Fluid inputs.
+ * @return Efficiency of the coolant. 100 if not found.
+ */
+ private int consumeCoolant(FluidStack[] input) {
+ for (Pair<FluidStack, Integer> fluidPair : coolant) {
+ FluidStack tFluid = fluidPair.getKey();
+ for (FluidStack inFluid : input) {
+ if (inFluid != null && inFluid.isFluidEqual(tFluid) && inFluid.amount >= tFluid.amount) {
+ inFluid.amount -= tFluid.amount;
+ return fluidPair.getValue();
+ }
+ }
+ }
+ return 100;
+ }
+
+ public void addAutoEnergy(long outputPower) {
+ if (this.eDynamoMulti.size() > 0) for (GT_MetaTileEntity_Hatch tHatch : this.eDynamoMulti) {
+ long voltage = tHatch.maxEUOutput();
+ long power = voltage * tHatch.maxAmperesOut();
+ long outputAmperes;
+ if (outputPower > power) doExplosion(8 * GT_Utility.getTier(power));
+ if (outputPower >= voltage) {
+ leftEnergy += outputPower;
+ outputAmperes = leftEnergy / voltage;
+ leftEnergy -= outputAmperes * voltage;
+ addEnergyOutput_EM(voltage, outputAmperes);
+ } else {
+ addEnergyOutput_EM(outputPower, 1);
+ }
+ }
+ if (this.mDynamoHatches.size() > 0) for (GT_MetaTileEntity_Hatch tHatch : this.mDynamoHatches) {
+ long voltage = tHatch.maxEUOutput();
+ long power = voltage * tHatch.maxAmperesOut();
+ long outputAmperes;
+ if (outputPower > power) doExplosion(8 * GT_Utility.getTier(power));
+ if (outputPower >= voltage) {
+ leftEnergy += outputPower;
+ outputAmperes = leftEnergy / voltage;
+ leftEnergy -= outputAmperes * voltage;
+ addEnergyOutput_EM(voltage, outputAmperes);
+ } else {
+ addEnergyOutput_EM(outputPower, 1);
+ }
+ }
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ return structureCheck_EM(mName, 3, 7, 0) && mMaintenanceHatches.size() == 1
+ && mDynamoHatches.size() + eDynamoMulti.size() == 1;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public int getPollutionPerTick(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new MultiNqGenerator(this.mName);
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Naquadah Reactor")
+ .addInfo("Controller block for the Naquadah Reactor")
+ .addInfo("Environmentally Friendly!")
+ .addInfo("Generate power from high-energy liquids.")
+ .addInfo(
+ String.format(
+ "Consumes %d L/s Liquid Air to keep running, otherwise" + EnumChatFormatting.YELLOW
+ + " it will void your fuel"
+ + EnumChatFormatting.GRAY
+ + ".",
+ LiquidAirConsumptionPerSecond))
+ .addInfo("Input liquid nuclear fuel or liquid naquadah fuel.")
+ .addInfo(
+ "The reactor will explode when there is more than" + EnumChatFormatting.RED
+ + " ONE"
+ + EnumChatFormatting.GRAY
+ + " type of fuel in hatches!")
+ .addInfo("Can consume 1000L/s of coolant to increase efficiency:")
+ .addInfo(
+ String.format(
+ "IC2 Coolant %d%%, Super Coolant %d%%, Cryotheum %d%%, Tachyon Rich Temporal Fluid %d%%",
+ CoolantEfficiency[3],
+ CoolantEfficiency[2],
+ CoolantEfficiency[1],
+ CoolantEfficiency[0]))
+ .addInfo("Can consume excited liquid to increase the output power and fuel usage:")
+ .addInfo(String.format("Molten Caesium | %dx power | 180 L/s ", ExcitedLiquidCoe[4]))
+ .addInfo(String.format("Molten Uranium-235 | %dx power | 180 L/s", ExcitedLiquidCoe[3]))
+ .addInfo(String.format("Molten Naquadah | %dx power | 20 L/s", ExcitedLiquidCoe[2]))
+ .addInfo(String.format("Molten Atomic Separation Catalyst | %dx power | 20 L/s", ExcitedLiquidCoe[1]))
+ .addInfo(String.format("Spatially Enlarged Fluid | %dx power | 20 L/s", ExcitedLiquidCoe[0]))
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .beginStructureBlock(7, 8, 7, true)
+ .addController("Front bottom")
+ .addDynamoHatch("Any bottom layer casing, only accept ONE!")
+ .addInputHatch("Any bottom layer casing")
+ .addOutputHatch("Any bottom layer casing")
+ .addMaintenanceHatch("Any bottom layer casing")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ @SuppressWarnings("ALL")
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(44),
+ new GT_RenderedTexture(Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_FRONT_ACTIVE),
+ TextureFactory.builder()
+ .addIcon(Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_FRONT_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(44),
+ new GT_RenderedTexture(Textures.BlockIcons.NAQUADAH_REACTOR_SOLID_FRONT) };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(44) };
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(mName, stackSize, 3, 7, 0, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/NeutronActivator.java b/src/main/java/goodgenerator/blocks/tileEntity/NeutronActivator.java
new file mode 100644
index 0000000000..f3a4fd7d3c
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/NeutronActivator.java
@@ -0,0 +1,515 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.util.GT_StructureUtility.buildHatchAdder;
+import static gregtech.api.util.GT_StructureUtility.ofFrame;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import goodgenerator.api.recipe.GoodGeneratorRecipeMaps;
+import goodgenerator.blocks.tileEntity.GTMetaTileEntity.NeutronAccelerator;
+import goodgenerator.blocks.tileEntity.GTMetaTileEntity.NeutronSensor;
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import goodgenerator.util.ItemRefer;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.Textures;
+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.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.multitileentity.multiblock.casing.Glasses;
+import gregtech.api.objects.XSTR;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.api.util.IGT_HatchAdder;
+
+public class NeutronActivator extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ protected static IStructureDefinition<NeutronActivator> multiDefinition = null;
+ protected final ArrayList<NeutronAccelerator> mNeutronAccelerator = new ArrayList<>();
+ protected final ArrayList<NeutronSensor> mNeutronSensor = new ArrayList<>();
+ protected int casingAmount = 0;
+ protected int height = 0;
+ protected int eV = 0, mCeil = 0, mFloor = 0;
+ private GT_Recipe lastRecipe;
+ protected static final NumberFormatMUI numberFormat;
+ static {
+ numberFormat = new NumberFormatMUI();
+ numberFormat.setMinimumFractionDigits(2);
+ numberFormat.setMaximumFractionDigits(2);
+ }
+ final XSTR R = new XSTR();
+
+ private static final IIconContainer textureFontOn = new Textures.BlockIcons.CustomIcon("icons/NeutronActivator_On");
+ private static final IIconContainer textureFontOn_Glow = new Textures.BlockIcons.CustomIcon(
+ "icons/NeutronActivator_On_GLOW");
+ private static final IIconContainer textureFontOff = new Textures.BlockIcons.CustomIcon(
+ "icons/NeutronActivator_Off");
+ private static final IIconContainer textureFontOff_Glow = new Textures.BlockIcons.CustomIcon(
+ "icons/NeutronActivator_Off_GLOW");
+
+ protected final String NA_BOTTOM = mName + "buttom";
+ protected final String NA_MID = mName + "mid";
+ protected final String NA_TOP = mName + "top";
+
+ public NeutronActivator(String name) {
+ super(name);
+ }
+
+ public NeutronActivator(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@NotNull GT_Recipe recipe) {
+ return GT_OverclockCalculator.ofNoOverclock(recipe)
+ .setDuration((int) Math.ceil(recipe.mDuration * Math.pow(0.9f, height - 4)))
+ .setDurationUnderOneTickSupplier(() -> recipe.mDuration * Math.pow(0.9f, height - 4));
+ }
+
+ @NotNull
+ @Override
+ public CheckRecipeResult process() {
+ CheckRecipeResult result = super.process();
+ if (!result.wasSuccessful()) {
+ return result;
+ }
+ mFloor = (lastRecipe.mSpecialValue % 10000) * 1000000;
+ mCeil = (lastRecipe.mSpecialValue / 10000) * 1000000;
+ if (eV > mCeil || eV < mFloor) {
+ setOutputItems(ItemRefer.Radioactive_Waste.get(4));
+ }
+ // NA does not consume power, its hatches do. Set it to 0 to be sure
+ calculatedEut = 0;
+ return result;
+ }
+ };
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ // NA does not use power, to prevent GT_ParallelHelper from failing we trick it into thinking
+ // we have infinite power
+ logic.setAvailableVoltage(Long.MAX_VALUE);
+ logic.setAvailableAmperage(1);
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ) {
+ batchMode = !batchMode;
+ if (batchMode) {
+ GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("misc.BatchModeTextOn"));
+ } else {
+ GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("misc.BatchModeTextOff"));
+ }
+ return true;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getPollutionPerTick(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ eV = aNBT.getInteger("mKeV");
+ mCeil = aNBT.getInteger("mCeil");
+ mFloor = aNBT.getInteger("mFloor");
+ height = aNBT.getInteger("height");
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("mKeV", eV);
+ aNBT.setInteger("mCeil", mCeil);
+ aNBT.setInteger("mFloor", mFloor);
+ aNBT.setInteger("height", height);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return GoodGeneratorRecipeMaps.neutronActivatorRecipes;
+ }
+
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Neutron Activator")
+ .addInfo("Controller block for the Neutron Activator")
+ .addInfo("Superluminal-velocity Motion.")
+ .addInfo("The minimum height of the Speeding Pipe Casing is 4.")
+ .addInfo("Per extra Speeding Pipe Casing will give time discount.")
+ .addInfo("But it will reduce the Neutron Accelerator efficiency.")
+ .addInfo("You need to input energy to the Neutron Accelerator to get it running.")
+ .addInfo("It will output correct products with Specific Neutron Kinetic Energy.")
+ .addInfo("Otherwise it will output trash.")
+ .addInfo("The Neutron Kinetic Energy will decrease 72KeV/s when no Neutron Accelerator is running.")
+ .addInfo(
+ "It will explode when the Neutron Kinetic Energy is over" + EnumChatFormatting.RED
+ + " 1200MeV"
+ + EnumChatFormatting.GRAY
+ + ".")
+ .addInfo("Inputting Graphite/Beryllium dust can reduce 10MeV per dust immediately.")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .addController("Front bottom")
+ .addInputHatch("Hint block with dot 1")
+ .addInputBus("Hint block with dot 1")
+ .addOutputHatch("Hint block with dot 2")
+ .addOutputBus("Hint block with dot 2")
+ .addMaintenanceHatch("Hint block with dot 2")
+ .addOtherStructurePart("Neutron Accelerator", "Hint block with dot 2")
+ .addOtherStructurePart("Neutron Sensor", "Hint block with dot 2")
+ .addCasingInfoRange("Clean Stainless Steel Machine Casing", 7, 31, false)
+ .addCasingInfoExactly("Processor Machine Casing", 18, false)
+ .addCasingInfoMin("Steel Frame Box", 16, false)
+ .addCasingInfoMin("Speeding Pipe Casing", 4, false)
+ .addCasingInfoMin("EV+ Glass", 32, false)
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public IStructureDefinition<NeutronActivator> getStructure_EM() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<NeutronActivator>builder()
+ .addShape(NA_TOP, transpose(new String[][] { { "CCCCC", "CDDDC", "CDDDC", "CDDDC", "CCCCC" } }))
+ .addShape(NA_MID, transpose(new String[][] { { "F F", " GGG ", " GPG ", " GGG ", "F F" } }))
+ .addShape(NA_BOTTOM, transpose(new String[][] { { "XX~XX", "XDDDX", "XDDDX", "XDDDX", "XXXXX" } }))
+ .addElement(
+ 'C',
+ ofChain(
+ buildHatchAdder(NeutronActivator.class)
+ .atLeast(GT_HatchElement.InputHatch, GT_HatchElement.InputBus, GT_HatchElement.Maintenance)
+ .casingIndex(49)
+ .dot(1)
+ .build(),
+ onElementPass(NeutronActivator::onCasingFound, ofBlock(GregTech_API.sBlockCasings4, 1))))
+ .addElement('D', ofBlock(GregTech_API.sBlockCasings2, 6))
+ .addElement('F', ofFrame(Materials.Steel))
+ .addElement('G', Glasses.chainAllGlasses())
+ .addElement('P', ofBlock(Loaders.speedingPipe, 0))
+ .addElement(
+ 'X',
+ ofChain(
+ buildHatchAdder(NeutronActivator.class)
+ .atLeast(
+ GT_HatchElement.OutputHatch,
+ GT_HatchElement.OutputBus,
+ GT_HatchElement.Maintenance,
+ NeutronHatchElement.NeutronAccelerator,
+ NeutronHatchElement.NeutronSensor)
+ .casingIndex(49)
+ .dot(2)
+ .build(),
+ onElementPass(NeutronActivator::onCasingFound, ofBlock(GregTech_API.sBlockCasings4, 1))))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ @Override
+ protected void clearHatches_EM() {
+ super.clearHatches_EM();
+ this.mNeutronAccelerator.clear();
+ this.mNeutronSensor.clear();
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ this.casingAmount = 0;
+ if (!structureCheck_EM(NA_BOTTOM, 2, 0, 0)) return false;
+ height = 0;
+ while (structureCheck_EM(NA_MID, 2, height + 1, 0)) {
+ height++;
+ }
+ if (height < 4) return false;
+ return structureCheck_EM(NA_TOP, 2, height + 1, 0) && casingAmount >= 7;
+ }
+
+ public final boolean addAcceleratorAndSensor(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity instanceof NeutronAccelerator) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.mNeutronAccelerator.add((NeutronAccelerator) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof NeutronSensor) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.mNeutronSensor.add((NeutronSensor) aMetaTileEntity);
+ }
+ }
+ return false;
+ }
+
+ public int maxNeutronKineticEnergy() {
+ return 1200000000;
+ }
+
+ public int getCurrentNeutronKineticEnergy() {
+ return eV;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+
+ @Override
+ public boolean protectsExcessItem() {
+ return !eSafeVoid;
+ }
+
+ @Override
+ public boolean protectsExcessFluid() {
+ return !eSafeVoid;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new NeutronActivator(this.mName);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ super.onPostTick(aBaseMetaTileEntity, aTick);
+ boolean anyWorking = false;
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (this.eV > 0 && (aTick % 20 == 0 || eV > mCeil)) {
+ tryUseModerator();
+ }
+
+ for (NeutronAccelerator tHatch : mNeutronAccelerator) {
+ if (tHatch.getBaseMetaTileEntity()
+ .isActive() && this.getRepairStatus() == this.getIdealStatus()) {
+ anyWorking = true;
+ this.eV += Math.max(
+ (R.nextInt(tHatch.getMaxEUConsume() + 1) + tHatch.getMaxEUConsume()) * 10
+ * Math.pow(0.95, height - 4),
+ 10);
+ }
+ }
+ if (!anyWorking) {
+ if (this.eV >= 72000 && aTick % 20 == 0) {
+ this.eV -= 72000;
+ } else if (this.eV > 0 && aTick % 20 == 0) {
+ this.eV = 0;
+ }
+ }
+ if (this.eV < 0) this.eV = 0;
+ if (this.eV > maxNeutronKineticEnergy()) doExplosion(4 * 32);
+
+ for (NeutronSensor tHatch : mNeutronSensor) {
+ tHatch.updateRedstoneOutput(this.eV);
+ }
+
+ if (mProgresstime < mMaxProgresstime && (eV > mCeil || eV < mFloor)) {
+ this.mOutputFluids = null;
+ this.mOutputItems = new ItemStack[] { ItemRefer.Radioactive_Waste.get(4) };
+ }
+ }
+ }
+
+ private void tryUseModerator() {
+ startRecipeProcessing();
+ for (ItemStack input : getStoredInputs()) {
+ if (input.isItemEqual(Materials.Graphite.getDust(1)) || input.isItemEqual(Materials.Beryllium.getDust(1))) {
+ int consume = Math.min(this.eV / 10000000, input.stackSize);
+ depleteInput(GT_Utility.copyAmount(consume, input));
+ this.eV -= 10000000 * consume;
+ }
+ }
+ endRecipeProcessing();
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ structureBuild_EM(NA_BOTTOM, 2, 0, 0, stackSize, hintsOnly);
+ int heights = stackSize.stackSize + 3;
+ structureBuild_EM(NA_TOP, 2, heights + 1, 0, stackSize, hintsOnly);
+ while (heights > 0) {
+ structureBuild_EM(NA_MID, 2, heights, 0, stackSize, hintsOnly);
+ heights--;
+ }
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack itemStack) {
+ return DescTextLocalization.addText("NeutronActivator.hint", 7);
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int currentNKEInput = 0;
+ boolean anyWorking = false;
+ for (NeutronAccelerator tHatch : mNeutronAccelerator) {
+ if (tHatch.getBaseMetaTileEntity()
+ .isActive()) {
+ currentNKEInput += (R.nextInt(tHatch.getMaxEUConsume() + 1) + tHatch.getMaxEUConsume()) * 10
+ * Math.pow(0.95, height - 4);
+ anyWorking = true;
+ }
+ }
+ if (!anyWorking) currentNKEInput = -72000;
+ return new String[] { "Progress:",
+ EnumChatFormatting.GREEN + Integer.toString(this.mProgresstime / 20)
+ + EnumChatFormatting.RESET
+ + " s / "
+ + EnumChatFormatting.YELLOW
+ + this.mMaxProgresstime / 20
+ + EnumChatFormatting.RESET
+ + " s",
+ "Current Neutron Kinetic Energy Input: " + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(currentNKEInput)
+ + EnumChatFormatting.RESET
+ + "eV",
+ StatCollector.translateToLocal("scanner.info.NA") + " "
+ + EnumChatFormatting.LIGHT_PURPLE
+ + GT_Utility.formatNumbers(getCurrentNeutronKineticEnergy())
+ + EnumChatFormatting.RESET
+ + "eV" };
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(49),
+ TextureFactory.of(textureFontOn), TextureFactory.builder()
+ .addIcon(textureFontOn_Glow)
+ .glow()
+ .build() };
+ else return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(49),
+ TextureFactory.of(textureFontOff), TextureFactory.builder()
+ .addIcon(textureFontOff_Glow)
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(49) };
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+
+ int built = survivialBuildPiece(NA_BOTTOM, stackSize, 2, 0, 0, elementBudget, env, false, true);
+ if (built >= 0) return built;
+ int heights = stackSize.stackSize + 3;
+ for (int i = 1; i <= heights; i++) {
+ built = survivialBuildPiece(NA_MID, stackSize, 2, i, 0, elementBudget, env, false, true);
+ if (built >= 0) return built;
+ }
+ return survivialBuildPiece(NA_TOP, stackSize, 2, heights + 1, 0, elementBudget, env, false, true);
+ }
+
+ protected void onCasingFound() {
+ casingAmount++;
+ }
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ super.drawTexts(screenElements, inventorySlot);
+
+ screenElements
+ .widget(
+ new TextWidget(StatCollector.translateToLocal("gui.NeutronActivator.0"))
+ .setDefaultColor(COLOR_TEXT_WHITE.get()))
+ .widget(
+ new TextWidget().setStringSupplier(() -> numberFormat.format(eV / 1_000_000d) + " MeV")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
+ .widget(new FakeSyncWidget.IntegerSyncer(() -> eV, val -> eV = val));
+ }
+
+ private enum NeutronHatchElement implements IHatchElement<NeutronActivator> {
+
+ NeutronSensor(NeutronActivator::addAcceleratorAndSensor, NeutronSensor.class) {
+
+ @Override
+ public long count(NeutronActivator t) {
+ return t.mNeutronSensor.size();
+ }
+ },
+ NeutronAccelerator(NeutronActivator::addAcceleratorAndSensor, NeutronAccelerator.class) {
+
+ @Override
+ public long count(NeutronActivator t) {
+ return t.mNeutronAccelerator.size();
+ }
+ };
+
+ private final List<Class<? extends IMetaTileEntity>> mteClasses;
+ private final IGT_HatchAdder<NeutronActivator> adder;
+
+ @SafeVarargs
+ NeutronHatchElement(IGT_HatchAdder<NeutronActivator> adder, Class<? extends IMetaTileEntity>... mteClasses) {
+ this.mteClasses = Collections.unmodifiableList(Arrays.asList(mteClasses));
+ this.adder = adder;
+ }
+
+ @Override
+ public List<? extends Class<? extends IMetaTileEntity>> mteClasses() {
+ return mteClasses;
+ }
+
+ public IGT_HatchAdder<? super NeutronActivator> adder() {
+ return adder;
+ }
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/PreciseAssembler.java b/src/main/java/goodgenerator/blocks/tileEntity/PreciseAssembler.java
new file mode 100644
index 0000000000..610716fc8a
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/PreciseAssembler.java
@@ -0,0 +1,491 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.github.bartimaeusnek.bartworks.util.BW_Util.ofGlassTieredMixed;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.GT_HatchElement.*;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+import static gregtech.api.util.GT_StructureUtility.ofFrame;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import javax.annotation.Nonnull;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizon.structurelib.structure.StructureUtility;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.CycleButtonWidget;
+
+import goodgenerator.api.recipe.GoodGeneratorRecipeMaps;
+import goodgenerator.client.GUI.GG_UITextures;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.Textures;
+import gregtech.api.gui.modularui.GT_UITextures;
+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.logic.ProcessingLogic;
+import gregtech.api.metatileentity.GregTechTileClientEvents;
+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_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.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_HatchElementBuilder;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.tileentities.machines.IDualInputHatch;
+
+public class PreciseAssembler extends GT_MetaTileEntity_ExtendedPowerMultiBlockBase<PreciseAssembler>
+ implements IConstructable, ISurvivalConstructable {
+
+ private static final IIconContainer textureFontOn = new Textures.BlockIcons.CustomIcon("iconsets/OVERLAY_QTANK");
+ private static final IIconContainer textureFontOn_Glow = new Textures.BlockIcons.CustomIcon(
+ "iconsets/OVERLAY_QTANK_GLOW");
+ private static final IIconContainer textureFontOff = new Textures.BlockIcons.CustomIcon("iconsets/OVERLAY_QCHEST");
+ private static final IIconContainer textureFontOff_Glow = new Textures.BlockIcons.CustomIcon(
+ "iconsets/OVERLAY_QCHEST_GLOW");
+
+ protected IStructureDefinition<PreciseAssembler> multiDefinition = null;
+ protected int casingAmount;
+ protected int casingTier;
+ protected int machineTier;
+ protected int mode;
+ protected int energyHatchTier;
+
+ public PreciseAssembler(String name) {
+ super(name);
+ }
+
+ public PreciseAssembler(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ @Override
+ public IStructureDefinition<PreciseAssembler> getStructureDefinition() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<PreciseAssembler>builder()
+ .addShape(
+ mName,
+ transpose(
+ new String[][] { { "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC", "CCCCCCCCC" },
+ { "F F", "CGGGGGGGC", "C-------C", "CGGGGGGGC", "F F" },
+ { "F F", "CGGGGGGGC", "C-------C", "CGGGGGGGC", "F F" },
+ { "F F", "CGGGGGGGC", "C-------C", "CGGGGGGGC", "F F" },
+ { "CCCC~CCCC", "CMMMMMMMC", "CMMMMMMMC", "CMMMMMMMC", "CCCCCCCCC" } }))
+ .addElement(
+ 'C',
+ GT_HatchElementBuilder.<PreciseAssembler>builder()
+ .atLeast(
+ InputBus,
+ InputHatch,
+ OutputHatch,
+ OutputBus,
+ Maintenance,
+ Muffler,
+ ExoticEnergy.or(Energy))
+ .adder(PreciseAssembler::addToPAssList)
+ .casingIndex(1539)
+ .dot(1)
+ .buildAndChain(
+ onElementPass(
+ x -> x.casingAmount++,
+ StructureUtility.ofBlocksTiered(
+ (block, meta) -> block == Loaders.preciseUnitCasing ? meta : -2,
+ IntStream.range(0, 3)
+ .mapToObj(
+ meta -> org.apache.commons.lang3.tuple.Pair
+ .of(Loaders.preciseUnitCasing, meta))
+ .collect(Collectors.toList()),
+ -1,
+ PreciseAssembler::setCasingTier,
+ PreciseAssembler::getCasingTier))))
+ .addElement('F', ofFrame(Materials.TungstenSteel))
+ .addElement('G', ofGlassTieredMixed((byte) 4, (byte) 127, 2))
+ .addElement(
+ 'M',
+ StructureUtility.ofBlocksTiered(
+ (block, meta) -> block == GregTech_API.sBlockCasings1 ? meta : -2,
+ IntStream.range(0, 10)
+ .mapToObj(meta -> org.apache.commons.lang3.tuple.Pair.of(GregTech_API.sBlockCasings1, meta))
+ .collect(Collectors.toList()),
+ -1,
+ PreciseAssembler::setMachineTier,
+ PreciseAssembler::getMachineTier))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ public boolean addToPAssList(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ }
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ return false;
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ return mInputHatches.add((GT_MetaTileEntity_Hatch_Input) aMetaTileEntity);
+ }
+ if (aMetaTileEntity instanceof IDualInputHatch) {
+ return mDualInputHatches.add((IDualInputHatch) aMetaTileEntity);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_InputBus) {
+ return mInputBusses.add((GT_MetaTileEntity_Hatch_InputBus) aMetaTileEntity);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output) {
+ return mOutputHatches.add((GT_MetaTileEntity_Hatch_Output) aMetaTileEntity);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_OutputBus) {
+ return mOutputBusses.add((GT_MetaTileEntity_Hatch_OutputBus) aMetaTileEntity);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Energy) {
+ return mEnergyHatches.add((GT_MetaTileEntity_Hatch_Energy) aMetaTileEntity);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Maintenance) {
+ return mMaintenanceHatches.add((GT_MetaTileEntity_Hatch_Maintenance) aMetaTileEntity);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Muffler) {
+ return mMufflerHatches.add((GT_MetaTileEntity_Hatch_Muffler) aMetaTileEntity);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_EnergyMulti) {
+ return mExoticEnergyHatches.add((GT_MetaTileEntity_Hatch_EnergyMulti) aMetaTileEntity);
+ }
+ return false;
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ casingTier = aNBT.getInteger("casingTier");
+ machineTier = aNBT.getInteger("machineTier");
+ mode = aNBT.getInteger("RunningMode");
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setInteger("casingTier", casingTier);
+ aNBT.setInteger("machineTier", machineTier);
+ aNBT.setInteger("RunningMode", mode);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (getBaseMetaTileEntity().isServerSide()) {
+ this.mode = (this.mode + 1) % 2;
+ GT_Utility.sendChatToPlayer(aPlayer, StatCollector.translateToLocal("preciseassembler.chat." + this.mode));
+ }
+ super.onScrewdriverRightClick(side, aPlayer, aX, aY, aZ);
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @Nonnull
+ @Override
+ protected CheckRecipeResult validateRecipe(@Nonnull GT_Recipe recipe) {
+ if (mode == 0) {
+ if (recipe.mSpecialValue > (casingTier + 1)) {
+ return CheckRecipeResultRegistry.insufficientMachineTier(recipe.mSpecialValue);
+ }
+ }
+ if (availableVoltage < recipe.mEUt) {
+ return CheckRecipeResultRegistry.insufficientPower(recipe.mEUt);
+ }
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @Nonnull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@Nonnull GT_Recipe recipe) {
+ return super.createOverclockCalculator(recipe).setSpeedBoost(mode == 0 ? 1 : 0.5F);
+ }
+ }.setMaxParallelSupplier(() -> mode == 0 ? 1 : (int) Math.pow(2, 4 + (casingTier + 1)));
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ boolean useSingleAmp = mEnergyHatches.size() == 1 && mExoticEnergyHatches.isEmpty();
+ logic.setAvailableVoltage(getMachineVoltageLimit());
+ logic.setAvailableAmperage(useSingleAmp ? 1 : getMaxInputAmps());
+ logic.setAmperageOC(true);
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ public long getMachineVoltageLimit() {
+ if (machineTier < 0) return 0;
+ if (machineTier >= 9) return GT_Values.V[energyHatchTier];
+ else return GT_Values.V[Math.min(machineTier, energyHatchTier)];
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ if (this.mode == 0) return GoodGeneratorRecipeMaps.preciseAssemblerRecipes;
+ else return RecipeMaps.assemblerRecipes;
+ }
+
+ @Nonnull
+ @Override
+ public Collection<RecipeMap<?>> getAvailableRecipeMaps() {
+ return Arrays.asList(GoodGeneratorRecipeMaps.preciseAssemblerRecipes, RecipeMaps.assemblerRecipes);
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(mName, stackSize, hintsOnly, 4, 4, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(mName, stackSize, 4, 4, 0, elementBudget, env, false, true);
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ this.machineTier = -1;
+ this.casingAmount = 0;
+ this.casingTier = -1;
+ this.energyHatchTier = 0;
+ if (checkPiece(mName, 4, 4, 0)) {
+ energyHatchTier = checkEnergyHatchTier();
+ if (casingTier >= 0) {
+ reUpdate(1539 + casingTier);
+ }
+ getBaseMetaTileEntity().sendBlockEvent(GregTechTileClientEvents.CHANGE_CUSTOM_DATA, getUpdateData());
+ return casingAmount >= 42 && machineTier >= 0
+ && casingTier >= 0
+ && mMaintenanceHatches.size() == 1
+ && !mMufflerHatches.isEmpty();
+ }
+ return false;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Precise Assembler/Assembler")
+ .addInfo("Controller block for the Precise Assembler")
+ .addInfo("The error is no more than 7nm.")
+ .addInfo("Can assemble precise component in Precise Mode.")
+ .addInfo("Can work like a normal assembler in Normal Mode.")
+ .addInfo("Use screwdriver to change mode.")
+ .addInfo("Machine Casing and Energy Hatch limits the voltage tier the machine can work on.")
+ .addInfo("UHV Machine Casing will unlock all voltage, but you still need good Energy Hatch.")
+ .addInfo("Precise Electronic Unit Casing won't limit recipe in Normal Mode.")
+ .addInfo("But gives more parallel with more advanced one.")
+ .addInfo("It is 100% faster in Normal Mode.")
+ .addInfo("MK-I = 32x, MK-II = 64x, MK-III = 128x")
+ .addPollutionAmount(getPollutionPerSecond(null))
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .beginStructureBlock(9, 5, 5, true)
+ .addController("Front bottom")
+ .addCasingInfoExactly("Machine Casing", 21, true)
+ .addCasingInfoExactly("Glass (EV+)", 42, false)
+ .addCasingInfoRange("Precise Electronic Unit Casing", 42, 86, true)
+ .addInputHatch("Any Casing")
+ .addInputBus("Any Casing")
+ .addOutputHatch("Any Casing")
+ .addOutputBus("Any Casing")
+ .addEnergyHatch("Any Casing")
+ .addMufflerHatch("Any Casing")
+ .addMaintenanceHatch("Any Casing")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public int getPollutionPerSecond(ItemStack aStack) {
+ return 780;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("PreciseAssembler.hint", 7);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new PreciseAssembler(this.mName);
+ }
+
+ private int checkEnergyHatchTier() {
+ int tier = 0;
+ for (GT_MetaTileEntity_Hatch_Energy tHatch : filterValidMTEs(mEnergyHatches)) {
+ tier = Math.max(tHatch.mTier, tier);
+ }
+ for (GT_MetaTileEntity_Hatch tHatch : filterValidMTEs(mExoticEnergyHatches)) {
+ tier = Math.max(tHatch.mTier, tier);
+ }
+ return tier;
+ }
+
+ public int getCasingTier() {
+ return casingTier;
+ }
+
+ public void setCasingTier(int i) {
+ casingTier = i;
+ }
+
+ public int getMachineTier() {
+ return machineTier;
+ }
+
+ public void setMachineTier(int i) {
+ machineTier = i;
+ }
+
+ public void reUpdate(int texture) {
+ for (IDualInputHatch hatch : mDualInputHatches) {
+ if (((MetaTileEntity) hatch).isValid()) {
+ hatch.updateTexture(texture);
+ }
+ }
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(mInputHatches)) {
+ hatch.updateTexture(texture);
+ }
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(mInputBusses)) {
+ hatch.updateTexture(texture);
+ }
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(mOutputHatches)) {
+ hatch.updateTexture(texture);
+ }
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(mOutputBusses)) {
+ hatch.updateTexture(texture);
+ }
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(mEnergyHatches)) {
+ hatch.updateTexture(texture);
+ }
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(mMaintenanceHatches)) {
+ hatch.updateTexture(texture);
+ }
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(mMufflerHatches)) {
+ hatch.updateTexture(texture);
+ }
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(mExoticEnergyHatches)) {
+ hatch.updateTexture(texture);
+ }
+ }
+
+ @Override
+ public byte getUpdateData() {
+ return (byte) casingTier;
+ }
+
+ @Override
+ public void receiveClientEvent(byte aEventID, byte aValue) {
+ super.receiveClientEvent(aEventID, aValue);
+ if (aEventID == GregTechTileClientEvents.CHANGE_CUSTOM_DATA && (aValue & 0x80) == 0) {
+ casingTier = aValue;
+ }
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ int t = Math.max(getCasingTier(), 0);
+ if (side == facing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1539 + t),
+ TextureFactory.of(textureFontOn), TextureFactory.builder()
+ .addIcon(textureFontOn_Glow)
+ .glow()
+ .build() };
+ else return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1539 + t),
+ TextureFactory.of(textureFontOff), TextureFactory.builder()
+ .addIcon(textureFontOff_Glow)
+ .glow()
+ .build() };
+ } else return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1539 + t) };
+ }
+
+ @Override
+ public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) {
+ super.addUIWidgets(builder, buildContext);
+ builder.widget(
+ new CycleButtonWidget().setToggle(() -> mode == 1, val -> mode = val ? 1 : 0)
+ .setTextureGetter(
+ state -> state == 1 ? GG_UITextures.OVERLAY_BUTTON_ASSEMBLER_MODE
+ : GG_UITextures.OVERLAY_BUTTON_PRECISE_MODE)
+ .setBackground(GT_UITextures.BUTTON_STANDARD)
+ .setPos(80, 91)
+ .setSize(16, 16)
+ .dynamicTooltip(
+ () -> Collections.singletonList(StatCollector.translateToLocal("preciseassembler.chat." + mode)))
+ .setUpdateTooltipEveryTick(true)
+ .setTooltipShowUpDelay(TOOLTIP_DELAY));
+ }
+
+ @Override
+ public boolean isInputSeparationEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsBatchMode() {
+ return true;
+ }
+
+ @Override
+ public boolean supportsVoidProtection() {
+ return true;
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/SupercriticalFluidTurbine.java b/src/main/java/goodgenerator/blocks/tileEntity/SupercriticalFluidTurbine.java
new file mode 100644
index 0000000000..7c8d9ee154
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/SupercriticalFluidTurbine.java
@@ -0,0 +1,184 @@
+package goodgenerator.blocks.tileEntity;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_LargeTurbineBase;
+import goodgenerator.loader.Loaders;
+import gregtech.api.enums.Textures;
+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.objects.XSTR;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_ModHandler;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Utility;
+
+public class SupercriticalFluidTurbine extends GT_MetaTileEntity_LargeTurbineBase {
+
+ private boolean looseFit = false;
+
+ private static final IIconContainer turbineOn = new Textures.BlockIcons.CustomIcon("icons/turbines/TURBINE_05");
+ private static final IIconContainer turbineOff = new Textures.BlockIcons.CustomIcon("icons/turbines/TURBINE_15");
+ private static final IIconContainer turbineEmpty = new Textures.BlockIcons.CustomIcon("icons/turbines/TURBINE_25");
+
+ public SupercriticalFluidTurbine(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public SupercriticalFluidTurbine(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff) {
+ if (looseFit) {
+ aOptFlow *= 4;
+ double pow = Math.pow(1.1f, ((aBaseEff - 7500) / 10000F) * 20f);
+ if (aBaseEff > 10000) {
+ aOptFlow *= pow;
+ aBaseEff = 7500;
+ } else if (aBaseEff > 7500) {
+ aOptFlow *= pow;
+ aBaseEff *= 0.75f;
+ } else {
+ aBaseEff *= 0.75f;
+ }
+ }
+ int tEU = 0;
+ int totalFlow = 0; // Byproducts are based on actual flow
+ int flow = 0;
+ int remainingFlow = GT_Utility.safeInt((long) (aOptFlow * 1.25f)); // Allowed to use up to 125% of optimal flow.
+ // Variable required outside of loop for
+ // multi-hatch scenarios.
+ this.realOptFlow = aOptFlow;
+
+ storedFluid = 0;
+ FluidStack tSCSteam = FluidRegistry.getFluidStack("supercriticalsteam", 1);
+ for (int i = 0; i < aFluids.size() && remainingFlow > 0; i++) {
+ final FluidStack aFluidStack = aFluids.get(i);
+ if (tSCSteam.isFluidEqual(aFluidStack)) {
+ flow = Math.min(aFluidStack.amount, remainingFlow);
+ depleteInput(new FluidStack(aFluidStack, flow));
+ this.storedFluid += aFluidStack.amount;
+ remainingFlow -= flow;
+ totalFlow += flow;
+ } else if (GT_ModHandler.isAnySteam(aFluidStack)) {
+ depleteInput(new FluidStack(aFluidStack, aFluidStack.amount));
+ }
+ }
+ if (totalFlow <= 0) return 0;
+ tEU = totalFlow;
+ addOutput(GT_ModHandler.getSteam(totalFlow));
+ if (totalFlow == aOptFlow) {
+ tEU = GT_Utility.safeInt((long) tEU * (long) aBaseEff / 100L);
+ } else {
+ float efficiency = 1.0f - Math.abs((totalFlow - aOptFlow) / (float) aOptFlow);
+ tEU *= efficiency;
+ tEU = Math.max(1, GT_Utility.safeInt((long) tEU * (long) aBaseEff / 100L));
+ }
+
+ if (tEU > maxPower) {
+ tEU = GT_Utility.safeInt(maxPower);
+ }
+
+ return tEU;
+ }
+
+ @Override
+ public void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) {
+ if (side == getBaseMetaTileEntity().getFrontFacing()) {
+ looseFit ^= true;
+ GT_Utility.sendChatToPlayer(
+ aPlayer,
+ looseFit ? trans("500", "Fitting: Loose - More Flow")
+ : trans("501", "Fitting: Tight - More Efficiency"));
+ }
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ // 2x more damage than normal turbine
+ return looseFit ? (XSTR.XSTR_INSTANCE.nextInt(2) == 0 ? 0 : 1) : 2;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ super.looseFit = looseFit;
+ return super.getInfoData();
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ aNBT.setBoolean("turbineFitting", looseFit);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ looseFit = aNBT.getBoolean("turbineFitting");
+ }
+
+ @Override
+ public Block getCasingBlock() {
+ return Loaders.supercriticalFluidTurbineCasing;
+ }
+
+ @Override
+ public int getCasingMeta() {
+ return 0;
+ }
+
+ @Override
+ public int getCasingTextureIndex() {
+ return 1538;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Supercritical Steam Turbine")
+ .addInfo("Controller block for Supercritical Fluid Turbine")
+ .addInfo("Needs a Turbine, place inside controller")
+ .addInfo("Use Supercritical Steam to generate power.")
+ .addInfo("Outputs Steam as well as producing power")
+ .addInfo("1L Supercritical Steam = 100 EU")
+ .addInfo("Extreme Heated Steam will cause more damage to the turbine.")
+ .addInfo("Power output depends on turbine and fitting")
+ .addInfo("Use screwdriver to adjust fitting of turbine")
+ .addSeparator()
+ .beginStructureBlock(3, 3, 4, true)
+ .addController("Front center")
+ .addCasingInfo("SC Turbine Casing", 24)
+ .addDynamoHatch("Back center", 1)
+ .addMaintenanceHatch("Side centered", 2)
+ .addInputHatch("Supercritical Fluid, Side centered", 2)
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new SupercriticalFluidTurbine(mName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1538),
+ facing == side
+ ? (aActive ? TextureFactory.of(turbineOn)
+ : hasTurbine() ? TextureFactory.of(turbineOff) : TextureFactory.of(turbineEmpty))
+ : Textures.BlockIcons.getCasingTextureForId(1538) };
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/UniversalChemicalFuelEngine.java b/src/main/java/goodgenerator/blocks/tileEntity/UniversalChemicalFuelEngine.java
new file mode 100644
index 0000000000..6c8ce62539
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/UniversalChemicalFuelEngine.java
@@ -0,0 +1,393 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.enums.Mods.GTPlusPlus;
+import static gregtech.api.enums.Textures.BlockIcons.*;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_DynamoMulti;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.GregTech_API;
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.TickTime;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+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_Input;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Maintenance;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.recipe.maps.FuelBackend;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gtPlusPlus.api.recipe.GTPPRecipeMaps;
+
+public class UniversalChemicalFuelEngine extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ protected final double DIESEL_EFFICIENCY_COEFFICIENT = 0.04D;
+ protected final double GAS_EFFICIENCY_COEFFICIENT = 0.04D;
+ protected final double ROCKET_EFFICIENCY_COEFFICIENT = 0.005D;
+ protected final double EFFICIENCY_CEILING = 1.5D;
+ protected final int HEATING_TIMER = TickTime.SECOND * 10;
+
+ private long tEff;
+ private int heatingTicks;
+ private boolean isStoppingSafe;
+
+ private IStructureDefinition<UniversalChemicalFuelEngine> multiDefinition = null;
+
+ public UniversalChemicalFuelEngine(String name) {
+ super(name);
+ super.useLongPower = true;
+ }
+
+ public UniversalChemicalFuelEngine(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ super.useLongPower = true;
+ }
+
+ public final boolean addMaintenance(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Maintenance) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.mMaintenanceHatches.add((GT_MetaTileEntity_Hatch_Maintenance) aMetaTileEntity);
+ }
+ }
+ return false;
+ }
+
+ public final boolean addMuffler(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Muffler) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.mMufflerHatches.add((GT_MetaTileEntity_Hatch_Muffler) aMetaTileEntity);
+ }
+ }
+ return false;
+ }
+
+ public final boolean addInputHatch(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.mInputHatches.add((GT_MetaTileEntity_Hatch_Input) aMetaTileEntity);
+ }
+ }
+ return false;
+ }
+
+ public final boolean addDynamoHatch(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Dynamo) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.mDynamoHatches.add((GT_MetaTileEntity_Hatch_Dynamo) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_DynamoMulti) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.eDynamoMulti.add((GT_MetaTileEntity_Hatch_DynamoMulti) aMetaTileEntity);
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public IStructureDefinition<UniversalChemicalFuelEngine> getStructure_EM() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<UniversalChemicalFuelEngine>builder()
+ .addShape(
+ mName,
+ transpose(
+ new String[][] {
+ { "TTTTT", "TTMMT", "TTMMT", "TTMMT", "TTMMT", "TTMMT", "TTMMT", "TTMMT", "TTTTT" },
+ { "TTTTT", "SPCCI-", "SPCCI-", "SPCCI-", "SPCCI-", "SPCCI-", "SPCCI-", "SPCCI-", "TTTTT" },
+ { "TT~TT", "SPGGI-", "SPGGI-", "SPGGI-", "SPGGI-", "SPGGI-", "SPGGI-", "SPGGI-", "TTETT" },
+ { "TTWTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT", "TTTTT" } }))
+ .addElement('T', ofBlock(GregTech_API.sBlockCasings4, 2))
+ .addElement('W', GT_HatchElement.Maintenance.newAny(50, 1))
+ .addElement('M', GT_HatchElement.Muffler.newAny(50, 2))
+ .addElement('S', GT_HatchElement.InputHatch.newAny(50, 3))
+ .addElement('E', GT_HatchElement.Dynamo.newAny(50, 4))
+ .addElement('P', ofBlock(GregTech_API.sBlockCasings2, 14))
+ .addElement('C', ofBlock(Loaders.titaniumPlatedCylinder, 0))
+ .addElement('G', ofBlock(GregTech_API.sBlockCasings2, 4))
+ .addElement('I', ofBlock(GregTech_API.sBlockCasings4, 13))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ return structureCheck_EM(mName, 2, 2, 0);
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ structureBuild_EM(mName, 2, 2, 0, stackSize, hintsOnly);
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack itemStack) {
+ return DescTextLocalization.addText("UniversalChemicalFuelEngine.hint", 11);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public int getPollutionPerTick(ItemStack aStack) {
+ return (int) Math.sqrt(this.getPowerFlow()) / 20;
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Chemical Engine")
+ .addInfo("Controller block for the Chemical Engine")
+ .addInfo("BURNING BURNING BURNING")
+ .addInfo("Use combustible liquid to generate power.")
+ .addInfo("You need to supply Combustion Promoter to keep it running.")
+ .addInfo("It will consume all the fuel and promoter in the hatch every second.")
+ .addInfo("If the Dynamo Hatch's buffer fills up, the machine will stop.")
+ .addInfo("When turned on, there's 10-second period where the machine will not stop.")
+ .addInfo("Even if it doesn't stop, all the fuel in the hatch will be consumed.")
+ .addInfo("The efficiency is determined by the proportion of Combustion Promoter to fuel.")
+ .addInfo("The proportion is bigger, and the efficiency will be higher.")
+ .addInfo("Start machine with power button to force structure check.")
+ .addInfo("It creates sqrt(Current Output Power) pollution every second")
+ .addInfo(
+ "If you forget to supply Combustion Promoter, this engine will swallow all the fuel "
+ + EnumChatFormatting.YELLOW
+ + "without outputting energy"
+ + EnumChatFormatting.GRAY
+ + ".")
+ .addInfo("The efficiency is up to 150%.")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .beginStructureBlock(5, 4, 9, false)
+ .addMaintenanceHatch("Hint block with dot 1")
+ .addMufflerHatch("Hint block with dot 2 (fill all slots with mufflers)")
+ .addInputHatch("Hint block with dot 3 (fill all slots with input hatches)")
+ .addDynamoHatch("Hint block with dot 4")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ @Override
+ public @NotNull CheckRecipeResult checkProcessing_EM() {
+
+ ArrayList<FluidStack> tFluids = getStoredFluids();
+
+ long PromoterAmount = findLiquidAmount(getPromoter(), tFluids);
+
+ CheckRecipeResult result;
+
+ result = processFuel(tFluids, RecipeMaps.dieselFuels, PromoterAmount, DIESEL_EFFICIENCY_COEFFICIENT, 1);
+ if (result.wasSuccessful()) return result;
+
+ result = processFuel(tFluids, RecipeMaps.gasTurbineFuels, PromoterAmount, GAS_EFFICIENCY_COEFFICIENT, 1);
+ if (result.wasSuccessful()) return result;
+
+ if (GTPlusPlus.isModLoaded()) {
+ result = processFuel(tFluids, GTPPRecipeMaps.rocketFuels, PromoterAmount, ROCKET_EFFICIENCY_COEFFICIENT, 3);
+ if (result.wasSuccessful()) return result;
+ }
+
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+
+ protected CheckRecipeResult processFuel(ArrayList<FluidStack> tFluids, RecipeMap<FuelBackend> recipeMap,
+ long PromoterAmount, double efficiencyCoefficient, double FuelsValueBonus) {
+ for (GT_Recipe recipe : recipeMap.getAllRecipes()) {
+ FluidStack tFuel = findFuel(recipe);
+ if (tFuel == null) continue;
+ long FuelAmount = findLiquidAmount(tFuel, tFluids);
+ if (FuelAmount == 0) continue;
+ calculateEfficiency(FuelAmount, PromoterAmount, efficiencyCoefficient);
+ consumeAllLiquid(tFuel, tFluids);
+ consumeAllLiquid(getPromoter(), tFluids);
+ this.setPowerFlow((long) (FuelAmount * recipe.mSpecialValue * FuelsValueBonus / 20.0D));
+ this.mMaxProgresstime = 20;
+ this.updateSlots();
+ return CheckRecipeResultRegistry.GENERATING;
+ }
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+
+ @Override
+ public void stopMachine() {
+ // Reset the counter for heating, so that it works again when the machine restarts
+ heatingTicks = 0;
+ super.stopMachine();
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack stack) {
+ super.onRunningTick(stack);
+ // Counts ticks up to the defined timer (200 ticks, 10 seconds)
+ // The multiblock will not stop due to excess energy during this time
+ // Machine used to explode in the past, this timer was first made to prevent that
+ if (heatingTicks < HEATING_TIMER) {
+ heatingTicks++;
+ isStoppingSafe = true;
+ } else if (isStoppingSafe) isStoppingSafe = false;
+
+ if (this.getBaseMetaTileEntity()
+ .isServerSide()) {
+ addAutoEnergy();
+ }
+ return true;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ String[] info = super.getInfoData();
+ info[4] = "Probably makes: " + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(this.getPowerFlow())
+ + EnumChatFormatting.RESET
+ + " EU/t";
+ info[6] = "Problems: " + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(this.getIdealStatus() - this.getRepairStatus())
+ + EnumChatFormatting.RESET
+ + " Efficiency: "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(tEff / 100D)
+ + EnumChatFormatting.RESET
+ + " %";
+ return info;
+ }
+
+ void addAutoEnergy() {
+ long exEU = this.getPowerFlow() * tEff / 10000;
+ if (!mDynamoHatches.isEmpty()) {
+ GT_MetaTileEntity_Hatch_Dynamo tHatch = mDynamoHatches.get(0);
+ if (tHatch.maxEUOutput() * tHatch.maxAmperesOut() >= exEU) {
+ tHatch.setEUVar(
+ Math.min(
+ tHatch.maxEUStore(),
+ tHatch.getBaseMetaTileEntity()
+ .getStoredEU() + exEU));
+ } else if (!isStoppingSafe) {
+ stopMachine();
+ }
+ }
+ if (!eDynamoMulti.isEmpty()) {
+ GT_MetaTileEntity_Hatch_DynamoMulti tHatch = eDynamoMulti.get(0);
+ if (tHatch.maxEUOutput() * tHatch.maxAmperesOut() >= exEU) {
+ tHatch.setEUVar(
+ Math.min(
+ tHatch.maxEUStore(),
+ tHatch.getBaseMetaTileEntity()
+ .getStoredEU() + exEU));
+ } else if (!isStoppingSafe) {
+ stopMachine();
+ }
+ }
+ }
+
+ public FluidStack getPromoter() {
+ return FluidRegistry.getFluidStack("combustionpromotor", 1);
+ }
+
+ public FluidStack findFuel(GT_Recipe aFuel) {
+ if (aFuel.mInputs != null && aFuel.mInputs.length > 0)
+ return GT_Utility.getFluidForFilledItem(aFuel.mInputs[0], true);
+ else return aFuel.mFluidInputs[0];
+ }
+
+ public void calculateEfficiency(long aFuel, long aPromoter, double coefficient) {
+ if (aPromoter == 0) {
+ this.tEff = 0;
+ return;
+ }
+ this.tEff = (int) (Math.exp(-coefficient * (double) aFuel / (double) aPromoter) * EFFICIENCY_CEILING * 10000);
+ }
+
+ public long findLiquidAmount(FluidStack liquid, List<FluidStack> input) {
+ long cnt = 0;
+ for (FluidStack fluid : input) {
+ if (fluid.isFluidEqual(liquid)) {
+ cnt += fluid.amount;
+ }
+ }
+ if (cnt < 0) cnt = 0;
+ return cnt;
+ }
+
+ public void consumeAllLiquid(FluidStack liquid, List<FluidStack> input) {
+ for (FluidStack fluid : input) {
+ if (fluid.isFluidEqual(liquid)) fluid.amount = 0;
+ }
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { casingTexturePages[0][50],
+ TextureFactory.of(OVERLAY_FRONT_DIESEL_ENGINE_ACTIVE), TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DIESEL_ENGINE_ACTIVE_GLOW)
+ .glow()
+ .build() };
+ return new ITexture[] { casingTexturePages[0][50], TextureFactory.of(OVERLAY_FRONT_DIESEL_ENGINE),
+ TextureFactory.builder()
+ .addIcon(OVERLAY_FRONT_DIESEL_ENGINE_GLOW)
+ .glow()
+ .build() };
+ }
+ return new ITexture[] { casingTexturePages[0][50] };
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new UniversalChemicalFuelEngine(this.mName);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(mName, stackSize, 2, 2, 0, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/YottaFluidTank.java b/src/main/java/goodgenerator/blocks/tileEntity/YottaFluidTank.java
new file mode 100644
index 0000000000..f712fa12a7
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/YottaFluidTank.java
@@ -0,0 +1,709 @@
+package goodgenerator.blocks.tileEntity;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static goodgenerator.util.DescTextLocalization.BLUE_PRINT_INFO;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+import static gregtech.api.util.GT_StructureUtility.*;
+
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.List;
+
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.ChatComponentTranslation;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
+
+import com.github.bartimaeusnek.bartworks.API.BorosilicateGlass;
+import com.github.technus.tectech.TecTech;
+import com.github.technus.tectech.thing.gui.TecTechUITextures;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import goodgenerator.blocks.tileEntity.GTMetaTileEntity.YOTTAHatch;
+import goodgenerator.blocks.tileEntity.base.GT_MetaTileEntity_TooltipMultiBlockBase_EM;
+import goodgenerator.client.GUI.GG_UITextures;
+import goodgenerator.loader.Loaders;
+import goodgenerator.util.CharExchanger;
+import goodgenerator.util.DescTextLocalization;
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.Textures;
+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.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Output;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.SimpleCheckRecipeResult;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public class YottaFluidTank extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable {
+
+ private static final IIconContainer textureFontOn = new Textures.BlockIcons.CustomIcon("iconsets/OVERLAY_QTANK");
+ private static final IIconContainer textureFontOn_Glow = new Textures.BlockIcons.CustomIcon(
+ "iconsets/OVERLAY_QTANK_GLOW");
+ private static final IIconContainer textureFontOff = new Textures.BlockIcons.CustomIcon("iconsets/OVERLAY_QCHEST");
+ private static final IIconContainer textureFontOff_Glow = new Textures.BlockIcons.CustomIcon(
+ "iconsets/OVERLAY_QCHEST_GLOW");
+
+ protected IStructureDefinition<YottaFluidTank> multiDefinition = null;
+ protected final ArrayList<YOTTAHatch> mYottaHatch = new ArrayList<>();
+
+ private static final BigInteger ONE_HUNDRED = BigInteger.valueOf(100);
+ private static final BigInteger FIVE = BigInteger.valueOf(5);
+
+ /** Tank capacity */
+ public BigInteger mStorage = BigInteger.ZERO;
+ /** Amount of fluid millibuckets currently in the tank */
+ public BigInteger mStorageCurrent = BigInteger.ZERO;
+ /**
+ * Fluid type currently stored in the tank, can be null. Stack size is always 1, real amount is stored in
+ * mStorageCurrent.
+ */
+ public FluidStack mFluid = null;
+ /**
+ * Fluid type currently the tank is currently locked to, can be null. Stack size is always 1, real amount is stored
+ * in mStorageCurrent.
+ */
+ public FluidStack mLockedFluid = null;
+ protected boolean isFluidLocked = false;
+ protected int glassMeta;
+ protected int maxCell;
+ protected final String YOTTANK_BOTTOM = mName + "buttom";
+ protected final String YOTTANK_MID = mName + "mid";
+ protected final String YOTTANK_TOP = mName + "top";
+ protected final NumberFormatMUI numberFormat = new NumberFormatMUI();
+ private int workTickCounter = 0;
+
+ public static final BigInteger MAX_INT_BIGINT = BigInteger.valueOf(Integer.MAX_VALUE);
+
+ protected boolean voidExcessEnabled = false;
+
+ public YottaFluidTank(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ public YottaFluidTank(String name) {
+ super(name);
+ }
+
+ public int getMeta() {
+ return glassMeta;
+ }
+
+ public void setMeta(int meta) {
+ glassMeta = meta;
+ }
+
+ public String getCap() {
+ return mStorage.toString(10);
+ }
+
+ public String getStored() {
+ return mStorageCurrent.toString(10);
+ }
+
+ public String getFluidName() {
+ if (mFluid == null) return StatCollector.translateToLocal("scanner.info.YOTTank.empty");
+ return mFluid.getLocalizedName();
+ }
+
+ public String getLockedFluidName() {
+ if (!isFluidLocked) return StatCollector.translateToLocal("scanner.info.YOTTank.none");
+ if (mLockedFluid == null) return StatCollector.translateToLocal("scanner.info.YOTTank.next");
+ return mLockedFluid.getLocalizedName();
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ String tAmount = aNBT.getString("mStorage");
+ String tAmountCurrent = aNBT.getString("mStorageCurrent");
+ if (StringUtils.isEmpty(tAmount)) tAmount = "0";
+ if (StringUtils.isEmpty(tAmountCurrent)) tAmountCurrent = "0";
+ mStorage = new BigInteger(tAmount, 10);
+ mStorageCurrent = new BigInteger(tAmountCurrent, 10);
+ mFluid = FluidRegistry.getFluidStack(aNBT.getString("mFluidName"), 1);
+ mLockedFluid = FluidRegistry.getFluidStack(aNBT.getString("mLockedFluidName"), 1);
+ voidExcessEnabled = aNBT.getBoolean("voidExcessEnabled");
+ isFluidLocked = aNBT.getBoolean("isFluidLocked");
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ aNBT.setString("mStorage", mStorage.toString(10));
+ aNBT.setString("mStorageCurrent", mStorageCurrent.toString(10));
+ aNBT.setString(
+ "mFluidName",
+ mFluid == null ? ""
+ : mFluid.getFluid()
+ .getName());
+ aNBT.setString(
+ "mLockedFluidName",
+ mLockedFluid == null ? ""
+ : mLockedFluid.getFluid()
+ .getName());
+ aNBT.setBoolean("voidExcessEnabled", voidExcessEnabled);
+ aNBT.setBoolean("isFluidLocked", isFluidLocked);
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public @NotNull CheckRecipeResult checkProcessing_EM() {
+ this.mEUt = 0;
+ this.mMaxProgresstime = 20;
+ return SimpleCheckRecipeResult.ofSuccess("");
+ }
+
+ public boolean getIsVoidExcessEnabled() {
+ return voidExcessEnabled;
+ }
+
+ /**
+ * Attempts to remove {@code amount} of fluid from the tank if possible, does not do partial removals.
+ *
+ * @param amount The millibucket amount of the fluid to remove
+ * @return True if successfully removed amount, false if no fluid was removed.
+ */
+ public boolean reduceFluid(long amount) {
+ final BigInteger bigAmount = BigInteger.valueOf(amount);
+ if (mStorageCurrent.compareTo(bigAmount) < 0) {
+ return false;
+ } else {
+ mStorageCurrent = mStorageCurrent.subtract(bigAmount);
+ return true;
+ }
+ }
+
+ /**
+ * Attempts to put {@code amount} of fluid into the tank if possible, fails if there's not enough space for all of
+ * it.
+ *
+ * @param amount The millibucket amount of the fluid to insert
+ * @param doFill Whether to actually fill, or just simulate a fill
+ * @return True if successfully added the given amount of fluid to the tank, false if failed.
+ */
+ public boolean addFluid(long amount, boolean doFill) {
+ final BigInteger bigAmount = BigInteger.valueOf(amount);
+ final BigInteger newTotal = mStorageCurrent.add(bigAmount);
+ if (newTotal.compareTo(mStorage) > 0) {
+ return false;
+ } else {
+ if (doFill) {
+ mStorageCurrent = newTotal;
+ }
+ return true;
+ }
+ }
+
+ // Avoid allocating a new array on every query
+ private final FluidTankInfo[] tankInfoCache = new FluidTankInfo[1];
+
+ @Override
+ public FluidTankInfo[] getTankInfo(ForgeDirection aSide) {
+ int fluidSize = mStorageCurrent.compareTo(MAX_INT_BIGINT) >= 0 ? Integer.MAX_VALUE : mStorageCurrent.intValue();
+ int tankCapacity = mStorage.compareTo(MAX_INT_BIGINT) >= 0 ? Integer.MAX_VALUE : mStorage.intValue();
+ final boolean cacheNeedsRecreation;
+ if (tankInfoCache[0] == null || tankInfoCache[0].capacity != tankCapacity) {
+ cacheNeedsRecreation = true;
+ } else if (tankInfoCache[0].fluid == null) {
+ cacheNeedsRecreation = (mFluid != null);
+ } else {
+ cacheNeedsRecreation = !tankInfoCache[0].fluid.isFluidEqual(mFluid);
+ }
+ if (cacheNeedsRecreation) {
+ final FluidStack storedFluid = mFluid.copy();
+ storedFluid.amount = fluidSize;
+ tankInfoCache[0] = new FluidTankInfo(storedFluid, tankCapacity);
+ } else if (mFluid != null) {
+ tankInfoCache[0].fluid.amount = fluidSize;
+ }
+ return tankInfoCache;
+ }
+
+ @Override
+ protected void clearHatches_EM() {
+ super.clearHatches_EM();
+ mYottaHatch.clear();
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ mStorage = BigInteger.ZERO;
+ glassMeta = 0;
+ maxCell = 0;
+ if (!structureCheck_EM(YOTTANK_BOTTOM, 2, 0, 0)) return false;
+ int cnt = 0;
+ while (structureCheck_EM(YOTTANK_MID, 2, cnt + 1, 0)) {
+ cnt++;
+ }
+ if (cnt > 15 || cnt < 1) return false;
+ if (!structureCheck_EM(YOTTANK_TOP, 2, cnt + 2, 0)) return false;
+ // maxCell+1 = Tier of highest Cell. glassMeta is the glass voltage tier
+ if (maxCell + 3 <= glassMeta) {
+ if (mStorage.compareTo(mStorageCurrent) < 0) mStorageCurrent = mStorage;
+ if (mFluid == null) {
+ mStorageCurrent = BigInteger.ZERO;
+ }
+ mWrench = true;
+ mScrewdriver = true;
+ mSolderingTool = true;
+ mSoftHammer = true;
+ mHardHammer = true;
+ mCrowbar = true;
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public IStructureDefinition<YottaFluidTank> getStructure_EM() {
+ if (multiDefinition == null) {
+ multiDefinition = StructureDefinition.<YottaFluidTank>builder()
+ .addShape(
+ YOTTANK_BOTTOM,
+ transpose(
+ new String[][] { { "MM~MM", "MCCCM", "MCCCM", "MCCCM", "MMMMM" },
+ { " ", " OOO ", " OOO ", " OOO ", " " } }))
+ .addShape(YOTTANK_MID, transpose(new String[][] { { "GGGGG", "GRRRG", "GRRRG", "GRRRG", "GGGGG" } }))
+ .addShape(
+ YOTTANK_TOP,
+ transpose(
+ new String[][] { { "FFFFF", "F F", "F F", "F F", "FFFFF" },
+ { "CCCCC", "CIIIC", "CIIIC", "CIIIC", "CCCCC" } }))
+ .addElement('C', ofBlock(Loaders.yottaFluidTankCasing, 0))
+ .addElement(
+ 'G',
+ withChannel(
+ "glass",
+ BorosilicateGlass.ofBoroGlass(
+ (byte) 0,
+ (byte) 1,
+ Byte.MAX_VALUE,
+ YottaFluidTank::setMeta,
+ te -> (byte) te.getMeta())))
+ .addElement('R', ofChain(cells(10)))
+ .addElement('F', ofFrame(Materials.Steel))
+ .addElement(
+ 'I',
+ buildHatchAdder(YottaFluidTank.class).atLeast(GT_HatchElement.InputHatch)
+ .casingIndex(1537)
+ .dot(1)
+ .buildAndChain(Loaders.yottaFluidTankCasing, 0))
+ .addElement(
+ 'M',
+ buildHatchAdder(YottaFluidTank.class).atLeast(GT_HatchElement.Maintenance)
+ .casingIndex(1537)
+ .dot(2)
+ .buildAndChain(Loaders.yottaFluidTankCasing, 0))
+ .addElement(
+ 'O',
+ buildHatchAdder(YottaFluidTank.class).atLeast(GT_HatchElement.OutputHatch)
+ .adder(YottaFluidTank::addOutput)
+ .casingIndex(1537)
+ .dot(1)
+ .buildAndChain(Loaders.yottaFluidTankCasing, 0))
+ .build();
+ }
+ return multiDefinition;
+ }
+
+ public List<IStructureElement<YottaFluidTank>> cells(int num) {
+ List<IStructureElement<YottaFluidTank>> out = new ArrayList<>();
+ for (int i = 0; i < num; ++i) {
+ int finalI = i;
+ out.add(onElementPass(x -> {
+ x.mStorage = x.mStorage.add(calStorage(finalI));
+ x.maxCell = Math.max(x.maxCell, finalI);
+ }, ofBlock(Loaders.yottaFluidTankCell, i)));
+ }
+ return out;
+ }
+
+ public final boolean addOutput(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null) {
+ return false;
+ } else {
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) {
+ return false;
+ } else {
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output) {
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return this.mOutputHatches.add((GT_MetaTileEntity_Hatch_Output) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof YOTTAHatch) {
+ // only one yothatch allowed
+ if (!this.mYottaHatch.isEmpty()) return false;
+ ((GT_MetaTileEntity_Hatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ ((YOTTAHatch) aMetaTileEntity).setTank(this);
+ return this.mYottaHatch.add((YOTTAHatch) aMetaTileEntity);
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ return new String[] { StatCollector.translateToLocal("scanner.info.YOTTank.1"),
+ StatCollector.translateToLocal(
+ EnumChatFormatting.YELLOW + CharExchanger.formatNumber(getFluidName() + EnumChatFormatting.RESET)),
+
+ StatCollector.translateToLocal("scanner.info.YOTTank.0"),
+ StatCollector.translateToLocal(
+ EnumChatFormatting.GREEN + CharExchanger.formatNumber(getCap()) + EnumChatFormatting.RESET + " L"),
+
+ StatCollector.translateToLocal("scanner.info.YOTTank.2"),
+ StatCollector.translateToLocal(
+ EnumChatFormatting.GREEN + CharExchanger.formatNumber(getStored())
+ + EnumChatFormatting.RESET
+ + " L"
+ + " ("
+ + EnumChatFormatting.GREEN
+ + getPercent()
+ + "%"
+ + EnumChatFormatting.RESET
+ + ")"),
+
+ StatCollector.translateToLocal("scanner.info.YOTTank.3"),
+ StatCollector.translateToLocal(
+ EnumChatFormatting.YELLOW + CharExchanger.formatNumber(getLockedFluidName())
+ + EnumChatFormatting.RESET) };
+ }
+
+ private String getPercent() {
+ if (mStorage.signum() == 0) return "0";
+ return mStorageCurrent.multiply(ONE_HUNDRED)
+ .divide(mStorage)
+ .toString();
+ }
+
+ @Override
+ protected GT_Multiblock_Tooltip_Builder createTooltip() {
+ final GT_Multiblock_Tooltip_Builder tt = new GT_Multiblock_Tooltip_Builder();
+ tt.addMachineType("Fluid Tank")
+ .addInfo("Controller block for the YOTTank.")
+ .addInfo("The max output speed is decided by the amount of stored liquid and the output hatch's capacity.")
+ .addInfo("The max fluid cell tier is limited by the glass tier.")
+ .addInfo("HV glass for T1, EV glass for T2, IV glass for T3. . .")
+ .addInfo("The max height of the cell blocks is 15.")
+ .addInfo("The structure is too complex!")
+ .addInfo(BLUE_PRINT_INFO)
+ .addSeparator()
+ .beginVariableStructureBlock(5, 5, 1, 15, 5, 5, false)
+ .addController("Front of the second layer")
+ .addCasingInfoExactly("Steel Frame Box", 16, false)
+ .addCasingInfoRange("Glass (HV+)", 16, 240, true)
+ .addCasingInfoRange("Fluid Cell Block", 9, 135, true)
+ .addCasingInfoRange("YOTTank Casing", 25, 43, false)
+ .addInputHatch("Hint block with dot 1")
+ .addOutputHatch("Hint block with dot 3")
+ .toolTipFinisher("Good Generator");
+ return tt;
+ }
+
+ private static final BigInteger[] storageWithCells;
+
+ static {
+ storageWithCells = new BigInteger[10];
+ final BigInteger baseStorage = BigInteger.valueOf(1_000_000);
+ final BigInteger storageMultiplier = BigInteger.valueOf(100);
+ BigInteger currentStorage = baseStorage;
+ for (int i = 0; i < 10; i++) {
+ storageWithCells[i] = currentStorage;
+ currentStorage = currentStorage.multiply(storageMultiplier);
+ }
+ }
+
+ public BigInteger calStorage(int meta) {
+ return storageWithCells[meta];
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack aStack) {
+ super.onRunningTick(aStack);
+ if (this.getBaseMetaTileEntity()
+ .isServerSide()) {
+ ++workTickCounter;
+ if (workTickCounter < 20) {
+ return true;
+ }
+ workTickCounter = 0;
+
+ List<FluidStack> tStore = getStoredFluids();
+ for (FluidStack tFluid : tStore) {
+ if (tFluid == null) continue;
+ if (isFluidLocked) {
+ if (mLockedFluid != null) {
+ if (!tFluid.isFluidEqual(mLockedFluid)) continue;;
+ } else {
+ mLockedFluid = tFluid.copy();
+ mLockedFluid.amount = 1;
+ }
+ }
+ if (mFluid == null || tFluid.isFluidEqual(mFluid)) {
+ if (mFluid == null) {
+ mFluid = tFluid.copy();
+ mFluid.amount = 1;
+ }
+ if (addFluid(tFluid.amount, true)) {
+ tFluid.amount = 0;
+ } else {
+ if (voidExcessEnabled) {
+ tFluid.amount = 0;
+ } else {
+ final BigInteger delta = mStorage.subtract(mStorageCurrent);
+ tFluid.amount -= delta.intValueExact();
+ }
+ mStorageCurrent = mStorage;
+ }
+ }
+ }
+
+ if (mStorageCurrent.compareTo(BigInteger.ZERO) <= 0) {
+ mFluid = null;
+ }
+
+ if (mFluid != null) {
+ // Try to drain 1% of the tank per tick, so 20% per second aka 1/5
+ int outputAmount = mStorageCurrent.divide(FIVE)
+ .min(MAX_INT_BIGINT)
+ .max(BigInteger.ONE)
+ .intValueExact();
+ final int originalOutputAmount = outputAmount;
+
+ for (final GT_MetaTileEntity_Hatch outputHatch : mOutputHatches) {
+ final FluidStack fluidInHatch = outputHatch.mFluid;
+
+ final int remainingHatchSpace;
+ if (fluidInHatch != null) {
+ if (fluidInHatch.isFluidEqual(mFluid)) {
+ remainingHatchSpace = outputHatch.getCapacity() - fluidInHatch.amount;
+ } else {
+ continue;
+ }
+ } else {
+ remainingHatchSpace = outputHatch.getCapacity();
+ }
+
+ final int amountToFillHatch = Math.min(remainingHatchSpace, outputAmount);
+ if (amountToFillHatch <= 0) {
+ continue;
+ }
+ final FluidStack fillStack = mFluid.copy();
+ fillStack.amount = amountToFillHatch;
+ final int transferredAmount = outputHatch.fill(fillStack, true);
+ outputAmount -= transferredAmount;
+ }
+
+ final int totalDrainedAmount = originalOutputAmount - outputAmount;
+ if (totalDrainedAmount > 0) {
+ mStorageCurrent = mStorageCurrent.subtract(BigInteger.valueOf(totalDrainedAmount));
+ if (mStorageCurrent.signum() < 0) {
+ throw new IllegalStateException(
+ "YOTTank drained beyond its fluid amount, indicating logic bug: " + mStorageCurrent);
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ structureBuild_EM(YOTTANK_BOTTOM, 2, 0, 0, stackSize, hintsOnly);
+ int height = stackSize.stackSize;
+ if (height > 15) height = 15;
+ structureBuild_EM(YOTTANK_TOP, 2, height + 2, 0, stackSize, hintsOnly);
+ while (height > 0) {
+ structureBuild_EM(YOTTANK_MID, 2, height, 0, stackSize, hintsOnly);
+ height--;
+ }
+ }
+
+ @Override
+ public boolean onSolderingToolRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ, ItemStack toolStack) {
+ if (side == getBaseMetaTileEntity().getFrontFacing()) {
+ voidExcessEnabled ^= true;
+ aPlayer.addChatMessage(
+ new ChatComponentTranslation(
+ voidExcessEnabled ? "yottank.chat.voidExcessEnabled" : "yottank.chat.voidExcessDisabled"));
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public boolean onWireCutterRightClick(ForgeDirection side, ForgeDirection wrenchingSide, EntityPlayer aPlayer,
+ float aX, float aY, float aZ, ItemStack toolStack) {
+ if (side == getBaseMetaTileEntity().getFrontFacing()) {
+ if (mLockedFluid == null) {
+ if (mFluid != null) {
+ mLockedFluid = mFluid;
+ aPlayer.addChatMessage(new ChatComponentTranslation("yottank.chat.1", getFluidName()));
+ } else {
+ aPlayer.addChatMessage(new ChatComponentTranslation("yottank.chat.2"));
+ }
+ isFluidLocked = true;
+ } else {
+ mLockedFluid = null;
+ isFluidLocked = false;
+ aPlayer.addChatMessage(new ChatComponentTranslation("yottank.chat.0"));
+ }
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public String[] getStructureDescription(ItemStack stackSize) {
+ return DescTextLocalization.addText("YOTTank.hint", 8);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) {
+ return new YottaFluidTank(this.mName);
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) {
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1537),
+ TextureFactory.of(textureFontOn), TextureFactory.builder()
+ .addIcon(textureFontOn_Glow)
+ .glow()
+ .build() };
+ else return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1537),
+ TextureFactory.of(textureFontOff), TextureFactory.builder()
+ .addIcon(textureFontOff_Glow)
+ .glow()
+ .build() };
+ } else return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(1537) };
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ int built = 0;
+ built += survivialBuildPiece(YOTTANK_BOTTOM, stackSize, 2, 0, 0, elementBudget, env, false, true);
+ int height = stackSize.stackSize;
+ if (height > 15) height = 15;
+ built += survivialBuildPiece(YOTTANK_TOP, stackSize, 2, height + 2, 0, elementBudget - built, env, false, true);
+ while (height > 0) {
+ built += survivialBuildPiece(YOTTANK_MID, stackSize, 2, height, 0, elementBudget - built, env, false, true);
+ height--;
+ }
+ return built;
+ }
+
+ @Override
+ protected boolean shouldDisplayCheckRecipeResult() {
+ return false;
+ }
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ super.drawTexts(screenElements, inventorySlot);
+
+ screenElements
+ .widget(
+ new TextWidget().setStringSupplier(
+ () -> StatCollector.translateToLocal("gui.YOTTank.0") + " " + numberFormat.format(mStorage) + " L")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
+ .widget(new FakeSyncWidget.BigIntegerSyncer(() -> mStorage, val -> mStorage = val))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(() -> StatCollector.translateToLocal("gui.YOTTank.1") + " " + getFluidName())
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
+ .widget(new FakeSyncWidget.FluidStackSyncer(() -> mFluid, val -> mFluid = val))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> StatCollector.translateToLocal("gui.YOTTank.2") + " "
+ + numberFormat.format(mStorageCurrent)
+ + " L")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
+ .widget(new FakeSyncWidget.BigIntegerSyncer(() -> mStorageCurrent, val -> mStorageCurrent = val))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> StatCollector.translateToLocal("gui.YOTTank.3") + " " + getLockedFluidName())
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
+ .widget(new FakeSyncWidget.FluidStackSyncer(() -> mLockedFluid, val -> mLockedFluid = val))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> isFluidLocked, val -> isFluidLocked = val))
+ .widget(new FakeSyncWidget.BooleanSyncer(() -> voidExcessEnabled, val -> voidExcessEnabled = val));
+ }
+
+ @Override
+ protected ButtonWidget createSafeVoidButton() {
+ return (ButtonWidget) new ButtonWidget().setOnClick((clickData, widget) -> {
+ TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click");
+ voidExcessEnabled = !voidExcessEnabled;
+ })
+ .setPlayClickSound(false)
+ .setBackground(() -> {
+ List<UITexture> ret = new ArrayList<>();
+ ret.add(TecTechUITextures.BUTTON_STANDARD_16x16);
+ ret.add(
+ voidExcessEnabled ? TecTechUITextures.OVERLAY_BUTTON_SAFE_VOID_ON
+ : TecTechUITextures.OVERLAY_BUTTON_SAFE_VOID_OFF);
+ return ret.toArray(new IDrawable[0]);
+ })
+ .setPos(174, doesBindPlayerInventory() ? 132 : 156)
+ .setSize(16, 16)
+ .addTooltip(StatCollector.translateToLocal("gui.YOTTank.button.void"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY);
+ }
+
+ @Override
+ protected ButtonWidget createPowerPassButton() {
+ return (ButtonWidget) new ButtonWidget().setOnClick((clickData, widget) -> {
+ TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click");
+ isFluidLocked = !isFluidLocked;
+ if (!widget.getContext()
+ .isClient()) mLockedFluid = isFluidLocked ? mFluid : null;
+ })
+ .setPlayClickSound(false)
+ .setBackground(() -> {
+ List<UITexture> ret = new ArrayList<>();
+ ret.add(TecTechUITextures.BUTTON_STANDARD_16x16);
+ ret.add(isFluidLocked ? GG_UITextures.OVERLAY_BUTTON_LOCK_ON : GG_UITextures.OVERLAY_BUTTON_LOCK_OFF);
+ return ret.toArray(new IDrawable[0]);
+ })
+ .setPos(174, doesBindPlayerInventory() ? 116 : 140)
+ .setSize(16, 16)
+ .addTooltip(StatCollector.translateToLocal("gui.YOTTank.button.locking"))
+ .setTooltipShowUpDelay(TOOLTIP_DELAY);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/base/GT_MetaTileEntity_LargeTurbineBase.java b/src/main/java/goodgenerator/blocks/tileEntity/base/GT_MetaTileEntity_LargeTurbineBase.java
new file mode 100644
index 0000000000..3df71aa25a
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/base/GT_MetaTileEntity_LargeTurbineBase.java
@@ -0,0 +1,345 @@
+// copied from gregtech.common.tileentities.machines.multi.GT_MetaTileEntity_LargeTurbine
+// The origin one in gt made the abstract method private so i can't imp it.
+package goodgenerator.blocks.tileEntity.base;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.lazy;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static gregtech.api.enums.GT_HatchElement.*;
+import static gregtech.api.util.GT_StructureUtility.*;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.ArrayList;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.StatCollector;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.IStructureElementCheckOnly;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.items.GT_MetaGenerated_Tool;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_EnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Dynamo;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch_Muffler;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.items.GT_MetaGenerated_Tool_01;
+
+public abstract class GT_MetaTileEntity_LargeTurbineBase extends
+ GT_MetaTileEntity_EnhancedMultiBlockBase<GT_MetaTileEntity_LargeTurbineBase> implements ISurvivalConstructable {
+
+ private static final String STRUCTURE_PIECE_MAIN = "main";
+ private static final ClassValue<IStructureDefinition<GT_MetaTileEntity_LargeTurbineBase>> STRUCTURE_DEFINITION = new ClassValue<IStructureDefinition<GT_MetaTileEntity_LargeTurbineBase>>() {
+
+ @Override
+ protected IStructureDefinition<GT_MetaTileEntity_LargeTurbineBase> computeValue(Class<?> type) {
+ return StructureDefinition.<GT_MetaTileEntity_LargeTurbineBase>builder()
+ .addShape(
+ STRUCTURE_PIECE_MAIN,
+ transpose(
+ new String[][] { { " ", "xxxxx", "xxxxx", "xxxxx", "xxxxx", },
+ { " --- ", "xcccx", "xchcx", "xchcx", "xcccx", },
+ { " --- ", "xc~cx", "xh-hx", "xh-hx", "xcdcx", },
+ { " --- ", "xcccx", "xchcx", "xchcx", "xcccx", },
+ { " ", "xxxxx", "xxxxx", "xxxxx", "xxxxx", }, }))
+ .addElement('c', lazy(t -> ofBlock(t.getCasingBlock(), t.getCasingMeta())))
+ .addElement('d', lazy(t -> Dynamo.newAny(t.getCasingTextureIndex(), 1)))
+ .addElement(
+ 'h',
+ lazy(
+ t -> buildHatchAdder(GT_MetaTileEntity_LargeTurbineBase.class)
+ .atLeast(Maintenance, InputHatch, OutputHatch, OutputBus, InputBus, Muffler)
+ .casingIndex(t.getCasingTextureIndex())
+ .dot(2)
+ .buildAndChain(t.getCasingBlock(), t.getCasingMeta())))
+ .addElement(
+ 'x',
+ (IStructureElementCheckOnly<GT_MetaTileEntity_LargeTurbineBase>) (aContext, aWorld, aX, aY, aZ) -> {
+ TileEntity tTile = aWorld.getTileEntity(aX, aY, aZ);
+ return !(tTile instanceof IGregTechTileEntity) || !(((IGregTechTileEntity) tTile)
+ .getMetaTileEntity() instanceof GT_MetaTileEntity_LargeTurbineBase);
+ })
+ .build();
+ }
+ };
+
+ protected int baseEff = 0;
+ protected int optFlow = 0;
+ protected double realOptFlow = 0;
+ protected int storedFluid = 0;
+ protected int counter = 0;
+ protected boolean looseFit = false;
+ protected long maxPower = 0;
+
+ public GT_MetaTileEntity_LargeTurbineBase(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public GT_MetaTileEntity_LargeTurbineBase(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return getMaxEfficiency(aStack) > 0;
+ }
+
+ @Override
+ public IStructureDefinition<GT_MetaTileEntity_LargeTurbineBase> getStructureDefinition() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ maxPower = 0;
+ if (checkPiece(STRUCTURE_PIECE_MAIN, 2, 2, 1) && mMaintenanceHatches.size() == 1
+ && mMufflerHatches.isEmpty() == (getPollutionPerTick(null) == 0)) {
+ maxPower = getMaximumOutput();
+ return true;
+ }
+ return false;
+ }
+
+ public abstract Block getCasingBlock();
+
+ public abstract int getCasingMeta();
+
+ public abstract int getCasingTextureIndex();
+
+ @Override
+ public boolean addToMachineList(IGregTechTileEntity tTileEntity, int aBaseCasingIndex) {
+ return addMaintenanceToMachineList(tTileEntity, getCasingTextureIndex())
+ || addInputToMachineList(tTileEntity, getCasingTextureIndex())
+ || addOutputToMachineList(tTileEntity, getCasingTextureIndex())
+ || addMufflerToMachineList(tTileEntity, getCasingTextureIndex());
+ }
+
+ @Override
+ public void saveNBTData(NBTTagCompound aNBT) {
+ super.saveNBTData(aNBT);
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ }
+
+ @Override
+ public @NotNull CheckRecipeResult checkProcessing() {
+ ItemStack controllerSlot = getControllerSlot();
+ if ((counter & 7) == 0
+ && (controllerSlot == null || !(controllerSlot.getItem() instanceof GT_MetaGenerated_Tool)
+ || controllerSlot.getItemDamage() < 170
+ || controllerSlot.getItemDamage() > 179)) {
+ stopMachine();
+ return CheckRecipeResultRegistry.NO_TURBINE_FOUND;
+ }
+ ArrayList<FluidStack> tFluids = getStoredFluids();
+ if (tFluids.size() > 0) {
+ if (baseEff == 0 || optFlow == 0
+ || counter >= 512
+ || this.getBaseMetaTileEntity()
+ .hasWorkJustBeenEnabled()
+ || this.getBaseMetaTileEntity()
+ .hasInventoryBeenModified()) {
+ counter = 0;
+ baseEff = GT_Utility.safeInt(
+ (long) ((5F
+ + ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolCombatDamage(controllerSlot))
+ * 1000F));
+ optFlow = GT_Utility.safeInt(
+ (long) Math.max(
+ Float.MIN_NORMAL,
+ ((GT_MetaGenerated_Tool) controllerSlot.getItem()).getToolStats(controllerSlot)
+ .getSpeedMultiplier() * GT_MetaGenerated_Tool.getPrimaryMaterial(controllerSlot).mToolSpeed
+ * 50));
+ if (optFlow <= 0 || baseEff <= 0) {
+ stopMachine(); // in case the turbine got removed
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ }
+ } else {
+ counter++;
+ }
+ }
+
+ int newPower = fluidIntoPower(tFluids, optFlow, baseEff); // How much the turbine should be producing with this
+ // flow
+ int difference = newPower - this.mEUt; // difference between current output and new output
+
+ // Magic numbers: can always change by at least 10 eu/t, but otherwise by at most 1 percent of the difference in
+ // power level (per tick)
+ // This is how much the turbine can actually change during this tick
+ int maxChangeAllowed = Math.max(10, GT_Utility.safeInt((long) Math.abs(difference) / 100));
+
+ if (Math.abs(difference) > maxChangeAllowed) { // If this difference is too big, use the maximum allowed change
+ int change = maxChangeAllowed * (difference > 0 ? 1 : -1); // Make the change positive or negative.
+ this.mEUt += change; // Apply the change
+ } else this.mEUt = newPower;
+
+ if (this.mEUt <= 0) {
+ // stopMachine();
+ this.mEUt = 0;
+ this.mEfficiency = 0;
+ return CheckRecipeResultRegistry.NO_FUEL_FOUND;
+ } else {
+ this.mMaxProgresstime = 1;
+ this.mEfficiencyIncrease = 10;
+ // Overvoltage is handled inside the MultiBlockBase when pushing out to dynamos. no need to do it here.
+ return CheckRecipeResultRegistry.GENERATING;
+ }
+ }
+
+ public abstract int fluidIntoPower(ArrayList<FluidStack> aFluids, int aOptFlow, int aBaseEff);
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 1;
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ if (GT_Utility.isStackInvalid(aStack)) {
+ return 0;
+ }
+ if (aStack.getItem() instanceof GT_MetaGenerated_Tool_01) {
+ return 10000;
+ }
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return true;
+ }
+
+ public long getMaximumOutput() {
+ long aTotal = 0;
+ for (GT_MetaTileEntity_Hatch_Dynamo aDynamo : filterValidMTEs(mDynamoHatches)) {
+ long aVoltage = aDynamo.maxEUOutput();
+ aTotal = aDynamo.maxAmperesOut() * aVoltage;
+ break;
+ }
+ return aTotal;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ int mPollutionReduction = 0;
+ for (GT_MetaTileEntity_Hatch_Muffler tHatch : filterValidMTEs(mMufflerHatches)) {
+ mPollutionReduction = Math.max(tHatch.calculatePollutionReduction(100), mPollutionReduction);
+ }
+
+ String tRunning = mMaxProgresstime > 0
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.running.true")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.running.false")
+ + EnumChatFormatting.RESET;
+ String tMaintainance = getIdealStatus() == getRepairStatus()
+ ? EnumChatFormatting.GREEN + StatCollector.translateToLocal("GT5U.turbine.maintenance.false")
+ + EnumChatFormatting.RESET
+ : EnumChatFormatting.RED + StatCollector.translateToLocal("GT5U.turbine.maintenance.true")
+ + EnumChatFormatting.RESET;
+ int tDura = 0;
+
+ if (mInventory[1] != null && mInventory[1].getItem() instanceof GT_MetaGenerated_Tool_01) {
+ tDura = GT_Utility.safeInt(
+ (long) (100.0f / GT_MetaGenerated_Tool.getToolMaxDamage(mInventory[1])
+ * (GT_MetaGenerated_Tool.getToolDamage(mInventory[1])) + 1));
+ }
+
+ long storedEnergy = 0;
+ long maxEnergy = 0;
+ for (GT_MetaTileEntity_Hatch_Dynamo tHatch : filterValidMTEs(mDynamoHatches)) {
+ storedEnergy += tHatch.getBaseMetaTileEntity()
+ .getStoredEU();
+ maxEnergy += tHatch.getBaseMetaTileEntity()
+ .getEUCapacity();
+ }
+ String[] ret = new String[] {
+ // 8 Lines available for information panels
+ tRunning + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(mEUt)
+ + EnumChatFormatting.RESET
+ + " EU/t", /* 1 */
+ tMaintainance, /* 2 */
+ StatCollector.translateToLocal("GT5U.turbine.efficiency") + ": "
+ + EnumChatFormatting.YELLOW
+ + (mEfficiency / 100F)
+ + EnumChatFormatting.RESET
+ + "%", /* 2 */
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(storedEnergy)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + /* 3 */ EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEnergy)
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.turbine.flow") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(GT_Utility.safeInt((long) realOptFlow))
+ + EnumChatFormatting.RESET
+ + " L/t"
+ + /* 4 */ EnumChatFormatting.YELLOW
+ + " ("
+ + (looseFit ? StatCollector.translateToLocal("GT5U.turbine.loose")
+ : StatCollector.translateToLocal("GT5U.turbine.tight"))
+ + ")", /* 5 */
+ StatCollector.translateToLocal("GT5U.turbine.fuel") + ": "
+ + EnumChatFormatting.GOLD
+ + GT_Utility.formatNumbers(storedFluid)
+ + EnumChatFormatting.RESET
+ + "L", /* 6 */
+ StatCollector.translateToLocal(
+ "GT5U.turbine.dmg") + ": " + EnumChatFormatting.RED + tDura + EnumChatFormatting.RESET + "%", /* 7 */
+ StatCollector.translateToLocal("GT5U.multiblock.pollution") + ": "
+ + EnumChatFormatting.GREEN
+ + mPollutionReduction
+ + EnumChatFormatting.RESET
+ + " %" /* 8 */
+ };
+ if (!this.getClass()
+ .getName()
+ .contains("Steam"))
+ ret[4] = StatCollector.translateToLocal("GT5U.turbine.flow") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.safeInt((long) realOptFlow)
+ + EnumChatFormatting.RESET
+ + " L/t";
+ return ret;
+ }
+
+ public boolean hasTurbine() {
+ return this.getMaxEfficiency(mInventory[1]) > 0;
+ }
+
+ @Override
+ public boolean isGivingInformation() {
+ return true;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ buildPiece(STRUCTURE_PIECE_MAIN, stackSize, hintsOnly, 2, 2, 1);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ return survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 2, 2, 1, elementBudget, env, false, true);
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/base/GT_MetaTileEntity_TooltipMultiBlockBase_EM.java b/src/main/java/goodgenerator/blocks/tileEntity/base/GT_MetaTileEntity_TooltipMultiBlockBase_EM.java
new file mode 100644
index 0000000000..010dc1db88
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/base/GT_MetaTileEntity_TooltipMultiBlockBase_EM.java
@@ -0,0 +1,62 @@
+package goodgenerator.blocks.tileEntity.base;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import net.minecraft.item.ItemStack;
+
+import org.lwjgl.input.Keyboard;
+
+import com.github.technus.tectech.thing.metaTileEntity.multi.base.GT_MetaTileEntity_MultiblockBase_EM;
+
+import gregtech.api.interfaces.ISecondaryDescribable;
+import gregtech.api.util.GT_Multiblock_Tooltip_Builder;
+
+public abstract class GT_MetaTileEntity_TooltipMultiBlockBase_EM extends GT_MetaTileEntity_MultiblockBase_EM
+ implements ISecondaryDescribable {
+
+ private static final Map<Integer, GT_Multiblock_Tooltip_Builder> tooltips = new ConcurrentHashMap<>();
+
+ protected GT_MetaTileEntity_TooltipMultiBlockBase_EM(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ protected GT_MetaTileEntity_TooltipMultiBlockBase_EM(String aName) {
+ super(aName);
+ }
+
+ protected GT_Multiblock_Tooltip_Builder getTooltip() {
+ int tId = getBaseMetaTileEntity().getMetaTileID();
+ GT_Multiblock_Tooltip_Builder tooltip = tooltips.get(tId);
+ if (tooltip == null) {
+ tooltip = createTooltip();
+ tooltips.put(tId, tooltip);
+ }
+ return tooltip;
+ }
+
+ protected abstract GT_Multiblock_Tooltip_Builder createTooltip();
+
+ @Override
+ public String[] getDescription() {
+ return getCurrentDescription();
+ }
+
+ @Override
+ public boolean isDisplaySecondaryDescription() {
+ return Keyboard.isKeyDown(Keyboard.KEY_LSHIFT);
+ }
+
+ public String[] getPrimaryDescription() {
+ return getTooltip().getInformation();
+ }
+
+ public String[] getSecondaryDescription() {
+ return getTooltip().getStructureInformation();
+ }
+
+ @Override
+ public int getPollutionPerTick(ItemStack itemStack) {
+ return getPollutionPerSecond(itemStack) / 20;
+ }
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputer.java b/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputer.java
new file mode 100644
index 0000000000..5608d19ae4
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputer.java
@@ -0,0 +1,733 @@
+package goodgenerator.blocks.tileEntity.base;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.*;
+import static gregtech.api.enums.Textures.BlockIcons.*;
+import static gregtech.api.util.GT_StructureUtility.filterByMTETier;
+import static gregtech.api.util.GT_StructureUtility.ofFrame;
+import static gregtech.api.util.GT_Utility.filterValidMTEs;
+
+import java.util.List;
+
+import javax.annotation.Nullable;
+
+import net.minecraft.block.Block;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.tileentity.TileEntity;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.ResourceLocation;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraftforge.common.util.ForgeDirection;
+import net.minecraftforge.fluids.FluidStack;
+
+import org.jetbrains.annotations.NotNull;
+
+import com.github.technus.tectech.thing.metaTileEntity.hatch.GT_MetaTileEntity_Hatch_EnergyMulti;
+import com.gtnewhorizon.structurelib.alignment.constructable.IConstructable;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.ISurvivalBuildEnvironment;
+import com.gtnewhorizon.structurelib.structure.StructureDefinition;
+import com.gtnewhorizons.modularui.api.NumberFormatMUI;
+import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+import com.gtnewhorizons.modularui.common.widget.SlotWidget;
+import com.gtnewhorizons.modularui.common.widget.TextWidget;
+
+import gregtech.api.enums.GT_HatchElement;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.SoundResource;
+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.interfaces.tileentity.IOverclockDescriptionProvider;
+import gregtech.api.logic.ProcessingLogic;
+import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
+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_Output;
+import gregtech.api.objects.GT_ChunkManager;
+import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.objects.overclockdescriber.FusionOverclockDescriber;
+import gregtech.api.objects.overclockdescriber.OverclockDescriber;
+import gregtech.api.recipe.RecipeMap;
+import gregtech.api.recipe.RecipeMaps;
+import gregtech.api.recipe.check.CheckRecipeResult;
+import gregtech.api.recipe.check.CheckRecipeResultRegistry;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GT_HatchElementBuilder;
+import gregtech.api.util.GT_OverclockCalculator;
+import gregtech.api.util.GT_ParallelHelper;
+import gregtech.api.util.GT_Recipe;
+import gregtech.api.util.GT_Utility;
+import gregtech.common.tileentities.machines.IDualInputHatch;
+
+public abstract class LargeFusionComputer extends GT_MetaTileEntity_TooltipMultiBlockBase_EM
+ implements IConstructable, ISurvivalConstructable, IOverclockDescriptionProvider {
+
+ public static final String MAIN_NAME = "largeFusion";
+ public static final int M = 1_000_000;
+ private boolean isLoadedChunk;
+ public GT_Recipe mLastRecipe;
+ public int para;
+ protected OverclockDescriber overclockDescriber;
+ private static final ClassValue<IStructureDefinition<LargeFusionComputer>> STRUCTURE_DEFINITION = new ClassValue<IStructureDefinition<LargeFusionComputer>>() {
+
+ @Override
+ protected IStructureDefinition<LargeFusionComputer> computeValue(Class<?> type) {
+ return StructureDefinition.<LargeFusionComputer>builder()
+ .addShape(MAIN_NAME, transpose(new String[][] { L0, L1, L2, L3, L2, L1, L0 }))
+ .addElement('H', lazy(x -> ofBlock(x.getCoilBlock(), x.getCoilMeta())))
+ .addElement('C', lazy(x -> ofBlock(x.getCasingBlock(), x.getCasingMeta())))
+ .addElement('B', lazy(x -> ofBlock(x.getGlassBlock(), x.getGlassMeta())))
+ .addElement(
+ 'I',
+ lazy(
+ x -> GT_HatchElementBuilder.<LargeFusionComputer>builder()
+ .atLeast(
+ GT_HatchElement.InputHatch.or(GT_HatchElement.InputBus),
+ GT_HatchElement.OutputHatch)
+ .adder(LargeFusionComputer::addFluidIO)
+ .casingIndex(x.textureIndex())
+ .dot(1)
+ .hatchItemFilterAnd(x2 -> filterByMTETier(x2.hatchTier(), Integer.MAX_VALUE))
+ .buildAndChain(x.getGlassBlock(), x.getGlassMeta())))
+ .addElement(
+ 'E',
+ lazy(
+ x -> GT_HatchElementBuilder.<LargeFusionComputer>builder()
+ .anyOf(HatchElement.EnergyMulti.or(GT_HatchElement.Energy))
+ .adder(LargeFusionComputer::addEnergyInjector)
+ .casingIndex(x.textureIndex())
+ .hatchItemFilterAnd(x2 -> filterByMTETier(x2.hatchTier(), Integer.MAX_VALUE))
+ .dot(2)
+ .buildAndChain(x.getCasingBlock(), x.getCasingMeta())))
+ .addElement('F', lazy(x -> ofFrame(x.getFrameBox())))
+ .build();
+ }
+ };
+
+ static {
+ Textures.BlockIcons.setCasingTextureForId(
+ 52,
+ TextureFactory.of(
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW)
+ .extFacing()
+ .build(),
+ TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS_YELLOW_GLOW)
+ .extFacing()
+ .glow()
+ .build()));
+ }
+
+ public LargeFusionComputer(String name) {
+ super(name);
+ useLongPower = true;
+ this.overclockDescriber = createOverclockDescriber();
+ }
+
+ public LargeFusionComputer(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ useLongPower = true;
+ this.overclockDescriber = createOverclockDescriber();
+ }
+
+ protected OverclockDescriber createOverclockDescriber() {
+ return new FusionOverclockDescriber((byte) tier(), capableStartupCanonical());
+ }
+
+ @Nullable
+ @Override
+ public OverclockDescriber getOverclockDescriber() {
+ return overclockDescriber;
+ }
+
+ public abstract int tier();
+
+ @Override
+ public long maxEUStore() {
+ return capableStartupCanonical() * (Math.min(32, this.mEnergyHatches.size() + this.eEnergyMulti.size())) / 32L;
+ }
+
+ /**
+ * Unlike {@link #maxEUStore()}, this provides theoretical limit of startup EU, without considering the amount of
+ * hatches nor the room for extra energy. Intended for simulation.
+ */
+ public abstract long capableStartupCanonical();
+
+ public abstract Block getCasingBlock();
+
+ public abstract int getCasingMeta();
+
+ public abstract Block getCoilBlock();
+
+ public abstract int getCoilMeta();
+
+ public abstract Block getGlassBlock();
+
+ public abstract int getGlassMeta();
+
+ public abstract int hatchTier();
+
+ public abstract Materials getFrameBox();
+
+ public abstract int getMaxPara();
+
+ public abstract int extraPara(int startEnergy);
+
+ public int textureIndex() {
+ return 53;
+ }
+
+ public abstract ITexture getTextureOverlay();
+
+ @Override
+ public boolean allowCoverOnSide(ForgeDirection side, GT_ItemStack aStack) {
+ return side != getBaseMetaTileEntity().getFrontFacing();
+ }
+
+ @Override
+ public void loadNBTData(NBTTagCompound aNBT) {
+ super.loadNBTData(aNBT);
+ // Migration code
+ if (lEUt > 0) {
+ lEUt = -lEUt;
+ }
+ }
+
+ @Override
+ public boolean checkMachine_EM(IGregTechTileEntity aBaseMetaTileEntity, ItemStack aStack) {
+ this.eEnergyMulti.clear();
+ if (structureCheck_EM(MAIN_NAME, 23, 3, 40) && mInputHatches.size() + mDualInputHatches.size() != 0
+ && !mOutputHatches.isEmpty()
+ && (mEnergyHatches.size() + eEnergyMulti.size()) != 0) {
+ fixAllIssue();
+ return true;
+ }
+ return false;
+ }
+
+ public void fixAllIssue() {
+ mWrench = true;
+ mScrewdriver = true;
+ mSoftHammer = true;
+ mHardHammer = true;
+ mSolderingTool = true;
+ mCrowbar = true;
+ }
+
+ @Override
+ public void construct(ItemStack itemStack, boolean b) {
+ structureBuild_EM(MAIN_NAME, 23, 3, 40, itemStack, b);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) {
+ if (mMachine) return -1;
+ int realBudget = elementBudget >= 200 ? elementBudget : Math.min(200, elementBudget * 5);
+ return survivialBuildPiece(MAIN_NAME, stackSize, 23, 3, 40, realBudget, env, false, true);
+ }
+
+ @Override
+ public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) {
+ if (aBaseMetaTileEntity.isServerSide() && !aBaseMetaTileEntity.isAllowedToWork()) {
+ // if machine has stopped, stop chunkloading
+ GT_ChunkManager.releaseTicket((TileEntity) aBaseMetaTileEntity);
+ this.isLoadedChunk = false;
+ } else if (aBaseMetaTileEntity.isServerSide() && aBaseMetaTileEntity.isAllowedToWork() && !this.isLoadedChunk) {
+ // load a 3x3 area when machine is running
+ GT_ChunkManager.releaseTicket((TileEntity) aBaseMetaTileEntity);
+ int offX = aBaseMetaTileEntity.getFrontFacing().offsetX;
+ int offZ = aBaseMetaTileEntity.getFrontFacing().offsetZ;
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() + offX, getChunkZ() + offZ));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() + 1 + offX, getChunkZ() + 1 + offZ));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() + 1 + offX, getChunkZ() + offZ));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() + 1 + offX, getChunkZ() - 1 + offZ));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() - 1 + offX, getChunkZ() + 1 + offZ));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() - 1 + offX, getChunkZ() + offZ));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() - 1 + offX, getChunkZ() - 1 + offZ));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() + offX, getChunkZ() + 1 + offZ));
+ GT_ChunkManager.requestChunkLoad(
+ (TileEntity) aBaseMetaTileEntity,
+ new ChunkCoordIntPair(getChunkX() + offX, getChunkZ() - 1 + offZ));
+ this.isLoadedChunk = true;
+ }
+
+ if (aBaseMetaTileEntity.isServerSide()) {
+ if (aTick % 400 == 0) fixAllIssue();
+ if (mEfficiency < 0) mEfficiency = 0;
+ if (mRunningOnLoad && checkMachine(aBaseMetaTileEntity, mInventory[1])) {
+ checkRecipe();
+ }
+ if (mUpdated) {
+ mUpdate = 50;
+ mUpdated = false;
+ }
+ if (--mUpdate == 0 || --mStartUpCheck == 0
+ || cyclicUpdate_EM()
+ || aBaseMetaTileEntity.hasWorkJustBeenEnabled()) {
+ if (mUpdate <= -1000) {
+ mUpdate = 5000;
+ }
+ checkStructure(true, aBaseMetaTileEntity);
+ }
+ if (mStartUpCheck < 0) {
+ if (mMachine) {
+ if (aBaseMetaTileEntity.getStoredEU() <= 0 && mMaxProgresstime > 0) {
+ criticalStopMachine();
+ }
+
+ long energyLimit = getSingleHatchPower();
+ List<GT_MetaTileEntity_Hatch> hatches = getExoticAndNormalEnergyHatchList();
+ for (GT_MetaTileEntity_Hatch hatch : filterValidMTEs(hatches)) {
+ long consumableEnergy = Math.min(hatch.getEUVar(), energyLimit);
+ long receivedEnergy = Math
+ .min(consumableEnergy, maxEUStore() - aBaseMetaTileEntity.getStoredEU());
+ if (receivedEnergy > 0) {
+ hatch.getBaseMetaTileEntity()
+ .decreaseStoredEnergyUnits(receivedEnergy, false);
+ aBaseMetaTileEntity.increaseStoredEnergyUnits(receivedEnergy, true);
+ }
+ }
+
+ if (mMaxProgresstime > 0) {
+ this.getBaseMetaTileEntity()
+ .decreaseStoredEnergyUnits(-lEUt, true);
+ if (mMaxProgresstime > 0 && ++mProgresstime >= mMaxProgresstime) {
+ if (mOutputItems != null)
+ for (ItemStack tStack : mOutputItems) if (tStack != null) addOutput(tStack);
+ if (mOutputFluids != null)
+ for (FluidStack tStack : mOutputFluids) if (tStack != null) addOutput(tStack);
+ mEfficiency = Math
+ .max(0, Math.min(mEfficiency + mEfficiencyIncrease, getMaxEfficiency(mInventory[1])));
+ mOutputItems = null;
+ mOutputFluids = null;
+ mProgresstime = 0;
+ mMaxProgresstime = 0;
+ mEfficiencyIncrease = 0;
+ para = 0;
+ if (aBaseMetaTileEntity.isAllowedToWork()) checkRecipe();
+ }
+ } else {
+ if (aTick % 100 == 0 || aBaseMetaTileEntity.hasWorkJustBeenEnabled()
+ || aBaseMetaTileEntity.hasInventoryBeenModified()) {
+ turnCasingActive(mMaxProgresstime > 0);
+ if (aBaseMetaTileEntity.isAllowedToWork()) {
+ if (checkRecipe()) {
+ if (aBaseMetaTileEntity.getStoredEU()
+ < this.mLastRecipe.mSpecialValue + this.lEUt) {
+ mMaxProgresstime = 0;
+ turnCasingActive(false);
+ criticalStopMachine();
+ }
+ getBaseMetaTileEntity()
+ .decreaseStoredEnergyUnits(this.mLastRecipe.mSpecialValue + this.lEUt, false);
+ }
+ }
+ if (mMaxProgresstime <= 0) mEfficiency = Math.max(0, mEfficiency - 1000);
+ }
+ }
+ } else {
+ turnCasingActive(false);
+ this.mLastRecipe = null;
+ stopMachine();
+ }
+ }
+ aBaseMetaTileEntity
+ .setErrorDisplayID((aBaseMetaTileEntity.getErrorDisplayID() & ~127) | (mMachine ? 0 : 64));
+ aBaseMetaTileEntity.setActive(mMaxProgresstime > 0);
+ } else {
+ soundMagic(getActivitySound());
+ }
+ }
+
+ /**
+ * @return The power one hatch can deliver to the reactor
+ */
+ protected long getSingleHatchPower() {
+ return GT_Values.V[tier()] * getMaxPara() * extraPara(100) / 32;
+ }
+
+ public boolean turnCasingActive(boolean status) {
+ if (this.mEnergyHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Energy hatch : this.mEnergyHatches) {
+ hatch.updateTexture(status ? 52 : 53);
+ }
+ }
+ if (this.eEnergyMulti != null) {
+ for (GT_MetaTileEntity_Hatch_EnergyMulti hatch : this.eEnergyMulti) {
+ hatch.updateTexture(status ? 52 : 53);
+ }
+ }
+ if (this.mOutputHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Output hatch : this.mOutputHatches) {
+ hatch.updateTexture(status ? 52 : 53);
+ }
+ }
+ if (this.mInputHatches != null) {
+ for (GT_MetaTileEntity_Hatch_Input hatch : this.mInputHatches) {
+ hatch.updateTexture(status ? 52 : 53);
+ }
+ }
+ if (this.mDualInputHatches != null) {
+ for (IDualInputHatch hatch : this.mDualInputHatches) {
+ hatch.updateTexture(status ? 52 : 53);
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing,
+ int colorIndex, boolean aActive, boolean aRedstone) {
+ if (side == facing) return new ITexture[] { TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS)
+ .extFacing()
+ .build(), getTextureOverlay() };
+ if (aActive) return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(52) };
+ return new ITexture[] { TextureFactory.builder()
+ .addIcon(MACHINE_CASING_FUSION_GLASS)
+ .extFacing()
+ .build() };
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack aStack) {
+ return true;
+ }
+
+ @Override
+ public void onMachineBlockUpdate() {
+ mUpdate = 100;
+ }
+
+ @Override
+ public RecipeMap<?> getRecipeMap() {
+ return RecipeMaps.fusionRecipes;
+ }
+
+ @Override
+ public int getRecipeCatalystPriority() {
+ return -2;
+ }
+
+ @Override
+ protected ProcessingLogic createProcessingLogic() {
+ return new ProcessingLogic() {
+
+ @NotNull
+ @Override
+ protected GT_ParallelHelper createParallelHelper(@NotNull GT_Recipe recipe) {
+ // When the fusion first loads and is still processing, it does the recipe check without consuming.
+ return super.createParallelHelper(recipe).setConsumption(!mRunningOnLoad);
+ }
+
+ @NotNull
+ @Override
+ protected GT_OverclockCalculator createOverclockCalculator(@NotNull GT_Recipe recipe) {
+ return overclockDescriber.createCalculator(super.createOverclockCalculator(recipe), recipe);
+ }
+
+ @NotNull
+ @Override
+ protected CheckRecipeResult validateRecipe(@NotNull GT_Recipe recipe) {
+ if (!mRunningOnLoad) {
+ if (recipe.mSpecialValue > maxEUStore()) {
+ return CheckRecipeResultRegistry.insufficientStartupPower(recipe.mSpecialValue);
+ }
+ if (recipe.mEUt > GT_Values.V[tier()]) {
+ return CheckRecipeResultRegistry.insufficientPower(recipe.mEUt);
+ }
+ }
+ maxParallel = getMaxPara() * extraPara(recipe.mSpecialValue);
+ return CheckRecipeResultRegistry.SUCCESSFUL;
+ }
+
+ @NotNull
+ @Override
+ public CheckRecipeResult process() {
+ CheckRecipeResult result = super.process();
+ if (mRunningOnLoad) mRunningOnLoad = false;
+ turnCasingActive(result.wasSuccessful());
+ if (result.wasSuccessful()) {
+ mLastRecipe = lastRecipe;
+ } else {
+ mLastRecipe = null;
+ }
+ para = getCurrentParallels();
+ return result;
+ }
+ };
+ }
+
+ @Override
+ protected void setProcessingLogicPower(ProcessingLogic logic) {
+ logic.setAvailableVoltage(GT_Values.V[tier()]);
+ logic.setAvailableAmperage(getSingleHatchPower() * 32 / GT_Values.V[tier()]);
+ }
+
+ @Override
+ public void onRemoval() {
+ if (this.isLoadedChunk) GT_ChunkManager.releaseTicket((TileEntity) getBaseMetaTileEntity());
+ super.onRemoval();
+ }
+
+ public int getChunkX() {
+ return getBaseMetaTileEntity().getXCoord() >> 4;
+ }
+
+ public int getChunkZ() {
+ return getBaseMetaTileEntity().getZCoord() >> 4;
+ }
+
+ private boolean addEnergyInjector(IGregTechTileEntity aBaseMetaTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = aBaseMetaTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Energy tHatch) {
+ if (tHatch.getTierForStructure() < hatchTier()) return false;
+ tHatch.updateTexture(aBaseCasingIndex);
+ return mEnergyHatches.add(tHatch);
+ } else if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_EnergyMulti tHatch) {
+ if (tHatch.getTierForStructure() < hatchTier()) return false;
+ tHatch.updateTexture(aBaseCasingIndex);
+ return eEnergyMulti.add(tHatch);
+ }
+ return false;
+ }
+
+ private boolean addFluidIO(IGregTechTileEntity aBaseMetaTileEntity, int aBaseCasingIndex) {
+ IMetaTileEntity aMetaTileEntity = aBaseMetaTileEntity.getMetaTileEntity();
+ if (aMetaTileEntity == null) return false;
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch hatch) {
+ hatch.updateTexture(aBaseCasingIndex);
+ hatch.updateCraftingIcon(this.getMachineCraftingIcon());
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Input tInput) {
+ if (tInput.getTierForStructure() < hatchTier()) return false;
+ tInput.mRecipeMap = getRecipeMap();
+ return mInputHatches.add(tInput);
+ }
+ if (aMetaTileEntity instanceof GT_MetaTileEntity_Hatch_Output tOutput) {
+ if (tOutput.getTierForStructure() < hatchTier()) return false;
+ return mOutputHatches.add(tOutput);
+ }
+ if (aMetaTileEntity instanceof IDualInputHatch tInput) {
+ tInput.updateCraftingIcon(this.getMachineCraftingIcon());
+ return mDualInputHatches.add(tInput);
+ }
+ return false;
+ }
+
+ @Override
+ public IStructureDefinition<LargeFusionComputer> getStructure_EM() {
+ return STRUCTURE_DEFINITION.get(getClass());
+ }
+
+ @Override
+ public int getMaxEfficiency(ItemStack aStack) {
+ return 10000;
+ }
+
+ @Override
+ public int getDamageToComponent(ItemStack aStack) {
+ return 0;
+ }
+
+ @Override
+ public boolean explodesOnComponentBreak(ItemStack aStack) {
+ return false;
+ }
+
+ @Override
+ protected ResourceLocation getActivitySound() {
+ return SoundResource.GT_MACHINES_FUSION_LOOP.resourceLocation;
+ }
+
+ @Override
+ public String[] getInfoData() {
+ IGregTechTileEntity baseMetaTileEntity = getBaseMetaTileEntity();
+ String tier = switch (tier()) {
+ case 6 -> EnumChatFormatting.RED + "I" + EnumChatFormatting.RESET;
+ case 7 -> EnumChatFormatting.RED + "II" + EnumChatFormatting.RESET;
+ case 8 -> EnumChatFormatting.RED + "III" + EnumChatFormatting.RESET;
+ case 9 -> EnumChatFormatting.RED + "IV" + EnumChatFormatting.RESET;
+ default -> EnumChatFormatting.GOLD + "V" + EnumChatFormatting.RESET;
+ };
+ double plasmaOut = 0;
+ if (mMaxProgresstime > 0) plasmaOut = (double) mOutputFluids[0].amount / mMaxProgresstime;
+
+ return new String[] { EnumChatFormatting.BLUE + "Fusion Reactor MK " + EnumChatFormatting.RESET + tier,
+ StatCollector.translateToLocal("scanner.info.UX.0") + ": "
+ + EnumChatFormatting.LIGHT_PURPLE
+ + GT_Utility.formatNumbers(this.para)
+ + EnumChatFormatting.RESET,
+ StatCollector.translateToLocal("GT5U.fusion.req") + ": "
+ + EnumChatFormatting.RED
+ + GT_Utility.formatNumbers(-lEUt)
+ + EnumChatFormatting.RESET
+ + "EU/t",
+ StatCollector.translateToLocal("GT5U.multiblock.energy") + ": "
+ + EnumChatFormatting.GREEN
+ + GT_Utility.formatNumbers(baseMetaTileEntity != null ? baseMetaTileEntity.getStoredEU() : 0)
+ + EnumChatFormatting.RESET
+ + " EU / "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(maxEUStore())
+ + EnumChatFormatting.RESET
+ + " EU",
+ StatCollector.translateToLocal("GT5U.fusion.plasma") + ": "
+ + EnumChatFormatting.YELLOW
+ + GT_Utility.formatNumbers(plasmaOut)
+ + EnumChatFormatting.RESET
+ + "L/t" };
+ }
+
+ protected long energyStorageCache;
+ protected static final NumberFormatMUI numberFormat = new NumberFormatMUI();
+
+ @Override
+ protected void drawTexts(DynamicPositionedColumn screenElements, SlotWidget inventorySlot) {
+ super.drawTexts(screenElements, inventorySlot);
+
+ screenElements
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> StatCollector.translateToLocal("gui.LargeFusion.0") + " "
+ + numberFormat.format(energyStorageCache)
+ + " EU")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
+ .widget(new FakeSyncWidget.LongSyncer(this::maxEUStore, val -> energyStorageCache = val))
+ .widget(
+ new TextWidget()
+ .setStringSupplier(
+ () -> StatCollector.translateToLocal("gui.LargeFusion.1") + " "
+ + numberFormat.format(getEUVar())
+ + " EU")
+ .setDefaultColor(COLOR_TEXT_WHITE.get())
+ .setEnabled(widget -> getBaseMetaTileEntity().getErrorDisplayID() == 0))
+ .widget(new FakeSyncWidget.LongSyncer(this::getEUVar, this::setEUVar));
+ }
+
+ public static final String[] L0 = { " ",
+ " ", " FCCCCCF ",
+ " FCIBICF ", " FCCCCCF ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " FFF FFF ",
+ " CCC CCC ", " CIC CIC ",
+ " CBC CBC ", " CIC CIC ",
+ " CCC CCC ", " FFF FFF ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " ",
+ " ", " FCCCCCF ",
+ " FCIBICF ", " FCCCCCF ",
+ " ", " ", };
+
+ public static final String[] L1 = { " ",
+ " FCBBBCF ", " CC CC ",
+ " CCCCC CCCCC ", " CCCCCCC CCCCCCC ",
+ " CCCCCCC FCBBBCF CCCCCCC ", " CCCCC CCCCC ",
+ " CCCC CCCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " FCCCF FCCCF ",
+ " C C C C ", " B B B B ",
+ " B B B B ", " B B B B ",
+ " C C C C ", " FCCCF FCCCF ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCC CCC ", " CCC CCC ",
+ " CCCC CCCC ", " CCCCC CCCCC ",
+ " CCCCCCC FCBBBCF CCCCCCC ", " CCCCCCC CCCCCCC ",
+ " CCCCC CCCCC ", " CC CC ",
+ " FCBBBCF ", " ", };
+
+ public static final String[] L2 = { " FCCCCCF ",
+ " CC CC ", " CCCCC CCCCC ",
+ " CCCCCHHHHHHHHHCCCCC ", " CCCCHHHCC CCHHHCCCC ",
+ " CCCHHCCCCC CCCCCHHCCC ", " ECHHCCCCC FCCCCCF CCCCCHHCE ",
+ " CCHCCCC CCCCHCC ", " CCHCCC CCCHCC ",
+ " CCHCE ECHCC ", " ECHCC CCHCE ",
+ " CCHCE ECHCC ", " CCHCC CCHCC ",
+ " CCHCC CCHCC ", " CCHCC CCHCC ",
+ " CCHCC CCHCC ", " CCHCC CCHCC ",
+ " CCHCC CCHCC ", " CCHCC CCHCC ",
+ " CCHCC CCHCC ", "FCCHCCF FCCHCCF",
+ "C H C C H C", "C H C C H C",
+ "C H C C H C", "C H C C H C",
+ "C H C C H C", "FCCHCCF FCCHCCF",
+ " CCHCC CCHCC ", " CCHCC CCHCC ",
+ " CCHCC CCHCC ", " CCHCC CCHCC ",
+ " CCHCC CCHCC ", " CCHCC CCHCC ",
+ " CCHCC CCHCC ", " CCHCC CCHCC ",
+ " CCHCE ECHCC ", " ECHCC CCHCE ",
+ " CCHCE ECHCC ", " CCHCCC CCCHCC ",
+ " CCHCCCC CCCCHCC ", " ECHHCCCCC FCCCCCF CCCCCHHCE ",
+ " CCCHHCCCCC CCCCCHHCCC ", " CCCCHHHCC CCHHHCCCC ",
+ " CCCCCHHHHHHHHHCCCCC ", " CCCCC CCCCC ",
+ " CC CC ", " FCCCCCF ", };
+
+ public static final String[] L3 = { " FCIBICF ",
+ " CC CC ", " CCCHHHHHHHHHCCC ",
+ " CCHHHHHHHHHHHHHHHCC ", " CCHHHHHHHHHHHHHHHHHHHCC ",
+ " CHHHHHHHCC CCHHHHHHHC ", " CHHHHHCCC FCIBICF CCCHHHHHC ",
+ " CHHHHCC CCHHHHC ", " CHHHCC CCHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", "FCHHHCF FCHHHCF",
+ "C HHH C C HHH C", "I HHH I I HHH I",
+ "B HHH B B HHH B", "I HHH I I HHH I",
+ "C HHH C C HHH C", "FCHHHCF FCHHHCF",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHC CHHHC ",
+ " CHHHC CHHHC ", " CHHHCC CCHHHC ",
+ " CHHHHCC CCHHHHC ", " CHHHHHCCC FCI~ICF CCCHHHHHC ",
+ " CHHHHHHHCC CCHHHHHHHC ", " CCHHHHHHHHHHHHHHHHHHHCC ",
+ " CCHHHHHHHHHHHHHHHCC ", " CCCHHHHHHHHHCCC ",
+ " CC CC ", " FCIBICF ", };
+}
diff --git a/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputerPP.java b/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputerPP.java
new file mode 100644
index 0000000000..7d87e6fdd1
--- /dev/null
+++ b/src/main/java/goodgenerator/blocks/tileEntity/base/LargeFusionComputerPP.java
@@ -0,0 +1,53 @@
+package goodgenerator.blocks.tileEntity.base;
+
+import static net.minecraft.util.StatCollector.translateToLocal;
+
+import com.github.technus.tectech.thing.metaTileEntity.multi.base.INameFunction;
+import com.github.technus.tectech.thing.metaTileEntity.multi.base.IStatusFunction;
+import com.github.technus.tectech.thing.metaTileEntity.multi.base.LedStatus;
+import com.github.technus.tectech.thing.metaTileEntity.multi.base.Parameters;
+
+import gregtech.api.objects.overclockdescriber.OverclockDescriber;
+import gregtech.api.util.AdvancedFusionOverclockDescriber;
+
+public abstract class LargeFusionComputerPP extends LargeFusionComputer {
+
+ protected Parameters.Group.ParameterIn batchSetting;
+
+ /** Name of the batch setting */
+ private static final INameFunction<LargeFusionComputerPP> BATCH_SETTING_NAME = (base,
+ p) -> translateToLocal("gt.blockmachines.LargeFusionComputerPP.cfgi.0"); // Batch size
+ /** Status of the batch setting */
+ private static final IStatusFunction<LargeFusionComputerPP> BATCH_STATUS = (base, p) -> LedStatus
+ .fromLimitsInclusiveOuterBoundary(p.get(), 1, 0, 32, 128);
+
+ public LargeFusionComputerPP(String name) {
+ super(name);
+ }
+
+ public LargeFusionComputerPP(int id, String name, String nameRegional) {
+ super(id, name, nameRegional);
+ }
+
+ @Override
+ protected OverclockDescriber createOverclockDescriber() {
+ return new AdvancedFusionOverclockDescriber((byte) tier(), capableStartupCanonical());
+ }
+
+ @Override
+ protected void parametersInstantiation_EM() {
+ batchSetting = parametrization.getGroup(9, false)
+ .makeInParameter(1, 1, BATCH_SETTING_NAME, BATCH_STATUS);
+ }
+
+ @Override
+ protected int getMaxBatchSize() {
+ // Batch size 1~128
+ return (int) Math.min(Math.max(batchSetting.get(), 1.0D), 128.0D);
+ }
+
+ @Override
+ public boolean getDefaultBatchMode() {
+ return true;
+ }
+}