aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/kekztech/common/tileentities/MTELapotronicSuperCapacitor.java
diff options
context:
space:
mode:
authorNotAPenguin <michiel.vandeginste@gmail.com>2024-09-02 23:17:17 +0200
committerGitHub <noreply@github.com>2024-09-02 23:17:17 +0200
commit1b820de08a05070909a267e17f033fcf58ac8710 (patch)
tree02831a025986a06b20f87e5bcc69d1e0c639a342 /src/main/java/kekztech/common/tileentities/MTELapotronicSuperCapacitor.java
parentafd3fd92b6a6ab9ab0d0dc3214e6bc8ff7a86c9b (diff)
downloadGT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.tar.gz
GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.tar.bz2
GT5-Unofficial-1b820de08a05070909a267e17f033fcf58ac8710.zip
The Great Renaming (#3014)
* move kekztech to a single root dir * move detrav to a single root dir * move gtnh-lanthanides to a single root dir * move tectech and delete some gross reflection in gt++ * remove more reflection inside gt5u * delete more reflection in gt++ * fix imports * move bartworks and bwcrossmod * fix proxies * move galactigreg and ggfab * move gtneioreplugin * try to fix gt++ bee loader * apply the rename rules to BW * apply rename rules to bwcrossmod * apply rename rules to detrav scanner mod * apply rename rules to galacticgreg * apply rename rules to ggfab * apply rename rules to goodgenerator * apply rename rules to gtnh-lanthanides * apply rename rules to gt++ * apply rename rules to kekztech * apply rename rules to kubatech * apply rename rules to tectech * apply rename rules to gt apply the rename rules to gt * fix tt import * fix mui hopefully * fix coremod except intergalactic * rename assline recipe class * fix a class name i stumbled on * rename StructureUtility to GTStructureUtility to prevent conflict with structurelib * temporary rename of GTTooltipDataCache to old name * fix gt client/server proxy names
Diffstat (limited to 'src/main/java/kekztech/common/tileentities/MTELapotronicSuperCapacitor.java')
-rw-r--r--src/main/java/kekztech/common/tileentities/MTELapotronicSuperCapacitor.java1213
1 files changed, 1213 insertions, 0 deletions
diff --git a/src/main/java/kekztech/common/tileentities/MTELapotronicSuperCapacitor.java b/src/main/java/kekztech/common/tileentities/MTELapotronicSuperCapacitor.java
new file mode 100644
index 0000000000..2672d0e994
--- /dev/null
+++ b/src/main/java/kekztech/common/tileentities/MTELapotronicSuperCapacitor.java
@@ -0,0 +1,1213 @@
+package kekztech.common.tileentities;
+
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofChain;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onElementPass;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.onlyIf;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.transpose;
+import static com.gtnewhorizon.structurelib.structure.StructureUtility.withChannel;
+import static gregtech.api.enums.HatchElement.Maintenance;
+import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY;
+import static gregtech.api.util.GTStructureUtility.buildHatchAdder;
+import static gregtech.api.util.GTStructureUtility.filterByMTEClass;
+import static java.lang.Math.min;
+import static kekztech.util.Util.toPercentageFrom;
+import static kekztech.util.Util.toStandardForm;
+
+import java.math.BigInteger;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+import java.util.UUID;
+import java.util.function.Consumer;
+
+import net.minecraft.block.Block;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.entity.player.EntityPlayerMP;
+import net.minecraft.item.Item;
+import net.minecraft.item.ItemStack;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.util.StatCollector;
+import net.minecraft.world.World;
+import net.minecraftforge.common.util.ForgeDirection;
+
+import com.google.common.collect.ImmutableList;
+import com.gtnewhorizon.structurelib.StructureLibAPI;
+import com.gtnewhorizon.structurelib.alignment.constructable.ChannelDataAccessor;
+import com.gtnewhorizon.structurelib.alignment.constructable.ISurvivalConstructable;
+import com.gtnewhorizon.structurelib.structure.IItemSource;
+import com.gtnewhorizon.structurelib.structure.IStructureDefinition;
+import com.gtnewhorizon.structurelib.structure.IStructureElement;
+import com.gtnewhorizon.structurelib.structure.StructureUtility;
+import com.gtnewhorizon.structurelib.util.ItemStackPredicate.NBTMode;
+import com.gtnewhorizons.modularui.api.drawable.IDrawable;
+import com.gtnewhorizons.modularui.api.drawable.UITexture;
+import com.gtnewhorizons.modularui.api.screen.ModularWindow;
+import com.gtnewhorizons.modularui.api.screen.UIBuildContext;
+import com.gtnewhorizons.modularui.common.widget.ButtonWidget;
+import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget;
+
+import bartworks.API.BorosilicateGlass;
+import gregtech.api.enums.Dyes;
+import gregtech.api.enums.GTValues;
+import gregtech.api.enums.Textures.BlockIcons;
+import gregtech.api.gui.modularui.GTUITextures;
+import gregtech.api.interfaces.IHatchElement;
+import gregtech.api.interfaces.ITexture;
+import gregtech.api.interfaces.metatileentity.IMetaTileEntity;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.metatileentity.implementations.MTEEnhancedMultiBlockBase;
+import gregtech.api.metatileentity.implementations.MTEHatch;
+import gregtech.api.metatileentity.implementations.MTEHatchDynamo;
+import gregtech.api.metatileentity.implementations.MTEHatchEnergy;
+import gregtech.api.metatileentity.implementations.MTEHatchMaintenance;
+import gregtech.api.render.TextureFactory;
+import gregtech.api.util.GTUtility;
+import gregtech.api.util.IGTHatchAdder;
+import gregtech.api.util.MultiblockTooltipBuilder;
+import gregtech.common.misc.WirelessNetworkManager;
+import kekztech.client.gui.KTUITextures;
+import kekztech.common.Blocks;
+import kekztech.common.itemBlocks.ItemBlockLapotronicEnergyUnit;
+import tectech.thing.metaTileEntity.hatch.MTEHatchDynamoMulti;
+import tectech.thing.metaTileEntity.hatch.MTEHatchDynamoTunnel;
+import tectech.thing.metaTileEntity.hatch.MTEHatchEnergyMulti;
+import tectech.thing.metaTileEntity.hatch.MTEHatchEnergyTunnel;
+
+public class MTELapotronicSuperCapacitor extends MTEEnhancedMultiBlockBase<MTELapotronicSuperCapacitor>
+ implements ISurvivalConstructable {
+
+ private enum TopState {
+ MayBeTop,
+ Top,
+ NotTop
+ }
+
+ private boolean canUseWireless = false;
+ private boolean wireless_mode = false;
+ private boolean not_processed_lsc = true;
+ private int counter = 1;
+ private boolean balanced = false;
+
+ private final Queue<Long> energyInputValues = new LinkedList<>();
+ private final Queue<Long> energyOutputValues = new LinkedList<>();
+
+ private final long max_passive_drain_eu_per_tick_per_uhv_cap = 1_000_000;
+ private final long max_passive_drain_eu_per_tick_per_uev_cap = 100_000_000;
+ private final long max_passive_drain_eu_per_tick_per_uiv_cap = (long) Math.pow(10, 10);
+ private final long max_passive_drain_eu_per_tick_per_umv_cap = (long) Math.pow(10, 12);
+
+ private enum Capacitor {
+
+ IV(2, BigInteger.valueOf(ItemBlockLapotronicEnergyUnit.IV_cap_storage)),
+ LuV(3, BigInteger.valueOf(ItemBlockLapotronicEnergyUnit.LuV_cap_storage)),
+ ZPM(4, BigInteger.valueOf(ItemBlockLapotronicEnergyUnit.ZPM_cap_storage)),
+ UV(5, BigInteger.valueOf(ItemBlockLapotronicEnergyUnit.UV_cap_storage)),
+ UHV(6, MAX_LONG),
+ None(0, BigInteger.ZERO),
+ EV(1, BigInteger.valueOf(ItemBlockLapotronicEnergyUnit.EV_cap_storage)),
+ UEV(7, MAX_LONG),
+ UIV(8, BigInteger.valueOf(ItemBlockLapotronicEnergyUnit.UIV_cap_storage)),
+ UMV(9, ItemBlockLapotronicEnergyUnit.UMV_cap_storage);
+
+ private final int minimalGlassTier;
+ private final BigInteger providedCapacity;
+ static final Capacitor[] VALUES = values();
+ static final Capacitor[] VALUES_BY_TIER = Arrays.stream(values())
+ .sorted(Comparator.comparingInt(Capacitor::getMinimalGlassTier))
+ .toArray(Capacitor[]::new);
+
+ Capacitor(int minimalGlassTier, BigInteger providedCapacity) {
+ this.minimalGlassTier = minimalGlassTier;
+ this.providedCapacity = providedCapacity;
+ }
+
+ public int getMinimalGlassTier() {
+ return minimalGlassTier;
+ }
+
+ public BigInteger getProvidedCapacity() {
+ return providedCapacity;
+ }
+
+ public static int getIndexFromGlassTier(int glassTier) {
+ for (int index = 0; index < values().length; index++) {
+ if (values()[index].getMinimalGlassTier() == glassTier) {
+ return index;
+ }
+ }
+ return -1;
+ }
+ }
+
+ private static final String STRUCTURE_PIECE_BASE = "base";
+ private static final String STRUCTURE_PIECE_LAYER = "slice";
+ private static final String STRUCTURE_PIECE_TOP = "top";
+ private static final String STRUCTURE_PIECE_MID = "mid";
+ private static final int GLASS_TIER_UNSET = -2;
+
+ private static final Block LSC_PART = Blocks.lscLapotronicEnergyUnit;
+ private static final Item LSC_PART_ITEM = Item.getItemFromBlock(LSC_PART);
+ private static final int CASING_META = 0;
+ private static final int CASING_TEXTURE_ID = (42 << 7) | 127;
+
+ private static final int DURATION_AVERAGE_TICKS = 100;
+
+ // height channel for height.
+ // glass channel for glass
+ // capacitor channel for capacitor, but it really just pick whatever capacitor it can find in survival
+ private static final IStructureDefinition<MTELapotronicSuperCapacitor> STRUCTURE_DEFINITION = IStructureDefinition
+ .<MTELapotronicSuperCapacitor>builder()
+ .addShape(
+ STRUCTURE_PIECE_BASE,
+ transpose(
+ new String[][] { { "bbbbb", "bbbbb", "bbbbb", "bbbbb", "bbbbb", },
+ { "bb~bb", "bbbbb", "bbbbb", "bbbbb", "bbbbb", }, }))
+ .addShape(
+ STRUCTURE_PIECE_LAYER,
+ transpose(new String[][] { { "ggggg", "gcccg", "gcccg", "gcccg", "ggggg", }, }))
+ .addShape(STRUCTURE_PIECE_TOP, transpose(new String[][] { { "ggggg", "ggggg", "ggggg", "ggggg", "ggggg", }, }))
+ .addShape(STRUCTURE_PIECE_MID, transpose(new String[][] { { "ggggg", "gCCCg", "gCCCg", "gCCCg", "ggggg", }, }))
+ .addElement(
+ 'b',
+ buildHatchAdder(
+ MTELapotronicSuperCapacitor.class).atLeast(LSCHatchElement.Energy, LSCHatchElement.Dynamo, Maintenance)
+ .hatchItemFilterAnd(
+ (t, h) -> ChannelDataAccessor.getChannelData(h, "glass") < 6
+ ? filterByMTEClass(ImmutableList.of(MTEHatchEnergyTunnel.class, MTEHatchDynamoTunnel.class))
+ .negate()
+ : s -> true)
+ .casingIndex(CASING_TEXTURE_ID)
+ .dot(1)
+ .buildAndChain(onElementPass(te -> te.casingAmount++, ofBlock(LSC_PART, CASING_META))))
+ .addElement(
+ 'g',
+ withChannel(
+ "glass",
+ BorosilicateGlass
+ .ofBoroGlass((byte) GLASS_TIER_UNSET, (te, t) -> te.glassTier = t, te -> te.glassTier)))
+ .addElement(
+ 'c',
+ ofChain(
+ onlyIf(
+ te -> te.topState != TopState.NotTop,
+ onElementPass(
+ te -> te.topState = TopState.Top,
+ withChannel(
+ "glass",
+ BorosilicateGlass.ofBoroGlass(
+ (byte) GLASS_TIER_UNSET,
+ (te, t) -> te.glassTier = t,
+ te -> te.glassTier)))),
+ onlyIf(
+ te -> te.topState != TopState.Top,
+ onElementPass(
+ te -> te.topState = TopState.NotTop,
+ new IStructureElement<MTELapotronicSuperCapacitor>() {
+
+ @Override
+ public boolean check(MTELapotronicSuperCapacitor t, World world, int x, int y, int z) {
+ Block worldBlock = world.getBlock(x, y, z);
+ int meta = worldBlock.getDamageValue(world, x, y, z);
+ if (LSC_PART != worldBlock || meta == 0) return false;
+ t.capacitors[meta - 1]++;
+ return true;
+ }
+
+ private int getHint(ItemStack stack) {
+ return Capacitor.VALUES_BY_TIER[Math.min(
+ Capacitor.VALUES_BY_TIER.length,
+ ChannelDataAccessor.getChannelData(stack, "capacitor")) - 1].getMinimalGlassTier()
+ + 1;
+ }
+
+ @Override
+ public boolean spawnHint(MTELapotronicSuperCapacitor t, World world, int x, int y, int z,
+ ItemStack trigger) {
+ StructureLibAPI.hintParticle(world, x, y, z, LSC_PART, getHint(trigger));
+ return true;
+ }
+
+ @Override
+ public boolean placeBlock(MTELapotronicSuperCapacitor t, World world, int x, int y, int z,
+ ItemStack trigger) {
+ world.setBlock(x, y, z, LSC_PART, getHint(trigger), 3);
+ return true;
+ }
+
+ @Override
+ public PlaceResult survivalPlaceBlock(MTELapotronicSuperCapacitor t, World world, int x,
+ int y, int z, ItemStack trigger, IItemSource source, EntityPlayerMP actor,
+ Consumer<IChatComponent> chatter) {
+ if (check(t, world, x, y, z)) return PlaceResult.SKIP;
+ int glassTier = ChannelDataAccessor.getChannelData(trigger, "glass") + 2;
+ ItemStack targetStack = source
+ .takeOne(
+ s -> s != null && s.stackSize >= 0
+ && s.getItem() == LSC_PART_ITEM
+ && Capacitor.VALUES[Math.min(s.getItemDamage(), Capacitor.VALUES.length)
+ - 1].getMinimalGlassTier() > glassTier,
+ true);
+ if (targetStack == null) return PlaceResult.REJECT;
+ return StructureUtility.survivalPlaceBlock(
+ targetStack,
+ NBTMode.EXACT,
+ targetStack.stackTagCompound,
+ true,
+ world,
+ x,
+ y,
+ z,
+ source,
+ actor,
+ chatter);
+ }
+ }))))
+ .addElement('C', ofBlock(LSC_PART, 1))
+ .build();
+
+ private static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
+
+ private final Set<MTEHatchEnergyMulti> mEnergyHatchesTT = new HashSet<>();
+ private final Set<MTEHatchDynamoMulti> mDynamoHatchesTT = new HashSet<>();
+ private final Set<MTEHatchEnergyTunnel> mEnergyTunnelsTT = new HashSet<>();
+ private final Set<MTEHatchDynamoTunnel> mDynamoTunnelsTT = new HashSet<>();
+ /**
+ * Count the amount of capacitors of each tier in each slot. Index = meta - 1
+ */
+ private final int[] capacitors = new int[10];
+
+ private BigInteger capacity = BigInteger.ZERO;
+ private BigInteger stored = BigInteger.ZERO;
+ private long passiveDischargeAmount = 0;
+ private long inputLastTick = 0;
+ private long outputLastTick = 0;
+ private int repairStatusCache = 0;
+
+ private byte glassTier = -1;
+ private int casingAmount = 0;
+ private TopState topState = TopState.MayBeTop;
+
+ private long mMaxEUIn = 0;
+ private long mMaxEUOut = 0;
+
+ public MTELapotronicSuperCapacitor(int aID, String aName, String aNameRegional) {
+ super(aID, aName, aNameRegional);
+ }
+
+ public MTELapotronicSuperCapacitor(String aName) {
+ super(aName);
+ }
+
+ @Override
+ public IMetaTileEntity newMetaEntity(IGregTechTileEntity var1) {
+ return new MTELapotronicSuperCapacitor(super.mName);
+ }
+
+ @Override
+ public IStructureDefinition<MTELapotronicSuperCapacitor> getStructureDefinition() {
+ return STRUCTURE_DEFINITION;
+ }
+
+ private void processInputHatch(MTEHatch aHatch, int aBaseCasingIndex) {
+ mMaxEUIn += aHatch.maxEUInput() * aHatch.maxAmperesIn();
+ aHatch.updateTexture(aBaseCasingIndex);
+ }
+
+ private void processOutputHatch(MTEHatch aHatch, int aBaseCasingIndex) {
+ mMaxEUOut += aHatch.maxEUOutput() * aHatch.maxAmperesOut();
+ aHatch.updateTexture(aBaseCasingIndex);
+ }
+
+ private boolean addBottomHatches(IGregTechTileEntity aTileEntity, int aBaseCasingIndex) {
+ if (aTileEntity == null || aTileEntity.isDead()) return false;
+ IMetaTileEntity aMetaTileEntity = aTileEntity.getMetaTileEntity();
+ if (!(aMetaTileEntity instanceof MTEHatch)) return false;
+ if (aMetaTileEntity instanceof MTEHatchMaintenance) {
+ ((MTEHatch) aMetaTileEntity).updateTexture(aBaseCasingIndex);
+ return MTELapotronicSuperCapacitor.this.mMaintenanceHatches.add((MTEHatchMaintenance) aMetaTileEntity);
+ } else if (aMetaTileEntity instanceof MTEHatchEnergy) {
+ // Add GT hatches
+ final MTEHatchEnergy tHatch = ((MTEHatchEnergy) aMetaTileEntity);
+ processInputHatch(tHatch, aBaseCasingIndex);
+ return mEnergyHatches.add(tHatch);
+ } else if (aMetaTileEntity instanceof MTEHatchEnergyTunnel) {
+ // Add TT Laser hatches
+ final MTEHatchEnergyTunnel tHatch = ((MTEHatchEnergyTunnel) aMetaTileEntity);
+ processInputHatch(tHatch, aBaseCasingIndex);
+ return mEnergyTunnelsTT.add(tHatch);
+ } else if (aMetaTileEntity instanceof MTEHatchEnergyMulti) {
+ // Add TT hatches
+ final MTEHatchEnergyMulti tHatch = (MTEHatchEnergyMulti) aMetaTileEntity;
+ processInputHatch(tHatch, aBaseCasingIndex);
+ return mEnergyHatchesTT.add(tHatch);
+ } else if (aMetaTileEntity instanceof MTEHatchDynamo) {
+ // Add GT hatches
+ final MTEHatchDynamo tDynamo = (MTEHatchDynamo) aMetaTileEntity;
+ processOutputHatch(tDynamo, aBaseCasingIndex);
+ return mDynamoHatches.add(tDynamo);
+ } else if (aMetaTileEntity instanceof MTEHatchDynamoTunnel) {
+ // Add TT Laser hatches
+ final MTEHatchDynamoTunnel tDynamo = (MTEHatchDynamoTunnel) aMetaTileEntity;
+ processOutputHatch(tDynamo, aBaseCasingIndex);
+ return mDynamoTunnelsTT.add(tDynamo);
+ } else if (aMetaTileEntity instanceof MTEHatchDynamoMulti) {
+ // Add TT hatches
+ final MTEHatchDynamoMulti tDynamo = (MTEHatchDynamoMulti) aMetaTileEntity;
+ processOutputHatch(tDynamo, aBaseCasingIndex);
+ return mDynamoHatchesTT.add(tDynamo);
+ }
+ return false;
+ }
+
+ private int getUHVCapacitorCount() {
+ return capacitors[4];
+ }
+
+ private int getUEVCapacitorCount() {
+ return capacitors[7];
+ }
+
+ private int getUIVCapacitorCount() {
+ return capacitors[8];
+ }
+
+ private int getUMVCapacitorCount() {
+ return capacitors[9];
+ }
+
+ private int wirelessCapableCapacitors() {
+ return capacitors[4] + capacitors[7] + capacitors[8] + capacitors[9];
+ }
+
+ @Override
+ protected MultiblockTooltipBuilder createTooltip() {
+ final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder();
+ tt.addMachineType("Energy Storage")
+ .addInfo("Loses energy equal to 1% of the total capacity every 24 hours.")
+ .addInfo(
+ "Capped at " + EnumChatFormatting.RED
+ + GTUtility.formatNumbers(max_passive_drain_eu_per_tick_per_uhv_cap)
+ + EnumChatFormatting.GRAY
+ + " EU/t passive loss per "
+ + GTValues.TIER_COLORS[9]
+ + GTValues.VN[9]
+ + EnumChatFormatting.GRAY
+ + " capacitor.")
+ .addInfo(
+ "The passive loss increases " + EnumChatFormatting.DARK_RED
+ + "100"
+ + EnumChatFormatting.GRAY
+ + "-fold"
+ + " for every capacitor tier above.")
+ .addInfo("Passive loss is multiplied by the number of maintenance issues present.")
+ .addSeparator()
+ .addInfo("Glass shell has to be Tier - 3 of the highest capacitor tier.")
+ .addInfo(
+ GTValues.TIER_COLORS[8] + GTValues.VN[8]
+ + EnumChatFormatting.GRAY
+ + "-tier glass required for "
+ + EnumChatFormatting.BLUE
+ + "Tec"
+ + EnumChatFormatting.DARK_BLUE
+ + "Tech"
+ + EnumChatFormatting.GRAY
+ + " Laser Hatches.")
+ .addInfo("Add more or better capacitors to increase capacity.")
+ .addSeparator()
+ .addInfo("Wireless mode can be enabled by right clicking with a screwdriver.")
+ .addInfo(
+ "This mode can only be enabled if you have a " + GTValues.TIER_COLORS[9]
+ + GTValues.VN[9]
+ + EnumChatFormatting.GRAY
+ + "+ capacitor in the multiblock.")
+ .addInfo(
+ "When enabled every " + EnumChatFormatting.BLUE
+ + GTUtility
+ .formatNumbers(ItemBlockLapotronicEnergyUnit.LSC_time_between_wireless_rebalance_in_ticks)
+ + EnumChatFormatting.GRAY
+ + " ticks the LSC will attempt to re-balance against your")
+ .addInfo("wireless EU network.")
+ .addInfo(
+ "If there is less than " + EnumChatFormatting.RED
+ + GTUtility.formatNumbers(ItemBlockLapotronicEnergyUnit.LSC_wireless_eu_cap)
+ + EnumChatFormatting.GRAY
+ + "("
+ + GTValues.TIER_COLORS[9]
+ + GTValues.VN[9]
+ + EnumChatFormatting.GRAY
+ + ") EU in the LSC")
+ .addInfo("it will withdraw from the network and add to the LSC.")
+ .addInfo("If there is more it will add the EU to the network and remove it from the LSC.")
+ .addInfo(
+ "The threshold increases " + EnumChatFormatting.DARK_RED
+ + "100"
+ + EnumChatFormatting.GRAY
+ + "-fold"
+ + " for every capacitor tier above.")
+ .addSeparator()
+ .beginVariableStructureBlock(5, 5, 4, 50, 5, 5, false)
+ .addStructureInfo("Modular height of 4-50 blocks.")
+ .addController("Front center bottom")
+ .addOtherStructurePart("Lapotronic Super Capacitor Casing", "5x2x5 base (at least 17x)")
+ .addOtherStructurePart(
+ "Lapotronic Capacitor (" + GTValues.TIER_COLORS[4]
+ + GTValues.VN[4]
+ + EnumChatFormatting.GRAY
+ + "-"
+ + GTValues.TIER_COLORS[8]
+ + GTValues.VN[8]
+ + EnumChatFormatting.GRAY
+ + "), Ultimate Capacitor ("
+ + GTValues.TIER_COLORS[9]
+ + GTValues.VN[9]
+ + EnumChatFormatting.GRAY
+ + "-"
+ + GTValues.TIER_COLORS[12]
+ + GTValues.VN[12]
+ + EnumChatFormatting.GRAY
+ + ")",
+ "Center 3x(1-47)x3 above base (9-423 blocks)")
+ .addStructureInfo(
+ "You can also use the Empty Capacitor to save materials if you use it for less than half the blocks")
+ .addOtherStructurePart("Borosilicate Glass (any)", "41-777x, Encase capacitor pillar")
+ .addEnergyHatch("Any casing")
+ .addDynamoHatch("Any casing")
+ .addOtherStructurePart(
+ "Laser Target/Source Hatches",
+ "Any casing, must be using " + GTValues.TIER_COLORS[8]
+ + GTValues.VN[8]
+ + EnumChatFormatting.GRAY
+ + "-tier glass")
+ .addStructureInfo("You can have several I/O Hatches")
+ .addSubChannelUsage("glass", "Borosilicate Glass Tier")
+ .addSubChannelUsage("capacitor", "Maximum Capacitor Tier")
+ .addSubChannelUsage("height", "Height of structure")
+ .addMaintenanceHatch("Any casing")
+ .toolTipFinisher("KekzTech");
+ return tt;
+ }
+
+ @Override
+ public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side,
+ ForgeDirection forgeDirectionacing, int colorIndex, boolean aActive, boolean aRedstone) {
+ ITexture[] sTexture = new ITexture[] {
+ TextureFactory.of(BlockIcons.MACHINE_CASING_FUSION_GLASS, Dyes.getModulation(-1, Dyes._NULL.mRGBa)) };
+ if (side == forgeDirectionacing && aActive) {
+ sTexture = new ITexture[] { TextureFactory
+ .of(BlockIcons.MACHINE_CASING_FUSION_GLASS_YELLOW, Dyes.getModulation(-1, Dyes._NULL.mRGBa)) };
+ }
+ return sTexture;
+ }
+
+ private UUID global_energy_user_uuid;
+
+ @Override
+ public void onPreTick(IGregTechTileEntity tileEntity, long aTick) {
+ super.onPreTick(tileEntity, aTick);
+
+ // On first tick (aTick restarts from 0 upon world reload).
+ if (not_processed_lsc && tileEntity.isServerSide()) {
+ // Add user to wireless network.
+ WirelessNetworkManager.strongCheckOrAddUser(tileEntity.getOwnerUuid());
+
+ // Get team UUID.
+ global_energy_user_uuid = tileEntity.getOwnerUuid();
+
+ not_processed_lsc = false;
+ }
+ }
+
+ @Override
+ public boolean isCorrectMachinePart(ItemStack stack) {
+ return true;
+ }
+
+ @Override
+ public boolean checkRecipe(ItemStack stack) {
+ this.mProgresstime = 1;
+ this.mMaxProgresstime = 1;
+ this.mEUt = 0;
+ this.mEfficiencyIncrease = 10000;
+ return true;
+ }
+
+ @Override
+ public boolean checkMachine(IGregTechTileEntity thisController, ItemStack guiSlotItem) {
+ WirelessNetworkManager.strongCheckOrAddUser(thisController.getOwnerUuid());
+
+ // Reset capacitor counts
+ Arrays.fill(capacitors, 0);
+ // Clear TT hatches
+ mEnergyHatchesTT.clear();
+ mDynamoHatchesTT.clear();
+ mEnergyTunnelsTT.clear();
+ mDynamoTunnelsTT.clear();
+
+ mMaxEUIn = 0;
+ mMaxEUOut = 0;
+
+ glassTier = GLASS_TIER_UNSET;
+ casingAmount = 0;
+
+ if (!checkPiece(STRUCTURE_PIECE_BASE, 2, 1, 0)) return false;
+
+ if (casingAmount < 17) return false;
+
+ topState = TopState.NotTop; // need at least one layer of capacitor to form, obviously
+ int layer = 2;
+ while (true) {
+ if (!checkPiece(STRUCTURE_PIECE_LAYER, 2, layer, 0)) return false;
+ layer++;
+ if (topState == TopState.Top) break; // top found, break out
+ topState = TopState.MayBeTop;
+ if (layer > 50) return false; // too many layers
+ }
+
+ // Make sure glass tier is T-2 of the highest tier capacitor in the structure
+ // Count down from the highest tier until an entry is found
+ // Borosilicate glass after 5 are just recolours of 0
+ for (int highestGlassTier = capacitors.length - 1; highestGlassTier >= 0; highestGlassTier--) {
+ int highestCapacitor = Capacitor.getIndexFromGlassTier(highestGlassTier);
+ if (capacitors[highestCapacitor] > 0) {
+ if (Capacitor.VALUES[highestCapacitor].getMinimalGlassTier() > glassTier) return false;
+ break;
+ }
+ }
+
+ // Glass has to be at least UV-tier to allow TT Laser hatches
+ if (glassTier < 8) {
+ if (mEnergyTunnelsTT.size() > 0 || mDynamoTunnelsTT.size() > 0) return false;
+ }
+
+ // Check if enough (more than 50%) non-empty caps
+ if (capacitors[5] > capacitors[0] + capacitors[1]
+ + capacitors[2]
+ + capacitors[3]
+ + getUHVCapacitorCount()
+ + capacitors[6]
+ + getUEVCapacitorCount()
+ + getUIVCapacitorCount()
+ + getUMVCapacitorCount()) return false;
+
+ // Calculate total capacity
+ capacity = BigInteger.ZERO;
+ for (int i = 0; i < capacitors.length; i++) {
+ int count = capacitors[i];
+ capacity = capacity.add(
+ Capacitor.VALUES[i].getProvidedCapacity()
+ .multiply(BigInteger.valueOf(count)));
+ }
+ // Calculate how much energy to void each tick
+ passiveDischargeAmount = recalculateLossWithMaintenance(getRepairStatus());
+ return mMaintenanceHatches.size() == 1;
+ }
+
+ @Override
+ public void construct(ItemStack stackSize, boolean hintsOnly) {
+ int layer = min(stackSize.stackSize + 3, 50);
+ buildPiece(STRUCTURE_PIECE_BASE, stackSize, hintsOnly, 2, 1, 0);
+ for (int i = 2; i < layer - 1; i++) buildPiece(STRUCTURE_PIECE_MID, stackSize, hintsOnly, 2, i, 0);
+ buildPiece(STRUCTURE_PIECE_TOP, stackSize, hintsOnly, 2, layer - 1, 0);
+ }
+
+ @Override
+ public int survivalConstruct(ItemStack stackSize, int elementBudget, IItemSource source, EntityPlayerMP actor) {
+ if (mMachine) return -1;
+ int layer = Math.min(ChannelDataAccessor.getChannelData(stackSize, "height") + 3, 50);
+ int built;
+ built = survivialBuildPiece(
+ STRUCTURE_PIECE_BASE,
+ stackSize,
+ 2,
+ 1,
+ 0,
+ elementBudget,
+ source,
+ actor,
+ false,
+ true);
+ if (built >= 0) return built;
+ for (int i = 2; i < layer - 1; i++) built = survivialBuildPiece(
+ STRUCTURE_PIECE_MID,
+ stackSize,
+ 2,
+ i,
+ 0,
+ elementBudget,
+ source,
+ actor,
+ false,
+ true);
+ if (built >= 0) return built;
+ return survivialBuildPiece(
+ STRUCTURE_PIECE_TOP,
+ stackSize,
+ 2,
+ layer - 1,
+ 0,
+ elementBudget,
+ source,
+ actor,
+ false,
+ true);
+ }
+
+ @Override
+ public boolean onRunningTick(ItemStack stack) {
+ // Reset I/O cache
+ inputLastTick = 0;
+ outputLastTick = 0;
+
+ long temp_stored = 0L;
+
+ // Draw energy from GT hatches
+ for (MTEHatchEnergy eHatch : super.mEnergyHatches) {
+ if (eHatch == null || !eHatch.isValid()) {
+ continue;
+ }
+ final long power = getPowerToDraw(eHatch.maxEUInput() * eHatch.maxAmperesIn());
+ if (eHatch.getEUVar() >= power) {
+ eHatch.setEUVar(eHatch.getEUVar() - power);
+ temp_stored += power;
+ inputLastTick += power;
+ }
+ }
+
+ // Output energy to GT hatches
+ for (MTEHatchDynamo eDynamo : super.mDynamoHatches) {
+ if (eDynamo == null || !eDynamo.isValid()) {
+ continue;
+ }
+ final long power = getPowerToPush(eDynamo.maxEUOutput() * eDynamo.maxAmperesOut());
+ if (power <= eDynamo.maxEUStore() - eDynamo.getEUVar()) {
+ eDynamo.setEUVar(eDynamo.getEUVar() + power);
+ temp_stored -= power;
+ outputLastTick += power;
+ }
+ }
+
+ // Draw energy from TT hatches
+ for (MTEHatchEnergyMulti eHatch : mEnergyHatchesTT) {
+ if (eHatch == null || !eHatch.isValid()) {
+ continue;
+ }
+ final long power = getPowerToDraw(eHatch.maxEUInput() * eHatch.maxAmperesIn());
+ if (eHatch.getEUVar() >= power) {
+ eHatch.setEUVar(eHatch.getEUVar() - power);
+ temp_stored += power;
+ inputLastTick += power;
+ }
+ }
+
+ // Output energy to TT hatches
+ for (MTEHatchDynamoMulti eDynamo : mDynamoHatchesTT) {
+ if (eDynamo == null || !eDynamo.isValid()) {
+ continue;
+ }
+ final long power = getPowerToPush(eDynamo.maxEUOutput() * eDynamo.maxAmperesOut());
+ if (power <= eDynamo.maxEUStore() - eDynamo.getEUVar()) {
+ eDynamo.setEUVar(eDynamo.getEUVar() + power);
+ temp_stored -= power;
+ outputLastTick += power;
+ }
+ }
+
+ // Draw energy from TT Laser hatches
+ for (MTEHatchEnergyTunnel eHatch : mEnergyTunnelsTT) {
+ if (eHatch == null || !eHatch.isValid()) {
+ continue;
+ }
+ final long ttLaserWattage = eHatch.maxEUInput() * eHatch.Amperes - (eHatch.Amperes / 20);
+ final long power = getPowerToDraw(ttLaserWattage);
+ if (eHatch.getEUVar() >= power) {
+ eHatch.setEUVar(eHatch.getEUVar() - power);
+ temp_stored += power;
+ inputLastTick += power;
+ }
+ }
+
+ // Output energy to TT Laser hatches
+ for (MTEHatchDynamoTunnel eDynamo : mDynamoTunnelsTT) {
+ if (eDynamo == null || !eDynamo.isValid()) {
+ continue;
+ }
+ final long ttLaserWattage = eDynamo.maxEUOutput() * eDynamo.Amperes - (eDynamo.Amperes / 20);
+ final long power = getPowerToPush(ttLaserWattage);
+ if (power <= eDynamo.maxEUStore() - eDynamo.getEUVar()) {
+ eDynamo.setEUVar(eDynamo.getEUVar() + power);
+ temp_stored -= power;
+ outputLastTick += power;
+ }
+ }
+
+ if (wirelessCapableCapacitors() <= 0) {
+ wireless_mode = false;
+ }
+
+ // Every LSC_time_between_wireless_rebalance_in_ticks check against wireless network for re-balancing.
+ counter++;
+ if (wireless_mode && (counter >= ItemBlockLapotronicEnergyUnit.LSC_time_between_wireless_rebalance_in_ticks)) {
+
+ // Reset tick counter.
+ counter = rebalance();
+ }
+
+ // Lose some energy.
+ // Re-calculate if the repair status changed.
+ if (super.getRepairStatus() != repairStatusCache) {
+ passiveDischargeAmount = recalculateLossWithMaintenance(super.getRepairStatus());
+ }
+
+ // This will break if you transfer more than 2^63 EU/t, so don't do that. Thanks <3
+ temp_stored -= passiveDischargeAmount;
+ stored = stored.add(BigInteger.valueOf(temp_stored));
+
+ // Check that the machine has positive EU stored.
+ stored = (stored.compareTo(BigInteger.ZERO) <= 0) ? BigInteger.ZERO : stored;
+
+ IGregTechTileEntity tBMTE = this.getBaseMetaTileEntity();
+
+ tBMTE.injectEnergyUnits(ForgeDirection.UNKNOWN, inputLastTick, 1L);
+ tBMTE.drainEnergyUnits(ForgeDirection.UNKNOWN, outputLastTick, 1L);
+
+ // Add I/O values to Queues
+ if (energyInputValues.size() > DURATION_AVERAGE_TICKS) {
+ energyInputValues.remove();
+ }
+ energyInputValues.offer(inputLastTick);
+
+ if (energyOutputValues.size() > DURATION_AVERAGE_TICKS) {
+ energyOutputValues.remove();
+ }
+
+ energyOutputValues.offer(outputLastTick);
+
+ return true;
+ }
+
+ private int rebalance() {
+
+ balanced = true;
+
+ // Find difference.
+ BigInteger transferred_eu = stored.subtract(
+ (ItemBlockLapotronicEnergyUnit.LSC_wireless_eu_cap.multiply(BigInteger.valueOf(getUHVCapacitorCount())))
+ .add(
+ ItemBlockLapotronicEnergyUnit.UEV_wireless_eu_cap
+ .multiply(BigInteger.valueOf(getUEVCapacitorCount())))
+ .add(
+ ItemBlockLapotronicEnergyUnit.UIV_wireless_eu_cap
+ .multiply(BigInteger.valueOf(getUIVCapacitorCount())))
+ .add(
+ ItemBlockLapotronicEnergyUnit.UMV_wireless_eu_cap
+ .multiply(BigInteger.valueOf(getUMVCapacitorCount()))));
+
+ if (transferred_eu.signum() == 1) {
+ inputLastTick += transferred_eu.longValue();
+ } else {
+ outputLastTick += transferred_eu.longValue();
+ }
+
+ // If that difference can be added then do so.
+ if (WirelessNetworkManager.addEUToGlobalEnergyMap(global_energy_user_uuid, transferred_eu)) {
+ // If it succeeds there was sufficient energy so set the internal capacity as such.
+ stored = ItemBlockLapotronicEnergyUnit.LSC_wireless_eu_cap