package tectech.thing.metaTileEntity.multi; import static com.gtnewhorizon.structurelib.structure.StructureUtility.ofBlock; import static gregtech.api.enums.Mods.Avaritia; import static gregtech.api.metatileentity.BaseTileEntity.TOOLTIP_DELAY; import static gregtech.api.util.GTModHandler.getModItem; import static gregtech.api.util.GTRecipeBuilder.SECONDS; import static gregtech.api.util.GTUtility.formatNumbers; import static java.lang.Math.floor; import static java.lang.Math.log; import static java.lang.Math.max; import static net.minecraft.util.StatCollector.translateToLocal; import static tectech.loader.recipe.Godforge.godforgeUpgradeMats; import static tectech.thing.casing.TTCasingsContainer.GodforgeCasings; import static tectech.thing.casing.TTCasingsContainer.forgeOfGodsRenderBlock; import static tectech.util.GodforgeMath.allowModuleConnection; import static tectech.util.GodforgeMath.calculateEnergyDiscountForModules; import static tectech.util.GodforgeMath.calculateFuelConsumption; import static tectech.util.GodforgeMath.calculateMaxFuelFactor; import static tectech.util.GodforgeMath.calculateMaxHeatForModules; import static tectech.util.GodforgeMath.calculateMaxParallelForModules; import static tectech.util.GodforgeMath.calculateProcessingVoltageForModules; import static tectech.util.GodforgeMath.calculateSpeedBonusForModules; import static tectech.util.GodforgeMath.calculateStartupFuelConsumption; import static tectech.util.GodforgeMath.queryMilestoneStats; import static tectech.util.GodforgeMath.setMiscModuleParameters; import static tectech.util.TTUtility.toExponentForm; import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Objects; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.common.util.ForgeDirection; import net.minecraftforge.fluids.FluidStack; import com.google.common.collect.ImmutableList; import com.google.common.math.LongMath; 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.gtnewhorizons.modularui.api.ModularUITextures; import com.gtnewhorizons.modularui.api.drawable.IDrawable; import com.gtnewhorizons.modularui.api.drawable.Text; import com.gtnewhorizons.modularui.api.drawable.UITexture; import com.gtnewhorizons.modularui.api.forge.IItemHandlerModifiable; import com.gtnewhorizons.modularui.api.forge.ItemStackHandler; import com.gtnewhorizons.modularui.api.math.Alignment; import com.gtnewhorizons.modularui.api.math.Color; import com.gtnewhorizons.modularui.api.math.MainAxisAlignment; import com.gtnewhorizons.modularui.api.math.Pos2d; import com.gtnewhorizons.modularui.api.math.Size; import com.gtnewhorizons.modularui.api.screen.ModularWindow; import com.gtnewhorizons.modularui.api.screen.UIBuildContext; import com.gtnewhorizons.modularui.api.widget.IWidgetBuilder; import com.gtnewhorizons.modularui.api.widget.Widget; import com.gtnewhorizons.modularui.common.widget.ButtonWidget; import com.gtnewhorizons.modularui.common.widget.DrawableWidget; import com.gtnewhorizons.modularui.common.widget.DynamicPositionedColumn; import com.gtnewhorizons.modularui.common.widget.DynamicPositionedRow; import com.gtnewhorizons.modularui.common.widget.FakeSyncWidget; import com.gtnewhorizons.modularui.common.widget.FluidNameHolderWidget; import com.gtnewhorizons.modularui.common.widget.MultiChildWidget; import com.gtnewhorizons.modularui.common.widget.ProgressBar; import com.gtnewhorizons.modularui.common.widget.Scrollable; import com.gtnewhorizons.modularui.common.widget.SlotGroup; import com.gtnewhorizons.modularui.common.widget.SlotWidget; import com.gtnewhorizons.modularui.common.widget.TextWidget; import com.gtnewhorizons.modularui.common.widget.textfield.NumericWidget; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import gregtech.api.enums.Materials; import gregtech.api.enums.MaterialsUEVplus; import gregtech.api.enums.OrePrefixes; import gregtech.api.enums.Textures; import gregtech.api.gui.modularui.GTUITextures; import gregtech.api.interfaces.IHatchElement; import gregtech.api.interfaces.ITexture; import gregtech.api.interfaces.metatileentity.IMetaTileEntity; import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.metatileentity.implementations.MTEHatchInput; import gregtech.api.metatileentity.implementations.MTEHatchInputBus; import gregtech.api.render.TextureFactory; import gregtech.api.util.GTOreDictUnificator; import gregtech.api.util.HatchElementBuilder; import gregtech.api.util.IGTHatchAdder; import gregtech.api.util.MultiblockTooltipBuilder; import gregtech.common.tileentities.machines.MTEHatchInputBusME; import gregtech.common.tileentities.machines.MTEHatchInputME; import gregtech.common.tileentities.machines.MTEHatchOutputBusME; import tectech.TecTech; import tectech.loader.TecTechConfig; import tectech.thing.block.BlockGodforgeGlass; import tectech.thing.block.TileEntityForgeOfGods; import tectech.thing.gui.TecTechUITextures; import tectech.thing.metaTileEntity.multi.base.TTMultiblockBase; import tectech.thing.metaTileEntity.multi.godforge_modules.MTEBaseModule; import tectech.thing.metaTileEntity.multi.godforge_modules.MTEExoticModule; import tectech.thing.metaTileEntity.multi.godforge_modules.MTEMoltenModule; import tectech.thing.metaTileEntity.multi.godforge_modules.MTEPlasmaModule; import tectech.thing.metaTileEntity.multi.godforge_modules.MTESmeltingModule; import tectech.util.CommonValues; public class MTEForgeOfGods extends TTMultiblockBase implements IConstructable, ISurvivalConstructable { private static Textures.BlockIcons.CustomIcon ScreenON; private int fuelConsumptionFactor = 1; private int selectedFuelType = 0; private int internalBattery = 0; private int maxBatteryCharge = 100; private int gravitonShardsAvailable = 0; private int gravitonShardsSpent = 0; private int ringAmount = 1; private int stellarFuelAmount = 0; private int neededStartupFuel = 0; private long fuelConsumption = 0; private long totalRecipesProcessed = 0; private long totalFuelConsumed = 0; private float totalExtensionsBuilt = 0; private float powerMilestonePercentage = 0; private float recipeMilestonePercentage = 0; private float fuelMilestonePercentage = 0; private float structureMilestonePercentage = 0; private float invertedPowerMilestonePercentage = 0; private float invertedRecipeMilestonePercentage = 0; private float invertedFuelMilestonePercentage = 0; private float invertedStructureMilestonePercentage = 0; private BigInteger totalPowerConsumed = BigInteger.ZERO; private boolean batteryCharging = false; private boolean inversion = false; private boolean gravitonShardEjection = false; private boolean noFormatting = false; private boolean isRenderActive = false; public ArrayList moduleHatches = new ArrayList<>(); protected ItemStackHandler inputSlotHandler = new ItemStackHandler(16); private static final int FUEL_CONFIG_WINDOW_ID = 9; private static final int UPGRADE_TREE_WINDOW_ID = 10; private static final int INDIVIDUAL_UPGRADE_WINDOW_ID = 11; private static final int BATTERY_CONFIG_WINDOW_ID = 12; private static final int MILESTONE_WINDOW_ID = 13; private static final int INDIVIDUAL_MILESTONE_WINDOW_ID = 14; private static final int MANUAL_INSERTION_WINDOW_ID = 15; private static final int GENERAL_INFO_WINDOW_ID = 16; private static final int SPECIAL_THANKS_WINDOW_ID = 17; private static final int TEXTURE_INDEX = 960; private static final int[] FIRST_SPLIT_UPGRADES = new int[] { 12, 13, 14 }; private static final Integer[] UPGRADE_MATERIAL_ID_CONVERSION = { 0, 5, 7, 11, 26, 29, 30 }; private static final long POWER_MILESTONE_CONSTANT = LongMath.pow(10, 15); private static final long RECIPE_MILESTONE_CONSTANT = LongMath.pow(10, 7); private static final long FUEL_MILESTONE_CONSTANT = 10_000; private static final long RECIPE_MILESTONE_T7_CONSTANT = RECIPE_MILESTONE_CONSTANT * LongMath.pow(6, 6); private static final long FUEL_MILESTONE_T7_CONSTANT = FUEL_MILESTONE_CONSTANT * LongMath.pow(3, 6); private static final BigInteger POWER_MILESTONE_T7_CONSTANT = BigInteger.valueOf(POWER_MILESTONE_CONSTANT) .multiply(BigInteger.valueOf(LongMath.pow(9, 6))); private static final double POWER_LOG_CONSTANT = Math.log(9); private static final double RECIPE_LOG_CONSTANT = Math.log(6); private static final double FUEL_LOG_CONSTANT = Math.log(3); protected static final String STRUCTURE_PIECE_MAIN = "main"; protected static final String STRUCTURE_PIECE_SHAFT = "beam_shaft"; protected static final String STRUCTURE_PIECE_FIRST_RING = "first_ring"; protected static final String STRUCTURE_PIECE_FIRST_RING_AIR = "first_ring_air"; protected static final String STRUCTURE_PIECE_SECOND_RING = "second_ring"; protected static final String STRUCTURE_PIECE_SECOND_RING_AIR = "second_ring_air"; protected static final String STRUCTURE_PIECE_THIRD_RING = "third_ring"; protected static final String STRUCTURE_PIECE_THIRD_RING_AIR = "third_ring_air"; private static final String SCANNER_INFO_BAR = EnumChatFormatting.BLUE + "--------------------------------------------"; private static final String TOOLTIP_BAR = EnumChatFormatting.AQUA + "--------------------------------------------------------------------------"; private static final ItemStack STELLAR_FUEL = Avaritia.isModLoaded() ? getModItem(Avaritia.ID, "Resource", 1, 8) : GTOreDictUnificator.get(OrePrefixes.block, Materials.CosmicNeutronium, 1); private final boolean debugMode = TecTechConfig.DEBUG_MODE; public int survivalConstruct(ItemStack stackSize, int elementBudget, ISurvivalBuildEnvironment env) { int realBudget = elementBudget >= 1000 ? elementBudget : Math.min(1000, elementBudget * 5); // 1000 blocks max per placement. int built = survivialBuildPiece(STRUCTURE_PIECE_MAIN, stackSize, 63, 14, 1, realBudget, env, false, true); if (stackSize.stackSize > 1) { built += survivialBuildPiece( STRUCTURE_PIECE_SECOND_RING, stackSize, 55, 11, -67, realBudget, env, false, true); } if (stackSize.stackSize > 2) { built += survivialBuildPiece( STRUCTURE_PIECE_THIRD_RING, stackSize, 47, 13, -76, realBudget, env, false, true); } return built; } @Override public IStructureDefinition getStructure_EM() { return STRUCTURE_DEFINITION; } public static final IStructureDefinition STRUCTURE_DEFINITION = IStructureDefinition .builder() .addShape(STRUCTURE_PIECE_MAIN, ForgeOfGodsStructureString.MAIN_STRUCTURE) .addShape(STRUCTURE_PIECE_SHAFT, ForgeOfGodsStructureString.BEAM_SHAFT) .addShape(STRUCTURE_PIECE_FIRST_RING, ForgeOfGodsStructureString.FIRST_RING) .addShape(STRUCTURE_PIECE_FIRST_RING_AIR, ForgeOfGodsStructureString.FIRST_RING_AIR) .addShape(STRUCTURE_PIECE_SECOND_RING, ForgeOfGodsRingsStructureString.SECOND_RING) .addShape(STRUCTURE_PIECE_SECOND_RING_AIR, ForgeOfGodsRingsStructureString.SECOND_RING_AIR) .addShape(STRUCTURE_PIECE_THIRD_RING, ForgeOfGodsRingsStructureString.THIRD_RING) .addShape(STRUCTURE_PIECE_THIRD_RING_AIR, ForgeOfGodsRingsStructureString.THIRD_RING_AIR) .addElement('A', classicHatches(TEXTURE_INDEX + 3, 1, GodforgeCasings, 3)) .addElement('B', ofBlock(GodforgeCasings, 0)) .addElement('C', ofBlock(GodforgeCasings, 1)) .addElement('D', ofBlock(GodforgeCasings, 2)) .addElement('E', ofBlock(GodforgeCasings, 3)) .addElement('F', ofBlock(GodforgeCasings, 4)) .addElement('G', ofBlock(GodforgeCasings, 5)) .addElement('H', ofBlock(BlockGodforgeGlass.INSTANCE, 0)) .addElement('I', ofBlock(GodforgeCasings, 7)) .addElement( 'J', HatchElementBuilder.builder() .atLeast(moduleElement.Module) .casingIndex(TEXTURE_INDEX) .dot(2) .buildAndChain(GodforgeCasings, 0)) .addElement('K', ofBlock(GodforgeCasings, 6)) .addElement('L', ofBlock(Blocks.air, 0)) .build(); public MTEForgeOfGods(int aID, String aName, String aNameRegional) { super(aID, aName, aNameRegional); } public MTEForgeOfGods(String aName) { super(aName); } @Override public IMetaTileEntity newMetaEntity(IGregTechTileEntity aTileEntity) { return new MTEForgeOfGods(mName); } @Override @SideOnly(Side.CLIENT) public void registerIcons(IIconRegister aBlockIconRegister) { ScreenON = new Textures.BlockIcons.CustomIcon("iconsets/GODFORGE_CONTROLLER"); super.registerIcons(aBlockIconRegister); } @Override public ITexture[] getTexture(IGregTechTileEntity aBaseMetaTileEntity, ForgeDirection side, ForgeDirection facing, int colorIndex, boolean aActive, boolean aRedstone) { if (side == facing) { return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(TEXTURE_INDEX + 1), TextureFactory.builder() .addIcon(ScreenON) .extFacing() .build(), TextureFactory.builder() .addIcon(ScreenON) .extFacing() .glow() .build() }; } return new ITexture[] { Textures.BlockIcons.getCasingTextureForId(TEXTURE_INDEX + 1) }; } @Override public void construct(ItemStack stackSize, boolean hintsOnly) { structureBuild_EM(STRUCTURE_PIECE_MAIN, 63, 14, 1, stackSize, hintsOnly); if (stackSize.stackSize > 1) { buildPiece(STRUCTURE_PIECE_SECOND_RING, stackSize, hintsOnly, 55, 11, -67); } if (stackSize.stackSize > 2) { buildPiece(STRUCTURE_PIECE_THIRD_RING, stackSize, hintsOnly, 47, 13, -76); } } private final ArrayList validFuelList = new ArrayList<>() { { add(MaterialsUEVplus.DimensionallyTranscendentResidue.getFluid(1)); add(MaterialsUEVplus.RawStarMatter.getFluid(1)); add(MaterialsUEVplus.MagnetohydrodynamicallyConstrainedStarMatter.getMolten(1)); } }; @Override public boolean checkMachine_EM(IGregTechTileEntity iGregTechTileEntity, ItemStack itemStack) { moduleHatches.clear(); // Check structure of multi if (isRenderActive) { if (!structureCheck_EM(STRUCTURE_PIECE_SHAFT, 63, 14, 1) || !structureCheck_EM(STRUCTURE_PIECE_FIRST_RING_AIR, 63, 14, -59)) { destroyRenderer(); return false; } } else if (!structureCheck_EM(STRUCTURE_PIECE_MAIN, 63, 14, 1)) { return false; } if (internalBattery != 0 && !isRenderActive) { createRenderer(); } // Check there is 1 input bus if (mInputBusses.size() != 1) { return false; } // Check there is 1 me output bus { if (mOutputBusses.size() != 1) { return false; } if (!(mOutputBusses.get(0) instanceof MTEHatchOutputBusME)) { return false; } } // Make sure there are no energy hatches { if (mEnergyHatches.size() > 0) { return false; } if (mExoticEnergyHatches.size() > 0) { return false; } } // Make sure there is 1 input hatch if (mInputHatches.size() != 1) { return false; } if (isUpgradeActive(26)) { if (checkPiece(STRUCTURE_PIECE_SECOND_RING, 55, 11, -67)) { ringAmount = 2; destroySecondRing(); UpdateRenderer(); } if (isRenderActive && ringAmount >= 2 && !checkPiece(STRUCTURE_PIECE_SECOND_RING_AIR, 55, 11, -67)) { destroyRenderer(); } } else { if (ringAmount == 3) { buildThirdRing(); } if (ringAmount >= 2) { ringAmount = 1; UpdateRenderer(); buildSecondRing(); } } if (isUpgradeActive(29)) { if (checkPiece(STRUCTURE_PIECE_THIRD_RING, 47, 13, -76)) { ringAmount = 3; destroyThirdRing(); UpdateRenderer(); } if (isRenderActive && ringAmount == 3 && !checkPiece(STRUCTURE_PIECE_THIRD_RING_AIR, 47, 13, -76)) { destroyRenderer(); } } else { if (ringAmount == 3) { ringAmount = 2; UpdateRenderer(); buildThirdRing(); } } return true; } int ticker = 0; @Override public void onPostTick(IGregTechTileEntity aBaseMetaTileEntity, long aTick) { super.onPostTick(aBaseMetaTileEntity, aTick); if (aBaseMetaTileEntity.isServerSide()) { ticker++; // Check and drain fuel if (ticker % (5 * SECONDS) == 0) { ticker = 0; startRecipeProcessing(); FluidStack[] fluidInHatch = null; boolean fuelDrained = false; if (mInputHatches != null && mInputHatches.size() != 0) { fluidInHatch = this.getStoredFluids() .toArray(new FluidStack[0]); } int maxModuleCount = 8; if (upgrades[26]) { maxModuleCount += 4; } if (upgrades[29]) { maxModuleCount += 4; } if (mInputBusses.size() != 0) { if (internalBattery == 0) { MTEHatchInputBus inputBus = mInputBusses.get(0); ItemStack[] inputBusInventory = inputBus.getRealInventory(); if (inputBusInventory != null) { for (int i = 0; i < inputBusInventory.length; i++) { ItemStack itemStack = inputBusInventory[i]; if (itemStack != null && itemStack.isItemEqual(STELLAR_FUEL)) { int stacksize = itemStack.stackSize; if (inputBus instanceof MTEHatchInputBusME meBus) { ItemStack realItem = meBus.getRealInventory()[i + 16]; if (realItem == null) { break; } stacksize = realItem.stackSize; } inputBus.decrStackSize(i, stacksize); stellarFuelAmount += stacksize; inputBus.updateSlots(); } } } neededStartupFuel = calculateStartupFuelConsumption(this); if (stellarFuelAmount >= neededStartupFuel) { stellarFuelAmount -= neededStartupFuel; increaseBattery(neededStartupFuel); createRenderer(); } } else { fuelConsumption = (long) calculateFuelConsumption(this) * 5 * (batteryCharging ? 2 : 1); if (fluidInHatch != null && fuelConsumption < Integer.MAX_VALUE) { for (FluidStack fluid : fluidInHatch) { if (fluid.isFluidEqual(validFuelList.get(selectedFuelType))) { FluidStack fluidNeeded = new FluidStack( validFuelList.get(selectedFuelType), (int) fuelConsumption); FluidStack fluidReal; if (mInputHatches.get(0) instanceof MTEHatchInputME meHatch) { fluidReal = meHatch.drain(ForgeDirection.UNKNOWN, fluidNeeded, true); } else { fluidReal = mInputHatches.get(0) .drain(fluidNeeded.amount, true); } if (fluidReal == null || fluidReal.amount < fluidNeeded.amount) { reduceBattery(fuelConsumptionFactor); } else { totalFuelConsumed += getFuelFactor(); if (batteryCharging) { increaseBattery(fuelConsumptionFactor); } } fuelDrained = true; } } if (!fuelDrained) { reduceBattery(fuelConsumptionFactor); } } else { reduceBattery(fuelConsumptionFactor); } } } determineCompositionMilestoneLevel(); checkInversionStatus(); determineMilestoneProgress(); if (!debugMode) { determineGravitonShardAmount(); } if (upgrades[30] && gravitonShardEjection) { ejectGravitonShards(); } // Do module calculations and checks if (moduleHatches.size() > 0 && internalBattery > 0 && moduleHatches.size() <= maxModuleCount) { for (MTEBaseModule module : moduleHatches) { if (allowModuleConnection(module, this)) { module.connect(); calculateMaxHeatForModules(module, this); calculateSpeedBonusForModules(module, this); calculateMaxParallelForModules(module, this); calculateEnergyDiscountForModules(module, this); setMiscModuleParameters(module, this); queryMilestoneStats(module, this); if (!upgrades[28]) { calculateProcessingVoltageForModules(module, this); } } else { module.disconnect(); } } } else if (moduleHatches.size() > maxModuleCount) { for (MTEBaseModule module : moduleHatches) { module.disconnect(); } } if (mEfficiency < 0) mEfficiency = 0; endRecipeProcessing(); } } } public boolean addModuleToMachineList(IGregTechTileEntity tileEntity, int baseCasingIndex) { if (tileEntity == null) { return false; } IMetaTileEntity metaTileEntity = tileEntity.getMetaTileEntity(); if (metaTileEntity == null) { return false; } if (metaTileEntity instanceof MTEBaseModule) { return moduleHatches.add((MTEBaseModule) metaTileEntity); } return false; } public enum moduleElement implements IHatchElement { Module(MTEForgeOfGods::addModuleToMachineList, MTEBaseModule.class) { @Override public long count(MTEForgeOfGods tileEntity) { return tileEntity.moduleHatches.size(); } }; private final List> mteClasses; private final IGTHatchAdder adder; @SafeVarargs moduleElement(IGTHatchAdder adder, Class... mteClasses) { this.mteClasses = Collections.unmodifiableList(Arrays.asList(mteClasses)); this.adder = adder; } @Override public List> mteClasses() { return mteClasses; } public IGTHatchAdder adder() { return adder; } } private TileEntityForgeOfGods getRenderer() { IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); int x = gregTechTileEntity.getXCoord(); int y = gregTechTileEntity.getYCoord(); int z = gregTechTileEntity.getZCoord(); double xOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetX; double zOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetZ; double yOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetY; TileEntity tile = this.getBaseMetaTileEntity() .getWorld() .getTileEntity((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset)); if (tile instanceof TileEntityForgeOfGods forgeTile) { return forgeTile; } return null; } private void UpdateRenderer() { TileEntityForgeOfGods tile = getRenderer(); if (tile == null) return; tile.setRingCount(ringAmount); tile.setStarRadius(20); tile.setRotationSpeed(5); tile.updateToClient(); } private void createRenderer() { IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); int x = gregTechTileEntity.getXCoord(); int y = gregTechTileEntity.getYCoord(); int z = gregTechTileEntity.getZCoord(); double xOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetX; double zOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetZ; double yOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetY; this.getBaseMetaTileEntity() .getWorld() .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), Blocks.air); this.getBaseMetaTileEntity() .getWorld() .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), forgeOfGodsRenderBlock); TileEntityForgeOfGods rendererTileEntity = (TileEntityForgeOfGods) this.getBaseMetaTileEntity() .getWorld() .getTileEntity((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset)); switch (ringAmount) { case 2 -> { destroyFirstRing(); destroySecondRing(); } case 3 -> { destroyFirstRing(); destroySecondRing(); destroyThirdRing(); } default -> { destroyFirstRing(); } } rendererTileEntity.setRenderRotation(getRotation(), getDirection()); UpdateRenderer(); isRenderActive = true; } private void destroyRenderer() { IGregTechTileEntity gregTechTileEntity = this.getBaseMetaTileEntity(); int x = gregTechTileEntity.getXCoord(); int y = gregTechTileEntity.getYCoord(); int z = gregTechTileEntity.getZCoord(); double xOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetX; double zOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetZ; double yOffset = 122 * getExtendedFacing().getRelativeBackInWorld().offsetY; this.getBaseMetaTileEntity() .getWorld() .setBlock((int) (x + xOffset), (int) (y + yOffset), (int) (z + zOffset), Blocks.air); switch (ringAmount) { case 2 -> { buildFirstRing(); buildSecondRing(); } case 3 -> { buildFirstRing(); buildSecondRing(); buildThirdRing(); } default -> { buildFirstRing(); } } isRenderActive = false; } private void destroyFirstRing() { buildPiece(STRUCTURE_PIECE_FIRST_RING_AIR, null, false, 63, 14, -59); } private void destroySecondRing() { buildPiece(STRUCTURE_PIECE_SECOND_RING_AIR, null, false, 55, 11, -67); } private void destroyThirdRing() { buildPiece(STRUCTURE_PIECE_THIRD_RING_AIR, null, false, 47, 13, -76); } private void buildFirstRing() { buildPiece(STRUCTURE_PIECE_FIRST_RING, null, false, 63, 14, -59); } private void buildSecondRing() { buildPiece(STRUCTURE_PIECE_SECOND_RING, null, false, 55, 11, -67); } private void buildThirdRing() { buildPiece(STRUCTURE_PIECE_THIRD_RING, null, false, 47, 13, -76); } @Override public final void onScrewdriverRightClick(ForgeDirection side, EntityPlayer aPlayer, float aX, float aY, float aZ) { if (!debugMode) return; if (isRenderActive) { destroyRenderer(); isRenderActive = false; } else { ringAmount = 3; createRenderer(); isRenderActive = true; } } @Override public void onBlockDestroyed() { super.onBlockDestroyed(); if (isRenderActive) { destroyRenderer(); } } @Override public String[] getInfoData() { ArrayList str = new ArrayList<>(Arrays.asList(super.getInfoData())); str.add(SCANNER_INFO_BAR); str.add("Number of Rings: " + EnumChatFormatting.GOLD + ringAmount); str.add("Total Upgrades Unlocked: " + EnumChatFormatting.GOLD + getTotalActiveUpgrades()); str.add("Connected Modules: " + EnumChatFormatting.GOLD + moduleHatches.size()); str.add(SCANNER_INFO_BAR); return str.toArray(new String[0]); } @Override public void onRemoval() { if (moduleHatches != null && moduleHatches.size() > 0) { for (MTEBaseModule module : moduleHatches) { module.disconnect(); } } super.onRemoval(); } @Override public void addUIWidgets(ModularWindow.Builder builder, UIBuildContext buildContext) { if (doesBindPlayerInventory()) { builder.widget( new DrawableWidget().setDrawable(TecTechUITextures.BACKGROUND_SCREEN_BLUE) .setPos(4, 4) .setSize(190, 85)); } else { builder.widget( new DrawableWidget().setDrawable(TecTechUITextures.BACKGROUND_SCREEN_BLUE_NO_INVENTORY) .setPos(4, 4) .setSize(190, 171)); } buildContext.addSyncedWindow(UPGRADE_TREE_WINDOW_ID, this::createUpgradeTreeWindow); buildContext.addSyncedWindow(INDIVIDUAL_UPGRADE_WINDOW_ID, this::createIndividualUpgradeWindow); buildContext.addSyncedWindow(FUEL_CONFIG_WINDOW_ID, this::createFuelConfigWindow); buildContext.addSyncedWindow(BATTERY_CONFIG_WINDOW_ID, this::createBatteryWindow); buildContext.addSyncedWindow(MILESTONE_WINDOW_ID, this::createMilestoneWindow); buildContext.addSyncedWindow(INDIVIDUAL_MILESTONE_WINDOW_ID, this::createIndividualMilestoneWindow); buildContext.addSyncedWindow(MANUAL_INSERTION_WINDOW_ID, this::createManualInsertionWindow); buildContext.addSyncedWindow(GENERAL_INFO_WINDOW_ID, this::createGeneralInfoWindow); buildContext.addSyncedWindow(SPECIAL_THANKS_WINDOW_ID, this::createSpecialThanksWindow); builder.widget( new ButtonWidget().setOnClick( (clickData, widget) -> { if (!widget.isClient()) widget.getContext() .openSyncedWindow(UPGRADE_TREE_WINDOW_ID); }) .setSize(16, 16) .setBackground(() -> { List button = new ArrayList<>(); button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); button.add(TecTechUITextures.OVERLAY_BUTTON_ARROW_BLUE_UP); return button.toArray(new IDrawable[0]); }) .addTooltip("Path of Celestial Transcendence") .setPos(174, 167) .setTooltipShowUpDelay(TOOLTIP_DELAY)) .widget( new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_HEAT_SINK_SMALL) .setPos(174, 183) .setSize(16, 6)) .widget(new ButtonWidget().setOnClick((clickData, widget) -> { if (!widget.isClient()) { widget.getContext() .openSyncedWindow(FUEL_CONFIG_WINDOW_ID); } }) .setSize(16, 16) .setBackground(() -> { List button = new ArrayList<>(); button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); button.add(TecTechUITextures.OVERLAY_BUTTON_HEAT_ON); return button.toArray(new IDrawable[0]); }) .addTooltip(translateToLocal("fog.button.fuelconfig.tooltip")) .setPos(174, 110) .setTooltipShowUpDelay(TOOLTIP_DELAY)) .widget( TextWidget.dynamicText(this::storedFuel) .setDefaultColor(EnumChatFormatting.WHITE) .setPos(6, 8) .setSize(74, 34)) .widget(createPowerSwitchButton()) .widget(createBatteryButton(builder)) .widget(createEjectionSwitch(builder)) .widget(new FakeSyncWidget.BooleanSyncer(() -> getBaseMetaTileEntity().isAllowedToWork(), val -> { if (val) { getBaseMetaTileEntity().enableWorking(); } else { getBaseMetaTileEntity().disableWorking(); } })) .widget(new ButtonWidget().setOnClick((clickData, widget) -> { if (!widget.isClient()) { checkMachine_EM(this.getBaseMetaTileEntity(), null); } }) .setSize(16, 16) .setBackground(() -> { List button = new ArrayList<>(); button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); button.add(TecTechUITextures.OVERLAY_CYCLIC_BLUE); return button.toArray(new IDrawable[0]); }) .addTooltip(translateToLocal("fog.button.structurecheck.tooltip")) .setPos(8, 91) .setTooltipShowUpDelay(TOOLTIP_DELAY)) .widget(new ButtonWidget().setOnClick((clickData, widget) -> { if (!widget.isClient()) { widget.getContext() .openSyncedWindow(MILESTONE_WINDOW_ID); } }) .setSize(16, 16) .setBackground(() -> { List button = new ArrayList<>(); button.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); button.add(TecTechUITextures.OVERLAY_BUTTON_FLAG); return button.toArray(new IDrawable[0]); }) .addTooltip(translateToLocal("fog.button.milestones.tooltip")) .setTooltipShowUpDelay(TOOLTIP_DELAY) .setPos(174, 91)) .widget( new ButtonWidget().setOnClick( (clickData, widget) -> { if (!widget.isClient()) widget.getContext() .openSyncedWindow(GENERAL_INFO_WINDOW_ID); }) .setSize(18, 18) .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.clickhere")) .setPos(172, 67) .setTooltipShowUpDelay(TOOLTIP_DELAY)) .widget( new ButtonWidget().setOnClick( (clickData, widget) -> { if (!widget.isClient()) widget.getContext() .openSyncedWindow(SPECIAL_THANKS_WINDOW_ID); }) .setSize(16, 16) .addTooltip(translateToLocal("fog.button.thanks.tooltip")) .setBackground(TecTechUITextures.OVERLAY_BUTTON_HEART) .setPos(8, 69) .setTooltipShowUpDelay(TOOLTIP_DELAY)); } @Override public void addGregTechLogo(ModularWindow.Builder builder) { builder.widget( new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_GODFORGE_LOGO) .setSize(18, 18) .setPos(172, 67)); } @Override protected ButtonWidget createPowerSwitchButton() { Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); if (getBaseMetaTileEntity().isAllowedToWork()) { getBaseMetaTileEntity().disableWorking(); } else { getBaseMetaTileEntity().enableWorking(); } }) .setPlayClickSound(false) .setBackground(() -> { List ret = new ArrayList<>(); ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); if (getBaseMetaTileEntity().isAllowedToWork()) { ret.add(TecTechUITextures.OVERLAY_BUTTON_POWER_SWITCH_ON); } else { ret.add(TecTechUITextures.OVERLAY_BUTTON_POWER_SWITCH_DISABLED); } return ret.toArray(new IDrawable[0]); }) .setPos(174, doesBindPlayerInventory() ? 148 : 172) .setSize(16, 16); button.addTooltip("Power Switch") .setTooltipShowUpDelay(TOOLTIP_DELAY); return (ButtonWidget) button; } protected ButtonWidget createEjectionSwitch(IWidgetBuilder builder) { Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { if (upgrades[30]) { gravitonShardEjection = !gravitonShardEjection; } }) .setPlayClickSound(upgrades[30]) .setBackground(() -> { List ret = new ArrayList<>(); if (!upgrades[30]) { return ret.toArray(new IDrawable[0]); } if (gravitonShardEjection) { ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); ret.add(TecTechUITextures.OVERLAY_EJECTION_ON); } else { ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); ret.add(TecTechUITextures.OVERLAY_EJECTION_LOCKED); } return ret.toArray(new IDrawable[0]); }) .attachSyncer( new FakeSyncWidget.BooleanSyncer(() -> gravitonShardEjection, val -> gravitonShardEjection = val), builder) .setPos(26, 91) .setSize(16, 16) .attachSyncer(new FakeSyncWidget.BooleanSyncer(() -> upgrades[30], val -> upgrades[30] = val), builder); if (upgrades[30]) { button.addTooltip(translateToLocal("fog.button.ejection.tooltip")); button.setTooltipShowUpDelay(TOOLTIP_DELAY); } return (ButtonWidget) button; } protected Widget createBatteryButton(IWidgetBuilder builder) { Widget button = new ButtonWidget().setOnClick((clickData, widget) -> { TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); if (clickData.mouseButton == 0) { batteryCharging = !batteryCharging; } else if (clickData.mouseButton == 1 && !widget.isClient() && upgrades[8]) { widget.getContext() .openSyncedWindow(BATTERY_CONFIG_WINDOW_ID); } }) .setPlayClickSound(false) .setBackground(() -> { List ret = new ArrayList<>(); ret.add(TecTechUITextures.BUTTON_CELESTIAL_32x32); if (batteryCharging) { ret.add(TecTechUITextures.OVERLAY_BUTTON_BATTERY_ON); } else { ret.add(TecTechUITextures.OVERLAY_BUTTON_BATTERY_OFF); } return ret.toArray(new IDrawable[0]); }) .setPos(174, 129) .setSize(16, 16); button.addTooltip(translateToLocal("fog.button.battery.tooltip.01")) .addTooltip(EnumChatFormatting.GRAY + translateToLocal("fog.button.battery.tooltip.02")) .setTooltipShowUpDelay(TOOLTIP_DELAY) .attachSyncer( new FakeSyncWidget.BooleanSyncer(() -> batteryCharging, val -> batteryCharging = val), builder); return button; } protected ModularWindow createBatteryWindow(final EntityPlayer player) { final int WIDTH = 78; final int HEIGHT = 52; final int PARENT_WIDTH = getGUIWidth(); final int PARENT_HEIGHT = getGUIHeight(); ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); builder.setGuiTint(getGUIColorization()); builder.setDraggable(true); builder.setPos( (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) .add( Alignment.BottomRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT)) .add(WIDTH - 3, 0) .subtract(0, 10))); builder.widget( TextWidget.localised("gt.blockmachines.multimachine.FOG.batteryinfo") .setPos(3, 4) .setSize(74, 20)) .widget( new NumericWidget().setSetter(val -> maxBatteryCharge = (int) val) .setGetter(() -> maxBatteryCharge) .setBounds(1, Integer.MAX_VALUE) .setDefaultValue(100) .setScrollValues(1, 4, 64) .setTextAlignment(Alignment.Center) .setTextColor(Color.WHITE.normal) .setSize(70, 18) .setPos(4, 25) .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)); return builder.build(); } protected ModularWindow createFuelConfigWindow(final EntityPlayer player) { final int WIDTH = 78; final int HEIGHT = 130; final int PARENT_WIDTH = getGUIWidth(); final int PARENT_HEIGHT = getGUIHeight(); ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); builder.setGuiTint(getGUIColorization()); builder.setDraggable(true); builder.setPos( (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) .add( Alignment.TopRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT)) .add(WIDTH - 3, 0))); builder.widget( TextWidget.localised("gt.blockmachines.multimachine.FOG.fuelconsumption") .setPos(3, 2) .setSize(74, 34)) .widget( new NumericWidget().setSetter(val -> fuelConsumptionFactor = (int) val) .setGetter(() -> fuelConsumptionFactor) .setBounds(1, calculateMaxFuelFactor(this)) .setDefaultValue(1) .setScrollValues(1, 4, 64) .setTextAlignment(Alignment.Center) .setTextColor(Color.WHITE.normal) .setSize(70, 18) .setPos(4, 35) .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)) .widget( new DrawableWidget().setDrawable(ModularUITextures.ICON_INFO) .setPos(64, 24) .setSize(10, 10) .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.0")) .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.1")) .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.2")) .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.3")) .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.4")) .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfo.5")) .setTooltipShowUpDelay(TOOLTIP_DELAY)) .widget( TextWidget.localised("gt.blockmachines.multimachine.FOG.fueltype") .setPos(3, 57) .setSize(74, 24)) .widget( TextWidget.localised("gt.blockmachines.multimachine.FOG.fuelusage") .setPos(3, 100) .setSize(74, 20)) .widget( TextWidget.dynamicText(this::fuelUsage) .setPos(3, 115) .setSize(74, 15)) .widget( new MultiChildWidget().addChild( new FluidNameHolderWidget( () -> MaterialsUEVplus.DimensionallyTranscendentResidue.getFluid(1) .getUnlocalizedName() .substring(6), (String) -> MaterialsUEVplus.DimensionallyTranscendentResidue.getFluid(1) .getUnlocalizedName()) { @Override public void buildTooltip(List tooltip) { FluidStack fluid = createFluidStack(); addFluidNameInfo(tooltip, fluid); addAdditionalFluidInfo(tooltip, fluid); } }.setTooltipShowUpDelay(TOOLTIP_DELAY) .setPos(1, 1) .setSize(16, 16)) .addChild(new ButtonWidget().setOnClick((clickData, widget) -> { TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); selectedFuelType = 0; }) .setBackground(() -> { if (selectedFuelType == 0) { return new IDrawable[] { TecTechUITextures.SLOT_OUTLINE_GREEN }; } else { return new IDrawable[] {}; } }) .setSize(18, 18) .attachSyncer(new FakeSyncWidget.IntegerSyncer(this::getFuelType, this::setFuelType), builder)) .setPos(6, 82) .setSize(18, 18)) .widget( new MultiChildWidget().addChild( new FluidNameHolderWidget( () -> MaterialsUEVplus.RawStarMatter.getFluid(1) .getUnlocalizedName() .substring(6), (String) -> MaterialsUEVplus.RawStarMatter.getFluid(1) .getUnlocalizedName()) { @Override public void buildTooltip(List tooltip) { FluidStack fluid = createFluidStack(); addFluidNameInfo(tooltip, fluid); addAdditionalFluidInfo(tooltip, fluid); } }.setTooltipShowUpDelay(TOOLTIP_DELAY) .setPos(1, 1) .setSize(16, 16)) .addChild(new ButtonWidget().setOnClick((clickData, widget) -> { TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); selectedFuelType = 1; }) .setBackground(() -> { if (selectedFuelType == 1) { return new IDrawable[] { TecTechUITextures.SLOT_OUTLINE_GREEN }; } else { return new IDrawable[] {}; } }) .setSize(18, 18)) .setPos(29, 82) .setSize(18, 18) .attachSyncer(new FakeSyncWidget.IntegerSyncer(this::getFuelType, this::setFuelType), builder)) .widget( new MultiChildWidget().addChild( new FluidNameHolderWidget( () -> MaterialsUEVplus.MagnetohydrodynamicallyConstrainedStarMatter.getMolten(1) .getUnlocalizedName() .substring(6), (String) -> MaterialsUEVplus.MagnetohydrodynamicallyConstrainedStarMatter.getMolten(1) .getUnlocalizedName()) { @Override public void buildTooltip(List tooltip) { FluidStack fluid = createFluidStack(); addFluidNameInfo(tooltip, fluid); addAdditionalFluidInfo(tooltip, fluid); } }.setTooltipShowUpDelay(TOOLTIP_DELAY) .setPos(1, 1) .setSize(16, 16)) .addChild(new ButtonWidget().setOnClick((clickData, widget) -> { TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); selectedFuelType = 2; }) .setBackground(() -> { if (selectedFuelType == 2) { return new IDrawable[] { TecTechUITextures.SLOT_OUTLINE_GREEN }; } else { return new IDrawable[] {}; } }) .setSize(18, 18)) .setPos(52, 82) .setSize(18, 18) .attachSyncer(new FakeSyncWidget.IntegerSyncer(this::getFuelType, this::setFuelType), builder)); return builder.build(); } private final int[] milestoneProgress = new int[] { 0, 0, 0, 0 }; protected ModularWindow createMilestoneWindow(final EntityPlayer player) { final int WIDTH = 400; final int HEIGHT = 300; ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); builder.setBackground(TecTechUITextures.BACKGROUND_SPACE); builder.setGuiTint(getGUIColorization()); builder.setDraggable(true); builder.widget(createMilestoneButton(0, 80, 100, new Pos2d(62, 24))); builder.widget(createMilestoneButton(1, 70, 98, new Pos2d(263, 25))); builder.widget(createMilestoneButton(2, 100, 100, new Pos2d(52, 169))); builder.widget(createMilestoneButton(3, 100, 100, new Pos2d(248, 169))); builder.widget( TextWidget.localised("gt.blockmachines.multimachine.FOG.powermilestone") .setDefaultColor(EnumChatFormatting.GOLD) .setPos(77, 45) .setSize(50, 30)); builder.widget( TextWidget.localised("gt.blockmachines.multimachine.FOG.recipemilestone") .setDefaultColor(EnumChatFormatting.GOLD) .setPos(268, 45) .setSize(60, 30)); builder.widget( TextWidget.localised("gt.blockmachines.multimachine.FOG.fuelmilestone") .setDefaultColor(EnumChatFormatting.GOLD) .setPos(77, 190) .setSize(50, 30)); builder.widget( TextWidget.localised("gt.blockmachines.multimachine.FOG.purchasablemilestone") .setDefaultColor(EnumChatFormatting.GOLD) .setPos(268, 190) .setSize(60, 30)); builder.widget( new DrawableWidget().setDrawable(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BACKGROUND) .setPos(37, 70) .setSize(130, 7)) .widget( new DrawableWidget().setDrawable(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BACKGROUND) .setPos(233, 70) .setSize(130, 7)) .widget( new DrawableWidget().setDrawable(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BACKGROUND) .setPos(37, 215) .setSize(130, 7)) .widget( new DrawableWidget().setDrawable(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BACKGROUND) .setPos(233, 215) .setSize(130, 7)); builder.widget( new ProgressBar().setProgress(() -> powerMilestonePercentage) .setDirection(ProgressBar.Direction.RIGHT) .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_RED, 130) .setSynced(true, false) .setSize(130, 7) .setPos(37, 70)) .widget( new ProgressBar().setProgress(() -> recipeMilestonePercentage) .setDirection(ProgressBar.Direction.RIGHT) .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_PURPLE, 130) .setSynced(true, false) .setSize(130, 7) .setPos(233, 70)) .widget( new ProgressBar().setProgress(() -> fuelMilestonePercentage) .setDirection(ProgressBar.Direction.RIGHT) .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BLUE, 130) .setSynced(true, false) .setSize(130, 7) .setPos(37, 215)) .widget( new ProgressBar().setProgress(() -> structureMilestonePercentage) .setDirection(ProgressBar.Direction.RIGHT) .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_RAINBOW, 130) .setSynced(true, false) .setSize(130, 7) .setPos(233, 215)) .widget( new ProgressBar().setProgress(() -> invertedPowerMilestonePercentage) .setDirection(ProgressBar.Direction.LEFT) .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_RED_INVERTED, 130) .setSynced(true, false) .setSize(130, 7) .setPos(37, 70)) .widget( new ProgressBar().setProgress(() -> invertedRecipeMilestonePercentage) .setDirection(ProgressBar.Direction.LEFT) .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_PURPLE_INVERTED, 130) .setSynced(true, false) .setSize(130, 7) .setPos(233, 70)) .widget( new ProgressBar().setProgress(() -> invertedFuelMilestonePercentage) .setDirection(ProgressBar.Direction.LEFT) .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_BLUE_INVERTED, 130) .setSynced(true, false) .setSize(130, 7) .setPos(37, 215)) .widget( new ProgressBar().setProgress(() -> invertedStructureMilestonePercentage) .setDirection(ProgressBar.Direction.LEFT) .setTexture(TecTechUITextures.PROGRESSBAR_GODFORGE_MILESTONE_RAINBOW_INVERTED, 130) .setSynced(true, false) .setSize(130, 7) .setPos(233, 215)) .widget( ButtonWidget.closeWindowButton(true) .setPos(382, 6)); return builder.build(); } protected ModularWindow createIndividualMilestoneWindow(final EntityPlayer player) { final int WIDTH = 150; final int HEIGHT = 150; int symbol_width; int symbol_height; String milestoneType; ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); UITexture symbol; switch (currentMilestoneID) { case 1 -> { symbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CONVERSION; symbol_width = 54; symbol_height = 75; milestoneType = "recipe"; } case 2 -> { symbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CATALYST; symbol_width = 75; symbol_height = 75; milestoneType = "fuel"; } case 3 -> { symbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_COMPOSITION; symbol_width = 75; symbol_height = 75; milestoneType = "purchasable"; } default -> { symbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CHARGE; symbol_width = 60; symbol_height = 75; milestoneType = "power"; } } builder.setBackground(TecTechUITextures.BACKGROUND_GLOW_WHITE); builder.setDraggable(true); builder.widget( ButtonWidget.closeWindowButton(true) .setPos(134, 4)) .widget( new DrawableWidget().setDrawable(symbol) .setSize(symbol_width, symbol_height) .setPos((WIDTH - symbol_width) / 2, (HEIGHT - symbol_height) / 2)) .widget( TextWidget.localised("gt.blockmachines.multimachine.FOG." + milestoneType + "milestone") .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.Center) .setPos(0, 8) .setSize(150, 15)) .widget( TextWidget.dynamicText(this::inversionStatusText) .setDefaultColor(EnumChatFormatting.AQUA) .setTextAlignment(Alignment.Center) .setScale(0.8f) .setPos(0, 120) .setSize(150, 15)) .widget( TextWidget.dynamicText(() -> totalMilestoneProgress(currentMilestoneID)) .setScale(0.7f) .setDefaultColor(EnumChatFormatting.WHITE) .setTextAlignment(Alignment.Center) .setPos(5, 30) .setSize(140, 30)) .widget( TextWidget.dynamicText(() -> currentMilestone(currentMilestoneID)) .setScale(0.7f) .setDefaultColor(EnumChatFormatting.WHITE) .setTextAlignment(Alignment.Center) .setPos(5, 50) .setSize(140, 30)) .widget( TextWidget.dynamicText(() -> milestoneProgressText(currentMilestoneID, true)) .setScale(0.7f) .setDefaultColor(EnumChatFormatting.WHITE) .setSize(140, 30) .setPos(5, 70)) .widget( TextWidget.dynamicText(() -> gravitonShardAmountText(currentMilestoneID)) .setScale(0.7f) .setDefaultColor(EnumChatFormatting.WHITE) .setSize(140, 30) .setPos(5, 90)) .widget(new ButtonWidget().setOnClick((clickData, widget) -> { TecTech.proxy.playSound(getBaseMetaTileEntity(), "fx_click"); if (clickData.mouseButton == 0) { noFormatting = !noFormatting; } }) .setSize(10, 10) .addTooltip(translateToLocal("fog.button.formatting.tooltip")) .setBackground(TecTechUITextures.OVERLAY_CYCLIC_BLUE) .setPos(5, 135) .setTooltipShowUpDelay(TOOLTIP_DELAY) .attachSyncer( new FakeSyncWidget.BooleanSyncer(() -> noFormatting, val -> noFormatting = val), builder)); return builder.build(); } private int currentMilestoneID = 0; private Widget createMilestoneButton(int milestoneID, int width, int height, Pos2d pos) { return new ButtonWidget().setOnClick((clickData, widget) -> { currentMilestoneID = milestoneID; if (!widget.isClient()) { if (widget.getContext() .isWindowOpen(INDIVIDUAL_MILESTONE_WINDOW_ID)) { widget.getContext() .closeWindow(INDIVIDUAL_MILESTONE_WINDOW_ID); } widget.getContext() .openSyncedWindow(INDIVIDUAL_MILESTONE_WINDOW_ID); } }) .setSize(width, height) .setBackground(() -> switch (milestoneID) { case 1 -> new IDrawable[] { TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CONVERSION_GLOW }; case 2 -> new IDrawable[] { TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CATALYST_GLOW }; case 3 -> new IDrawable[] { TecTechUITextures.PICTURE_GODFORGE_MILESTONE_COMPOSITION_GLOW }; default -> new IDrawable[] { TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CHARGE_GLOW }; }) .addTooltip(translateToLocal("gt.blockmachines.multimachine.FOG.milestoneinfo")) .setPos(pos) .setTooltipShowUpDelay(TOOLTIP_DELAY); } private int currentUpgradeID = 0; private int currentColorCode = 0; private int currentMilestoneBG = 0; private int gravitonShardCost = 0; private int[][] prereqUpgrades = new int[31][]; private int[] followupUpgrades = new int[] {}; private boolean isUpradeSplitStart = false; private boolean doesCurrentUpgradeRequireExtraMats = false; private boolean[] allPrereqRequired = new boolean[31]; private boolean[] upgrades = new boolean[31]; private boolean[] materialPaidUpgrades = new boolean[7]; protected ModularWindow createUpgradeTreeWindow(final EntityPlayer player) { final Scrollable scrollable = new Scrollable().setVerticalScroll(); final int PARENT_WIDTH = 300; final int PARENT_HEIGHT = 300; ModularWindow.Builder builder = ModularWindow.builder(PARENT_WIDTH, PARENT_HEIGHT); scrollable.widget(createUpgradeConnectorLine(new Pos2d(143, 71), 45, 0, 0, 0, 1)) .widget(createUpgradeConnectorLine(new Pos2d(124, 124), 60, 27, 0, 1, 2)) .widget(createUpgradeConnectorLine(new Pos2d(162, 124), 60, 333, 0, 1, 3)) .widget(createUpgradeConnectorLine(new Pos2d(94, 184), 60, 27, 0, 2, 4)) .widget(createUpgradeConnectorLine(new Pos2d(130, 184), 60, 336, 0, 2, 5)) .widget(createUpgradeConnectorLine(new Pos2d(156, 184), 60, 24, 0, 3, 5)) .widget(createUpgradeConnectorLine(new Pos2d(192, 184), 60, 333, 0, 3, 6)) .widget(createUpgradeConnectorLine(new Pos2d(143, 251), 45, 0, 0, 5, 7)) .widget(createUpgradeConnectorLine(new Pos2d(143, 311), 45, 0, 0, 7, 9)) .widget(createUpgradeConnectorLine(new Pos2d(78, 250), 110, 5, 4, 4, 8)) .widget(createUpgradeConnectorLine(new Pos2d(110, 290), 80, 40, 4, 7, 8)) .widget(createUpgradeConnectorLine(new Pos2d(208, 250), 110, 355, 4, 6, 10)) .widget(createUpgradeConnectorLine(new Pos2d(176, 290), 80, 320, 4, 7, 10)) .widget(createUpgradeConnectorLine(new Pos2d(100, 355), 80, 313, 0, 8, 11)) .widget(createUpgradeConnectorLine(new Pos2d(186, 355), 80, 47, 0, 10, 11)) .widget(createUpgradeConnectorLine(new Pos2d(143, 430), 48, 0, 2, 11, 13)) .widget(createUpgradeConnectorLine(new Pos2d(143, 490), 48, 0, 2, 13, 18)) .widget(createUpgradeConnectorLine(new Pos2d(143, 550), 48, 0, 2, 18, 21)) .widget(createUpgradeConnectorLine(new Pos2d(143, 610), 48, 0, 2, 21, 23)) .widget(createUpgradeConnectorLine(new Pos2d(110, 410), 80, 40, 1, 11, 12)) .widget(createUpgradeConnectorLine(new Pos2d(83, 490), 48, 0, 1, 12, 17)) .widget(createUpgradeConnectorLine(new Pos2d(83, 550), 48, 0, 1, 17, 20)) .widget(createUpgradeConnectorLine(new Pos2d(101, 590), 80, 320, 1, 20, 23)) .widget(createUpgradeConnectorLine(new Pos2d(53, 536), 35, 45, 1, 17, 16)) .widget(createUpgradeConnectorLine(new Pos2d(176, 410), 80, 320, 3, 11, 14)) .widget(createUpgradeConnectorLine(new Pos2d(203, 490), 48, 0, 3, 14, 19)) .widget(createUpgradeConnectorLine(new Pos2d(203, 550), 48, 0, 3, 19, 22)) .widget(createUpgradeConnectorLine(new Pos2d(185, 590), 80, 40, 3, 22, 23)) .widget(createUpgradeConnectorLine(new Pos2d(233, 476), 35, 315, 3, 14, 15)) .widget(createUpgradeConnectorLine(new Pos2d(143, 670), 48, 0, 0, 23, 24)) .widget(createUpgradeConnectorLine(new Pos2d(101, 707), 75, 62.3f, 0, 24, 25)) .widget(createUpgradeConnectorLine(new Pos2d(53, 772), 78, 0, 0, 25, 26)) .widget(createUpgradeConnectorLine(new Pos2d(95, 837), 75, 297.7f, 0, 26, 27)) .widget(createUpgradeConnectorLine(new Pos2d(191, 837), 75, 62.3f, 0, 27, 28)) .widget(createUpgradeConnectorLine(new Pos2d(233, 772), 78, 0, 0, 28, 29)) .widget(createUpgradeConnectorLine(new Pos2d(191, 747), 75, 62.3f, 0, 29, 30)); scrollable .widget( createUpgradeBox( 0, 0, 3, new int[] {}, false, new int[] { 1 }, false, true, 0, new Pos2d(126, 56), scrollable)) .widget( createUpgradeBox( 1, 0, 1, new int[] { 0 }, false, new int[] { 2, 3 }, false, false, 1, new Pos2d(126, 116), scrollable)) .widget( createUpgradeBox( 2, 0, 2, new int[] { 1 }, false, new int[] { 4, 5 }, false, false, 1, new Pos2d(96, 176), scrollable)) .widget( createUpgradeBox( 3, 0, 2, new int[] { 1 }, false, new int[] { 5, 6 }, false, false, 1, new Pos2d(156, 176), scrollable)) .widget( createUpgradeBox( 4, 0, 0, new int[] { 2 }, false, new int[] { 8 }, false, false, 1, new Pos2d(66, 236), scrollable)) .widget( createUpgradeBox( 5, 0, 3, new int[] { 2, 3 }, false, new int[] { 7 }, false, true, 1, new Pos2d(126, 236), scrollable)) .widget( createUpgradeBox( 6, 0, 1, new int[] { 3 }, false, new int[] { 10 }, false, false, 1, new Pos2d(186, 236), scrollable)) .widget( createUpgradeBox( 7, 0, 3, new int[] { 5 }, false, new int[] { 8, 9, 10 }, false, true, 2, new Pos2d(126, 296), scrollable)) .widget( createUpgradeBox( 8, 0, 0, new int[] { 4, 7 }, true, new int[] { 11 }, false, false, 2, new Pos2d(56, 356), scrollable)) .widget( createUpgradeBox( 9, 0, 2, new int[] { 7 }, false, new int[] {}, false, false, 2, new Pos2d(126, 356), scrollable)) .widget( createUpgradeBox( 10, 0, 1, new int[] { 6, 7 }, true, new int[] { 11 }, false, false, 2, new Pos2d(196, 356), scrollable)) .widget( createUpgradeBox( 11, 0, 3, new int[] { 8, 10 }, false, new int[] { 12, 13, 14 }, false, true, 2, new Pos2d(126, 416), scrollable)) .widget( createUpgradeBox( 12, 1, 2, new int[] { 11 }, false, new int[] { 17 }, true, false, 3, new Pos2d(66, 476), scrollable)) .widget( createUpgradeBox( 13, 2, 1, new int[] { 11 }, false, new int[] { 18 }, true, false, 3, new Pos2d(126, 476), scrollable)) .widget( createUpgradeBox( 14, 3, 0, new int[] { 11 }, false, new int[] { 15, 19 }, true, false, 3, new Pos2d(186, 476), scrollable)) .widget( createUpgradeBox( 15, 3, 1, new int[] { 14 }, false, new int[] {}, false, false, 4, new Pos2d(246, 496), scrollable)) .widget( createUpgradeBox( 16, 1, 1, new int[] { 17 }, false, new int[] {}, false, false, 4, new Pos2d(6, 556), scrollable)) .widget( createUpgradeBox( 17, 1, 0, new int[] { 12 }, false, new int[] { 16, 20 }, false, false, 3, new Pos2d(66, 536), scrollable)) .widget( createUpgradeBox( 18, 2, 1, new int[] { 13 }, false, new int[] { 21 }, false, false, 3, new Pos2d(126, 536), scrollable)) .widget( createUpgradeBox( 19, 3, 0, new int[] { 14 }, false, new int[] { 22 }, false, false, 3, new Pos2d(186, 536), scrollable)) .widget( createUpgradeBox( 20, 1, 0, new int[] { 17 }, false, new int[] { 23 }, false, false, 3, new Pos2d(66, 596), scrollable)) .widget( createUpgradeBox( 21, 2, 1, new int[] { 18 }, false, new int[] { 23 }, false, false, 3, new Pos2d(126, 596), scrollable)) .widget( createUpgradeBox( 22, 3, 1, new int[] { 19 }, false, new int[] { 23 }, false, false, 3, new Pos2d(186, 596), scrollable)) .widget( createUpgradeBox( 23, 0, 0, new int[] { 20, 21, 22 }, false, new int[] { 24 }, false, false, 4, new Pos2d(126, 656), scrollable)) .widget( createUpgradeBox( 24, 0, 1, new int[] { 23 }, false, new int[] { 25 }, false, false, 5, new Pos2d(126, 718), scrollable)) .widget( createUpgradeBox( 25, 0, 1, new int[] { 24 }, false, new int[] { 26 }, false, false, 6, new Pos2d(36, 758), scrollable)) .widget( createUpgradeBox( 26, 0, 3, new int[] { 25 }, false, new int[] { 27 }, false, true, 7, new Pos2d(36, 848), scrollable)) .widget( createUpgradeBox( 27, 0, 2, new int[] { 26 }, false, new int[] { 28 }, false, false, 8, new Pos2d(126, 888), scrollable)) .widget( createUpgradeBox( 28, 0, 0, new int[] { 27 }, false, new int[] { 29 }, false, false, 9, new Pos2d(216, 848), scrollable)) .widget( createUpgradeBox( 29, 0, 3, new int[] { 28 }, false, new int[] { 30 }, false, true, 10, new Pos2d(216, 758), scrollable)) .widget( createUpgradeBox( 30, 0, 3, new int[] { 29 }, false, new int[] {}, false, true, 12, new Pos2d(126, 798), scrollable)) .widget(new TextWidget("").setPos(0, 945)); builder.widget( new DrawableWidget().setDrawable(TecTechUITextures.BACKGROUND_STAR) .setPos(0, 0) .setSize(300, 300)) .widget( scrollable.setSize(292, 292) .setPos(4, 4)) .widget( ButtonWidget.closeWindowButton(true) .setOnClick((data, widget) -> { if (!widget.isClient()) { widget.getWindow() .closeWindow(); widget.getContext() .closeWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); } }) .setPos(282, 4)); if (debugMode) { builder.widget(new MultiChildWidget().addChild(new ButtonWidget().setOnClick((clickData, widget) -> { upgrades = new boolean[31]; materialPaidUpgrades = new boolean[7]; }) .setSize(40, 15) .setBackground(GTUITextures.BUTTON_STANDARD) .addTooltip(translateToLocal("fog.debug.resetbutton.tooltip")) .setTooltipShowUpDelay(TOOLTIP_DELAY)) .addChild( new TextWidget(translateToLocal("fog.debug.resetbutton.text")).setTextAlignment(Alignment.Center) .setScale(0.57f) .setMaxWidth(36) .setPos(3, 3)) .addChild( new NumericWidget().setSetter(val -> gravitonShardsAvailable = (int) val) .setGetter(() -> gravitonShardsAvailable) .setBounds(0, 112) .setDefaultValue(0) .setScrollValues(1, 4, 64) .setTextAlignment(Alignment.Center) .setTextColor(Color.WHITE.normal) .setSize(25, 18) .setPos(4, 16) .addTooltip(translateToLocal("fog.debug.gravitonshardsetter.tooltip")) .setTooltipShowUpDelay(TOOLTIP_DELAY) .setBackground(GTUITextures.BACKGROUND_TEXT_FIELD)) .addChild( new ButtonWidget().setOnClick((clickData, widget) -> Arrays.fill(upgrades, true)) .setSize(40, 15) .setBackground(GTUITextures.BUTTON_STANDARD) .addTooltip(translateToLocal("fog.debug.unlockall.text")) .setTooltipShowUpDelay(TOOLTIP_DELAY) .setPos(0, 35)) .addChild( new TextWidget(translateToLocal("fog.debug.unlockall.text")).setTextAlignment(Alignment.Center) .setScale(0.57f) .setMaxWidth(36) .setPos(3, 38)) .setPos(4, 4)); } return builder.build(); } protected ModularWindow createIndividualUpgradeWindow(final EntityPlayer player) { UITexture background; UITexture overlay; UITexture milestoneSymbol; float widthRatio; switch (currentColorCode) { case 1 -> { background = TecTechUITextures.BACKGROUND_GLOW_PURPLE; overlay = TecTechUITextures.PICTURE_OVERLAY_PURPLE; } case 2 -> { background = TecTechUITextures.BACKGROUND_GLOW_ORANGE; overlay = TecTechUITextures.PICTURE_OVERLAY_ORANGE; } case 3 -> { background = TecTechUITextures.BACKGROUND_GLOW_GREEN; overlay = TecTechUITextures.PICTURE_OVERLAY_GREEN; } default -> { background = TecTechUITextures.BACKGROUND_GLOW_BLUE; overlay = TecTechUITextures.PICTURE_OVERLAY_BLUE; } } switch (currentMilestoneBG) { case 1 -> { milestoneSymbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CONVERSION; widthRatio = 0.72f; } case 2 -> { milestoneSymbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CATALYST; widthRatio = 1f; } case 3 -> { milestoneSymbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_COMPOSITION; widthRatio = 1f; } default -> { milestoneSymbol = TecTechUITextures.PICTURE_GODFORGE_MILESTONE_CHARGE; widthRatio = 0.8f; } } int WIDTH = 250; int HEIGHT = 250; int LORE_POS = 110; if (currentUpgradeID == 0 || currentUpgradeID == 30) { WIDTH = 300; HEIGHT = 300; LORE_POS = 85; } ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT) .setBackground(background) .widget( ButtonWidget.closeWindowButton(true) .setPos(WIDTH - 15, 3)) .widget( new DrawableWidget().setDrawable(milestoneSymbol) .setPos((int) ((1 - widthRatio / 2) * WIDTH / 2), HEIGHT / 4) .setSize((int) (WIDTH / 2 * widthRatio), HEIGHT / 2)) .widget( new DrawableWidget().setDrawable(overlay) .setPos(WIDTH / 4, HEIGHT / 4) .setSize(WIDTH / 2, HEIGHT / 2)) .widget( new MultiChildWidget() .addChild( new TextWidget(translateToLocal("fog.upgrade.tt." + (currentUpgradeID))) .setTextAlignment(Alignment.Center) .setDefaultColor(EnumChatFormatting.GOLD) .setSize(WIDTH - 15, 30) .setPos(9, 5)) .addChild( new TextWidget(translateToLocal("fog.upgrade.text." + (currentUpgradeID))) .setTextAlignment(Alignment.CenterLeft) .setDefaultColor(EnumChatFormatting.WHITE) .setSize(WIDTH - 15, LORE_POS - 30) .setPos(9, 30)) .addChild( new TextWidget( EnumChatFormatting.ITALIC + translateToLocal("fog.upgrade.lore." + (currentUpgradeID))) .setTextAlignment(Alignment.Center) .setDefaultColor(0xbbbdbd) .setSize(WIDTH - 15, (int) (HEIGHT * 0.9) - LORE_POS) .setPos(9, LORE_POS)) .addChild( new TextWidget( translateToLocal("gt.blockmachines.multimachine.FOG.shardcost") + " " + EnumChatFormatting.BLUE + gravitonShardCost).setTextAlignment(Alignment.Center) .setScale(0.7f) .setMaxWidth(70) .setDefaultColor(0x9c9c9c) .setPos(11, HEIGHT - 25)) .addChild( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.availableshards")) .setTextAlignment(Alignment.Center) .setScale(0.7f) .setMaxWidth(90) .setDefaultColor(0x9c9c9c) .setPos(WIDTH - 87, HEIGHT - 25)) .addChild( TextWidget.dynamicText(this::gravitonShardAmount) .setTextAlignment(Alignment.Center) .setScale(0.7f) .setMaxWidth(90) .setDefaultColor(0x9c9c9c) .setPos(WIDTH - 27, HEIGHT - 18))) .setSize(WIDTH, HEIGHT) .widget(new MultiChildWidget().addChild(new ButtonWidget().setOnClick((clickData, widget) -> { int unlockedPrereqUpgrades = 0; int unlockedSplitUpgrades = 0; if (!upgrades[currentUpgradeID]) { for (int prereqUpgrade : prereqUpgrades[currentUpgradeID]) { if (upgrades[prereqUpgrade]) { unlockedPrereqUpgrades++; } } if (!doesCurrentUpgradeRequireExtraMats || materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) .indexOf(currentUpgradeID)]) { if (allPrereqRequired[currentUpgradeID]) { if (unlockedPrereqUpgrades == prereqUpgrades[currentUpgradeID].length && gravitonShardsAvailable >= gravitonShardCost) { gravitonShardsAvailable -= gravitonShardCost; gravitonShardsSpent += gravitonShardCost; upgrades[currentUpgradeID] = true; } } else if (unlockedPrereqUpgrades > 0 || prereqUpgrades[currentUpgradeID].length == 0) { if (isUpradeSplitStart) { for (int splitUpgrade : FIRST_SPLIT_UPGRADES) { if (upgrades[splitUpgrade]) { unlockedSplitUpgrades++; } } unlockedSplitUpgrades -= (ringAmount - 1); } if (unlockedSplitUpgrades <= 0 && gravitonShardsAvailable >= gravitonShardCost) { gravitonShardsAvailable -= gravitonShardCost; gravitonShardsSpent += gravitonShardCost; upgrades[currentUpgradeID] = true; } } } } else { int unlockedFollowupUpgrades = 0; int unlockedNeighboringUpgrades = 0; boolean doesFollowupRequireAllPrereqs = false; boolean canFollowupSpareAConnection = true; for (int followupUpgrade : followupUpgrades) { if (upgrades[followupUpgrade]) { unlockedFollowupUpgrades++; } if (allPrereqRequired[followupUpgrade]) { doesFollowupRequireAllPrereqs = true; } int[] currentPrereqs = prereqUpgrades[followupUpgrade]; for (int prereqUpgrade : currentPrereqs) { if (upgrades[prereqUpgrade]) { unlockedNeighboringUpgrades++; } } if (unlockedNeighboringUpgrades <= 1) { canFollowupSpareAConnection = false; } unlockedNeighboringUpgrades = 0; } if (!doesFollowupRequireAllPrereqs && followupUpgrades.length > 0 && canFollowupSpareAConnection) { unlockedFollowupUpgrades = 0; } if (unlockedFollowupUpgrades == 0) { gravitonShardsAvailable += gravitonShardCost; gravitonShardsSpent -= gravitonShardCost; upgrades[currentUpgradeID] = false; } } }) .setSize(40, 15) .setBackground(() -> { if (upgrades[currentUpgradeID]) { return new IDrawable[] { GTUITextures.BUTTON_STANDARD_PRESSED }; } else { return new IDrawable[] { GTUITextures.BUTTON_STANDARD }; } }) .dynamicTooltip(this::constructionStatus) .setTooltipShowUpDelay(TOOLTIP_DELAY)) .addChild( TextWidget.dynamicText(this::constructionStatusText) .setTextAlignment(Alignment.Center) .setScale(0.7f) .setMaxWidth(36) .setPos(3, 5)) .setPos(WIDTH / 2 - 21, (int) (HEIGHT * 0.9))); if (Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) .contains(currentUpgradeID)) { builder.widget(createMaterialInputButton(currentUpgradeID, WIDTH / 2 - 40, (int) (HEIGHT * 0.9), builder)); } return builder.build(); } private Widget createMaterialInputButton(int upgradeID, int xCoord, int yCoord, IWidgetBuilder builder) { return new ButtonWidget().setOnClick((clickData, widget) -> { if (!widget.isClient() && doesCurrentUpgradeRequireExtraMats) { widget.getContext() .openSyncedWindow(MANUAL_INSERTION_WINDOW_ID); widget.getContext() .closeWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); widget.getContext() .closeWindow(UPGRADE_TREE_WINDOW_ID); } }) .setPlayClickSound(doesCurrentUpgradeRequireExtraMats) .setBackground(() -> { if (doesCurrentUpgradeRequireExtraMats) { if (materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) .indexOf(upgradeID)]) { return new IDrawable[] { TecTechUITextures.BUTTON_BOXED_CHECKMARK_18x18 }; } else { return new IDrawable[] { TecTechUITextures.BUTTON_BOXED_EXCLAMATION_POINT_18x18 }; } } else { return new IDrawable[] { GTUITextures.TRANSPARENT }; } }) .setPos(xCoord, yCoord) .setSize(15, 15) .dynamicTooltip(this::upgradeMaterialRequirements) .addTooltip(EnumChatFormatting.GRAY + translateToLocal("fog.button.materialrequirements.tooltip.clickhere")) .attachSyncer( new FakeSyncWidget.BooleanSyncer( () -> materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) .indexOf(upgradeID)], val -> materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) .indexOf(upgradeID)] = val), builder); } /** * @param upgradeID ID of the upgrade * @param colorCode Number deciding which colored background to use, 0 for blue, 1 for purple, 2 for * orange and 3 for green * @param milestone Number deciding which milestone symbol to display in the background, 0 for charge, * 1 for conversion, 2 for catalyst and 3 for composition * @param prerequisiteUpgradeIDs IDs of the prior upgrades directly connected to the current one * @param requireAllPrerequisites Decides how many connected prerequisite upgrades have to be unlocked to be able to * unlock this one. True means ALL, False means AT LEAST ONE * @param followingUpgradeIDs IDs of the following upgrades directly connected to the current one * @param isStartOfSplit Whether this upgrade is one of the initial split upgrades * @param requiresExtraMaterials Whether this upgrade requires materials other than graviton shards to unlock * @param shardCost How many graviton shards are needed to unlock this upgrade * @param pos Position of the upgrade inside the scrollableWidget */ private Widget createUpgradeBox(int upgradeID, int colorCode, int milestone, int[] prerequisiteUpgradeIDs, boolean requireAllPrerequisites, int[] followingUpgradeIDs, boolean isStartOfSplit, boolean requiresExtraMaterials, int shardCost, Pos2d pos, IWidgetBuilder builder) { prereqUpgrades[upgradeID] = prerequisiteUpgradeIDs; allPrereqRequired[upgradeID] = requireAllPrerequisites; return new MultiChildWidget().addChild(new ButtonWidget().setOnClick((clickData, widget) -> { currentUpgradeID = upgradeID; currentColorCode = colorCode; currentMilestoneBG = milestone; gravitonShardCost = shardCost; followupUpgrades = followingUpgradeIDs; isUpradeSplitStart = isStartOfSplit; doesCurrentUpgradeRequireExtraMats = requiresExtraMaterials; if (!widget.isClient()) { // unfortunately this is the easiest way to prevent this window desyncing. it causes the window to // reposition itself on the screen which would be a good thing to not do. if (widget.getContext() .isWindowOpen(INDIVIDUAL_UPGRADE_WINDOW_ID)) { widget.getContext() .closeWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); } widget.getContext() .openSyncedWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); } }) .setSize(40, 15) .setBackground(() -> { if (upgrades[upgradeID]) { return new IDrawable[] { TecTechUITextures.BUTTON_SPACE_PRESSED_32x16 }; } else { return new IDrawable[] { TecTechUITextures.BUTTON_SPACE_32x16 }; } }) .addTooltip(translateToLocal("fog.upgrade.tt." + upgradeID)) .setTooltipShowUpDelay(TOOLTIP_DELAY)) .addChild( new TextWidget(translateToLocal("fog.upgrade.tt.short." + upgradeID)).setScale(0.8f) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.Center) .setSize(34, 9) .setPos(3, 4)) .setPos(pos) .attachSyncer( new FakeSyncWidget.BooleanSyncer(() -> upgrades[upgradeID], val -> upgrades[upgradeID] = val), builder); } private Widget createUpgradeConnectorLine(Pos2d pos, int length, float rotationAngle, int colorCode, int startUpgradeID, int endUpgradeID) { return new DrawableWidget() .setDrawable( () -> (upgrades[startUpgradeID] && upgrades[endUpgradeID]) ? coloredLine(colorCode, true).withRotationDegree(rotationAngle) : coloredLine(colorCode, false).withRotationDegree(rotationAngle)) .setPos(pos) .setSize(6, length); } private IDrawable coloredLine(int colorCode, boolean opaque) { IDrawable line; switch (colorCode) { case 1 -> { line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_PURPLE_OPAQUE : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_PURPLE; } case 2 -> { line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_ORANGE_OPAQUE : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_ORANGE; } case 3 -> { line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_GREEN_OPAQUE : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_GREEN; } case 4 -> { line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_RED_OPAQUE : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_RED; } default -> { line = opaque ? TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_BLUE_OPAQUE : TecTechUITextures.PICTURE_UPGRADE_CONNECTOR_BLUE; } } return line; } protected ModularWindow createManualInsertionWindow(final EntityPlayer player) { ItemStack[] inputs = godforgeUpgradeMats.get(currentUpgradeID); final int WIDTH = 189; final int HEIGHT = 106; final int PARENT_WIDTH = getGUIWidth(); final int PARENT_HEIGHT = getGUIHeight(); final MultiChildWidget columns = new MultiChildWidget(); final DynamicPositionedColumn column1 = new DynamicPositionedColumn(); final DynamicPositionedColumn column2 = new DynamicPositionedColumn(); final DynamicPositionedColumn column3 = new DynamicPositionedColumn(); final DynamicPositionedColumn column4 = new DynamicPositionedColumn(); final DynamicPositionedColumn column5 = new DynamicPositionedColumn(); final DynamicPositionedColumn column6 = new DynamicPositionedColumn(); List columnList = Arrays.asList(column1, column2, column3, column4, column5, column6); ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); builder.setBackground(GTUITextures.BACKGROUND_SINGLEBLOCK_DEFAULT); builder.setGuiTint(getGUIColorization()); builder.setDraggable(true); builder.setPos( (size, window) -> Alignment.Center.getAlignedPos(size, new Size(PARENT_WIDTH, PARENT_HEIGHT)) .add(Alignment.TopRight.getAlignedPos(new Size(PARENT_WIDTH, PARENT_HEIGHT), new Size(WIDTH, HEIGHT))) .subtract(5, 0) .add(0, 4)); builder.widget( SlotGroup.ofItemHandler(inputSlotHandler, 4) .startFromSlot(0) .endAtSlot(15) .phantom(false) .background(getGUITextureSet().getItemSlot()) .build() .setPos(112, 6)); builder.widget(new ButtonWidget().setOnClick((clickData, widget) -> { if (!widget.isClient()) { widget.getWindow() .closeWindow(); widget.getContext() .openSyncedWindow(UPGRADE_TREE_WINDOW_ID); widget.getContext() .openSyncedWindow(INDIVIDUAL_UPGRADE_WINDOW_ID); } }) .setBackground(ModularUITextures.VANILLA_BACKGROUND, new Text("x")) .setPos(179, 0) .setSize(10, 10)); builder.widget(new MultiChildWidget().addChild(new ButtonWidget().setOnClick((clickData, widget) -> { if (!widget.isClient()) { ArrayList list = new ArrayList<>(inputSlotHandler.getStacks()); list.removeIf(Objects::isNull); int foundInputs = 0; int[] foundInputIndices = new int[inputs.length]; for (ItemStack inputStack : list) { for (ItemStack requiredStack : inputs) { if (ItemStack.areItemStacksEqual(requiredStack, inputStack)) { foundInputIndices[foundInputs] = inputSlotHandler.getStacks() .indexOf(inputStack); foundInputs++; } } } if (foundInputs == inputs.length) { for (int index : foundInputIndices) { inputSlotHandler.extractItem(index, inputSlotHandler.getStackInSlot(index).stackSize, false); } materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) .indexOf(currentUpgradeID)] = true; } } }) .setPlayClickSound(true) .setBackground(GTUITextures.BUTTON_STANDARD) .setSize(179, 18)) .addChild( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.consumeUpgradeMats")) .setTextAlignment(Alignment.Center) .setScale(0.75f) .setPos(0, 1) .setSize(179, 18)) .setPos(5, 82) .setSize(179, 16)); IItemHandlerModifiable upgradeMatsHandler = new ItemStackHandler(12); int uniqueItems = inputs.length; for (int i = 0; i < 12; i++) { int index = i; int cleanDiv4 = index / 4; if (i < uniqueItems) { ItemStack stack = inputs[index]; if (stack != null) { stack = stack.copy(); stack.stackSize = 1; upgradeMatsHandler.setStackInSlot(index, stack); } builder.widget( new DrawableWidget().setDrawable(GTUITextures.BUTTON_STANDARD_PRESSED) .setPos(5 + cleanDiv4 * 36, 6 + index % 4 * 18) .setSize(18, 18)); columnList.get(cleanDiv4) .addChild( new SlotWidget(upgradeMatsHandler, index).setAccess(false, false) .disableInteraction()); columnList.get(cleanDiv4 + 3) .addChild( new TextWidget("x" + inputs[i].stackSize).setTextAlignment(Alignment.CenterLeft) .setScale(0.8f) .setSize(18, 8)); } else { builder.widget( new DrawableWidget().setDrawable(GTUITextures.BUTTON_STANDARD_DISABLED) .setPos(5 + cleanDiv4 * 36, 6 + index % 4 * 18) .setSize(18, 18)); } } int counter = 0; for (DynamicPositionedColumn column : columnList) { int spacing = 0; int xCord = counter * 36; int yCord = 0; if (counter > 2) { spacing = 10; xCord = 19 + (counter - 3) * 36; yCord = 5; } columns.addChild( column.setSpace(spacing) .setAlignment(MainAxisAlignment.SPACE_BETWEEN) .setSize(16, 72) .setPos(xCord, yCord)); counter++; } builder.widget( columns.setSize(108, 72) .setPos(5, 6)); return builder.build(); } protected ModularWindow createGeneralInfoWindow(final EntityPlayer player) { final Scrollable scrollable = new Scrollable().setVerticalScroll(); final int WIDTH = 300; final int HEIGHT = 300; ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); builder.setDraggable(true); scrollable.widget( new TextWidget(EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.introduction")) .setDefaultColor(EnumChatFormatting.DARK_PURPLE) .setTextAlignment(Alignment.TopCenter) .setPos(7, 13) .setSize(280, 15)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.introductioninfotext")) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 30) .setSize(280, 50)) .widget( new TextWidget( EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.tableofcontents")) .setDefaultColor(EnumChatFormatting.AQUA) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 80) .setSize(150, 15)) .widget( new ButtonWidget().setOnClick((clickData, widget) -> scrollable.setVerticalScrollOffset(150)) .setBackground( new Text(EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.fuel")) .alignment(Alignment.CenterLeft) .color(0x55ffff)) .setPos(7, 95) .setSize(150, 15)) .widget( new ButtonWidget().setOnClick((clickData, widget) -> scrollable.setVerticalScrollOffset(434)) .setBackground( new Text( EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.modules")) .alignment(Alignment.CenterLeft) .color(0x55ffff)) .setPos(7, 110) .setSize(150, 15)) .widget( new ButtonWidget().setOnClick((clickData, widget) -> scrollable.setVerticalScrollOffset(1088)) .setBackground( new Text( EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.upgrades")) .alignment(Alignment.CenterLeft) .color(0x55ffff)) .setPos(7, 125) .setSize(150, 15)) .widget( new ButtonWidget().setOnClick((clickData, widget) -> scrollable.setVerticalScrollOffset(1412)) .setBackground( new Text( EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.milestones")) .alignment(Alignment.CenterLeft) .color(0x55ffff)) .setPos(7, 140) .setSize(150, 15)) .widget( TextWidget.dynamicText(this::inversionHeaderText) .setDefaultColor(EnumChatFormatting.WHITE) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 155) .setSize(150, 15)) .widget(new ButtonWidget().setOnClick((clickData, widget) -> { if (inversion) { scrollable.setVerticalScrollOffset(1766); } }) .setPlayClickSound(inversion) .setPos(7, 155) .setSize(150, 15) .attachSyncer(new FakeSyncWidget.BooleanSyncer(() -> inversion, (val) -> inversion = val), scrollable)) .widget( new TextWidget( EnumChatFormatting.BOLD + "§N" + translateToLocal("gt.blockmachines.multimachine.FOG.fuel")) .setDefaultColor(EnumChatFormatting.DARK_PURPLE) .setTextAlignment(Alignment.TopCenter) .setPos(127, 160) .setSize(40, 15)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.fuelinfotext")) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 177) .setSize(280, 250)) .widget( new TextWidget( EnumChatFormatting.BOLD + "§N" + translateToLocal("gt.blockmachines.multimachine.FOG.modules")) .setDefaultColor(EnumChatFormatting.DARK_PURPLE) .setTextAlignment(Alignment.TopCenter) .setPos(7, 440) .setSize(280, 15)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.moduleinfotext")) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 461) .setSize(280, 620)) .widget( new TextWidget( EnumChatFormatting.BOLD + "§N" + translateToLocal("gt.blockmachines.multimachine.FOG.upgrades")) .setDefaultColor(EnumChatFormatting.DARK_PURPLE) .setTextAlignment(Alignment.TopCenter) .setPos(7, 1098) .setSize(280, 15)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.upgradeinfotext")) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 1115) .setSize(280, 290)) .widget( new TextWidget( EnumChatFormatting.BOLD + "§N" + translateToLocal("gt.blockmachines.multimachine.FOG.milestones")) .setDefaultColor(EnumChatFormatting.DARK_PURPLE) .setTextAlignment(Alignment.TopCenter) .setPos(7, 1422) .setSize(280, 15)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.milestoneinfotext")) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 1439) .setSize(280, 320)) .widget( TextWidget.dynamicText(this::inversionHeaderText) .setDefaultColor(EnumChatFormatting.WHITE) .setTextAlignment(Alignment.TopCenter) .setPos(7, 1776) .setSize(280, 15)) .widget( TextWidget.dynamicText(this::inversionInfoText) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 1793) .setSize(280, 160)) .widget( new TextWidget("").setPos(7, 1965) .setSize(10, 10)); builder.widget( new DrawableWidget().setDrawable(TecTechUITextures.BACKGROUND_GLOW_WHITE) .setPos(0, 0) .setSize(300, 300)) .widget( scrollable.setSize(292, 292) .setPos(4, 4)) .widget( ButtonWidget.closeWindowButton(true) .setPos(284, 4)); return builder.build(); } protected ModularWindow createSpecialThanksWindow(final EntityPlayer player) { final int WIDTH = 200; final int HEIGHT = 200; ModularWindow.Builder builder = ModularWindow.builder(WIDTH, HEIGHT); builder.setBackground(TecTechUITextures.BACKGROUND_GLOW_RAINBOW); builder.setDraggable(true); builder.widget( ButtonWidget.closeWindowButton(true) .setPos(184, 4)) .widget( new DrawableWidget().setDrawable(TecTechUITextures.PICTURE_GODFORGE_THANKS) .setPos(50, 50) .setSize(100, 100)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.contributors")) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.Center) .setScale(1f) .setPos(0, 5) .setSize(200, 15)) .widget( new TextWidget( EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.lead")) .setScale(0.8f) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 30) .setSize(60, 10)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.cloud")).setScale(0.8f) .setDefaultColor(EnumChatFormatting.AQUA) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 40) .setSize(60, 10)) .widget( new TextWidget( EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.programming")) .setScale(0.8f) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 55) .setSize(60, 10)) .widget( new TextWidget( EnumChatFormatting.DARK_AQUA + translateToLocal("gt.blockmachines.multimachine.FOG.teg") + " " + EnumChatFormatting.RESET + translateToLocal("gt.blockmachines.multimachine.FOG.serenybiss")).setScale(0.8f) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 67) .setSize(60, 10)) .widget( new TextWidget( EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.textures")) .setScale(0.8f) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 85) .setSize(100, 10)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.ant")).setScale(0.8f) .setDefaultColor(EnumChatFormatting.GREEN) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 95) .setSize(60, 10)) .widget( new TextWidget( EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.rendering")) .setScale(0.8f) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 110) .setSize(100, 10)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.bucket")).setScale(0.8f) .setDefaultColor(EnumChatFormatting.WHITE) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 120) .setSize(60, 10)) .widget( new TextWidget( EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.lore")) .setScale(0.8f) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 135) .setSize(100, 10)) .widget( delenoName().setSpace(-1) .setAlignment(MainAxisAlignment.SPACE_BETWEEN) .setPos(7, 145) .setSize(60, 10)) .widget( new TextWidget( EnumChatFormatting.UNDERLINE + translateToLocal("gt.blockmachines.multimachine.FOG.playtesting")) .setScale(0.8f) .setDefaultColor(EnumChatFormatting.GOLD) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 160) .setSize(100, 10)) .widget( new TextWidget(translateToLocal("gt.blockmachines.multimachine.FOG.misi")).setScale(0.8f) .setDefaultColor(0xffc26f) .setTextAlignment(Alignment.CenterLeft) .setPos(7, 170) .setSize(60, 10)) .widget( new TextWidget(EnumChatFormatting.ITALIC + translateToLocal("gt.blockmachines.multimachine.FOG.thanks")) .setScale(0.8f) .setDefaultColor(0xbbbdbd) .setTextAlignment(Alignment.Center) .setPos(90, 140) .setSize(100, 60)); return builder.build(); } private DynamicPositionedRow delenoName() { DynamicPositionedRow nameRow = new DynamicPositionedRow(); String deleno = translateToLocal("gt.blockmachines.multimachine.FOG.deleno"); int[] colors = new int[] { 0xffffff, 0xf6fff5, 0xecffec, 0xe3ffe2, 0xd9ffd9, 0xd0ffcf }; for (int i = 0; i < 6; i++) { nameRow.addChild( new TextWidget(Character.toString(deleno.charAt(i))).setDefaultColor(colors[i]) .setScale(0.8f) .setTextAlignment(Alignment.CenterLeft)); } return nameRow; } @Override public MultiblockTooltipBuilder createTooltip() { final MultiblockTooltipBuilder tt = new MultiblockTooltipBuilder(); tt.addMachineType("Stellar Forge") .addInfo(EnumChatFormatting.ITALIC + "Also known as Godforge or Gorge for short.") .addInfo(TOOLTIP_BAR) .addInfo("Controller block for the Godforge, a massive structure harnessing the thermal,") .addInfo("gravitational and kinetic energy of a stabilised neutron star for material processing.") .addInfo( "This multiblock can house " + EnumChatFormatting.RED + "up to 16 modules " + EnumChatFormatting.GRAY + "which utilize the star to energize materials") .addInfo("to varying degrees, ranging from regular smelting to matter degeneration.") .addInfo(TOOLTIP_BAR) .addInfo( "This multiblock has an " + EnumChatFormatting.GOLD + "extensive upgrade tree " + EnumChatFormatting.GRAY + "which influences all of its functions,") .addInfo( "such as " + EnumChatFormatting.GOLD + "unlocking new module types, increasing heat levels " + EnumChatFormatting.GRAY + "and " + EnumChatFormatting.GOLD + "granting") .addInfo( EnumChatFormatting.GOLD + "various processing speed bonuses. " + EnumChatFormatting.GRAY + "These upgrades can be unlocked by reaching") .addInfo("certain milestones and/or spending materials.") .addInfo(TOOLTIP_BAR) .addInfo( EnumChatFormatting.GREEN + "Clicking on the logo in the controller gui opens an extensive information window,") .addInfo("explaining everything there is to know about this multiblock.") .addInfo(TOOLTIP_BAR) .beginStructureBlock(126, 29, 186, false) .addStructureInfo("The structure is too complex! See schematic for details.") .addStructureInfo( "Total blocks needed for the structure with " + EnumChatFormatting.DARK_PURPLE + "1" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.DARK_GREEN + "2" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.AQUA + "3" + EnumChatFormatting.GRAY + " rings:") .addStructureInfo( EnumChatFormatting.DARK_PURPLE + "3943" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.DARK_GREEN + "7279" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.AQUA + "11005" + EnumChatFormatting.GRAY + " Transcendentally Amplified Magnetic Confinement Casing") .addStructureInfo( EnumChatFormatting.DARK_PURPLE + "2819" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.DARK_GREEN + "4831" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.AQUA + "6567" + EnumChatFormatting.GRAY + " Singularity Reinforced Stellar Shielding Casing") .addStructureInfo( EnumChatFormatting.DARK_PURPLE + "272" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.DARK_GREEN + "512" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.AQUA + "824" + EnumChatFormatting.GRAY + " Celestial Matter Guidance Casing") .addStructureInfo( EnumChatFormatting.DARK_PURPLE + "130" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.DARK_GREEN + "144" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.AQUA + "158" + EnumChatFormatting.GRAY + " Boundless Gravitationally Severed Structure Casing") .addStructureInfo( EnumChatFormatting.DARK_PURPLE + "9" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.DARK_GREEN + "54" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.AQUA + "155" + EnumChatFormatting.GRAY + " Spatially Transcendent Gravitational Lens Block") .addStructureInfo( EnumChatFormatting.DARK_PURPLE + "345" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.DARK_GREEN + "357" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.AQUA + "397" + EnumChatFormatting.DARK_PURPLE + " Remote" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.DARK_GREEN + "Medial" + EnumChatFormatting.GRAY + "/" + EnumChatFormatting.AQUA + "Central" + EnumChatFormatting.GRAY + " Graviton Flow Modulator") .addStructureInfo( EnumChatFormatting.GOLD + "36" + EnumChatFormatting.GRAY + " Stellar Energy Siphon Casing") .addStructureInfo("--------------------------------------------") .addStructureInfo("Requires " + EnumChatFormatting.GOLD + 1 + EnumChatFormatting.GRAY + " Input Hatch") .addStructureInfo("Requires " + EnumChatFormatting.GOLD + 1 + EnumChatFormatting.GRAY + " Output Bus (ME)") .addStructureInfo("Requires " + EnumChatFormatting.GOLD + 1 + EnumChatFormatting.GRAY + " Input Bus") .addStructureInfo("--------------------------------------------") .toolTipFinisher(CommonValues.GODFORGE_MARK); return tt; } @Override public boolean energyFlowOnRunningTick(ItemStack aStack, boolean allowProduction) { return true; } @Override public String[] getStructureDescription(ItemStack stackSize) { return new String[] { EnumChatFormatting.AQUA + translateToLocal("tt.keyphrase.Hint_Details") + ":", translateToLocal("gt.blockmachines.multimachine.FOG.hint.0"), translateToLocal("gt.blockmachines.multimachine.FOG.hint.1") }; } public int getFuelType() { return selectedFuelType; } private void setFuelType(int fuelType) { selectedFuelType = fuelType; } public int getFuelFactor() { return fuelConsumptionFactor; } public boolean isUpgradeActive(int upgradeID) { return upgrades[upgradeID]; } public int getRingAmount() { return ringAmount; } public int getTotalActiveUpgrades() { int totalUpgrades = 0; for (boolean upgrade : upgrades) { if (upgrade) { totalUpgrades++; } } return totalUpgrades; } private Text fuelUsage() { return new Text(fuelConsumption + " L/5s"); } private Text gravitonShardAmount() { EnumChatFormatting enoughGravitonShards = EnumChatFormatting.RED; if (gravitonShardsAvailable >= gravitonShardCost) { enoughGravitonShards = EnumChatFormatting.GREEN; } return new Text(enoughGravitonShards + Integer.toString(gravitonShardsAvailable)); } private Text storedFuel() { if (internalBattery == 0) { return new Text( translateToLocal("gt.blockmachines.multimachine.FOG.storedstartupfuel") + " " + stellarFuelAmount + "/" + neededStartupFuel); } return new Text( translateToLocal("gt.blockmachines.multimachine.FOG.storedfuel") + " " + internalBattery + "/" + maxBatteryCharge); } private void checkInversionStatus() { int inversionChecker = 0; for (int progress : milestoneProgress) { if (progress < 7) { break; } inversionChecker++; } inversion = inversionChecker == 4; } private Text inversionStatusText() { String inversionStatus = ""; if (inversion) { inversionStatus = EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.inversionactive"); } return new Text(inversionStatus); } private void determineCompositionMilestoneLevel() { int[] uniqueModuleCount = new int[5]; int smelting = 0; int molten = 0; int plasma = 0; int exotic = 0; int exoticMagmatter = 0; for (MTEBaseModule module : moduleHatches) { if (module instanceof MTESmeltingModule) { uniqueModuleCount[0] = 1; smelting++; continue; } if (module instanceof MTEMoltenModule) { uniqueModuleCount[1] = 1; molten++; continue; } if (module instanceof MTEPlasmaModule) { uniqueModuleCount[2] = 1; plasma++; continue; } if (module instanceof MTEExoticModule) { if (!((MTEExoticModule) module).isMagmatterModeOn()) { uniqueModuleCount[3] = 1; exotic++; } else { uniqueModuleCount[4] = 1; exoticMagmatter++; } } } totalExtensionsBuilt = Arrays.stream(uniqueModuleCount) .sum() + ringAmount - 1; if (inversion) { totalExtensionsBuilt += (smelting - 1 + (molten - 1) * 2 + (plasma - 1) * 3 + (exotic - 1) * 4 + (exoticMagmatter - 1) * 5) / 5f; } milestoneProgress[3] = (int) Math.floor(totalExtensionsBuilt); } private void determineMilestoneProgress() { int closestRelevantSeven; float rawProgress; float actualProgress; if (milestoneProgress[0] < 7) { powerMilestonePercentage = (float) max( (log((totalPowerConsumed.divide(BigInteger.valueOf(POWER_MILESTONE_CONSTANT))).longValue()) / POWER_LOG_CONSTANT + 1), 0) / 7; milestoneProgress[0] = (int) floor(powerMilestonePercentage * 7); } if (inversion) { rawProgress = (totalPowerConsumed.divide(POWER_MILESTONE_T7_CONSTANT) .floatValue() - 1) / 7; closestRelevantSeven = (int) floor(rawProgress); actualProgress = rawProgress - closestRelevantSeven; milestoneProgress[0] = 7 + (int) floor(rawProgress * 7); if (closestRelevantSeven % 2 == 0) { invertedPowerMilestonePercentage = actualProgress; powerMilestonePercentage = 1 - invertedPowerMilestonePercentage; } else { powerMilestonePercentage = actualProgress; invertedPowerMilestonePercentage = 1 - powerMilestonePercentage; } } if (milestoneProgress[1] < 7) { recipeMilestonePercentage = (float) max( (log(totalRecipesProcessed * 1f / RECIPE_MILESTONE_CONSTANT) / RECIPE_LOG_CONSTANT + 1), 0) / 7; milestoneProgress[1] = (int) floor(recipeMilestonePercentage * 7); } if (inversion) { rawProgress = (((float) totalRecipesProcessed / RECIPE_MILESTONE_T7_CONSTANT) - 1) / 7; closestRelevantSeven = (int) floor(rawProgress); actualProgress = rawProgress - closestRelevantSeven; milestoneProgress[1] = 7 + (int) floor(rawProgress * 7); if (closestRelevantSeven % 2 == 0) { invertedRecipeMilestonePercentage = actualProgress; recipeMilestonePercentage = 1 - invertedRecipeMilestonePercentage; } else { recipeMilestonePercentage = actualProgress; invertedRecipeMilestonePercentage = 1 - recipeMilestonePercentage; } } if (milestoneProgress[2] < 7) { fuelMilestonePercentage = (float) max( (log(totalFuelConsumed * 1f / FUEL_MILESTONE_CONSTANT) / FUEL_LOG_CONSTANT + 1), 0) / 7; milestoneProgress[2] = (int) floor(fuelMilestonePercentage * 7); } if (inversion) { rawProgress = (((float) totalFuelConsumed / FUEL_MILESTONE_T7_CONSTANT) - 1) / 7; closestRelevantSeven = (int) floor(rawProgress); actualProgress = rawProgress - closestRelevantSeven; milestoneProgress[2] = 7 + (int) floor(rawProgress * 7); if ((closestRelevantSeven % 2) == 0) { invertedFuelMilestonePercentage = actualProgress; fuelMilestonePercentage = 1 - invertedFuelMilestonePercentage; } else { fuelMilestonePercentage = actualProgress; invertedFuelMilestonePercentage = 1 - fuelMilestonePercentage; } } if (milestoneProgress[3] <= 7) { structureMilestonePercentage = totalExtensionsBuilt / 7f; } if (inversion) { rawProgress = (totalExtensionsBuilt - 7) / 7f; closestRelevantSeven = (int) floor(rawProgress); actualProgress = rawProgress - closestRelevantSeven; if ((closestRelevantSeven % 2) == 0) { invertedStructureMilestonePercentage = actualProgress; structureMilestonePercentage = 1 - invertedStructureMilestonePercentage; } else { structureMilestonePercentage = actualProgress; invertedStructureMilestonePercentage = 1 - structureMilestonePercentage; } } } private void determineGravitonShardAmount() { int sum = 0; for (int progress : milestoneProgress) { if (!inversion) { progress = Math.min(progress, 7); } sum += progress * (progress + 1) / 2; } gravitonShardsAvailable = sum - gravitonShardsSpent; } private void ejectGravitonShards() { if (mOutputBusses.size() == 1) { while (gravitonShardsAvailable >= 64) { addOutput(GTOreDictUnificator.get(OrePrefixes.gem, MaterialsUEVplus.GravitonShard, 64)); gravitonShardsAvailable -= 64; } addOutput( GTOreDictUnificator.get(OrePrefixes.gem, MaterialsUEVplus.GravitonShard, gravitonShardsAvailable)); gravitonShardsAvailable = 0; } } private Text gravitonShardAmountText(int milestoneID) { int sum; int progress = milestoneProgress[milestoneID]; if (!inversion) { progress = Math.min(progress, 7); } sum = progress * (progress + 1) / 2; return new Text( translateToLocal("gt.blockmachines.multimachine.FOG.shardgain") + ": " + EnumChatFormatting.GRAY + sum); } private Text totalMilestoneProgress(int milestoneID) { long progress; BigInteger bigProgress; String suffix; switch (milestoneID) { case 1 -> { suffix = translateToLocal("gt.blockmachines.multimachine.FOG.recipes"); progress = totalRecipesProcessed; } case 2 -> { suffix = translateToLocal("gt.blockmachines.multimachine.FOG.fuelconsumed"); progress = totalFuelConsumed; } case 3 -> { suffix = translateToLocal("gt.blockmachines.multimachine.FOG.extensions"); progress = milestoneProgress[3]; } default -> { suffix = translateToLocal("gt.blockmachines.multimachine.FOG.power"); bigProgress = totalPowerConsumed; if (!noFormatting && (totalPowerConsumed.compareTo(BigInteger.valueOf(1_000L)) > 0)) { return new Text( translateToLocal("gt.blockmachines.multimachine.FOG.totalprogress") + ": " + EnumChatFormatting.GRAY + toExponentForm(bigProgress) + " " + suffix); } else { return new Text( translateToLocal("gt.blockmachines.multimachine.FOG.totalprogress") + ": " + EnumChatFormatting.GRAY + bigProgress + " " + suffix); } } } if (!noFormatting) { return new Text( translateToLocal("gt.blockmachines.multimachine.FOG.totalprogress") + ": " + EnumChatFormatting.GRAY + formatNumbers(progress) + " " + suffix); } else { return new Text( translateToLocal("gt.blockmachines.multimachine.FOG.totalprogress") + ": " + EnumChatFormatting.GRAY + progress + " " + suffix); } } private Text currentMilestone(int milestoneID) { return new Text( translateToLocal("gt.blockmachines.multimachine.FOG.milestoneprogress") + ": " + EnumChatFormatting.GRAY + milestoneProgress[milestoneID]); } private Text milestoneProgressText(int milestoneID, boolean formatting) { long max; BigInteger bigMax; String suffix; String progressText = translateToLocal("gt.blockmachines.multimachine.FOG.progress"); Text done = new Text(translateToLocal("gt.blockmachines.multimachine.FOG.milestonecomplete")); if (noFormatting) { formatting = false; done = new Text( translateToLocal("gt.blockmachines.multimachine.FOG.milestonecomplete") + EnumChatFormatting.DARK_RED + "?"); } switch (milestoneID) { case 0: if (milestoneProgress[0] < 7 || inversion) { suffix = translateToLocal("gt.blockmachines.multimachine.FOG.power"); if (inversion) { bigMax = POWER_MILESTONE_T7_CONSTANT.multiply(BigInteger.valueOf(milestoneProgress[0] - 5)); } else { bigMax = BigInteger.valueOf(LongMath.pow(9, milestoneProgress[0])) .multiply(BigInteger.valueOf(LongMath.pow(10, 15))); } if (formatting && (totalPowerConsumed.compareTo(BigInteger.valueOf(1_000L)) > 0)) { return new Text( progressText + ": " + EnumChatFormatting.GRAY + toExponentForm(bigMax) + " " + suffix); } else { return new Text(progressText + ": " + EnumChatFormatting.GRAY + bigMax + " " + suffix); } } else { return done; } case 1: if (milestoneProgress[1] < 7 || inversion) { suffix = translateToLocal("gt.blockmachines.multimachine.FOG.recipes"); if (inversion) { max = RECIPE_MILESTONE_T7_CONSTANT * (milestoneProgress[1] - 5); } else { max = LongMath.pow(6, milestoneProgress[1]) * LongMath.pow(10, 7); } break; } else { return done; } case 2: if (milestoneProgress[2] < 7 || inversion) { suffix = translateToLocal("gt.blockmachines.multimachine.FOG.fuelconsumed"); if (inversion) { max = FUEL_MILESTONE_T7_CONSTANT * (milestoneProgress[2] - 5); } else { max = LongMath.pow(3, milestoneProgress[2]) * LongMath.pow(10, 4); } break; } else { return done; } case 3: if (milestoneProgress[3] < 7 || inversion) { suffix = translateToLocal("gt.blockmachines.multimachine.FOG.extensions"); max = milestoneProgress[3] + 1; break; } else { return done; } default: return new Text("Error"); } if (formatting) { return new Text(progressText + ": " + EnumChatFormatting.GRAY + formatNumbers(max) + " " + suffix); } else { return new Text(progressText + ": " + EnumChatFormatting.GRAY + max + " " + suffix); } } private Text inversionHeaderText() { return inversion ? new Text( EnumChatFormatting.BOLD + "§k2" + EnumChatFormatting.RESET + EnumChatFormatting.WHITE + EnumChatFormatting.BOLD + translateToLocal("gt.blockmachines.multimachine.FOG.inversion") + EnumChatFormatting.BOLD + "§k2") : new Text(""); } private Text inversionInfoText() { return inversion ? new Text(translateToLocal("gt.blockmachines.multimachine.FOG.inversioninfotext")) : new Text(""); } private Text constructionStatusText() { return upgrades[currentUpgradeID] ? new Text(translateToLocal("fog.upgrade.respec")) : new Text(translateToLocal("fog.upgrade.confirm")); } private List constructionStatus() { if (upgrades[currentUpgradeID]) { return ImmutableList.of(translateToLocal("fog.upgrade.respec")); } return ImmutableList.of(translateToLocal("fog.upgrade.confirm")); } private List upgradeMaterialRequirements() { if (materialPaidUpgrades[Arrays.asList(UPGRADE_MATERIAL_ID_CONVERSION) .indexOf(currentUpgradeID)]) { return ImmutableList.of(translateToLocal("fog.button.materialrequirementsmet.tooltip")); } return ImmutableList.of(translateToLocal("fog.button.materialrequirements.tooltip")); } private void increaseBattery(int amount) { if ((internalBattery + amount) <= maxBatteryCharge) { internalBattery += amount; } else { internalBattery = maxBatteryCharge; batteryCharging = false; } } public void reduceBattery(int amount) { if (internalBattery - amount <= 0) { internalBattery = 0; if (moduleHatches.size() > 0) { for (MTEBaseModule module : moduleHatches) { module.disconnect(); } } destroyRenderer(); } else { internalBattery -= amount; totalFuelConsumed += amount; } } public int getBatteryCharge() { return internalBattery; } public int getMaxBatteryCharge() { return maxBatteryCharge; } public void addTotalPowerConsumed(BigInteger amount) { totalPowerConsumed = totalPowerConsumed.add(amount); } public void addTotalRecipesProcessed(long amount) { totalRecipesProcessed += amount; } @Override protected void setHatchRecipeMap(MTEHatchInput hatch) {} @Override public void setItemNBT(NBTTagCompound NBT) { NBT.setInteger("selectedFuelType", selectedFuelType); NBT.setInteger("fuelConsumptionFactor", fuelConsumptionFactor); NBT.setInteger("internalBattery", internalBattery); NBT.setBoolean("batteryCharging", batteryCharging); NBT.setInteger("batterySize", maxBatteryCharge); NBT.setInteger("gravitonShardsAvailable", gravitonShardsAvailable); NBT.setInteger("gravitonShardsSpent", gravitonShardsSpent); NBT.setByteArray("totalPowerConsumed", totalPowerConsumed.toByteArray()); NBT.setLong("totalRecipesProcessed", totalRecipesProcessed); NBT.setLong("totalFuelConsumed", totalFuelConsumed); NBT.setInteger("starFuelStored", stellarFuelAmount); NBT.setBoolean("gravitonShardEjection", gravitonShardEjection); // Store booleanArrays of all upgrades NBTTagCompound upgradeBooleanArrayNBTTag = new NBTTagCompound(); int upgradeIndex = 0; for (Boolean upgrade : upgrades) { upgradeBooleanArrayNBTTag.setBoolean("upgrade" + upgradeIndex, upgrade); upgradeIndex++; } NBT.setTag("upgrades", upgradeBooleanArrayNBTTag); NBTTagCompound upgradeMaterialBooleanArrayNBTTag = new NBTTagCompound(); int upgradeMaterialIndex = 0; for (Boolean upgrade : materialPaidUpgrades) { upgradeBooleanArrayNBTTag.setBoolean("upgradeMaterial" + upgradeMaterialIndex, upgrade); upgradeMaterialIndex++; } NBT.setTag("upgradeMaterials", upgradeMaterialBooleanArrayNBTTag); super.saveNBTData(NBT); } @Override public void saveNBTData(NBTTagCompound NBT) { NBT.setInteger("selectedFuelType", selectedFuelType); NBT.setInteger("fuelConsumptionFactor", fuelConsumptionFactor); NBT.setInteger("internalBattery", internalBattery); NBT.setBoolean("batteryCharging", batteryCharging); NBT.setInteger("batterySize", maxBatteryCharge); NBT.setInteger("gravitonShardsAvailable", gravitonShardsAvailable); NBT.setInteger("gravitonShardsSpent", gravitonShardsSpent); NBT.setByteArray("totalPowerConsumed", totalPowerConsumed.toByteArray()); NBT.setLong("totalRecipesProcessed", totalRecipesProcessed); NBT.setLong("totalFuelConsumed", totalFuelConsumed); NBT.setInteger("starFuelStored", stellarFuelAmount); NBT.setBoolean("gravitonShardEjection", gravitonShardEjection); NBT.setBoolean("isRenderActive", isRenderActive); NBT.setInteger("ringAmount", ringAmount); // Store booleanArray of all upgrades NBTTagCompound upgradeBooleanArrayNBTTag = new NBTTagCompound(); int upgradeIndex = 0; for (boolean upgrade : upgrades) { upgradeBooleanArrayNBTTag.setBoolean("upgrade" + upgradeIndex, upgrade); upgradeIndex++; } NBT.setTag("upgrades", upgradeBooleanArrayNBTTag); NBTTagCompound upgradeMaterialBooleanArrayNBTTag = new NBTTagCompound(); int upgradeMaterialIndex = 0; for (boolean upgrade : materialPaidUpgrades) { upgradeMaterialBooleanArrayNBTTag.setBoolean("upgradeMaterial" + upgradeMaterialIndex, upgrade); upgradeMaterialIndex++; } NBT.setTag("upgradeMaterials", upgradeMaterialBooleanArrayNBTTag); super.saveNBTData(NBT); } @Override public void loadNBTData(NBTTagCompound NBT) { selectedFuelType = NBT.getInteger("selectedFuelType"); fuelConsumptionFactor = NBT.getInteger("fuelConsumptionFactor"); internalBattery = NBT.getInteger("internalBattery"); batteryCharging = NBT.getBoolean("batteryCharging"); maxBatteryCharge = NBT.getInteger("batterySize"); gravitonShardsAvailable = NBT.getInteger("gravitonShardsAvailable"); gravitonShardsSpent = NBT.getInteger("gravitonShardsSpent"); totalPowerConsumed = new BigInteger(NBT.getByteArray("totalPowerConsumed")); totalRecipesProcessed = NBT.getLong("totalRecipesProcessed"); totalFuelConsumed = NBT.getLong("totalFuelConsumed"); stellarFuelAmount = NBT.getInteger("starFuelStored"); gravitonShardEjection = NBT.getBoolean("gravitonShardEjection"); isRenderActive = NBT.getBoolean("isRenderActive"); ringAmount = NBT.getInteger("ringAmount"); NBTTagCompound tempBooleanTag = NBT.getCompoundTag("upgrades"); for (int upgradeIndex = 0; upgradeIndex < 31; upgradeIndex++) { boolean upgrade = tempBooleanTag.getBoolean("upgrade" + upgradeIndex); upgrades[upgradeIndex] = upgrade; } tempBooleanTag = NBT.getCompoundTag("upgradeMaterials"); for (int upgradeIndex = 0; upgradeIndex < 7; upgradeIndex++) { boolean upgrade = tempBooleanTag.getBoolean("upgradeMaterial" + upgradeIndex); materialPaidUpgrades[upgradeIndex] = upgrade; } super.loadNBTData(NBT); } @Override public boolean getDefaultHasMaintenanceChecks() { return false; } }