diff --git a/src/main/java/gregtech/api/capability/IHPCAComponentHatch.java b/src/main/java/gregtech/api/capability/IHPCAComponentHatch.java index fbd9915ebdb..47a9cce3729 100644 --- a/src/main/java/gregtech/api/capability/IHPCAComponentHatch.java +++ b/src/main/java/gregtech/api/capability/IHPCAComponentHatch.java @@ -1,6 +1,9 @@ package gregtech.api.capability; import gregtech.api.gui.resources.TextureArea; +import gregtech.api.mui.GTGuiTextures; + +import com.cleanroommc.modularui.drawable.UITexture; public interface IHPCAComponentHatch { @@ -46,5 +49,13 @@ default void setDamaged(boolean damaged) {} /** * The icon for this component in the HPCA's UI. Should be a 13x13 px sprite. */ + @Deprecated TextureArea getComponentIcon(); + + /** + * The icon for this component in the HPCA's UI. Should be a 13x13 px sprite. + */ + default UITexture getComponentIcon2() { + return GTGuiTextures.HPCA_ICON_EMPTY_COMPONENT; + } } diff --git a/src/main/java/gregtech/api/capability/impl/MultiblockFuelRecipeLogic.java b/src/main/java/gregtech/api/capability/impl/MultiblockFuelRecipeLogic.java index 4c374985014..324934fb394 100644 --- a/src/main/java/gregtech/api/capability/impl/MultiblockFuelRecipeLogic.java +++ b/src/main/java/gregtech/api/capability/impl/MultiblockFuelRecipeLogic.java @@ -23,6 +23,7 @@ public class MultiblockFuelRecipeLogic extends MultiblockRecipeLogic { protected long totalContinuousRunningTime; + private int previousDuration = 0; public MultiblockFuelRecipeLogic(RecipeMapMultiblockController tileEntity) { super(tileEntity); @@ -127,18 +128,24 @@ public String getRecipeFluidInputInfo() { } else { recipe = previousRecipe; } + previousDuration = recipe.getDuration(); FluidStack requiredFluidInput = recipe.getFluidInputs().get(0).getInputFluidStack(); int ocAmount = GTUtility.safeCastLongToInt(getMaxVoltage() / recipe.getEUt()); int neededAmount = ocAmount * requiredFluidInput.amount; if (rotorHolder != null && rotorHolder.hasRotor()) { - neededAmount /= (rotorHolder.getTotalEfficiency() / 100.0); + neededAmount /= (int) (rotorHolder.getTotalEfficiency() / 100.0); } else if (rotorHolder != null && !rotorHolder.hasRotor()) { return null; } return TextFormatting.RED + TextFormattingUtil.formatNumbers(neededAmount) + "L"; } + @Override + public int getPreviousRecipeDuration() { + return previousDuration; + } + public FluidStack getInputFluidStack() { // Previous Recipe is always null on first world load, so try to acquire a new recipe if (previousRecipe == null) { diff --git a/src/main/java/gregtech/api/fluids/GTFluid.java b/src/main/java/gregtech/api/fluids/GTFluid.java index 5b808f034f8..23237a0ecdd 100644 --- a/src/main/java/gregtech/api/fluids/GTFluid.java +++ b/src/main/java/gregtech/api/fluids/GTFluid.java @@ -12,6 +12,7 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.api.drawable.IKey; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -78,6 +79,23 @@ public GTMaterialFluid(@NotNull String fluidName, ResourceLocation still, Resour return localizedName; } + public @NotNull IKey toIKey() { + IKey localizedName; + String customMaterialTranslation = "fluid." + material.getUnlocalizedName(); + + if (net.minecraft.util.text.translation.I18n.canTranslate(customMaterialTranslation)) { + localizedName = IKey.lang(customMaterialTranslation); + } else { + localizedName = IKey.lang(material.getUnlocalizedName()); + } + + if (translationKey != null) { + return IKey.lang(translationKey, localizedName); + } + + return localizedName; + } + @Override @SideOnly(Side.CLIENT) public String getLocalizedName(FluidStack stack) { diff --git a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java index eada02187ab..f0082eab785 100644 --- a/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java +++ b/src/main/java/gregtech/api/metatileentity/MetaTileEntity.java @@ -492,7 +492,7 @@ public GTGuiTheme getUITheme() { } @Override - public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager) { + public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager panelSyncManager) { return null; } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/FuelMultiblockController.java b/src/main/java/gregtech/api/metatileentity/multiblock/FuelMultiblockController.java index fb3a1993fc2..4b77471d840 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/FuelMultiblockController.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/FuelMultiblockController.java @@ -5,6 +5,8 @@ import gregtech.api.capability.IMultipleTankHandler; import gregtech.api.capability.impl.EnergyContainerList; import gregtech.api.capability.impl.MultiblockFuelRecipeLogic; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.sync.FixedIntArraySyncValue; import gregtech.api.recipes.RecipeMap; import gregtech.api.util.GTUtility; import gregtech.api.util.TextComponentUtil; @@ -16,8 +18,13 @@ import net.minecraft.util.text.Style; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; import net.minecraftforge.fluids.FluidStack; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.screen.RichTooltip; +import com.cleanroommc.modularui.value.sync.StringSyncValue; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -41,16 +48,21 @@ protected void initializeAbilities() { } @Override - protected void addDisplayText(List textList) { + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { MultiblockFuelRecipeLogic recipeLogic = (MultiblockFuelRecipeLogic) recipeMapWorkable; - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()) + builder.setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()) .addEnergyProductionLine(getMaxVoltage(), recipeLogic.getRecipeEUt()) .addFuelNeededLine(recipeLogic.getRecipeFluidInputInfo(), recipeLogic.getPreviousRecipeDuration()) .addWorkingStatusLine(); } + @Override + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addLowDynamoTierLine(isDynamoTierTooLow()) + .addMaintenanceProblemLines(getMaintenanceProblems()); + } + protected long getMaxVoltage() { IEnergyContainer energyContainer = recipeMapWorkable.getEnergyContainer(); if (energyContainer != null && energyContainer.getEnergyCapacity() > 0) { @@ -60,13 +72,6 @@ protected long getMaxVoltage() { } } - @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addLowDynamoTierLine(isDynamoTierTooLow()) - .addMaintenanceProblemLines(getMaintenanceProblems()); - } - protected boolean isDynamoTierTooLow() { if (isStructureFormed()) { IEnergyContainer energyContainer = recipeMapWorkable.getEnergyContainer(); @@ -138,6 +143,7 @@ protected int[] getTotalFluidAmount(FluidStack testStack, IMultipleTankHandler m return new int[] { fluidAmount, fluidCapacity }; } + @Deprecated protected void addFuelText(List textList) { // Fuel int fuelStored = 0; @@ -170,4 +176,26 @@ protected void addFuelText(List textList) { "0 / 0 L")); } } + + /** + * @param tooltip the tooltip to populate + * @param amounts the sync value containing an array of [fuel stored, fuel capacity] + * @param fuelNameValue the name of the fuel + */ + protected void createFuelTooltip(@NotNull RichTooltip tooltip, @NotNull FixedIntArraySyncValue amounts, + @NotNull StringSyncValue fuelNameValue) { + if (isStructureFormed()) { + Fluid fluid = fuelNameValue.getStringValue() == null ? null : + FluidRegistry.getFluid(fuelNameValue.getStringValue()); + if (fluid == null) { + tooltip.addLine(IKey.lang("gregtech.multiblock.large_combustion_engine.fuel_none")); + } else { + tooltip.addLine( + IKey.lang("gregtech.multiblock.large_combustion_engine.fuel_amount", amounts.getValue(0), + amounts.getValue(1), fluid.getLocalizedName(new FluidStack(fluid, 1)))); + } + } else { + tooltip.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + } } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/IProgressBarMultiblock.java b/src/main/java/gregtech/api/metatileentity/multiblock/IProgressBarMultiblock.java index 77567e09af2..21258d166a5 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/IProgressBarMultiblock.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/IProgressBarMultiblock.java @@ -2,11 +2,19 @@ import gregtech.api.gui.GuiTextures; import gregtech.api.gui.resources.TextureArea; +import gregtech.api.mui.GTGuiTextures; import net.minecraft.util.text.ITextComponent; +import com.cleanroommc.modularui.drawable.UITexture; +import com.cleanroommc.modularui.screen.Tooltip; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; + import java.util.List; +@ApiStatus.ScheduledForRemoval +@Deprecated public interface IProgressBarMultiblock { default boolean showProgressBar() { @@ -24,14 +32,26 @@ default int getNumProgressBars() { double getFillPercentage(int index); /** Textures for the progress bar(s). */ + @Deprecated default TextureArea getProgressBarTexture(int index) { return GuiTextures.PROGRESS_BAR_MULTI_ENERGY_YELLOW; } + default UITexture getProgressBarTexture2(int index) { + return GTGuiTextures.PROGRESS_BAR_MULTI_ENERGY_YELLOW; + } + + default int getProgressBarTextureHeight(int index) { + return 18; + } + /** * Add hover text to your progress bar(s). * * @param index The index, 0, 1, or 2, of your progress bar. Only relevant if you have multiple bars. */ + @Deprecated default void addBarHoverText(List hoverList, int index) {} + + default void addBarHoverText2(@NotNull Tooltip tooltip, int index) {} } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiMapMultiblockController.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiMapMultiblockController.java index f80337e10c8..85ccc575bdd 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiMapMultiblockController.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiMapMultiblockController.java @@ -3,12 +3,10 @@ import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.GregtechTileCapabilities; import gregtech.api.capability.IMultipleRecipeMaps; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.ImageCycleButtonWidget; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.pattern.TraceabilityPredicate; import gregtech.api.recipes.RecipeMap; -import gregtech.api.util.LocalizationUtils; import net.minecraft.client.resources.I18n; import net.minecraft.entity.player.EntityPlayer; @@ -25,7 +23,9 @@ import net.minecraftforge.fml.relauncher.SideOnly; import codechicken.lib.raytracer.CuboidRayTraceResult; -import org.jetbrains.annotations.NotNull; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -133,17 +133,27 @@ public TraceabilityPredicate autoAbilities(boolean checkEnergyIn, boolean checkM } @Override - protected @NotNull Widget getFlexButton(int x, int y, int width, int height) { - if (getAvailableRecipeMaps() != null && getAvailableRecipeMaps().length > 1) { - return new ImageCycleButtonWidget(x, y, width, height, GuiTextures.BUTTON_MULTI_MAP, - getAvailableRecipeMaps().length, this::getRecipeMapIndex, this::setRecipeMapIndex) - .shouldUseBaseBackground().singleTexture() - .setTooltipHoverString(i -> LocalizationUtils - .format("gregtech.multiblock.multiple_recipemaps.header") + " " + - LocalizationUtils.format( - "recipemap." + getAvailableRecipeMaps()[i].getUnlocalizedName() + ".name")); - } - return super.getFlexButton(x, y, width, height); + protected MultiblockUIFactory createUIFactory() { + IntSyncValue recipeMapValue = new IntSyncValue(this::getRecipeMapIndex, this::setRecipeMapIndex); + return super.createUIFactory() + .createFlexButton((guiData, syncManager) -> { + if (getAvailableRecipeMaps() == null || getAvailableRecipeMaps().length <= 1) + return null; + + return new CycleButtonWidget() + // .textureGetter(i -> GTGuiTextures.BUTTON_MULTI_MAP) + .overlay(GTGuiTextures.BUTTON_MULTI_MAP) + .background(GTGuiTextures.BUTTON) + // TODO find out why this needs to be called + .disableHoverBackground() + .value(recipeMapValue) + .length(getAvailableRecipeMaps().length) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> t.addLine(IKey.comp( + IKey.lang("gregtech.multiblock.multiple_recipemaps.value", + IKey.lang(getAvailableRecipeMaps()[recipeMapValue.getIntValue()] + .getTranslationKey()))))); + }); } @Override diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockWithDisplayBase.java b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockWithDisplayBase.java index 55723ef456d..301a5e13911 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockWithDisplayBase.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/MultiblockWithDisplayBase.java @@ -5,7 +5,6 @@ import gregtech.api.capability.*; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; -import gregtech.api.gui.Widget; import gregtech.api.gui.Widget.ClickData; import gregtech.api.gui.resources.TextureArea; import gregtech.api.gui.widgets.AdvancedTextWidget; @@ -13,6 +12,7 @@ import gregtech.api.gui.widgets.ImageWidget; import gregtech.api.gui.widgets.IndicatorImageWidget; import gregtech.api.gui.widgets.ProgressWidget; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.pattern.TraceabilityPredicate; import gregtech.api.unification.OreDictUnifier; @@ -33,10 +33,14 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.factory.PosGuiData; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import java.util.*; +import java.util.function.BiFunction; import static gregtech.api.capability.GregtechDataCodes.IS_WORKING; import static gregtech.api.capability.GregtechDataCodes.STORE_TAPED; @@ -46,6 +50,7 @@ public abstract class MultiblockWithDisplayBase extends MultiblockControllerBase private static final String NBT_VOIDING_MODE = "VoidingMode"; private static final String NBT_VOIDING_ITEMS = "VoidingItems"; private static final String NBT_VOIDING_FLUIDS = "VoidingFluids"; + private MultiblockUIFactory uiFactory; private boolean voidingItems = false; private boolean voidingFluids = false; @@ -366,6 +371,7 @@ protected TraceabilityPredicate maintenancePredicate() { * each element of list is displayed on new line * to use translation, use TextComponentTranslation */ + @Deprecated protected void addDisplayText(List textList) { MultiblockDisplayText.builder(textList, isStructureFormed()); } @@ -375,8 +381,10 @@ protected void addDisplayText(List textList) { * with special click event handler * Data is the data specified in the component */ + @Deprecated protected void handleDisplayClick(String componentData, ClickData clickData) {} + @Deprecated protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 198, 208); @@ -458,7 +466,7 @@ protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { if (shouldShowVoidingModeButton()) { builder.widget(new ImageCycleButtonWidget(173, 161, 18, 18, GuiTextures.BUTTON_VOID_MULTIBLOCK, 4, this::getVoidingMode, this::setVoidingMode) - .setTooltipHoverString(MultiblockWithDisplayBase::getVoidingModeTooltip)); + .setTooltipHoverString(this::getVoidingModeTooltip)); } else { builder.widget(new ImageWidget(173, 161, 18, 18, GuiTextures.BUTTON_VOID_NONE) .setTooltip("gregtech.gui.multiblock_voiding_not_supported")); @@ -483,15 +491,17 @@ protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { } /** - * Add a custom third button to the Multiblock UI. By default, this is a placeholder - * stating that there is no additional functionality for this Multiblock. + * Add a custom third button to the Multiblock UI. By default, this is a placeholder stating that there is no + * additional functionality for this Multiblock. *
*
* Parameters should be passed directly to the created widget. Size will be 18x18. + * + * @deprecated override {@link MultiblockUIFactory#createFlexButton(BiFunction)} */ + @Deprecated @SuppressWarnings("SameParameterValue") - @NotNull - protected Widget getFlexButton(int x, int y, int width, int height) { + protected gregtech.api.gui.@NotNull Widget getFlexButton(int x, int y, int width, int height) { return new ImageWidget(x, y, width, height, GuiTextures.BUTTON_NO_FLEX) .setTooltip("gregtech.multiblock.universal.no_flex_button"); } @@ -512,6 +522,7 @@ protected Widget getFlexButton(int x, int y, int width, int height) { * Returns a list of text indicating any current warnings in this Multiblock. * Recommended to only display warnings if the structure is already formed. */ + @Deprecated protected void addWarningText(List textList) { MultiblockDisplayText.builder(textList, isStructureFormed(), false) .addMaintenanceProblemLines(getMaintenanceProblems()); @@ -521,20 +532,21 @@ protected void addWarningText(List textList) { * Returns a list of translation keys indicating any current errors in this Multiblock. * Prioritized over any warnings provided by {@link MultiblockWithDisplayBase#addWarningText}. */ + @Deprecated protected void addErrorText(List textList) { MultiblockDisplayText.builder(textList, isStructureFormed()) .addMufflerObstructedLine(hasMufflerMechanics() && !isMufflerFaceFree()); } - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return true; } - protected int getVoidingMode() { + public final int getVoidingMode() { return voidingMode.ordinal(); } - protected void setVoidingMode(int mode) { + public final void setVoidingMode(int mode) { this.voidingMode = VoidingMode.VALUES[mode]; this.voidingFluids = mode >= 2; @@ -551,10 +563,34 @@ protected void setVoidingMode(int mode) { markDirty(); } - protected static String getVoidingModeTooltip(int mode) { + public @NotNull String getVoidingModeTooltip(int mode) { return VoidingMode.VALUES[mode].getName(); } + @Override + public boolean usesMui2() { + return true; + } + + protected void configureDisplayText(MultiblockUIFactory.Builder builder) {} + + protected void configureErrorText(MultiblockUIFactory.Builder builder) {} + + protected void configureWarningText(MultiblockUIFactory.Builder builder) {} + + protected MultiblockUIFactory createUIFactory() { + return new MultiblockUIFactory(this) + .configureDisplayText(this::configureDisplayText) + .configureWarningText(this::configureWarningText) + .configureErrorText(this::configureErrorText); + } + + @Override + public final ModularPanel buildUI(PosGuiData guiData, PanelSyncManager panelSyncManager) { + if (uiFactory == null) uiFactory = createUIFactory(); + return this.uiFactory.buildUI(guiData, panelSyncManager); + } + @Override protected ModularUI createUI(EntityPlayer entityPlayer) { return createUITemplate(entityPlayer).build(getHolder(), entityPlayer); diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/ProgressBarMultiblock.java b/src/main/java/gregtech/api/metatileentity/multiblock/ProgressBarMultiblock.java new file mode 100644 index 00000000000..8f5813018ea --- /dev/null +++ b/src/main/java/gregtech/api/metatileentity/multiblock/ProgressBarMultiblock.java @@ -0,0 +1,43 @@ +package gregtech.api.metatileentity.multiblock; + +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.ProgressWidget; +import org.jetbrains.annotations.NotNull; + +public interface ProgressBarMultiblock { + + int getProgressBarCount(); + + @NotNull + ProgressWidget createProgressBar(PanelSyncManager panelSyncManager, int index); + + /** + * @return the amount of columns in the progress bar grid + */ + default int getProgressBarCols() { + int count = getProgressBarCount(); + return switch (count) { + case 0, 1, 2, 3 -> count; + case 4 -> 2; + case 5, 6 -> 3; + case 7, 8 -> 4; + default -> throw new UnsupportedOperationException("Cannot compute progress bar cols for count " + count); + }; + } + + /** + * @return the amount of rows in the progress bar grid + */ + default int getProgressBarRows() { + int count = getProgressBarCount(); + if (count <= 3) { + return 1; + } + + if (count <= 8) { + return 2; + } + + throw new UnsupportedOperationException("Cannot compute progress bar rows for count " + count); + } +} diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapMultiblockController.java b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapMultiblockController.java index 06032732857..d04bcd7bb6f 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapMultiblockController.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapMultiblockController.java @@ -10,6 +10,7 @@ import gregtech.api.capability.impl.MultiblockRecipeLogic; import gregtech.api.items.itemhandlers.GTItemStackHandler; import gregtech.api.metatileentity.IDataInfoProvider; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.pattern.TraceabilityPredicate; import gregtech.api.recipes.Recipe; @@ -144,22 +145,17 @@ protected boolean allowSameFluidFillForOutputs() { return true; } - @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) - .addEnergyUsageLine(recipeMapWorkable.getEnergyContainer()) + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) + .addEnergyUsageLine(this.getEnergyContainer()) .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage())) .addParallelsLine(recipeMapWorkable.getParallelLimit()) .addWorkingStatusLine() .addProgressLine(recipeMapWorkable.getProgressPercent()); } - @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addLowPowerLine(recipeMapWorkable.isHasNotEnoughEnergy()) - .addMaintenanceProblemLines(getMaintenanceProblems()); + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addLowPowerLine(recipeMapWorkable.isHasNotEnoughEnergy()); } @Override diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapSteamMultiblockController.java b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapSteamMultiblockController.java index fd396609419..fa6e79698fc 100644 --- a/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapSteamMultiblockController.java +++ b/src/main/java/gregtech/api/metatileentity/multiblock/RecipeMapSteamMultiblockController.java @@ -10,18 +10,18 @@ import gregtech.api.gui.widgets.IndicatorImageWidget; import gregtech.api.items.itemhandlers.GTItemStackHandler; import gregtech.api.metatileentity.MTETrait; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.pattern.TraceabilityPredicate; import gregtech.api.recipes.Recipe; import gregtech.api.recipes.RecipeMap; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.api.util.TextFormattingUtil; import gregtech.common.ConfigHolder; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fluids.IFluidTank; import net.minecraftforge.items.IItemHandlerModifiable; @@ -29,8 +29,7 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; - -import java.util.List; +import com.cleanroommc.modularui.api.drawable.IKey; public abstract class RecipeMapSteamMultiblockController extends MultiblockWithDisplayBase { @@ -101,24 +100,18 @@ private void resetTileAbilities() { } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) - .addCustom(tl -> { + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) + .addCustom(list -> { // custom steam tank line IFluidTank steamFluidTank = recipeMapWorkable.getSteamFluidTankCombined(); if (steamFluidTank != null && steamFluidTank.getCapacity() > 0) { String stored = TextFormattingUtil.formatNumbers(steamFluidTank.getFluidAmount()); String capacity = TextFormattingUtil.formatNumbers(steamFluidTank.getCapacity()); - ITextComponent steamInfo = TextComponentUtil.stringWithColor( - TextFormatting.BLUE, - stored + " / " + capacity + " L"); - - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.steam.steam_stored", - steamInfo)); + IKey steamInfo = KeyUtil.string(TextFormatting.BLUE, stored + " / " + capacity + " L"); + list.add( + KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.steam.steam_stored", steamInfo)); } }) .addParallelsLine(recipeMapWorkable.getParallelLimit()) @@ -127,15 +120,12 @@ protected void addDisplayText(List textList) { } @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addCustom(tl -> { - if (isStructureFormed() && recipeMapWorkable.isHasNotEnoughEnergy()) { - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.YELLOW, - "gregtech.multiblock.steam.low_steam")); - } - }) + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addCustom(list -> { + if (isStructureFormed() && recipeMapWorkable.isHasNotEnoughEnergy()) { + list.add(KeyUtil.lang(TextFormatting.YELLOW, "gregtech.multiblock.steam.low_steam")); + } + }) .addMaintenanceProblemLines(getMaintenanceProblems()); } diff --git a/src/main/java/gregtech/api/metatileentity/multiblock/ui/MultiblockUIFactory.java b/src/main/java/gregtech/api/metatileentity/multiblock/ui/MultiblockUIFactory.java new file mode 100644 index 00000000000..7d69ac374d0 --- /dev/null +++ b/src/main/java/gregtech/api/metatileentity/multiblock/ui/MultiblockUIFactory.java @@ -0,0 +1,930 @@ +package gregtech.api.metatileentity.multiblock.ui; + +import gregtech.api.GTValues; +import gregtech.api.capability.GregtechTileCapabilities; +import gregtech.api.capability.IControllable; +import gregtech.api.capability.IDistinctBusController; +import gregtech.api.capability.IEnergyContainer; +import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; +import gregtech.api.metatileentity.multiblock.ProgressBarMultiblock; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; +import gregtech.api.util.GTLog; +import gregtech.api.util.JsonUtils; +import gregtech.api.util.KeyUtil; +import gregtech.api.util.TextFormattingUtil; +import gregtech.common.ConfigHolder; + +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.text.TextFormatting; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.drawable.IRichTextBuilder; +import com.cleanroommc.modularui.api.widget.IWidget; +import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.factory.PosGuiData; +import com.cleanroommc.modularui.network.NetworkUtils; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Alignment; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.value.sync.SyncHandler; +import com.cleanroommc.modularui.widget.ParentWidget; +import com.cleanroommc.modularui.widget.ScrollWidget; +import com.cleanroommc.modularui.widget.Widget; +import com.cleanroommc.modularui.widget.scroll.VerticalScrollData; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; +import com.cleanroommc.modularui.widgets.ProgressWidget; +import com.cleanroommc.modularui.widgets.RichTextWidget; +import com.cleanroommc.modularui.widgets.SlotGroupWidget; +import com.cleanroommc.modularui.widgets.layout.Flow; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.BiFunction; +import java.util.function.Consumer; + +public class MultiblockUIFactory { + + private final MultiblockWithDisplayBase mte; + protected Consumer displayText, warningText, errorText; + protected BiFunction flexButton = (guiData, syncManager) -> null; + private int width = 198, height = 202; + private int screenHeight = 109; + private Consumer> childrenConsumer; + + public MultiblockUIFactory(@NotNull MultiblockWithDisplayBase mte) { + this.mte = mte; + configureErrorText(builder -> { + if (mte.hasMufflerMechanics()) + builder.addMufflerObstructedLine(!mte.isMufflerFaceFree()); + }); + configureWarningText(builder -> { + if (mte.hasMaintenanceMechanics()) + builder.addMaintenanceProblemLines(mte.getMaintenanceProblems()); + }); + configureDisplayText(builder -> builder.title(mte.getMetaFullName()).structureFormed(mte.isStructureFormed())); + } + + private static @NotNull Consumer addAction(@Nullable Consumer first, @NotNull Consumer andThen) { + return first == null ? andThen : first.andThen(andThen); + } + + /** + * Constructs the multiblock ui panel
+ * It is not recommended to override this method + */ + public @NotNull ModularPanel buildUI(PosGuiData guiData, PanelSyncManager panelSyncManager) { + // this.valueSyncer.accept(panelSyncManager); + var panel = createRootPanel(); + + panel.child(createScreen(panelSyncManager)); + + // TODO createExtras() hook for overrides? + if (mte instanceof ProgressBarMultiblock progressBarMultiblock && + progressBarMultiblock.getProgressBarCount() > 0) { + panel.height(height + (Bars.HEIGHT * 2) - 2); + panel.child(createBars(progressBarMultiblock, panelSyncManager)); + } + + return panel.child(Flow.row() + .bottom(7) + .height(77) + .margin(4, 0) + .child(SlotGroupWidget.playerInventory(0) + .alignX(0f)) + .child(createButtons(panel, panelSyncManager, guiData))); + } + + private Widget createIndicator(PanelSyncManager syncManager) { + Builder error = builder(); + error.sync("error", syncManager); + error.setAction(this.errorText); + error.onRebuild(() -> error.isStructureFormed = mte.isStructureFormed()); + + Builder warning = builder(); + warning.sync("warning", syncManager); + warning.setAction(this.warningText); + warning.onRebuild(() -> warning.isStructureFormed = mte.isStructureFormed()); + + IDrawable indicator = new DynamicDrawable(() -> { + if (!error.isEmpty()) { + return GTGuiTextures.GREGTECH_LOGO_BLINKING_RED; + } else if (!warning.isEmpty()) { + return GTGuiTextures.GREGTECH_LOGO_BLINKING_YELLOW; + } else { + // todo getLogo()? + return GTGuiTextures.GREGTECH_LOGO; + } + }); + + return new Widget<>() + .size(18) + .pos(174 - 5, screenHeight - 18 - 3) + .overlay(indicator) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (!error.isEmpty()) { + error.build(t); + } else if (!warning.isEmpty()) { + warning.build(t); + } + }); + } + + /** + * Returns a list of text indicating any current warnings in this Multiblock.
+ * Recommended to only display warnings if the structure is already formed.
+ * This is called every tick on the client-side + */ + public MultiblockUIFactory configureWarningText(boolean merge, Consumer warningText) { + this.warningText = merge ? addAction(this.warningText, warningText) : warningText; + return this; + } + + /** + * Returns a list of text indicating any current warnings in this Multiblock.
+ * Recommended to only display warnings if the structure is already formed.
+ * This is called every tick on the client-side + */ + public MultiblockUIFactory configureWarningText(Consumer warningText) { + return configureWarningText(true, warningText); + } + + /** + * Returns a list of translation keys indicating any current errors in this Multiblock.
+ * Prioritized over any warnings provided by {@link #configureWarningText(Consumer)}.
+ * This is called every tick on the client-side + */ + public MultiblockUIFactory configureErrorText(boolean merge, Consumer errorText) { + this.errorText = merge ? addAction(this.errorText, errorText) : errorText; + return this; + } + + /** + * Returns a list of translation keys indicating any current errors in this Multiblock.
+ * Prioritized over any warnings provided by {@link #configureWarningText(Consumer)}.
+ * This is called every tick on the client-side + */ + public MultiblockUIFactory configureErrorText(Consumer errorText) { + return configureErrorText(true, errorText); + } + + /** + * Called per tick on client side
+ * Each element of list is displayed on new line
+ * To use translation, use {@link KeyUtil#lang(TextFormatting, String, Object...)} + * or {@link KeyUtil#lang(String, Object...)} + */ + public MultiblockUIFactory configureDisplayText(boolean merge, Consumer displayText) { + this.displayText = merge ? addAction(this.displayText, displayText) : displayText; + return this; + } + + /** + * Called per tick on client side
+ * Each element of list is displayed on new line
+ * To use translation, use {@link KeyUtil#lang(TextFormatting, String, Object...)} + * or {@link KeyUtil#lang(String, Object...)} + */ + public MultiblockUIFactory configureDisplayText(Consumer displayText) { + return configureDisplayText(true, displayText); + } + + /** + * Add a custom third button to the Multiblock UI. By default, this is a placeholder stating that there is no + * additional functionality for this Multiblock. + *
+ * Size will be 18x18. + */ + public MultiblockUIFactory createFlexButton( + BiFunction flexButton) { + this.flexButton = flexButton; + return this; + } + + public MultiblockUIFactory setSize(int width, int height) { + this.width = width; + this.height = height; + return this; + } + + public MultiblockUIFactory setScreenHeight(int height) { + this.screenHeight = height; + return this; + } + + protected @NotNull ModularPanel createRootPanel() { + return GTGuis.createPanel(mte, width, height); + } + + /** + * @param progressMulti the multiblock with progress bars + * @param panelSyncManager the sync manager for synchronizing widgets + */ + @Nullable + protected Flow createBars(@NotNull ProgressBarMultiblock progressMulti, + @NotNull PanelSyncManager panelSyncManager) { + final int rows = progressMulti.getProgressBarRows(); + final int cols = progressMulti.getProgressBarCols(); + + Flow column = Flow.column() + .margin(4, 0) + .top(114) + .widthRel(1f) + .height(Bars.HEIGHT * 2); + + for (int r = 0; r < rows; r++) { + + Flow row = Flow.row() + .widthRel(1f) + .mainAxisAlignment(Alignment.MainAxis.SPACE_BETWEEN) + .height(Bars.HEIGHT); + + // the numbers for the given row of bars + int from = r * cols; + int to = Math.min(from + cols, cols); + + // calculate bar width + int barCount = Math.max(1, to - from); + int barWidth = (Bars.FULL_WIDTH / barCount) - (barCount - 1); + + for (int i = from; i < to; i++) { + row.child(progressMulti.createProgressBar(panelSyncManager, i) + .height(Bars.HEIGHT) + .width(barWidth) + .direction(ProgressWidget.Direction.RIGHT)); + } + + column.child(row); + } + return column; + } + + public MultiblockUIFactory addScreenChildren(Consumer> consumer) { + this.childrenConsumer = consumer; + return this; + } + + protected Widget createScreen(PanelSyncManager syncManager) { + Builder display = builder(); + display.setAction(this.displayText); + display.sync("display", syncManager); + + // todo scrolling doesn't work for rich text widget + var scrollWidget = new ScrollWidget<>(new VerticalScrollData()) + .sizeRel(1f) + .child(new RichTextWidget() + .sizeRel(1f) + .alignment(Alignment.TopLeft) + .margin(4, 4) + .autoUpdate(true) + .textBuilder(display::build)); + + if (this.childrenConsumer != null) { + List extra = new ArrayList<>(); + this.childrenConsumer.accept(extra); + extra.forEach(scrollWidget::child); + } + + return new ParentWidget<>() + .child(scrollWidget) + .child(createIndicator(syncManager)) + .background(GTGuiTextures.DISPLAY) + .size(190, screenHeight) + .pos(4, 4); + } + + @NotNull + protected Flow createButtons(@NotNull ModularPanel mainPanel, @NotNull PanelSyncManager panelSyncManager, + PosGuiData guiData) { + IWidget flexButton = this.flexButton.apply(guiData, panelSyncManager); + if (flexButton == null) { + flexButton = GTGuiTextures.BUTTON_NO_FLEX.asWidget() + .size(18) + .addTooltipLine(IKey.lang("gregtech.multiblock.universal.no_flex_button")); + } + var powerButton = createPowerButton(mainPanel, panelSyncManager); + + return Flow.column() + .alignX(1f) + .right(4) + .size(18, 77) + .child(createDistinctButton(mainPanel, panelSyncManager)) + .child(createVoidingButton(mainPanel, panelSyncManager)) + .child(flexButton) + .childIf(powerButton != null, powerButton); + } + + protected IWidget createDistinctButton(@NotNull ModularPanel mainPanel, + @NotNull PanelSyncManager panelSyncManager) { + if (!(mte instanceof IDistinctBusController distinct) || !distinct.canBeDistinct()) { + return GTGuiTextures.BUTTON_NO_DISTINCT_BUSES.asWidget() + .size(18, 18) + .addTooltipLine(IKey.lang("gregtech.multiblock.universal.distinct_not_supported")); + } + + BooleanSyncValue distinctValue = new BooleanSyncValue(distinct::isDistinct, distinct::setDistinct); + + return new CycleButtonWidget() + .size(18, 18) + .value(distinctValue) + .stateBackground(true, GTGuiTextures.BUTTON_DISTINCT_BUSES[1]) + .stateBackground(false, GTGuiTextures.BUTTON_DISTINCT_BUSES[0]) + .background(GTGuiTextures.BUTTON) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> t.addLine(distinctValue.getBoolValue() ? + IKey.lang("gregtech.multiblock.universal.distinct_enabled") : + IKey.lang("gregtech.multiblock.universal.distinct_disabled"))); + } + + protected IWidget createVoidingButton(@NotNull ModularPanel mainPanel, @NotNull PanelSyncManager panelSyncManager) { + if (!mte.shouldShowVoidingModeButton()) { + return GTGuiTextures.BUTTON_VOID_NONE.asWidget() + .size(18, 18) + .addTooltipLine(IKey.lang("gregtech.gui.multiblock_voiding_not_supported")); + } + + IntSyncValue voidingValue = new IntSyncValue(mte::getVoidingMode, mte::setVoidingMode); + + return new CycleButtonWidget() + .size(18, 18) + .stateOverlay(0, GTGuiTextures.MULTIBLOCK_VOID[0]) + .stateOverlay(1, GTGuiTextures.MULTIBLOCK_VOID[1]) + .stateOverlay(2, GTGuiTextures.MULTIBLOCK_VOID[2]) + .stateOverlay(3, GTGuiTextures.MULTIBLOCK_VOID[3]) + .background(GTGuiTextures.BUTTON) + .value(voidingValue) + .length(4) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> t.addLine(IKey.lang(mte.getVoidingModeTooltip(voidingValue.getIntValue())))); + } + + @Nullable + protected Widget createPowerButton(@NotNull ModularPanel mainPanel, @NotNull PanelSyncManager panelSyncManager) { + IControllable controllable; + if (!(mte instanceof IControllable)) { + // is this actually relevant? + // todo in the future, refactor so that this multis are instanceof IControllable. + controllable = mte.getCapability(GregtechTileCapabilities.CAPABILITY_CONTROLLABLE, null); + if (controllable == null) return null; + GTLog.logger.warn("MTE [{}] does not extend IControllable when it should!", mte.getClass().getSimpleName()); + } else { + controllable = (IControllable) mte; + } + + return new CycleButtonWidget() + .size(18) + .stateOverlay(true, GTGuiTextures.BUTTON_POWER[1]) + .stateOverlay(false, GTGuiTextures.BUTTON_POWER[0]) + .disableHoverBackground() + .background(GTGuiTextures.BUTTON_POWER_DETAIL.asIcon().size(18, 6).marginTop(24), GTGuiTextures.BUTTON) + .value(new BooleanSyncValue(controllable::isWorkingEnabled, controllable::setWorkingEnabled)) + .marginTop(5); + } + + public static final class Screen { + + public static int WIDTH = 190; + + private Screen() {} + } + + public static final class Bars { + + public static int FULL_WIDTH = Screen.WIDTH; + public static int HALF_WIDTH = 94; + public static int THIRD_WIDTH = 62; + public static int HEIGHT = 7; + + private Bars() {} + } + + public static Builder builder() { + return new Builder(); + } + + @SuppressWarnings({ "UnusedReturnValue", "unused" }) + public static class Builder { + + private final List textList = new ArrayList<>(); + private Consumer action; + private final SyncHandler syncHandler = makeSyncHandler(); + + private boolean isWorkingEnabled; + private boolean isActive; + private boolean isStructureFormed; + + // Keys for the three-state working system, can be set custom by multiblocks. + private IKey idlingKey = IKey.lang("gregtech.multiblock.idling").style(TextFormatting.GRAY); + private IKey pausedKey = IKey.lang("gregtech.multiblock.work_paused").style(TextFormatting.GOLD); + private IKey runningKey = IKey.lang("gregtech.multiblock.running").style(TextFormatting.GREEN); + private boolean dirty; + private Runnable onRebuild; + + public Builder structureFormed(boolean structureFormed) { + this.isStructureFormed = structureFormed; + if (!structureFormed) { + var base = KeyUtil.lang(TextFormatting.RED, "gregtech.multiblock.invalid_structure"); + var hover = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.invalid_structure.tooltip"); + addKey(base, hover); + } + return this; + } + + public Builder title(String lang) { + addKey(KeyUtil.lang(TextFormatting.WHITE, lang)); + return this; + } + + /** Set the current working enabled and active status of this multiblock, used by many line addition calls. */ + public Builder setWorkingStatus(boolean isWorkingEnabled, boolean isActive) { + this.isWorkingEnabled = isWorkingEnabled; + this.isActive = isActive; + return this; + } + + /** + * Set custom translation keys for the three-state "Idling", "Paused", "Running" display text. + * You still must call {@link Builder#addWorkingStatusLine()} for these to appear! + *
+ * Pass any key as null for it to continue to use the default key. + * + * @param idlingKey The translation key for the Idle state, or "!isActive && isWorkingEnabled". + * @param pausedKey The translation key for the Paused state, or "!isWorkingEnabled". + * @param runningKey The translation key for the Running state, or "isActive". + */ + public Builder setWorkingStatusKeys(String idlingKey, String pausedKey, String runningKey) { + if (idlingKey != null) this.idlingKey = IKey.lang(idlingKey).style(TextFormatting.GRAY); + if (pausedKey != null) this.pausedKey = IKey.lang(pausedKey).style(TextFormatting.GOLD); + if (runningKey != null) this.runningKey = IKey.lang(runningKey).style(TextFormatting.GREEN); + return this; + } + + /** + * Adds the max EU/t that this multiblock can use. + *
+ * Added if the structure is formed and if the passed energy container has greater than zero capacity. + */ + public Builder addEnergyUsageLine(IEnergyContainer energyContainer) { + if (!isStructureFormed || energyContainer == null) return this; + if (energyContainer.getEnergyCapacity() <= 0) return this; + + long maxVoltage = Math.max(energyContainer.getInputVoltage(), energyContainer.getOutputVoltage()); + + IKey bodyText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.max_energy_per_tick", + KeyUtil.number(maxVoltage), + KeyUtil.voltage(GTValues.VOCNF, maxVoltage)); + + var hoverText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.max_energy_per_tick_hover"); + + addKey(bodyText, hoverText); + return this; + } + + /** + * Adds the max Recipe Tier that this multiblock can use for recipe lookup. + *
+ * Added if the structure is formed and if the passed tier is a valid energy tier index for + * {@link GTValues#VNF}. + */ + public Builder addEnergyTierLine(int tier) { + if (!isStructureFormed) return this; + if (tier < GTValues.ULV || tier > GTValues.MAX) return this; + + var bodyText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.max_recipe_tier", GTValues.VNF[tier]); + var hoverText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.max_recipe_tier_hover"); + addKey(bodyText, hoverText); + return this; + } + + /** + * Adds the exact EU/t that this multiblock needs to run. + *
+ * Added if the structure is formed and if the passed value is greater than zero. + */ + public Builder addEnergyUsageExactLine(long energyUsage) { + if (!isStructureFormed) return this; + if (energyUsage > 0) { + String energyFormatted = TextFormattingUtil.formatNumbers(energyUsage); + // wrap in text component to keep it from being formatted + var voltageName = KeyUtil.overclock(GTValues.VOCNF, energyUsage); + + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.energy_consumption", energyFormatted, voltageName)); + } + return this; + } + + /** + * Adds the max EU/t that this multiblock can produce. + *
+ * Added if the structure is formed and if the max voltage is greater than zero and the recipe EU/t. + */ + public Builder addEnergyProductionLine(long maxVoltage, long recipeEUt) { + if (!isStructureFormed) return this; + if (maxVoltage != 0 && maxVoltage >= -recipeEUt) { + String energyFormatted = TextFormattingUtil.formatNumbers(maxVoltage); + // wrap in text component to keep it from being formatted + var voltageName = KeyUtil.voltage(GTValues.VOCNF, maxVoltage); + + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.max_energy_per_tick", energyFormatted, voltageName)); + } + return this; + } + + /** + * Adds the max EU/t that this multiblock can produce, including how many amps. Recommended for multi-amp + * outputting multis. + *
+ * Added if the structure is formed, if the amperage is greater than zero and if the max voltage is greater than + * zero. + */ + public Builder addEnergyProductionAmpsLine(long maxVoltage, int amperage) { + if (!isStructureFormed) return this; + if (maxVoltage != 0 && amperage != 0) { + String energyFormatted = TextFormattingUtil.formatNumbers(maxVoltage); + // wrap in text component to keep it from being formatted + var voltageName = KeyUtil.voltage(GTValues.VOCNF, maxVoltage); + + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.max_energy_per_tick_amps", + energyFormatted, amperage, voltageName)); + } + return this; + } + + /** + * Adds the max CWU/t that this multiblock can use. + *
+ * Added if the structure is formed and if the max CWU/t is greater than zero. + */ + public Builder addComputationUsageLine(int maxCWUt) { + if (!isStructureFormed) return this; + if (maxCWUt > 0) { + var computation = KeyUtil.number(TextFormatting.AQUA, maxCWUt); + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.computation.max", computation)); + } + return this; + } + + /** + * Adds a currently used CWU/t line. + *
+ * Added if the structure is formed, the machine is active, and the current CWU/t is greater than zero. + */ + public Builder addComputationUsageExactLine(int currentCWUt) { + if (!isStructureFormed) return this; + if (isActive && currentCWUt > 0) { + var computation = KeyUtil.number(TextFormatting.AQUA, currentCWUt, " CWU/t"); + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.computation.usage", computation)); + } + return this; + } + + /** + * Adds a three-state indicator line, showing if the machine is running, paused, or idling. + *
+ * Added if the structure is formed. + */ + public Builder addWorkingStatusLine() { + if (!isStructureFormed) return this; + + if (!isWorkingEnabled) { + addKey(pausedKey); + } else if (isActive) { + addKey(runningKey); + } else { + addKey(idlingKey); + } + return this; + } + + /** + * Adds the "Work Paused." line. + *
+ * Added if working is not enabled, or if the checkState passed parameter is false. + * Also added only if formed. + */ + public Builder addWorkPausedLine(boolean checkState) { + if (!isStructureFormed) return this; + if (!checkState || !isWorkingEnabled) { + addKey(pausedKey); + } + return this; + } + + /** + * Adds the "Running Perfectly." line. + *
+ * Added if machine is active, or if the checkState passed parameter is false. + * Also added only if formed. + */ + public Builder addRunningPerfectlyLine(boolean checkState) { + if (!isStructureFormed) return this; + if (!checkState || isActive) { + addKey(runningKey); + } + return this; + } + + /** + * Adds the "Idling." line. + *
+ * Added if the machine is not active and working is enabled, or if the checkState passed parameter is false. + * Also added only if formed. + */ + public Builder addIdlingLine(boolean checkState) { + if (!isStructureFormed) return this; + if (!checkState || (isWorkingEnabled && !isActive)) { + addKey(idlingKey); + } + return this; + } + + /** + * Adds a simple progress line that displays progress as a percentage. + *
+ * Added if structure is formed and the machine is active. + * + * @param progressPercent Progress formatted as a range of [0,1] representing the progress of the recipe. + */ + public Builder addProgressLine(double progressPercent) { + if (!isStructureFormed || !isActive) return this; + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.progress", + (int) (progressPercent * 100))); + return this; + } + + /** + * Adds a line indicating how many parallels this multi can potentially perform. + *
+ * Added if structure is formed and the number of parallels is greater than one. + */ + public Builder addParallelsLine(int numParallels) { + if (!isStructureFormed) return this; + if (numParallels > 1) { + var parallels = KeyUtil.number(TextFormatting.DARK_PURPLE, numParallels); + + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.parallel", parallels)); + } + return this; + } + + /** + * Adds a warning line when the machine is low on power. + *
+ * Added if the structure is formed and if the passed parameter is true. + */ + public Builder addLowPowerLine(boolean isLowPower) { + if (!isStructureFormed) return this; + if (isLowPower) { + addKey(KeyUtil.lang(TextFormatting.YELLOW, + "gregtech.multiblock.not_enough_energy")); + } + return this; + } + + /** + * Adds a warning line when the machine is low on computation. + *
+ * Added if the structure is formed and if the passed parameter is true. + */ + public Builder addLowComputationLine(boolean isLowComputation) { + if (!isStructureFormed) return this; + if (isLowComputation) { + addKey(KeyUtil.lang(TextFormatting.YELLOW, + "gregtech.multiblock.computation.not_enough_computation")); + } + return this; + } + + /** + * Adds a warning line when the machine's dynamo tier is too low for current conditions. + *
+ * Added if the structure is formed and if the passed parameter is true. + */ + public Builder addLowDynamoTierLine(boolean isTooLow) { + if (!isStructureFormed) return this; + if (isTooLow) { + addKey(KeyUtil.lang(TextFormatting.YELLOW, + "gregtech.multiblock.not_enough_energy_output")); + } + return this; + } + + /** + * Adds warning line(s) when the machine has maintenance problems. + *
+ * Added if there are any maintenance problems, one line per problem as well as a header.
+ * Will check the config setting for if maintenance is enabled automatically. + */ + public Builder addMaintenanceProblemLines(byte maintenanceProblems) { + if (!isStructureFormed || !ConfigHolder.machines.enableMaintenance) return this; + if (maintenanceProblems < 63) { + addKey(KeyUtil.lang(TextFormatting.YELLOW, + "gregtech.multiblock.universal.has_problems")); + + // Wrench + if ((maintenanceProblems & 1) == 0) { + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.universal.problem.wrench")); + } + + // Screwdriver + if (((maintenanceProblems >> 1) & 1) == 0) { + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.universal.problem.screwdriver")); + } + + // Soft Mallet + if (((maintenanceProblems >> 2) & 1) == 0) { + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.universal.problem.soft_mallet")); + } + + // Hammer + if (((maintenanceProblems >> 3) & 1) == 0) { + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.universal.problem.hard_hammer")); + } + + // Wire Cutters + if (((maintenanceProblems >> 4) & 1) == 0) { + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.universal.problem.wire_cutter")); + } + + // Crowbar + if (((maintenanceProblems >> 5) & 1) == 0) { + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.universal.problem.crowbar")); + } + } + return this; + } + + /** + * Adds two error lines when the machine's muffler hatch is obstructed. + *
+ * Added if the structure is formed and if the passed parameter is true. + */ + public Builder addMufflerObstructedLine(boolean isObstructed) { + if (!isStructureFormed) return this; + if (isObstructed) { + addKey(KeyUtil.lang(TextFormatting.RED, + "gregtech.multiblock.universal.muffler_obstructed")); + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.universal.muffler_obstructed_desc")); + } + return this; + } + + /** + * Adds a fuel consumption line showing the fuel name and the number of ticks per recipe run. + *
+ * Added if structure is formed, the machine is active, and the passed fuelName parameter is not null. + */ + public Builder addFuelNeededLine(String fuelName, int previousRecipeDuration) { + if (!isStructureFormed || !isActive || fuelName == null) return this; + + addKey(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.turbine.fuel_needed", + KeyUtil.string(TextFormatting.RED, fuelName), + KeyUtil.number(TextFormatting.AQUA, previousRecipeDuration))); + return this; + } + + /** Insert an empty line into the text list. */ + public Builder addEmptyLine() { + this.textList.add(IKey.LINE_FEED); + return this; + } + + /** Add custom text dynamically, allowing for custom application logic. */ + public Builder addCustom(Consumer> customConsumer) { + customConsumer.accept(this.textList); + return this; + } + + public boolean isEmpty() { + return this.textList.isEmpty(); + } + + public void clear() { + this.textList.clear(); + } + + protected boolean hasChanged() { + if (this.action == null) return false; + List old = new ArrayList<>(); + for (var drawable : this.textList) old.add(JsonUtils.toJsonString(drawable)); + build(); + if (textList.size() != old.size()) return true; + for (int i = 0; i < textList.size(); i++) { + if (!JsonUtils.toJsonString(textList.get(i)).equals(old.get(i))) + return true; + } + return false; + } + + protected void sync(String key, PanelSyncManager syncManager) { + syncManager.syncValue(key, this.syncHandler); + } + + private SyncHandler makeSyncHandler() { + return new SyncHandler() { + + @Override + public void detectAndSendChanges(boolean init) { + if (init || hasChanged()) { + if (init) { + onRebuild(); + build(); + } + sync(0, this::syncText); + markDirty(); + } + } + + private void syncText(PacketBuffer buffer) { + buffer.writeVarInt(textList.size()); + for (IDrawable drawable : textList) { + var jsonString = JsonUtils.toJsonString(drawable); + NetworkUtils.writeStringSafe(buffer, jsonString); + } + } + + @Override + public void readOnClient(int id, PacketBuffer buf) { + if (id == 0) { + clear(); + for (int i = buf.readVarInt(); i > 0; i--) { + String jsonString = NetworkUtils.readStringSafe(buf); + addKey(JsonUtils.fromJsonString(jsonString)); + } + } + } + + @Override + public void readOnServer(int id, PacketBuffer buf) {} + }; + } + + public void build(IRichTextBuilder richText) { + if (dirty) { + onRebuild(); + build(); + dirty = false; + } + for (IDrawable drawable : textList) { + richText.addLine(drawable).spaceLine(2); + } + } + + private void onRebuild() { + if (this.onRebuild != null) { + this.onRebuild.run(); + } + } + + public void markDirty() { + dirty = true; + } + + protected void build() { + clear(); + if (this.action != null) this.action.accept(this); + } + + protected void setAction(Consumer action) { + this.action = action; + } + + public void onRebuild(Runnable onRebuild) { + this.onRebuild = onRebuild; + } + + private void addKey(IDrawable key) { + this.textList.add(key); + } + + private void addKey(IKey key, IDrawable... hover) { + addKey(KeyUtil.setHover(key, hover)); + } + } +} diff --git a/src/main/java/gregtech/api/mui/GTGuiTextures.java b/src/main/java/gregtech/api/mui/GTGuiTextures.java index b92acd290b0..b58261af180 100644 --- a/src/main/java/gregtech/api/mui/GTGuiTextures.java +++ b/src/main/java/gregtech/api/mui/GTGuiTextures.java @@ -8,6 +8,8 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import java.util.concurrent.atomic.AtomicInteger; + /** * GT MUI textures.
* Marked experimental as some of these textures may disappear or be renamed at some point @@ -43,7 +45,12 @@ public static class IDs { /** @apiNote You may want {@link GTGuiTextures#getLogo} instead. */ public static final UITexture GREGTECH_LOGO_XMAS = fullImage("textures/gui/icon/gregtech_logo_xmas.png"); public static final UITexture GREGTECH_LOGO_DARK = fullImage("textures/gui/icon/gregtech_logo_dark.png"); - // todo blinking GT logos + public static final IDrawable GREGTECH_LOGO_BLINKING_YELLOW = animated( + "textures/gui/icon/gregtech_logo_blinking_yellow.png", + 17, 34, true, 60); + public static final IDrawable GREGTECH_LOGO_BLINKING_RED = animated( + "textures/gui/icon/gregtech_logo_blinking_red.png", + 17, 34, true, 36); public static final UITexture INDICATOR_NO_ENERGY = fullImage("textures/gui/base/indicator_no_energy.png"); public static final UITexture INDICATOR_NO_STEAM_BRONZE = fullImage( @@ -117,6 +124,17 @@ public static class IDs { // todo primitive display? + // FUSION + public static final UITexture FUSION_REACTOR_MK1_TITLE = fullImage( + "textures/gui/widget/fusion_reactor_mk1_title.png"); + public static final UITexture FUSION_REACTOR_MK2_TITLE = fullImage( + "textures/gui/widget/fusion_reactor_mk2_title.png"); + public static final UITexture FUSION_REACTOR_MK3_TITLE = fullImage( + "textures/gui/widget/fusion_reactor_mk3_title.png"); + public static final UITexture FUSION_DIAGRAM = fullImage("textures/gui/widget/fusion_reactor_diagram.png"); + public static final UITexture FUSION_LEGEND = fullImage("textures/gui/widget/fusion_reactor_legend.png"); + public static final UITexture FUSION_PROGRESS = fullImage("textures/gui/progress_bar/fusion_diagram/stitched.png"); + // SLOTS public static final UITexture SLOT = new UITexture.Builder() .location(GTValues.MODID, "textures/gui/base/slot.png") @@ -156,6 +174,25 @@ public static class IDs { .canApplyTheme() .build(); + // HPCA Component icons + public static final UITexture BLANK_TRANSPARENT = fullImage("textures/gui/base/blank_transparent.png"); + public static final UITexture HPCA_COMPONENT_OUTLINE = fullImage("textures/gui/widget/hpca/component_outline.png"); + public static final UITexture HPCA_ICON_EMPTY_COMPONENT = fullImage("textures/gui/widget/hpca/empty_component.png"); + public static final UITexture HPCA_ICON_ADVANCED_COMPUTATION_COMPONENT = fullImage( + "textures/gui/widget/hpca/advanced_computation_component.png"); + public static final UITexture HPCA_ICON_BRIDGE_COMPONENT = fullImage( + "textures/gui/widget/hpca/bridge_component.png"); + public static final UITexture HPCA_ICON_COMPUTATION_COMPONENT = fullImage( + "textures/gui/widget/hpca/computation_component.png"); + public static final UITexture HPCA_ICON_ACTIVE_COOLER_COMPONENT = fullImage( + "textures/gui/widget/hpca/active_cooler_component.png"); + public static final UITexture HPCA_ICON_HEAT_SINK_COMPONENT = fullImage( + "textures/gui/widget/hpca/heat_sink_component.png"); + public static final UITexture HPCA_ICON_DAMAGED_ADVANCED_COMPUTATION_COMPONENT = fullImage( + "textures/gui/widget/hpca/damaged_advanced_computation_component.png"); + public static final UITexture HPCA_ICON_DAMAGED_COMPUTATION_COMPONENT = fullImage( + "textures/gui/widget/hpca/damaged_computation_component.png"); + public static final UITexture[] BUTTON_BLACKLIST = slice("textures/gui/widget/button_blacklist.png", 16, 32, 16, 16, true); public static final UITexture[] BUTTON_IGNORE_DAMAGE = slice("textures/gui/widget/button_filter_damage.png", @@ -359,8 +396,42 @@ public static class IDs { public static final UITexture BUTTON_CROSS = fullImage("textures/gui/widget/button_cross.png"); public static final UITexture BUTTON_REDSTONE_ON = fullImage("textures/gui/widget/button_redstone_on.png"); public static final UITexture BUTTON_REDSTONE_OFF = fullImage("textures/gui/widget/button_redstone_off.png"); - public static final UITexture BUTTON_THROTTLE_PLUS = fullImage("textures/gui/widget/button_throttle_plus.png"); - public static final UITexture BUTTON_THROTTLE_MINUS = fullImage("textures/gui/widget/button_throttle_minus.png"); + + /** + * 0 = OFF
+ * 1 = ON
+ */ + public static final UITexture[] BUTTON_POWER = slice("textures/gui/widget/button_power.png", + 18, 36, 18, 18, true); + + public static final UITexture BUTTON_POWER_DETAIL = fullImage("textures/gui/widget/button_power_detail.png", true); + + /** + * 0 = DISABLED
+ * 1 = ITEM VOID
+ * 2 = FLUID VOID
+ * 3 = VOID BOTH
+ **/ + public static final UITexture[] MULTIBLOCK_VOID = slice("textures/gui/widget/button_void_multiblock.png", + 18, 72, 18, 18, true); + + public static final UITexture BUTTON_VOID_NONE = fullImage("textures/gui/widget/button_void_none.png", true); + + /** + * 0 = DISABLED
+ * 1 = ENABLED
+ */ + public static final UITexture[] BUTTON_DISTINCT_BUSES = slice("textures/gui/widget/button_distinct_buses.png", + 18, 36, 18, 18, true); + public static final UITexture BUTTON_NO_DISTINCT_BUSES = fullImage( + "textures/gui/widget/button_no_distinct_buses.png", true); + public static final UITexture BUTTON_NO_FLEX = fullImage("textures/gui/widget/button_no_flex.png", true); + public static final UITexture BUTTON_MULTI_MAP = fullImage("textures/gui/widget/button_multi_map.png", true); + public static final UITexture BUTTON_MINER_MODES = fullImage("textures/gui/widget/button_miner_modes.png", true); + public static final UITexture BUTTON_THROTTLE_MINUS = fullImage("textures/gui/widget/button_throttle_minus.png", + true); // TODO new texture + public static final UITexture BUTTON_THROTTLE_PLUS = fullImage("textures/gui/widget/button_throttle_plus.png", + true); // TODO remove this // PROGRESS BARS public static final UITexture PROGRESS_BAR_ARC_FURNACE = progressBar( @@ -463,9 +534,9 @@ public static class IDs { .adaptable(1) .build(); public static final UITexture PROGRESS_BAR_BOILER_FUEL_BRONZE = progressBar( - "textures/gui/progress_bar/progress_bar_boiler_fuel_bronze.png", 18, 36); + "textures/gui/progress_bar/progress_bar_boiler_fuel_bronze.png", 18, 36, true); public static final UITexture PROGRESS_BAR_BOILER_FUEL_STEEL = progressBar( - "textures/gui/progress_bar/progress_bar_boiler_fuel_steel.png", 18, 36); + "textures/gui/progress_bar/progress_bar_boiler_fuel_steel.png", 18, 36, true); public static final UITexture PROGRESS_BAR_BOILER_HEAT = progressBar( "textures/gui/progress_bar/progress_bar_boiler_heat.png", true); public static final UITexture PROGRESS_BAR_ASSEMBLY_LINE = progressBar( @@ -477,9 +548,9 @@ public static class IDs { public static final UITexture PROGRESS_BAR_DISTILLATION_TOWER = progressBar( "textures/gui/progress_bar/progress_bar_distillation_tower.png", 66, 116, true); public static final UITexture PROGRESS_BAR_SOLAR_BRONZE = progressBar( - "textures/gui/progress_bar/progress_bar_solar_bronze.png", 10, 20); + "textures/gui/progress_bar/progress_bar_solar_bronze.png", 10, 20, true); public static final UITexture PROGRESS_BAR_SOLAR_STEEL = progressBar( - "textures/gui/progress_bar/progress_bar_solar_steel.png", 10, 20); + "textures/gui/progress_bar/progress_bar_solar_steel.png", 10, 20, true); public static final UITexture PROGRESS_BAR_RESEARCH_STATION_1 = progressBar( "textures/gui/progress_bar/progress_bar_research_station_1.png", 54, 10, true); public static final UITexture PROGRESS_BAR_RESEARCH_STATION_2 = progressBar( @@ -487,25 +558,25 @@ public static class IDs { public static final UITexture PROGRESS_BAR_RESEARCH_STATION_BASE = fullImage( "textures/gui/progress_bar/progress_bar_research_station_base.png", true); public static final UITexture PROGRESS_BAR_FUSION_ENERGY = progressBar( - "textures/gui/progress_bar/progress_bar_fusion_energy.png", 94, 14); + "textures/gui/progress_bar/progress_bar_fusion_energy.png", 94, 14, true); public static final UITexture PROGRESS_BAR_FUSION_HEAT = progressBar( - "textures/gui/progress_bar/progress_bar_fusion_heat.png", 94, 14); + "textures/gui/progress_bar/progress_bar_fusion_heat.png", 94, 14, true); public static final UITexture PROGRESS_BAR_MULTI_ENERGY_YELLOW = progressBar( - "textures/gui/progress_bar/progress_bar_multi_energy_yellow.png", 190, 14); + "textures/gui/progress_bar/progress_bar_multi_energy_yellow.png", 190, 14, true); public static final UITexture PROGRESS_BAR_HPCA_COMPUTATION = progressBar( - "textures/gui/progress_bar/progress_bar_hpca_computation.png", 94, 14); + "textures/gui/progress_bar/progress_bar_hpca_computation.png", 94, 14, true); public static final UITexture PROGRESS_BAR_LCE_FUEL = progressBar( - "textures/gui/progress_bar/progress_bar_lce_fuel.png", 62, 14); + "textures/gui/progress_bar/progress_bar_lce_fuel.png", 62, 14, true); public static final UITexture PROGRESS_BAR_LCE_LUBRICANT = progressBar( - "textures/gui/progress_bar/progress_bar_lce_lubricant.png", 62, 14); + "textures/gui/progress_bar/progress_bar_lce_lubricant.png", 62, 14, true); public static final UITexture PROGRESS_BAR_LCE_OXYGEN = progressBar( - "textures/gui/progress_bar/progress_bar_lce_oxygen.png", 62, 14); + "textures/gui/progress_bar/progress_bar_lce_oxygen.png", 62, 14, true); public static final UITexture PROGRESS_BAR_TURBINE_ROTOR_SPEED = progressBar( - "textures/gui/progress_bar/progress_bar_turbine_rotor_speed.png", 62, 14); + "textures/gui/progress_bar/progress_bar_turbine_rotor_speed.png", 62, 14, true); public static final UITexture PROGRESS_BAR_TURBINE_ROTOR_DURABILITY = progressBar( - "textures/gui/progress_bar/progress_bar_turbine_rotor_durability.png", 62, 14); + "textures/gui/progress_bar/progress_bar_turbine_rotor_durability.png", 62, 14, true); public static final UITexture PROGRESS_BAR_FLUID_RIG_DEPLETION = progressBar( - "textures/gui/progress_bar/progress_bar_fluid_rig_depletion.png", 190, 14); + "textures/gui/progress_bar/progress_bar_fluid_rig_depletion.png", 190, 14, true); // MISC @@ -542,6 +613,15 @@ private static UITexture[] slice(String path, int imageWidth, int imageHeight, i return slices; } + private static UITexture[] slice(String path, int imageWidth, int imageHeight, boolean canApplyTheme) { + int sliceSize = Math.min(imageWidth, imageHeight); + return slice(path, imageWidth, imageHeight, sliceSize, sliceSize, canApplyTheme); + } + + private static IDrawable animated(String path, int imageWidth, int imageHeight, boolean canApplyTheme, int rate) { + return dynamic(slice(path, imageWidth, imageHeight, canApplyTheme), rate); + } + private static UITexture progressBar(String path) { return progressBar(path, 20, 40, false); } @@ -570,4 +650,17 @@ private static UITexture progressBar(String path, int width, int height, boolean } return GTValues.XMAS.get() ? GREGTECH_LOGO_XMAS : GREGTECH_LOGO; } + + public static IDrawable dynamic(UITexture[] textures, int rate) { + AtomicInteger index = new AtomicInteger(); + AtomicInteger tick = new AtomicInteger(); + // todo something is wrong with this + // also this method is client only so that could cause problems too + return (context, x, y, width, height, widgetTheme) -> { + int a = tick.getAndIncrement() % rate; // this makes rate per frame ? + int i = a == 0 ? index.incrementAndGet() : index.get(); + index.set(i % textures.length); + textures[index.get()].draw(context, x, y, width, height, widgetTheme); + }; + } } diff --git a/src/main/java/gregtech/api/mui/drawables/HoverableKey.java b/src/main/java/gregtech/api/mui/drawables/HoverableKey.java new file mode 100644 index 00000000000..7cbf0a30a51 --- /dev/null +++ b/src/main/java/gregtech/api/mui/drawables/HoverableKey.java @@ -0,0 +1,123 @@ +package gregtech.api.mui.drawables; + +import net.minecraft.client.gui.FontRenderer; + +import com.cleanroommc.modularui.api.MCHelper; +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IHoverable; +import com.cleanroommc.modularui.api.drawable.IIcon; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.ITooltip; +import com.cleanroommc.modularui.screen.RichTooltip; +import com.cleanroommc.modularui.screen.viewport.GuiContext; +import com.cleanroommc.modularui.theme.WidgetTheme; +import com.cleanroommc.modularui.widget.sizer.Area; +import com.cleanroommc.modularui.widget.sizer.Box; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +public class HoverableKey implements IIcon, IHoverable, ITooltip { + + private final Box margin = new Box(); + private final Area area = new Area(); + private final List tooltipLines = new ArrayList<>(); + private RichTooltip tooltip; + private IKey key; + + private HoverableKey() { + tooltipAutoUpdate(true); + tooltipBuilder(t -> t.addDrawableLines(getTooltipLines())); + } + + public static HoverableKey of(IKey key) { + return new HoverableKey().setKey(key); + } + + public static HoverableKey of(IKey key, IDrawable... lines) { + return of(key).addLines(Arrays.asList(lines)); + } + + public FontRenderer getFontRenderer() { + return MCHelper.getFontRenderer(); + } + + @Override + public int getWidth() { + return getFontRenderer().getStringWidth(key.get()) + this.margin.horizontal(); + } + + @Override + public int getHeight() { + return getFontRenderer().FONT_HEIGHT + this.margin.vertical(); + } + + @Override + public Box getMargin() { + return margin; + } + + @Override + public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) { + int w = getWidth(), h = getHeight(); + x += (int) (width / 2f - w / 2f); + y += (int) (height / 2f - h / 2f); + this.key.draw(context, x, y, width, height, widgetTheme); + } + + public IKey getKey() { + return key; + } + + public HoverableKey setKey(IKey key) { + this.key = key; + return getThis(); + } + + public List getTooltipLines() { + return tooltipLines; + } + + public HoverableKey addLines(Collection drawables) { + this.getTooltipLines().addAll(drawables); + return getThis(); + } + + @Override + @Nullable + public RichTooltip getTooltip() { + return tooltip; + } + + @Override + public void setRenderedAt(int x, int y) { + getRenderedArea().setPos(x, y); + } + + @Override + public Area getRenderedArea() { + this.area.setSize(getWidth(), getHeight()); + return this.area; + } + + @Override + public @NotNull RichTooltip tooltip() { + if (this.tooltip == null) this.tooltip = new RichTooltip(area -> area.set(getRenderedArea())); + return tooltip; + } + + @Override + public HoverableKey tooltip(RichTooltip tooltip) { + this.tooltip = tooltip; + return this; + } + + @Override + public String toString() { + return "HoverableKey(" + key.getFormatted() + ")"; + } +} diff --git a/src/main/java/gregtech/api/mui/serialize/DrawableSerializer.java b/src/main/java/gregtech/api/mui/serialize/DrawableSerializer.java new file mode 100644 index 00000000000..6316ba15ab0 --- /dev/null +++ b/src/main/java/gregtech/api/mui/serialize/DrawableSerializer.java @@ -0,0 +1,45 @@ +package gregtech.api.mui.serialize; + +import gregtech.api.mui.drawables.HoverableKey; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; + +import java.util.Arrays; + +public class DrawableSerializer implements JsonHandler { + + KeySerializer keySerializer = new KeySerializer(); + + @Override + public IDrawable deserialize(JsonElement json, JsonDeserializationContext context) + throws JsonParseException { + if (!json.isJsonObject()) return IDrawable.EMPTY; + JsonObject parsed = json.getAsJsonObject(); + if (parsed.has("key") && parsed.has("tooltip")) { + IKey key = context.deserialize(parsed.get("key"), IKey.class); + + IDrawable[] list = deserializeArray(parsed.getAsJsonArray("tooltip"), context, IDrawable[]::new); + return HoverableKey.of(key).addLines(Arrays.asList(list)); + } else { + return keySerializer.deserialize(json, context); + } + } + + @Override + public JsonElement serialize(IDrawable src, JsonSerializationContext context) { + JsonObject object = new JsonObject(); + if (src instanceof IKey key) { + return keySerializer.serialize(key, context); + } else if (src instanceof HoverableKey hoverable) { + object.add("key", keySerializer.serialize(hoverable.getKey(), context)); + object.add("tooltip", serializeArray(hoverable.getTooltipLines(), context)); + } + return object; + } +} diff --git a/src/main/java/gregtech/api/mui/serialize/FormatSerializer.java b/src/main/java/gregtech/api/mui/serialize/FormatSerializer.java new file mode 100644 index 00000000000..1fe8f7e2476 --- /dev/null +++ b/src/main/java/gregtech/api/mui/serialize/FormatSerializer.java @@ -0,0 +1,23 @@ +package gregtech.api.mui.serialize; + +import net.minecraft.util.text.TextFormatting; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; + +public class FormatSerializer implements JsonHandler { + + @Override + public TextFormatting deserialize(JsonElement json, + JsonDeserializationContext context) throws JsonParseException { + return TextFormatting.getValueByName(json.getAsString()); + } + + @Override + public JsonElement serialize(TextFormatting src, + JsonSerializationContext context) { + return context.serialize(src.getFriendlyName()); + } +} diff --git a/src/main/java/gregtech/api/mui/serialize/JsonHandler.java b/src/main/java/gregtech/api/mui/serialize/JsonHandler.java new file mode 100644 index 00000000000..447e8723dad --- /dev/null +++ b/src/main/java/gregtech/api/mui/serialize/JsonHandler.java @@ -0,0 +1,97 @@ +package gregtech.api.mui.serialize; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonPrimitive; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import java.lang.reflect.Array; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.Collection; +import java.util.function.IntFunction; + +public interface JsonHandler extends JsonSerializer, JsonDeserializer { + + @Override + default JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) { + return serialize(src, context); + } + + @Override + default T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + return deserialize(json, context); + } + + JsonElement serialize(T src, JsonSerializationContext context); + + T deserialize(JsonElement json, JsonDeserializationContext context) throws JsonParseException; + + default JsonArray serializeArray(R[] objects, JsonSerializationContext context) { + JsonArray array = new JsonArray(); + if (objects == null) return array; + Type arrayType = objects.getClass().getComponentType(); + for (R t : objects) { + JsonElement element = context.serialize(t, arrayType); + if (element.isJsonPrimitive() && element.getAsJsonPrimitive().isNumber()) { + JsonObject typed = new JsonObject(); + typed.addProperty("typed", t.getClass().getSimpleName()); + typed.add("element", element); + array.add(typed); + } else { + array.add(element); + } + } + return array; + } + + @SuppressWarnings("unchecked") + default JsonArray serializeArray(Collection objects, JsonSerializationContext context) { + R[] array = null; + int i = 0; + for (R object : objects) { + if (array == null) array = (R[]) Array.newInstance(object.getClass(), objects.size()); + array[i++] = object; + } + return serializeArray(array, context); + } + + default R[] deserializeArray(JsonArray jsonArray, JsonDeserializationContext context, + IntFunction function) { + if (jsonArray == null || jsonArray.size() == 0) return function.apply(0); + R[] array = function.apply(jsonArray.size()); + Type arrayType = array.getClass().getComponentType(); + Arrays.setAll(array, i -> handleArg(jsonArray.get(i), context, arrayType)); + return array; + } + + static Object handleArg(JsonElement element, JsonDeserializationContext context, Type arrayType) { + // args can sometimes be keys + if (element.isJsonObject()) { + JsonObject object = element.getAsJsonObject(); + if (!object.has("typed")) + return context.deserialize(object, IDrawable.class); + + JsonElement value = object.get("element"); + return switch (object.get("typed").getAsString()) { + case "Integer" -> value.getAsInt(); + case "Long" -> value.getAsLong(); + case "Double" -> value.getAsDouble(); + case "Float" -> value.getAsFloat(); + case "Byte" -> value.getAsByte(); + default -> value.getAsNumber(); + }; + } else if (element instanceof JsonPrimitive primitive && primitive.isNumber()) { + return primitive.getAsNumber(); + } else { + return context.deserialize(element, arrayType); + } + } +} diff --git a/src/main/java/gregtech/api/mui/serialize/KeySerializer.java b/src/main/java/gregtech/api/mui/serialize/KeySerializer.java new file mode 100644 index 00000000000..4563c179125 --- /dev/null +++ b/src/main/java/gregtech/api/mui/serialize/KeySerializer.java @@ -0,0 +1,82 @@ +package gregtech.api.mui.serialize; + +import net.minecraft.util.text.TextFormatting; + +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.text.CompoundKey; +import com.cleanroommc.modularui.drawable.text.DynamicKey; +import com.cleanroommc.modularui.drawable.text.FormattingState; +import com.cleanroommc.modularui.drawable.text.LangKey; +import com.cleanroommc.modularui.drawable.text.StringKey; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.Map; + +public class KeySerializer implements JsonHandler { + + private static final Map FORMATTING_MAP = new Object2ObjectOpenHashMap<>(); + + static { + for (var tf : TextFormatting.values()) { + FORMATTING_MAP.put(tf.toString(), tf); + } + } + + @Override + public IKey deserialize(JsonElement json, JsonDeserializationContext context) + throws JsonParseException { + JsonObject object = json.getAsJsonObject(); + if (object.has("string")) { + return IKey.str(object.get("string").getAsString()); + } else if (object.has("lang")) { + String lang = context.deserialize(object.get("lang"), String.class); + TextFormatting[] formatting = deserializeArray(object.getAsJsonArray("format"), context, + TextFormatting[]::new); + Object[] args = deserializeArray( + object.getAsJsonArray("args"), context, Object[]::new); + return IKey.lang(lang, args).style(formatting); + } else if (object.has("keys")) { + IKey[] keys = deserializeArray( + object.getAsJsonArray("keys"), context, IKey[]::new); + TextFormatting[] formatting = deserializeArray( + object.getAsJsonArray("format"), context, TextFormatting[]::new); + return IKey.comp(keys).style(formatting); + } + return IKey.EMPTY; + } + + @Override + public JsonElement serialize(IKey src, JsonSerializationContext context) { + JsonObject obj = new JsonObject(); + if (src instanceof StringKey || src instanceof DynamicKey) { + obj.add("string", context.serialize(src.getFormatted())); + } else if (src instanceof LangKey langKey) { + obj.add("lang", context.serialize(langKey.getKeySupplier().get())); + TextFormatting[] formattings = convert(langKey.getFormatting()); + obj.add("format", serializeArray(formattings, context)); + Object[] args = langKey.getArgsSupplier().get(); + if (!ArrayUtils.isEmpty(args)) + obj.add("args", serializeArray(args, context)); + } else if (src instanceof CompoundKey compoundKey) { + obj.add("keys", serializeArray(compoundKey.getKeys(), context)); + obj.add("format", serializeArray(convert(compoundKey.getFormatting()), context)); + } + return obj; + } + + public static TextFormatting[] convert(FormattingState state) { + if (state == null) return new TextFormatting[0]; + String s = state.getFormatting(); + TextFormatting[] formattings = new TextFormatting[s.length() / 2]; + for (int i = 0; i < s.length(); i += 2) { + formattings[i / 2] = FORMATTING_MAP.get(s.substring(i, i + 2)); + } + return formattings; + } +} diff --git a/src/main/java/gregtech/api/mui/sync/BigIntegerSyncValue.java b/src/main/java/gregtech/api/mui/sync/BigIntegerSyncValue.java new file mode 100644 index 00000000000..6b48af3f85a --- /dev/null +++ b/src/main/java/gregtech/api/mui/sync/BigIntegerSyncValue.java @@ -0,0 +1,92 @@ +package gregtech.api.mui.sync; + +import net.minecraft.network.PacketBuffer; + +import com.cleanroommc.modularui.api.value.sync.IStringSyncValue; +import com.cleanroommc.modularui.network.NetworkUtils; +import com.cleanroommc.modularui.value.sync.ValueSyncHandler; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.math.BigInteger; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; + +public class BigIntegerSyncValue extends ValueSyncHandler implements IStringSyncValue { + + private BigInteger cache = BigInteger.ZERO; + private final Supplier getter; + private final @Nullable Consumer setter; + + public BigIntegerSyncValue(@NotNull Supplier<@NotNull BigInteger> getter, + @Nullable Consumer<@NotNull BigInteger> setter) { + this.getter = getter; + this.setter = setter; + } + + @Contract("null, _, null, _ -> fail") + public BigIntegerSyncValue(@Nullable Supplier<@NotNull BigInteger> clientGetter, + @Nullable Consumer<@NotNull BigInteger> clientSetter, + @Nullable Supplier<@NotNull BigInteger> serverGetter, + @Nullable Consumer<@NotNull BigInteger> serverSetter) { + if (clientGetter == null && serverGetter == null) { + throw new NullPointerException("Client or server getter must not be null!"); + } + if (NetworkUtils.isClient()) { + this.getter = clientGetter != null ? clientGetter : serverGetter; + this.setter = clientSetter != null ? clientSetter : serverSetter; + } else { + this.getter = serverGetter != null ? serverGetter : clientGetter; + this.setter = serverSetter != null ? serverSetter : clientSetter; + } + this.cache = this.getter.get(); + } + + @Override + public void setStringValue(String value, boolean setSource, boolean sync) { + setValue(new BigInteger(value), setSource, sync); + } + + @Override + public String getStringValue() { + return cache.toString(); + } + + @Override + public void setValue(BigInteger value, boolean setSource, boolean sync) { + this.cache = value; + if (setSource && this.setter != null) { + this.setter.accept(value); + } + if (sync) { + sync(0, this::write); + } + } + + @Override + public boolean updateCacheFromSource(boolean isFirstSync) { + if (this.getter != null && (isFirstSync || !Objects.equals(this.getter.get(), this.cache))) { + setValue(this.getter.get(), false, false); + return true; + } + return false; + } + + @Override + public void write(@NotNull PacketBuffer buffer) throws IOException { + buffer.writeByteArray(cache.toByteArray()); + } + + @Override + public void read(@NotNull PacketBuffer buffer) throws IOException { + this.cache = new BigInteger(buffer.readByteArray()); + } + + @Override + public BigInteger getValue() { + return this.cache; + } +} diff --git a/src/main/java/gregtech/api/mui/sync/FixedIntArraySyncValue.java b/src/main/java/gregtech/api/mui/sync/FixedIntArraySyncValue.java new file mode 100644 index 00000000000..c3f29ee80b5 --- /dev/null +++ b/src/main/java/gregtech/api/mui/sync/FixedIntArraySyncValue.java @@ -0,0 +1,95 @@ +package gregtech.api.mui.sync; + +import net.minecraft.network.PacketBuffer; + +import com.cleanroommc.modularui.network.NetworkUtils; +import com.cleanroommc.modularui.value.sync.ValueSyncHandler; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; + +/** + * Sync Value for an array with fixed length. + *

+ * Does not create new arrays. + */ +public class FixedIntArraySyncValue extends ValueSyncHandler { + + private final int[] cache; + private final Supplier getter; + private final @Nullable Consumer setter; + + public FixedIntArraySyncValue(@NotNull Supplier getter, @Nullable Consumer setter) { + this.getter = Objects.requireNonNull(getter); + this.setter = setter; + this.cache = getter.get(); + } + + @Contract("null, _, null, _ -> fail") + public FixedIntArraySyncValue(@Nullable Supplier clientGetter, @Nullable Consumer clientSetter, + @Nullable Supplier serverGetter, @Nullable Consumer serverSetter) { + if (clientGetter == null && serverGetter == null) { + throw new NullPointerException("Client or server getter must not be null!"); + } + if (NetworkUtils.isClient()) { + this.getter = clientGetter != null ? clientGetter : serverGetter; + this.setter = clientSetter != null ? clientSetter : serverSetter; + } else { + this.getter = serverGetter != null ? serverGetter : clientGetter; + this.setter = serverSetter != null ? serverSetter : clientSetter; + } + this.cache = this.getter.get(); + } + + @Override + public void setValue(int @NotNull [] value, boolean setSource, boolean sync) { + if (value.length != cache.length) { + throw new IllegalArgumentException("Incompatible array lengths"); + } + System.arraycopy(value, 0, cache, 0, value.length); + if (setSource && this.setter != null) { + this.setter.accept(value); + } + if (sync) { + sync(0, this::write); + } + } + + @Override + public boolean updateCacheFromSource(boolean isFirstSync) { + if (isFirstSync || !Arrays.equals(this.getter.get(), this.cache)) { + setValue(this.getter.get(), false, false); + return true; + } + return false; + } + + @Override + public void write(@NotNull PacketBuffer buffer) throws IOException { + for (int i : cache) { + buffer.writeVarInt(i); + } + } + + @Override + public void read(@NotNull PacketBuffer buffer) throws IOException { + for (int i = 0; i < cache.length; i++) { + cache[i] = buffer.readVarInt(); + } + } + + @Override + public int[] getValue() { + return this.cache; + } + + public int getValue(int index) { + return this.cache[index]; + } +} diff --git a/src/main/java/gregtech/api/util/GTUtility.java b/src/main/java/gregtech/api/util/GTUtility.java index 39b4a6a0d65..fd29f7f70e3 100644 --- a/src/main/java/gregtech/api/util/GTUtility.java +++ b/src/main/java/gregtech/api/util/GTUtility.java @@ -54,6 +54,7 @@ import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandlerModifiable; +import com.cleanroommc.modularui.api.drawable.IKey; import com.google.common.util.concurrent.AtomicDouble; import it.unimi.dsi.fastutil.objects.ObjectOpenCustomHashSet; import org.apache.commons.lang3.ArrayUtils; @@ -894,6 +895,15 @@ public static TextComponentTranslation getFluidTranslation(@Nullable Fluid fluid return new TextComponentTranslation(fluid.getUnlocalizedName()); } + @Contract("null -> null") + public static IKey getFluidIKey(@Nullable Fluid fluid) { + if (fluid == null) return null; + if (fluid instanceof GTFluid.GTMaterialFluid materialFluid) { + return materialFluid.toIKey(); + } + return IKey.lang(fluid.getUnlocalizedName()); + } + public static @NotNull Pair createPairedSupplier(int ticksPerCycle, int width, double splitPoint) { AtomicDouble tracker = new AtomicDouble(0.0); diff --git a/src/main/java/gregtech/api/util/JsonUtils.java b/src/main/java/gregtech/api/util/JsonUtils.java new file mode 100644 index 00000000000..ebcf949f671 --- /dev/null +++ b/src/main/java/gregtech/api/util/JsonUtils.java @@ -0,0 +1,31 @@ +package gregtech.api.util; + +import gregtech.api.mui.serialize.DrawableSerializer; +import gregtech.api.mui.serialize.FormatSerializer; + +import net.minecraft.util.text.TextFormatting; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + +public class JsonUtils { + + private static final Gson gson = new GsonBuilder() + .setPrettyPrinting() + .registerTypeHierarchyAdapter(IDrawable.class, new DrawableSerializer()) + .registerTypeAdapter(TextFormatting.class, new FormatSerializer()) + .create(); + + public static String toJsonString(IDrawable drawable) { + return getGson().toJson(drawable, IDrawable.class); + } + + public static Gson getGson() { + return gson; + } + + public static IDrawable fromJsonString(String jsonString) { + return getGson().fromJson(jsonString, IDrawable.class); + } +} diff --git a/src/main/java/gregtech/api/util/KeyUtil.java b/src/main/java/gregtech/api/util/KeyUtil.java new file mode 100644 index 00000000000..41d9fa06feb --- /dev/null +++ b/src/main/java/gregtech/api/util/KeyUtil.java @@ -0,0 +1,131 @@ +package gregtech.api.util; + +import gregtech.api.mui.drawables.HoverableKey; + +import net.minecraft.util.text.TextFormatting; + +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.function.LongSupplier; +import java.util.function.Supplier; + +public class KeyUtil { + + public static final String SECTION = "§"; + + public static IKey string(String s) { + return IKey.str(s); + } + + public static IKey string(Supplier s) { + return IKey.dynamic(s); + } + + public static IKey string(TextFormatting formatting, String string) { + if (string == null) return IKey.EMPTY; + return IKey.str(string).style(formatting); + } + + public static IKey string(TextFormatting formatting, String string, Object... args) { + if (string == null) return IKey.EMPTY; + return IKey.str(string, args).style(formatting); + } + + public static IKey string(TextFormatting formatting, Supplier stringSupplier) { + return IKey.dynamic(stringSupplier).style(formatting); + } + + public static IKey string(TextFormatting formatting, Supplier stringSupplier, + Supplier argSupplier) { + return IKey.dynamic(() -> String.format(stringSupplier.get(), argSupplier.get())).style(formatting); + } + + public static IKey string(Supplier formatting, String s) { + return IKey.dynamic(() -> IKey.str(s).style(formatting.get()).getFormatted()); + } + + public static IKey string(Supplier formatting, Supplier stringSupplier) { + return IKey.dynamic(() -> IKey.str(stringSupplier.get()).style(formatting.get()).getFormatted()); + } + + public static IKey lang(String lang, Object... args) { + return IKey.lang(lang, args); + } + + public static IKey lang(TextFormatting formatting, String lang, Object... args) { + return IKey.lang(lang, args).style(formatting); + } + + public static IKey lang(TextFormatting formatting, String lang, Supplier argSupplier) { + return IKey.lang(lang, argSupplier).style(formatting); + } + + public static IKey lang(Supplier formatting, String lang, Supplier argSupplier) { + return IKey.dynamic(() -> lang(lang, argSupplier.get()).style(formatting.get()).getFormatted()); + } + + public static IKey number(long number) { + return string(TextFormattingUtil.formatNumbers(number)); + } + + public static IKey number(TextFormatting formatting, long number) { + return number(number).style(formatting); + } + + public static IKey number(TextFormatting formatting, long number, String suffix) { + return string(formatting, TextFormattingUtil.formatNumbers(number) + suffix); + } + + public static IKey number(TextFormatting formatting, LongSupplier supplier) { + return string(formatting, () -> TextFormattingUtil.formatNumbers(supplier.getAsLong())); + } + + public static IKey number(TextFormatting formatting, LongSupplier supplier, String suffix) { + return string(formatting, () -> TextFormattingUtil.formatNumbers(supplier.getAsLong()) + suffix); + } + + public static IKey number(Supplier formatting, LongSupplier supplier) { + return string(formatting, () -> TextFormattingUtil.formatNumbers(supplier.getAsLong())); + } + + public static IKey number(Supplier formatting, long number) { + return string(formatting, () -> TextFormattingUtil.formatNumbers(number)); + } + + public static IKey number(Supplier formatting, long number, String suffix) { + return string(formatting, () -> TextFormattingUtil.formatNumbers(number) + suffix); + } + + public static IKey number(Supplier formatting, LongSupplier supplier, String suffix) { + return string(formatting, () -> TextFormattingUtil.formatNumbers(supplier.getAsLong()) + suffix); + } + + /** + * Calls {@link GTUtility#getFloorTierByVoltage(long)} to get the voltage tier + * + * @param array Array of voltage names + * @param voltage The max voltage + * @return the voltage name for the given voltage tier + */ + public static IKey voltage(String[] array, long voltage) { + return string(array[GTUtility.getFloorTierByVoltage(voltage)]); + } + + /** + * Calls {@link GTUtility#getFloorTierByVoltage(long)} to get the voltage tier + * + * @param array Array of voltage names + * @param voltage The max voltage + * @return the voltage name for the given voltage tier + */ + public static IKey overclock(String[] array, long voltage) { + return string(array[GTUtility.getOCTierByVoltage(voltage)]); + } + + public static IDrawable setHover(IKey body, IDrawable... hover) { + if (ArrayUtils.isEmpty(hover)) return body; + return HoverableKey.of(body, hover); + } +} diff --git a/src/main/java/gregtech/api/util/TextFormattingUtil.java b/src/main/java/gregtech/api/util/TextFormattingUtil.java index 00a1f5f0aea..895df71e5fa 100644 --- a/src/main/java/gregtech/api/util/TextFormattingUtil.java +++ b/src/main/java/gregtech/api/util/TextFormattingUtil.java @@ -1,5 +1,6 @@ package gregtech.api.util; +import java.math.BigInteger; import java.text.NumberFormat; public class TextFormattingUtil { @@ -13,9 +14,23 @@ public class TextFormattingUtil { 1_000_000_000_000_000_000L }; + private static final BigInteger[] metricBigSuffixValues = { + BigInteger.TEN.pow(3), + BigInteger.TEN.pow(6), + BigInteger.TEN.pow(9), + BigInteger.TEN.pow(12), + BigInteger.TEN.pow(15), + BigInteger.TEN.pow(18), + BigInteger.TEN.pow(21), + BigInteger.TEN.pow(24), + BigInteger.TEN.pow(27), + BigInteger.TEN.pow(30) + }; + private static final char[] metricSuffixChars = { - 'k', 'M', 'G', 'T', 'P', 'E' + 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q' }; + private static final NumberFormat NUMBER_FORMAT = NumberFormat.getInstance(); public static String formatLongToCompactString(long value, int precision) { @@ -36,13 +51,36 @@ public static String formatLongToCompactString(long value, int precision) { long suffixValue = metricSuffixValues[i]; stb.append(value / suffixValue); - long truncatedDigit = value % suffixValue / (suffixValue / 10); + long truncatedDigit = value % suffixValue / (suffixValue / (long) Math.pow(10, precision - 3)); if (truncatedDigit > 0) { stb.append('.').append(truncatedDigit); } return stb.append(metricSuffixChars[i]).toString(); } + public static String formatBigIntToCompactString(BigInteger value, int precision) { + if (BigInteger.ZERO.equals(value) || value.abs().compareTo(BigInteger.TEN.pow(precision)) < 0) { + return value.toString(); // deal with easy case + } + + StringBuilder stb = new StringBuilder(); + if (value.signum() == -1) { + stb.append('-'); + value = value.abs(); + } + + int c = 0; + while (value.compareTo(metricBigSuffixValues[c]) >= 0) { + c++; + } + + return stb.append(value.divide(metricBigSuffixValues[c - 1])) + .append('.') + .append(value.toString(), 4, precision + 1) + .append(metricSuffixChars[c - 1]) + .toString(); + } + public static String formatLongToCompactString(long value) { return formatLongToCompactString(value, 3); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityLargeBoiler.java b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityLargeBoiler.java index 6921ca44d5f..c07b8ef20f7 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityLargeBoiler.java +++ b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityLargeBoiler.java @@ -4,21 +4,17 @@ import gregtech.api.capability.impl.CommonFluidFilters; import gregtech.api.capability.impl.FluidTankList; import gregtech.api.capability.impl.ItemHandlerList; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.Widget; -import gregtech.api.gui.Widget.ClickData; -import gregtech.api.gui.resources.TextureArea; -import gregtech.api.gui.widgets.ClickButtonWidget; -import gregtech.api.gui.widgets.WidgetGroup; import gregtech.api.metatileentity.MTETrait; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.*; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.GTGuis; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; -import gregtech.api.util.TextComponentUtil; -import gregtech.api.util.TextFormattingUtil; +import gregtech.api.util.KeyUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.utils.TooltipHelper; import gregtech.core.sound.GTSoundEvents; @@ -29,8 +25,6 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.fluids.IFluidTank; @@ -41,13 +35,29 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.GuiAxis; +import com.cleanroommc.modularui.api.IPanelHandler; +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.ItemDrawable; +import com.cleanroommc.modularui.drawable.Rectangle; +import com.cleanroommc.modularui.screen.ModularPanel; +import com.cleanroommc.modularui.utils.Color; +import com.cleanroommc.modularui.value.sync.DoubleSyncValue; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.ButtonWidget; +import com.cleanroommc.modularui.widgets.ProgressWidget; +import com.cleanroommc.modularui.widgets.SliderWidget; +import com.cleanroommc.modularui.widgets.layout.Row; +import com.cleanroommc.modularui.widgets.textfield.TextFieldWidget; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; -public class MetaTileEntityLargeBoiler extends MultiblockWithDisplayBase implements IProgressBarMultiblock { +public class MetaTileEntityLargeBoiler extends MultiblockWithDisplayBase implements ProgressBarMultiblock { public final BoilerType boilerType; protected BoilerRecipeLogic recipeLogic; @@ -95,46 +105,6 @@ private void resetTileAbilities() { this.steamOutputTank = new FluidTankList(true); } - @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()) - .addCustom(tl -> { - if (isStructureFormed()) { - // Steam Output line - ITextComponent steamOutput = TextComponentUtil.stringWithColor( - TextFormatting.AQUA, - TextFormattingUtil.formatNumbers(recipeLogic.getLastTickSteam()) + " L/t"); - - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.large_boiler.steam_output", - steamOutput)); - - // Efficiency line - ITextComponent efficiency = TextComponentUtil.stringWithColor( - getNumberColor(recipeLogic.getHeatScaled()), - recipeLogic.getHeatScaled() + "%"); - - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.large_boiler.efficiency", - efficiency)); - - // Throttle line - ITextComponent throttle = TextComponentUtil.stringWithColor( - getNumberColor(getThrottle()), - getThrottle() + "%"); - - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.large_boiler.throttle", - throttle)); - } - }) - .addWorkingStatusLine(); - } - private TextFormatting getNumberColor(int number) { if (number == 0) { return TextFormatting.DARK_RED; @@ -148,37 +118,121 @@ private TextFormatting getNumberColor(int number) { } @Override - protected void addWarningText(List textList) { - super.addWarningText(textList); - if (isStructureFormed()) { - int[] waterAmount = getWaterAmount(); - if (waterAmount[0] == 0) { - textList.add(TextComponentUtil.translationWithColor(TextFormatting.YELLOW, + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()) + .addCustom(this::addCustomData) + .addWorkingStatusLine(); + } + + @Override + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + super.configureWarningText(builder); + builder.addCustom(richText -> { + if (isStructureFormed() && getWaterFilled() == 0) { + richText.add(KeyUtil.lang(TextFormatting.YELLOW, "gregtech.multiblock.large_boiler.no_water")); - textList.add(TextComponentUtil.translationWithColor(TextFormatting.GRAY, + richText.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.large_boiler.explosion_tooltip")); } - } + }); } @Override - protected @NotNull Widget getFlexButton(int x, int y, int width, int height) { - WidgetGroup group = new WidgetGroup(x, y, width, height); - group.addWidget(new ClickButtonWidget(0, 0, 9, 18, "", this::decrementThrottle) - .setButtonTexture(GuiTextures.BUTTON_THROTTLE_MINUS) - .setTooltipText("gregtech.multiblock.large_boiler.throttle_decrement")); - group.addWidget(new ClickButtonWidget(9, 0, 9, 18, "", this::incrementThrottle) - .setButtonTexture(GuiTextures.BUTTON_THROTTLE_PLUS) - .setTooltipText("gregtech.multiblock.large_boiler.throttle_increment")); - return group; - } - - private void incrementThrottle(ClickData clickData) { - this.throttlePercentage = MathHelper.clamp(throttlePercentage + 5, 25, 100); + protected MultiblockUIFactory createUIFactory() { + return super.createUIFactory() + .createFlexButton((guiData, syncManager) -> { + var throttle = syncManager.panel("throttle_panel", this::makeThrottlePanel, true); + + return new ButtonWidget<>() + .width(18) + .overlay(GTGuiTextures.FILTER_SETTINGS_OVERLAY) + // todo lang + .addTooltipLine("Configure Boiler Throttle") + .background(GTGuiTextures.BUTTON) + .onMousePressed(i -> { + if (throttle.isPanelOpen()) { + throttle.closePanel(); + } else { + throttle.openPanel(); + } + return true; + }); + }); + } + + private void addCustomData(List keyList) { + if (isStructureFormed()) { + // Steam Output line + IKey steamOutput = KeyUtil.number(TextFormatting.AQUA, + recipeLogic.getLastTickSteam(), " L/t"); + + keyList.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.large_boiler.steam_output", steamOutput)); + + // Efficiency line + IKey efficiency = KeyUtil.number( + () -> getNumberColor(recipeLogic.getHeatScaled()), + recipeLogic.getHeatScaled(), "%"); + keyList.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.large_boiler.efficiency", efficiency)); + + // Throttle line + IKey throttle = KeyUtil.number( + () -> getNumberColor(getThrottle()), + getThrottle(), "%"); + keyList.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.large_boiler.throttle", throttle)); + } } - private void decrementThrottle(ClickData clickData) { - this.throttlePercentage = MathHelper.clamp(throttlePercentage - 5, 25, 100); + private ModularPanel makeThrottlePanel(PanelSyncManager syncManager, IPanelHandler syncHandler) { + IntSyncValue throttleValue = new IntSyncValue(this::getThrottlePercentage, this::setThrottlePercentage); + DoubleSyncValue sliderValue = new DoubleSyncValue( + () -> (double) getThrottlePercentage() / 100, + d -> setThrottlePercentage((int) (d * 100))); + + return GTGuis.createPopupPanel("boiler_throttle", 116, 53) + .child(new Row() + .pos(4, 4) + .height(16) + .coverChildrenWidth() + .child(new ItemDrawable(getStackForm()) + .asWidget() + .size(16) + .marginRight(4)) + .child(IKey.lang("gregtech.multiblock.large_boiler.throttle.title") + .asWidget() + .heightRel(1.0f))) + .child(new Row() + .top(20) + .margin(4, 0) + .coverChildrenHeight() + .child(new SliderWidget() + .background(new Rectangle().setColor(Color.BLACK.brighter(2)).asIcon() + .height(8)) + .bounds(0, 1) + .setAxis(GuiAxis.X) + .value(sliderValue) + .widthRel(0.7f) + .height(20)) + // TODO add inc/dec buttons + .child(new TextFieldWidget() + .widthRel(0.3f) + .height(20) + // TODO proper color + .setTextColor(Color.WHITE.darker(1)) + .setNumbers(0, 100) + // TODO show % sign + .value(throttleValue) + .background(GTGuiTextures.DISPLAY))); + } + + private void setThrottlePercentage(int amount) { + this.throttlePercentage = amount; + } + + private int getThrottlePercentage() { + return this.throttlePercentage; } @Override @@ -187,7 +241,7 @@ public boolean isActive() { } @Override - protected BlockPattern createStructurePattern() { + protected @NotNull BlockPattern createStructurePattern() { return FactoryBlockPattern.start() .aisle("XXX", "CCC", "CCC", "CCC") .aisle("XXX", "CPC", "CPC", "CCC") @@ -311,61 +365,70 @@ protected boolean shouldUpdate(MTETrait trait) { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } @Override - public double getFillPercentage(int index) { - if (!isStructureFormed()) return 0; - int[] waterAmount = getWaterAmount(); - if (waterAmount[1] == 0) return 0; // no water capacity - return (1.0 * waterAmount[0]) / waterAmount[1]; + public int getProgressBarCount() { + return 1; } @Override - public TextureArea getProgressBarTexture(int index) { - return GuiTextures.PROGRESS_BAR_FLUID_RIG_DEPLETION; + public @NotNull ProgressWidget createProgressBar(PanelSyncManager panelSyncManager, int index) { + IntSyncValue waterFilledValue = new IntSyncValue(this::getWaterFilled); + IntSyncValue waterCapacityValue = new IntSyncValue(this::getWaterCapacity); + panelSyncManager.syncValue("water_filled", waterFilledValue); + panelSyncManager.syncValue("water_capacity", waterCapacityValue); + + return new ProgressWidget() + .progress(() -> waterCapacityValue.getIntValue() == 0 ? 0 : + waterFilledValue.getIntValue() * 1.0 / waterCapacityValue.getIntValue()) + .texture(GTGuiTextures.PROGRESS_BAR_FLUID_RIG_DEPLETION, MultiblockUIFactory.Bars.FULL_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + if (waterFilledValue.getIntValue() == 0) { + t.addLine(IKey.lang("gregtech.multiblock.large_boiler.no_water")); + } else { + t.addLine(IKey.lang("gregtech.multiblock.large_boiler.water_bar_hover", + waterFilledValue.getIntValue(), waterCapacityValue.getIntValue())); + } + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); } - @Override - public void addBarHoverText(List hoverList, int index) { - if (!isStructureFormed()) { - hoverList.add(TextComponentUtil.translationWithColor(TextFormatting.GRAY, - "gregtech.multiblock.invalid_structure")); - } else { - int[] waterAmount = getWaterAmount(); - if (waterAmount[0] == 0) { - hoverList.add(TextComponentUtil.translationWithColor(TextFormatting.YELLOW, - "gregtech.multiblock.large_boiler.no_water")); - } else { - ITextComponent waterInfo = TextComponentUtil.translationWithColor( - TextFormatting.BLUE, - "%s / %s L", - waterAmount[0], waterAmount[1]); - hoverList.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.large_boiler.water_bar_hover", - waterInfo)); + /** + * @return the total amount of water filling the inputs + */ + private int getWaterFilled() { + if (!isStructureFormed()) return 0; + List tanks = getAbilities(MultiblockAbility.IMPORT_FLUIDS); + int filled = 0; + for (IFluidTank tank : tanks) { + if (tank == null || tank.getFluid() == null) continue; + if (CommonFluidFilters.BOILER_FLUID.test(tank.getFluid())) { + filled += tank.getFluidAmount(); } } + return filled; } /** - * Returns an int[] of {AmountFilled, Capacity} where capacity is the sum of hatches with some water in them. - * If there is no water in the boiler (or the structure isn't formed, both of these values will be zero. + * @return the total capacity for water-containing inputs */ - private int[] getWaterAmount() { - if (!isStructureFormed()) return new int[] { 0, 0 }; + private int getWaterCapacity() { + if (!isStructureFormed()) return 0; List tanks = getAbilities(MultiblockAbility.IMPORT_FLUIDS); - int filled = 0, capacity = 0; + int capacity = 0; for (IFluidTank tank : tanks) { if (tank == null || tank.getFluid() == null) continue; if (CommonFluidFilters.BOILER_FLUID.test(tank.getFluid())) { - filled += tank.getFluidAmount(); capacity += tank.getCapacity(); } } - return new int[] { filled, capacity }; + return capacity; } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java index d22e681fad3..17ba047729a 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityActiveTransformer.java @@ -9,13 +9,13 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.pattern.TraceabilityPredicate; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; @@ -31,7 +31,6 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; @@ -41,6 +40,7 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -164,51 +164,40 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(true, isActive()) // set to true because we only want a two-state system (running or - // not running) + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(true, isActive()) .setWorkingStatusKeys( "gregtech.multiblock.idling", "gregtech.multiblock.idling", "gregtech.machine.active_transformer.routing") .addWorkingStatusLine() - .addCustom(tl -> { + .addCustom(list -> { if (isStructureFormed()) { // Max input line - ITextComponent maxInputFormatted = TextComponentUtil.stringWithColor( - TextFormatting.WHITE, - TextFormattingUtil.formatNumbers( - powerInput.getInputVoltage() * powerInput.getInputAmperage()) + " EU/t"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GREEN, - "gregtech.multiblock.active_transformer.max_in", + IKey maxInputFormatted = KeyUtil.string(TextFormatting.WHITE, TextFormattingUtil + .formatNumbers(powerInput.getInputVoltage() * powerInput.getInputAmperage()) + " EU/t"); + list.add(KeyUtil.lang(TextFormatting.GREEN, "gregtech.multiblock.active_transformer.max_in", maxInputFormatted)); // Max output line - ITextComponent maxOutputFormatted = TextComponentUtil.stringWithColor( - TextFormatting.WHITE, - TextFormattingUtil.formatNumbers( - powerOutput.getOutputVoltage() * powerOutput.getOutputAmperage()) + " EU/t"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.RED, - "gregtech.multiblock.active_transformer.max_out", + IKey maxOutputFormatted = KeyUtil + .string(TextFormatting.WHITE, TextFormattingUtil.formatNumbers( + powerOutput.getOutputVoltage() * powerOutput.getOutputAmperage()) + + " EU/t"); + list.add(KeyUtil.lang(TextFormatting.RED, "gregtech.multiblock.active_transformer.max_out", maxOutputFormatted)); // Average I/O line - ITextComponent avgInputFormatted = TextComponentUtil.stringWithColor( - TextFormatting.WHITE, + IKey avgIOFormatted = KeyUtil.string(TextFormatting.WHITE, TextFormattingUtil.formatNumbers(averageIOLastSec) + " EU/t"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.AQUA, - "gregtech.multiblock.active_transformer.average_io", - avgInputFormatted)); + list.add(KeyUtil.lang(TextFormatting.AQUA, "gregtech.multiblock.active_transformer.average_io", + avgIOFormatted)); } }); } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityCleanroom.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityCleanroom.java index 99f1d89726e..0902c470a87 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityCleanroom.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityCleanroom.java @@ -20,8 +20,8 @@ import gregtech.api.metatileentity.multiblock.ICleanroomReceiver; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.MultiblockShapeInfo; @@ -30,8 +30,8 @@ import gregtech.api.pattern.TraceabilityPredicate; import gregtech.api.util.BlockInfo; import gregtech.api.util.GTUtility; +import gregtech.api.util.KeyUtil; import gregtech.api.util.Mods; -import gregtech.api.util.TextComponentUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.TooltipHelper; @@ -62,7 +62,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; @@ -75,6 +74,7 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -484,55 +484,44 @@ protected boolean isMachineBanned(MetaTileEntity metaTileEntity) { } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(cleanroomLogic.isWorkingEnabled(), cleanroomLogic.isActive()) + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(cleanroomLogic.isWorkingEnabled(), cleanroomLogic.isActive()) .addEnergyUsageLine(energyContainer) - .addCustom(tl -> { + .addEnergyUsageExactLine(isClean() ? 4 : GTValues.VA[getEnergyTier()]) + .addCustom(list -> { // Cleanliness status line if (isStructureFormed()) { - ITextComponent cleanState; + IKey cleanState; if (isClean()) { - cleanState = TextComponentUtil.translationWithColor( - TextFormatting.GREEN, - "gregtech.multiblock.cleanroom.clean_state", - this.cleanAmount); + cleanState = KeyUtil.lang(TextFormatting.GREEN, "gregtech.multiblock.cleanroom.clean_state", + cleanAmount); } else { - cleanState = TextComponentUtil.translationWithColor( - TextFormatting.DARK_RED, - "gregtech.multiblock.cleanroom.dirty_state", - this.cleanAmount); + cleanState = KeyUtil.lang(TextFormatting.DARK_RED, + "gregtech.multiblock.cleanroom.dirty_state", cleanAmount); } - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.cleanroom.clean_status", + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.cleanroom.clean_status", cleanState)); } }) - .addCustom(tl -> { - if (!cleanroomLogic.isVoltageHighEnough()) { - ITextComponent energyNeeded = new TextComponentString( - GTValues.VNF[cleanroomFilter.getMinTier()]); - tl.add(TextComponentUtil.translationWithColor(TextFormatting.YELLOW, - "gregtech.multiblock.cleanroom.low_tier", energyNeeded)); - } - }) - .addEnergyUsageExactLine(isClean() ? 4 : GTValues.VA[getEnergyTier()]) - .addWorkingStatusLine() - .addProgressLine(getProgressPercent() / 100.0); + .addProgressLine(getProgressPercent() / 100.0) + .addWorkingStatusLine(); } @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addLowPowerLine(!drainEnergy(true)) - .addCustom(tl -> { + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addLowPowerLine(!drainEnergy(true)) + .addCustom(list -> { if (isStructureFormed() && !isClean()) { - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.YELLOW, + list.add(KeyUtil.lang(TextFormatting.YELLOW, "gregtech.multiblock.cleanroom.warning_contaminated")); } + + if (!cleanroomLogic.isVoltageHighEnough()) { + IKey energyNeeded = IKey.str(GTValues.VNF[cleanroomFilter.getMinTier()]); + list.add(KeyUtil.lang(TextFormatting.YELLOW, "gregtech.multiblock.cleanroom.low_tier", + energyNeeded)); + } }) .addMaintenanceProblemLines(getMaintenanceProblems()); } @@ -780,7 +769,7 @@ public List getMatchingShapes() { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityCrackingUnit.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityCrackingUnit.java index b1bd30b8574..a3ee2b3c391 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityCrackingUnit.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityCrackingUnit.java @@ -5,8 +5,8 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; @@ -14,7 +14,7 @@ import gregtech.api.recipes.logic.OCResult; import gregtech.api.recipes.properties.RecipePropertyStorage; import gregtech.api.util.GTUtility; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.blocks.BlockMetalCasing; @@ -26,12 +26,12 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.api.drawable.IKey; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -80,28 +80,25 @@ public SoundEvent getBreakdownSound() { } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) .addEnergyUsageLine(getEnergyContainer()) .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage())) - .addCustom(tl -> { + .addCustom(textList -> { + if (!isStructureFormed()) return; + // Coil energy discount line - if (isStructureFormed()) { - ITextComponent energyDiscount = TextComponentUtil.stringWithColor(TextFormatting.AQUA, - (100 - 10 * coilTier) + "%"); + IKey energyDiscount = KeyUtil.number(TextFormatting.AQUA, + 100 - 10L * getCoilTier(), "%"); - ITextComponent base = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.cracking_unit.energy", - energyDiscount); + IKey base = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.cracking_unit.energy", + energyDiscount); - ITextComponent hover = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.cracking_unit.energy_hover"); + IKey hover = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.cracking_unit.energy_hover"); - tl.add(TextComponentUtil.setHover(base, hover)); - } + textList.add(KeyUtil.setHover(base, hover)); }) .addParallelsLine(recipeMapWorkable.getParallelLimit()) .addWorkingStatusLine() diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDataBank.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDataBank.java index 5b52829f001..ebd225c4630 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDataBank.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityDataBank.java @@ -7,8 +7,8 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; @@ -28,7 +28,6 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; -import net.minecraft.util.text.ITextComponent; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.relauncher.Side; @@ -226,7 +225,7 @@ protected ICubeRenderer getFrontOverlay() { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } @@ -250,11 +249,9 @@ public void addInformation(ItemStack stack, @Nullable World world, @NotNull List } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(true, isActive() && isWorkingEnabled()) // transform into two-state system for display - .setWorkingStatusKeys( - "gregtech.multiblock.idling", + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(true, isActive() && isWorkingEnabled()) // transform into two-state system for display + .setWorkingStatusKeys("gregtech.multiblock.idling", "gregtech.multiblock.idling", "gregtech.multiblock.data_bank.providing") .addEnergyUsageExactLine(getEnergyUsage()) @@ -262,9 +259,8 @@ protected void addDisplayText(List textList) { } @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addLowPowerLine(hasNotEnoughEnergy) + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addLowPowerLine(hasNotEnoughEnergy) .addMaintenanceProblemLines(getMaintenanceProblems()); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityElectricBlastFurnace.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityElectricBlastFurnace.java index 89c277d7c8d..5124cde5065 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityElectricBlastFurnace.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityElectricBlastFurnace.java @@ -9,8 +9,8 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.MultiblockShapeInfo; @@ -19,7 +19,7 @@ import gregtech.api.recipes.RecipeMaps; import gregtech.api.recipes.properties.impl.TemperatureProperty; import gregtech.api.util.GTUtility; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; @@ -45,6 +45,7 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.api.drawable.IDrawable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -69,38 +70,31 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) - .addEnergyUsageLine(getEnergyContainer()) + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) + .addEnergyUsageLine(this.getEnergyContainer()) .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage())) - .addCustom(tl -> { - // Coil heat capacity line - if (isStructureFormed()) { - ITextComponent heatString = TextComponentUtil.stringWithColor( - TextFormatting.RED, - TextFormattingUtil.formatNumbers(blastFurnaceTemperature) + "K"); - - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.blast_furnace.max_temperature", - heatString)); - } - }) + .addCustom(this::addHeatCapacity) .addParallelsLine(recipeMapWorkable.getParallelLimit()) .addWorkingStatusLine() .addProgressLine(recipeMapWorkable.getProgressPercent()); } + private void addHeatCapacity(List keyList) { + if (isStructureFormed()) { + var heatString = KeyUtil.number(TextFormatting.RED, + getCurrentTemperature(), "K"); + + keyList.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.blast_furnace.max_temperature", heatString)); + } + } + @Override protected void formStructure(PatternMatchContext context) { super.formStructure(context); - Object type = context.get("CoilType"); - if (type instanceof IHeatingCoilBlockStats) { - this.blastFurnaceTemperature = ((IHeatingCoilBlockStats) type).getCoilTemperature(); - } else { - this.blastFurnaceTemperature = CoilType.CUPRONICKEL.getCoilTemperature(); - } + IHeatingCoilBlockStats type = context.getOrDefault("CoilType", CoilType.CUPRONICKEL); + this.blastFurnaceTemperature = type.getCoilTemperature(); // the subtracted tier gives the starting level (exclusive) of the +100K heat bonus this.blastFurnaceTemperature += 100 * Math.max(0, GTUtility.getFloorTierByVoltage(getEnergyContainer().getInputVoltage()) - GTValues.MV); diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFluidDrill.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFluidDrill.java index dca07a39e5f..d5663d0fcb2 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFluidDrill.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFluidDrill.java @@ -8,12 +8,12 @@ import gregtech.api.capability.impl.EnergyContainerList; import gregtech.api.capability.impl.FluidDrillLogic; import gregtech.api.capability.impl.FluidTankList; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.resources.TextureArea; import gregtech.api.metatileentity.ITieredMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.*; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; @@ -21,7 +21,7 @@ import gregtech.api.unification.material.Materials; import gregtech.api.util.GTTransferUtils; import gregtech.api.util.GTUtility; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.api.util.TextFormattingUtil; import gregtech.api.worldgen.bedrockFluids.BedrockFluidVeinHandler; import gregtech.client.renderer.ICubeRenderer; @@ -36,7 +36,6 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; @@ -48,6 +47,10 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.ProgressWidget; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -56,7 +59,7 @@ import java.util.List; public class MetaTileEntityFluidDrill extends MultiblockWithDisplayBase - implements ITieredMetaTileEntity, IWorkable, IProgressBarMultiblock { + implements ITieredMetaTileEntity, IWorkable, ProgressBarMultiblock { private final FluidDrillLogic minerLogic; private final int tier; @@ -110,7 +113,7 @@ protected void updateFormedValid() { } @Override - protected BlockPattern createStructurePattern() { + protected @NotNull BlockPattern createStructurePattern() { return FactoryBlockPattern.start() .aisle("XXX", "#F#", "#F#", "#F#", "###", "###", "###") .aisle("XXX", "FCF", "FCF", "FCF", "#F#", "#F#", "#F#") @@ -159,59 +162,46 @@ public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(minerLogic.isWorkingEnabled(), minerLogic.isActive()) + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(minerLogic.isWorkingEnabled(), minerLogic.isActive()) .setWorkingStatusKeys( "gregtech.multiblock.idling", "gregtech.multiblock.work_paused", "gregtech.multiblock.miner.drilling") .addEnergyUsageLine(energyContainer) - .addCustom(tl -> { + .addCustom(list -> { if (isStructureFormed()) { if (minerLogic.getDrilledFluid() != null) { // Fluid name Fluid drilledFluid = minerLogic.getDrilledFluid(); - ITextComponent fluidInfo = TextComponentUtil - .setColor(GTUtility.getFluidTranslation(drilledFluid), TextFormatting.GREEN); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.fluid_rig.drilled_fluid", + IKey fluidInfo = GTUtility.getFluidIKey(drilledFluid).style(TextFormatting.GREEN); + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.fluid_rig.drilled_fluid", fluidInfo)); - // Fluid amount - ITextComponent amountInfo = TextComponentUtil.stringWithColor( - TextFormatting.BLUE, + IKey amountInfo = KeyUtil.lang(TextFormatting.BLUE, TextFormattingUtil.formatNumbers( minerLogic.getFluidToProduce() * 20L / FluidDrillLogic.MAX_PROGRESS) + " L/s"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.fluid_rig.fluid_amount", + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.fluid_rig.fluid_amount", amountInfo)); } else { - ITextComponent noFluid = TextComponentUtil.translationWithColor(TextFormatting.RED, + IKey noFluid = KeyUtil.lang(TextFormatting.RED, "gregtech.multiblock.fluid_rig.no_fluid_in_area"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.fluid_rig.drilled_fluid", + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.fluid_rig.drilled_fluid", noFluid)); } } }) - .addWorkingStatusLine() - .addProgressLine(minerLogic.getProgressPercent()); + .addProgressLine(minerLogic.getProgressPercent()) + .addWorkingStatusLine(); } @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addLowPowerLine(isStructureFormed() && !drainEnergy(true)) - .addCustom(tl -> { + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addLowPowerLine(isStructureFormed() && !drainEnergy(true)) + .addCustom(list -> { if (isStructureFormed() && minerLogic.isInventoryFull()) { - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.YELLOW, - "gregtech.machine.miner.invfull")); + list.add(KeyUtil.lang(TextFormatting.YELLOW, "gregtech.machine.miner.invfull")); } }); } @@ -367,50 +357,53 @@ public T getCapability(Capability capability, EnumFacing side) { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } - @Override - public boolean showProgressBar() { - return tier > GTValues.MV; // only show for T2/3 fluid rigs - } - - @Override - public double getFillPercentage(int index) { - int numOperationsLeft = BedrockFluidVeinHandler.getOperationsRemaining(getWorld(), minerLogic.getChunkX(), - minerLogic.getChunkZ()); - int maxOperations = BedrockFluidVeinHandler.MAXIMUM_VEIN_OPERATIONS; - return 1.0 * numOperationsLeft / maxOperations; + public boolean allowsExtendedFacing() { + return false; } @Override - public TextureArea getProgressBarTexture(int index) { - return GuiTextures.PROGRESS_BAR_FLUID_RIG_DEPLETION; + public int getProgressBarCount() { + // only show for T2/3 fluid rigs + return tier > GTValues.MV ? 1 : 0; } @Override - public void addBarHoverText(List hoverList, int index) { - int numOperationsLeft = BedrockFluidVeinHandler.getOperationsRemaining(getWorld(), minerLogic.getChunkX(), - minerLogic.getChunkZ()); - int maxOperations = BedrockFluidVeinHandler.MAXIMUM_VEIN_OPERATIONS; - int percentage = (int) Math.round(1.0 * numOperationsLeft / maxOperations * 100); - TextFormatting color = percentage > 40 ? TextFormatting.GREEN : - percentage > 10 ? TextFormatting.YELLOW : TextFormatting.RED; - - if (numOperationsLeft == 0) { - hoverList.add(TextComponentUtil.translationWithColor(TextFormatting.RED, - "gregtech.multiblock.fluid_rig.vein_depleted")); - } else { - ITextComponent veinInfo = TextComponentUtil.stringWithColor(color, percentage + "%"); - hoverList.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.fluid_rig.vein_depletion", - veinInfo)); - } - } - - public boolean allowsExtendedFacing() { - return false; + public @NotNull ProgressWidget createProgressBar(PanelSyncManager panelSyncManager, int index) { + IntSyncValue operationsValue = new IntSyncValue(() -> BedrockFluidVeinHandler.getOperationsRemaining(getWorld(), + minerLogic.getChunkX(), minerLogic.getChunkZ())); + panelSyncManager.syncValue("operations_remaining", operationsValue); + + return new ProgressWidget() + .progress(() -> operationsValue.getIntValue() * 1.0 / BedrockFluidVeinHandler.MAXIMUM_VEIN_OPERATIONS) + .texture(GTGuiTextures.PROGRESS_BAR_FLUID_RIG_DEPLETION, MultiblockUIFactory.Bars.FULL_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + if (operationsValue.getIntValue() == 0) { + t.addLine(IKey.lang("gregtech.multiblock.fluid_rig.vein_depleted")); + } else { + t.addLine(KeyUtil.string(() -> { + int percent = (int) Math.round(100.0 * operationsValue.getIntValue() / + BedrockFluidVeinHandler.MAXIMUM_VEIN_OPERATIONS); + if (percent > 40) { + return TextFormatting.GREEN + IKey + .lang("gregtech.multiblock.fluid_rig.vein_depletion.high", percent).get(); + } else if (percent > 10) { + return TextFormatting.YELLOW + IKey + .lang("gregtech.multiblock.fluid_rig.vein_depletion.medium", percent).get(); + } else { + return TextFormatting.RED + IKey + .lang("gregtech.multiblock.fluid_rig.vein_depletion.low", percent).get(); + } + })); + } + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFusionReactor.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFusionReactor.java index b9a918639f3..a29e24b9016 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFusionReactor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityFusionReactor.java @@ -14,15 +14,15 @@ import gregtech.api.gui.widgets.ImageCycleButtonWidget; import gregtech.api.gui.widgets.ImageWidget; import gregtech.api.gui.widgets.IndicatorImageWidget; -import gregtech.api.gui.widgets.ProgressWidget; import gregtech.api.metatileentity.IFastRenderMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; -import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.MultiblockShapeInfo; @@ -73,6 +73,10 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.value.sync.DoubleSyncValue; +import com.cleanroommc.modularui.widgets.ProgressWidget; +import com.cleanroommc.modularui.widgets.layout.Column; import com.google.common.collect.Lists; import com.google.common.util.concurrent.AtomicDouble; import org.jetbrains.annotations.NotNull; @@ -368,18 +372,18 @@ protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { builder.image(4, 4, 190, 138, GuiTextures.DISPLAY); // Energy Bar - builder.widget(new ProgressWidget( + builder.widget(new gregtech.api.gui.widgets.ProgressWidget( () -> energyContainer.getEnergyCapacity() > 0 ? 1.0 * energyContainer.getEnergyStored() / energyContainer.getEnergyCapacity() : 0, 4, 144, 94, 7, - GuiTextures.PROGRESS_BAR_FUSION_ENERGY, ProgressWidget.MoveType.HORIZONTAL) + GuiTextures.PROGRESS_BAR_FUSION_ENERGY, gregtech.api.gui.widgets.ProgressWidget.MoveType.HORIZONTAL) .setHoverTextConsumer(this::addEnergyBarHoverText)); // Heat Bar - builder.widget(new ProgressWidget( + builder.widget(new gregtech.api.gui.widgets.ProgressWidget( () -> energyContainer.getEnergyCapacity() > 0 ? 1.0 * heat / energyContainer.getEnergyCapacity() : 0, 100, 144, 94, 7, - GuiTextures.PROGRESS_BAR_FUSION_HEAT, ProgressWidget.MoveType.HORIZONTAL) + GuiTextures.PROGRESS_BAR_FUSION_HEAT, gregtech.api.gui.widgets.ProgressWidget.MoveType.HORIZONTAL) .setHoverTextConsumer(this::addHeatBarHoverText)); // Indicator Widget @@ -417,7 +421,7 @@ protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { // Voiding Mode Button builder.widget(new ImageCycleButtonWidget(173, 189, 18, 18, GuiTextures.BUTTON_VOID_MULTIBLOCK, 4, this::getVoidingMode, this::setVoidingMode) - .setTooltipHoverString(MultiblockWithDisplayBase::getVoidingModeTooltip)); + .setTooltipHoverString(this::getVoidingModeTooltip)); // Distinct Buses Unavailable Image builder.widget(new ImageWidget(173, 171, 18, 18, GuiTextures.BUTTON_NO_DISTINCT_BUSES) @@ -431,6 +435,53 @@ protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { return builder; } + @Override + protected MultiblockUIFactory createUIFactory() { + IDrawable title; + if (tier == GTValues.LuV) { + // MK1 + title = GTGuiTextures.FUSION_REACTOR_MK1_TITLE; + } else if (tier == GTValues.ZPM) { + // MK2 + title = GTGuiTextures.FUSION_REACTOR_MK2_TITLE; + } else { + // MK3 + title = GTGuiTextures.FUSION_REACTOR_MK3_TITLE; + } + + DoubleSyncValue progress = new DoubleSyncValue(recipeMapWorkable::getProgressPercent); + return new MultiblockUIFactory(this) + .setSize(198, 236) + .setScreenHeight(138) + .configureDisplayText(false, builder -> {}) + .addScreenChildren(widgets -> widgets.add(new Column() + .padding(4) + .expanded() + .child(title.asWidget() + .marginBottom(8) + .size(69, 12)) + .child(new ProgressWidget() + .size(77, 77) + .tooltipAutoUpdate(true) + // this is fine client only because these values are already synced + .tooltipBuilder(tooltip -> MultiblockUIFactory.builder() + .structureFormed(isStructureFormed()) + .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), + recipeMapWorkable.isActive()) + .addWorkingStatusLine() + .build(tooltip)) + .background(GTGuiTextures.FUSION_DIAGRAM.asIcon() + .size(89, 101) + .marginTop(11)) + .direction(ProgressWidget.Direction.CIRCULAR_CW) + .value(progress) + .texture(null, GTGuiTextures.FUSION_PROGRESS, 77)) + .child(GTGuiTextures.FUSION_LEGEND.asWidget() + .left(4) + .bottom(4) + .size(108, 41)))); + } + private void addEnergyBarHoverText(List hoverList) { ITextComponent energyInfo = TextComponentUtil.stringWithColor( TextFormatting.AQUA, @@ -456,14 +507,14 @@ private void addHeatBarHoverText(List hoverList) { private static class FusionProgressSupplier { private final AtomicDouble tracker = new AtomicDouble(0.0); - private final ProgressWidget.TimedProgressSupplier bottomLeft; + private final gregtech.api.gui.widgets.ProgressWidget.TimedProgressSupplier bottomLeft; private final DoubleSupplier topLeft; private final DoubleSupplier topRight; private final DoubleSupplier bottomRight; public FusionProgressSupplier() { // Bottom Left, fill on [0, 0.25) - bottomLeft = new ProgressWidget.TimedProgressSupplier(200, 164, false) { + bottomLeft = new gregtech.api.gui.widgets.ProgressWidget.TimedProgressSupplier(200, 164, false) { @Override public double getAsDouble() { @@ -533,25 +584,30 @@ private enum Type { BOTTOM_LEFT( 61, 66, 35, 41, - GuiTextures.PROGRESS_BAR_FUSION_REACTOR_DIAGRAM_BL, ProgressWidget.MoveType.VERTICAL), + GuiTextures.PROGRESS_BAR_FUSION_REACTOR_DIAGRAM_BL, + gregtech.api.gui.widgets.ProgressWidget.MoveType.VERTICAL), TOP_LEFT( 61, 30, 41, 35, - GuiTextures.PROGRESS_BAR_FUSION_REACTOR_DIAGRAM_TL, ProgressWidget.MoveType.HORIZONTAL), + GuiTextures.PROGRESS_BAR_FUSION_REACTOR_DIAGRAM_TL, + gregtech.api.gui.widgets.ProgressWidget.MoveType.HORIZONTAL), TOP_RIGHT( 103, 30, 35, 41, - GuiTextures.PROGRESS_BAR_FUSION_REACTOR_DIAGRAM_TR, ProgressWidget.MoveType.VERTICAL_DOWNWARDS), + GuiTextures.PROGRESS_BAR_FUSION_REACTOR_DIAGRAM_TR, + gregtech.api.gui.widgets.ProgressWidget.MoveType.VERTICAL_DOWNWARDS), BOTTOM_RIGHT( 97, 72, 41, 35, - GuiTextures.PROGRESS_BAR_FUSION_REACTOR_DIAGRAM_BR, ProgressWidget.MoveType.HORIZONTAL_BACKWARDS); + GuiTextures.PROGRESS_BAR_FUSION_REACTOR_DIAGRAM_BR, + gregtech.api.gui.widgets.ProgressWidget.MoveType.HORIZONTAL_BACKWARDS); private final int x; private final int y; private final int width; private final int height; private final TextureArea texture; - private final ProgressWidget.MoveType moveType; + private final gregtech.api.gui.widgets.ProgressWidget.MoveType moveType; - Type(int x, int y, int width, int height, TextureArea texture, ProgressWidget.MoveType moveType) { + Type(int x, int y, int width, int height, TextureArea texture, + gregtech.api.gui.widgets.ProgressWidget.MoveType moveType) { this.x = x; this.y = y; this.width = width; @@ -560,8 +616,8 @@ private enum Type { this.moveType = moveType; } - public ProgressWidget getWidget(MetaTileEntityFusionReactor instance) { - return new ProgressWidget( + public gregtech.api.gui.widgets.ProgressWidget getWidget(MetaTileEntityFusionReactor instance) { + return new gregtech.api.gui.widgets.ProgressWidget( () -> instance.recipeMapWorkable.isActive() ? instance.progressBarSupplier.getSupplier(this).getAsDouble() : 0, x, y, width, height, texture, moveType) diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java index f1bf2dc9593..1adc8fb4e5e 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityHPCA.java @@ -5,20 +5,19 @@ import gregtech.api.capability.impl.EnergyContainerList; import gregtech.api.capability.impl.FluidTankList; import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.resources.IGuiTexture; import gregtech.api.gui.resources.TextureArea; -import gregtech.api.gui.widgets.ProgressWidget; -import gregtech.api.gui.widgets.SuppliedImageWidget; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.*; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.MultiblockShapeInfo; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.unification.material.Materials; import gregtech.api.util.GTUtility; +import gregtech.api.util.KeyUtil; import gregtech.api.util.RelativeDirection; import gregtech.api.util.TextComponentUtil; import gregtech.api.util.TextFormattingUtil; @@ -32,7 +31,6 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.client.resources.I18n; -import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.PacketBuffer; @@ -53,6 +51,15 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IDrawable; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.drawable.DynamicDrawable; +import com.cleanroommc.modularui.drawable.UITexture; +import com.cleanroommc.modularui.value.sync.DoubleSyncValue; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.ProgressWidget; +import com.cleanroommc.modularui.widgets.layout.Grid; import it.unimi.dsi.fastutil.objects.ObjectArrayList; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import org.jetbrains.annotations.NotNull; @@ -62,12 +69,11 @@ import java.util.Collection; import java.util.List; import java.util.Set; -import java.util.function.Supplier; import static gregtech.api.util.RelativeDirection.*; public class MetaTileEntityHPCA extends MultiblockWithDisplayBase - implements IOpticalComputationProvider, IControllable, IProgressBarMultiblock { + implements IOpticalComputationProvider, IControllable, ProgressBarMultiblock { private static final double IDLE_TEMPERATURE = 200; private static final double DAMAGE_TEMPERATURE = 1000; @@ -82,12 +88,12 @@ public class MetaTileEntityHPCA extends MultiblockWithDisplayBase private double temperature = IDLE_TEMPERATURE; // start at idle temperature - private final ProgressWidget.TimedProgressSupplier progressSupplier; + private final gregtech.api.gui.widgets.ProgressWidget.TimedProgressSupplier progressSupplier; public MetaTileEntityHPCA(ResourceLocation metaTileEntityId) { super(metaTileEntityId); this.energyContainer = new EnergyContainerList(new ArrayList<>()); - this.progressSupplier = new ProgressWidget.TimedProgressSupplier(200, 47, false); + this.progressSupplier = new gregtech.api.gui.widgets.ProgressWidget.TimedProgressSupplier(200, 47, false); this.hpcaHandler = new HPCAGridHandler(this); } @@ -353,106 +359,79 @@ public void setWorkingEnabled(boolean isWorkingAllowed) { } @Override - protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { - ModularUI.Builder builder = super.createUITemplate(entityPlayer); - - // Create the hover grid - builder.widget(new ProgressWidget( - () -> hpcaHandler.getAllocatedCWUt() > 0 ? progressSupplier.getAsDouble() : 0, - 74, 57, 47, 47, GuiTextures.HPCA_COMPONENT_OUTLINE, ProgressWidget.MoveType.HORIZONTAL) - .setIgnoreColor(true) - .setHoverTextConsumer(hpcaHandler::addInfo)); - int startX = 76; - int startY = 59; - for (int i = 0; i < 3; i++) { - for (int j = 0; j < 3; j++) { - final int index = i * 3 + j; - Supplier textureSupplier = () -> hpcaHandler.getComponentTexture(index); - builder.widget(new SuppliedImageWidget(startX + (15 * j), startY + (15 * i), 13, 13, textureSupplier) - .setIgnoreColor(true)); - } - } - return builder; + protected MultiblockUIFactory createUIFactory() { + return super.createUIFactory() + .addScreenChildren(iWidgets -> iWidgets.add(new Grid() + .coverChildren() + .leftRel(0.5f) + .bottom(4) + .minElementMargin(1) + .mapTo(3, 9, value -> new DynamicDrawable(() -> hpcaHandler.getComponentTexture2(value)) + .asWidget() + // could add tooltips here showing the name of the component + .size(18)))); } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(true, hpcaHandler.getAllocatedCWUt() > 0) // transform into two-state system for - // display + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(true, hpcaHandler.getAllocatedCWUt() > 0) .setWorkingStatusKeys( "gregtech.multiblock.idling", "gregtech.multiblock.idling", "gregtech.multiblock.data_bank.providing") - .addCustom(tl -> { - if (isStructureFormed()) { - // Energy Usage - ITextComponent voltageName = new TextComponentString( - GTValues.VNF[GTUtility.getTierByVoltage(hpcaHandler.getMaxEUt())]); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.hpca.energy", - TextFormattingUtil.formatNumbers(hpcaHandler.cachedEUt), - TextFormattingUtil.formatNumbers(hpcaHandler.getMaxEUt()), - voltageName)); - - // Provided Computation - ITextComponent cwutInfo = TextComponentUtil.stringWithColor( - TextFormatting.AQUA, - hpcaHandler.cachedCWUt + " / " + hpcaHandler.getMaxCWUt() + " CWU/t"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.hpca.computation", - cwutInfo)); - } + .addCustom(richText -> { + if (!isStructureFormed()) return; + + // Energy Usage + String voltageName = GTValues.VNF[GTUtility.getTierByVoltage(hpcaHandler.getMaxEUt())]; + richText.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.hpca.energy", + TextFormattingUtil.formatNumbers(hpcaHandler.cachedEUt), + TextFormattingUtil.formatNumbers(hpcaHandler.getMaxEUt()), + voltageName)); + + // Provided Computation + richText.add(KeyUtil.lang("gregtech.multiblock.hpca.computation", + hpcaHandler.cachedCWUt, hpcaHandler.getMaxCWUt())); }) .addWorkingStatusLine(); } - private TextFormatting getDisplayTemperatureColor() { - if (temperature < 500) { - return TextFormatting.GREEN; - } else if (temperature < 750) { - return TextFormatting.YELLOW; - } - return TextFormatting.RED; - } - @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addLowPowerLine(hasNotEnoughEnergy) - .addCustom(tl -> { - if (isStructureFormed()) { - if (temperature > 500) { - // Temperature warning - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.YELLOW, - "gregtech.multiblock.hpca.warning_temperature")); - - // Active cooler overdrive warning - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.hpca.warning_temperature_active_cool")); - } + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addLowPowerLine(hasNotEnoughEnergy) + .addCustom(richText -> { + if (!isStructureFormed()) return; + + if (temperature > 500) { + // Temperature warning + richText.add(KeyUtil.lang(TextFormatting.YELLOW, + "gregtech.multiblock.hpca.warning_temperature")); - // Structure warnings - hpcaHandler.addWarnings(tl); + // Active cooler overdrive warning + richText.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.hpca.warning_temperature_active_cool")); } + + // Structure warnings + // hpcaHandler.addWarnings(richText); + hpcaHandler.addWarnings2(richText); }) .addMaintenanceProblemLines(getMaintenanceProblems()); } @Override - protected void addErrorText(List textList) { - super.addErrorText(textList); - if (isStructureFormed()) { + protected void configureErrorText(MultiblockUIFactory.Builder builder) { + builder.addCustom(richText -> { + if (!isStructureFormed()) return; + if (temperature > 1000) { - textList.add(TextComponentUtil.translationWithColor(TextFormatting.RED, + richText.add(KeyUtil.lang(TextFormatting.RED, "gregtech.multiblock.hpca.error_temperature")); } - hpcaHandler.addErrors(textList); - } + // hpcaHandler.addErrors(textList); + hpcaHandler.addErrors2(richText); + }); } @Override @@ -465,7 +444,7 @@ public void addInformation(ItemStack stack, @Nullable World world, @NotNull List } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } @@ -529,40 +508,61 @@ public T getCapability(Capability capability, EnumFacing side) { } @Override - public int getNumProgressBars() { + public int getProgressBarCount() { return 2; } @Override - public double getFillPercentage(int index) { - return index == 0 ? 1.0 * hpcaHandler.cachedCWUt / hpcaHandler.getMaxCWUt() : - Math.min(1.0, temperature / DAMAGE_TEMPERATURE); - } - - @Override - public TextureArea getProgressBarTexture(int index) { - return index == 0 ? GuiTextures.PROGRESS_BAR_HPCA_COMPUTATION : GuiTextures.PROGRESS_BAR_FUSION_HEAT; - } - - @Override - public void addBarHoverText(List hoverList, int index) { - if (index == 0) { - ITextComponent cwutInfo = TextComponentUtil.stringWithColor( - TextFormatting.AQUA, - hpcaHandler.cachedCWUt + " / " + hpcaHandler.getMaxCWUt() + " CWU/t"); - hoverList.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.hpca.computation", - cwutInfo)); - } else { - ITextComponent tempInfo = TextComponentUtil.stringWithColor( - getDisplayTemperatureColor(), - Math.round(temperature / 10.0D) + "°C"); - hoverList.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.hpca.temperature", - tempInfo)); - } + public @NotNull ProgressWidget createProgressBar(PanelSyncManager panelSyncManager, + int index) { + return switch (index) { + case 0 -> { + IntSyncValue currentCWUtValue = new IntSyncValue(() -> hpcaHandler.cachedCWUt); + IntSyncValue maxCWUtValue = new IntSyncValue(hpcaHandler::getMaxCWUt); + panelSyncManager.syncValue("current_cwut", currentCWUtValue); + panelSyncManager.syncValue("max_cwut", maxCWUtValue); + + yield new ProgressWidget() + .progress(() -> 1.0 * currentCWUtValue.getIntValue() / maxCWUtValue.getIntValue()) + .texture(GTGuiTextures.PROGRESS_BAR_HPCA_COMPUTATION, MultiblockUIFactory.Bars.HALF_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + t.addLine(IKey.lang("gregtech.multiblock.hpca.computation", + currentCWUtValue.getIntValue(), maxCWUtValue.getIntValue())); + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); + } + case 1 -> { + DoubleSyncValue temperatureValue = new DoubleSyncValue(() -> temperature); + panelSyncManager.syncValue("temperature", temperatureValue); + + yield new ProgressWidget() + .progress(() -> Math.min(1.0, temperatureValue.getDoubleValue() / DAMAGE_TEMPERATURE)) + .texture(GTGuiTextures.PROGRESS_BAR_FUSION_HEAT, MultiblockUIFactory.Bars.HALF_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + double temp = temperatureValue.getDoubleValue(); + int degrees = (int) Math.round(temp / 10.0); + + // TODO working dynamic color substitutions into IKey.lang + if (temp < 500) { + t.addLine(IKey.lang("gregtech.multiblock.hpca.temperature.low", degrees)); + } else if (temp < 750) { + t.addLine(IKey.lang("gregtech.multiblock.hpca.temperature.medium", degrees)); + } else { + t.addLine(IKey.lang("gregtech.multiblock.hpca.temperature.high", degrees)); + } + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); + } + default -> throw new IllegalStateException("Invalid index received " + index); + }; } // Handles the logic of this structure's specific HPCA component grid @@ -904,6 +904,38 @@ public void addErrors(List textList) { } } + public void addWarnings2(List richText) { + List warnings = new ArrayList<>(); + if (numBridges > 1) { + warnings.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.hpca.warning_multiple_bridges")); + } + if (computationProviders.isEmpty()) { + warnings.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.hpca.warning_no_computation")); + } + if (getMaxCoolingDemand() > getMaxCoolingAmount()) { + warnings.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.hpca.warning_low_cooling")); + } + if (!warnings.isEmpty()) { + richText.add(KeyUtil.lang(TextFormatting.YELLOW, + "gregtech.multiblock.hpca.warning_structure_header")); + richText.addAll(warnings); + } + } + + public void addErrors2(List richText) { + for (IHPCAComponentHatch component : components) { + if (component.isDamaged()) { + richText.add(KeyUtil.lang(TextFormatting.RED, + "gregtech.multiblock.hpca.error_damaged")); + return; + } + } + } + + @Deprecated public TextureArea getComponentTexture(int index) { if (components.size() <= index) { return GuiTextures.BLANK_TRANSPARENT; @@ -911,6 +943,13 @@ public TextureArea getComponentTexture(int index) { return components.get(index).getComponentIcon(); } + public UITexture getComponentTexture2(int index) { + if (components.size() <= index) { + return GTGuiTextures.BLANK_TRANSPARENT; + } + return components.get(index).getComponentIcon2(); + } + public void tryGatherClientComponents(World world, BlockPos pos, EnumFacing frontFacing, EnumFacing upwardsFacing, boolean flip) { EnumFacing relativeUp = RelativeDirection.UP.getRelativeFacing(frontFacing, upwardsFacing, flip); diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityLargeMiner.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityLargeMiner.java index cc2b78fa6ba..2f6a2ddeae0 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityLargeMiner.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityLargeMiner.java @@ -6,19 +6,15 @@ import gregtech.api.capability.impl.FluidTankList; import gregtech.api.capability.impl.ItemHandlerList; import gregtech.api.capability.impl.miner.MultiblockMinerLogic; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.ModularUI; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.AdvancedTextWidget; -import gregtech.api.gui.widgets.ImageCycleButtonWidget; import gregtech.api.items.itemhandlers.GTItemStackHandler; import gregtech.api.metatileentity.IDataInfoProvider; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; @@ -27,7 +23,7 @@ import gregtech.api.unification.material.Material; import gregtech.api.unification.material.Materials; import gregtech.api.util.GTUtility; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.blocks.BlockMetalCasing; @@ -57,6 +53,10 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.api.widget.Interactable; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.widgets.CycleButtonWidget; import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -232,79 +232,85 @@ public void addToolUsages(ItemStack stack, @Nullable World world, List t } @Override - protected void addDisplayText(List textList) { - super.addDisplayText(textList); + protected MultiblockUIFactory createUIFactory() { + return super.createUIFactory() + .createFlexButton((posGuiData, panelSyncManager) -> { + IntSyncValue buttonSync = new IntSyncValue(this::getCurrentMode, this::setCurrentMode); - if (this.isStructureFormed()) { - if (energyContainer != null && energyContainer.getEnergyCapacity() > 0) { - int energyContainer = getEnergyTier(); - long maxVoltage = GTValues.V[energyContainer]; - String voltageName = GTValues.VNF[energyContainer]; - textList.add(new TextComponentTranslation("gregtech.multiblock.max_energy_per_tick", maxVoltage, - voltageName)); - } - - int workingAreaChunks = this.minerLogic.getCurrentRadius() * 2 / CHUNK_LENGTH; - int workingArea = getWorkingArea(minerLogic.getCurrentRadius()); - textList.add(new TextComponentTranslation("gregtech.machine.miner.startx", - this.minerLogic.getX().get() == Integer.MAX_VALUE ? 0 : this.minerLogic.getX().get())); - textList.add(new TextComponentTranslation("gregtech.machine.miner.starty", - this.minerLogic.getY().get() == Integer.MAX_VALUE ? 0 : this.minerLogic.getY().get())); - textList.add(new TextComponentTranslation("gregtech.machine.miner.startz", - this.minerLogic.getZ().get() == Integer.MAX_VALUE ? 0 : this.minerLogic.getZ().get())); - if (this.minerLogic.isChunkMode()) { - textList.add(new TextComponentTranslation("gregtech.machine.miner.working_area_chunks", - workingAreaChunks, workingAreaChunks)); - } else { - textList.add( - new TextComponentTranslation("gregtech.machine.miner.working_area", workingArea, workingArea)); - } - if (this.minerLogic.isDone()) - textList.add(new TextComponentTranslation("gregtech.machine.miner.done") - .setStyle(new Style().setColor(TextFormatting.GREEN))); - else if (this.minerLogic.isWorking()) - textList.add(new TextComponentTranslation("gregtech.machine.miner.working") - .setStyle(new Style().setColor(TextFormatting.GOLD))); - else if (!this.isWorkingEnabled()) - textList.add(new TextComponentTranslation("gregtech.multiblock.work_paused")); - } - } + return new CycleButtonWidget() { - private void addDisplayText2(List textList) { - if (this.isStructureFormed()) { - ITextComponent mCoords = new TextComponentString(" ") - .appendSibling(new TextComponentTranslation("gregtech.machine.miner.minex", - this.minerLogic.getMineX().get())) - .appendText("\n ") - .appendSibling(new TextComponentTranslation("gregtech.machine.miner.miney", - this.minerLogic.getMineY().get())) - .appendText("\n ") - .appendSibling(new TextComponentTranslation("gregtech.machine.miner.minez", - this.minerLogic.getMineZ().get())); - textList.add(mCoords); - } + @Override + public @NotNull Result onMousePressed(int mouseButton) { + if (minerLogic.isWorking()) { + Interactable.playButtonClickSound(); + return Result.IGNORE; + } else { + return super.onMousePressed(mouseButton); + } + } + } + .stateCount(4) + .value(buttonSync) + .stateBackground(GTGuiTextures.BUTTON_MINER_MODES) + .addTooltip(0, IKey.lang("gregtech.multiblock.miner.neither_mode")) + .addTooltip(1, IKey.lang("gregtech.multiblock.miner.chunk_mode")) + .addTooltip(2, IKey.lang("gregtech.multiblock.miner.silk_touch_mode")) + .addTooltip(3, IKey.lang("gregtech.multiblock.miner.both_modes")); + }); } @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addLowPowerLine(isStructureFormed() && !drainEnergy(true)) - .addCustom(tl -> { - if (isStructureFormed() && isInventoryFull) { - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.YELLOW, - "gregtech.machine.miner.invfull")); + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(minerLogic.isWorkingEnabled(), minerLogic.isActive()) + .addEnergyUsageLine(energyContainer) + .addCustom(list -> { + if (isStructureFormed()) { + int workingAreaChunks = this.minerLogic.getCurrentRadius() * 2 / CHUNK_LENGTH; + int workingArea = getWorkingArea(minerLogic.getCurrentRadius()); + + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.machine.miner.mining_at")); + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.machine.miner.mining_pos", + minerLogic.getMineX().get(), + minerLogic.getMineY().get(), + minerLogic.getMineZ().get())); + + if (minerLogic.isChunkMode()) { + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.machine.miner.working_area_chunks", + workingAreaChunks, + workingAreaChunks)); + } else { + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.machine.miner.working_area", + workingArea, workingArea)); + } + + if (minerLogic.isDone()) { + list.add(KeyUtil.lang(TextFormatting.GREEN, "gregtech.machine.miner.done")); + } else if (minerLogic.isWorking()) { + list.add(KeyUtil.lang(TextFormatting.GOLD, "gregtech.machine.miner.working")); + } else if (!isWorkingEnabled()) { + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.work_paused")); + } } }); } @Override - protected void addErrorText(List textList) { - super.addErrorText(textList); - if (isStructureFormed() && !drainFluid(true)) { - textList.add(TextComponentUtil.translationWithColor(TextFormatting.RED, - "gregtech.machine.miner.multi.needsfluid")); - } + protected void configureErrorText(MultiblockUIFactory.Builder builder) { + builder.addCustom(list -> { + if (isStructureFormed() && !drainFluid(false)) { + list.add(KeyUtil.lang(TextFormatting.RED, "gregtech.machine.miner.multi.needsfluid")); + } + }); + } + + @Override + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addLowPowerLine(!drainEnergy(true)); + builder.addCustom(list -> { + if (isStructureFormed() && isInventoryFull) { + list.add(KeyUtil.lang(TextFormatting.YELLOW, "gregtech.machine.miner.invfull")); + } + }); } public IBlockState getCasingState() { @@ -383,14 +389,6 @@ public long getMaxVoltage() { return GTValues.V[GTUtility.getTierByVoltage(energyContainer.getInputVoltage())]; } - @Override - protected ModularUI.Builder createUITemplate(EntityPlayer entityPlayer) { - ModularUI.Builder builder = super.createUITemplate(entityPlayer); - builder.widget(new AdvancedTextWidget(63, 31, this::addDisplayText2, 0xFFFFFF) - .setMaxWidthLimit(68).setClickHandler(this::handleDisplayClick)); - return builder; - } - // used for UI private int getCurrentMode() { // 0 -> not chunk mode, not silk touch mode @@ -431,18 +429,6 @@ private void setCurrentMode(int mode) { } } - @Override - protected @NotNull Widget getFlexButton(int x, int y, int width, int height) { - return new ImageCycleButtonWidget(x, y, width, height, GuiTextures.BUTTON_MINER_MODES, 4, this::getCurrentMode, - this::setCurrentMode) - .setTooltipHoverString(mode -> switch (mode) { - case 0 -> "gregtech.multiblock.miner.neither_mode"; - case 1 -> "gregtech.multiblock.miner.chunk_mode"; - case 2 -> "gregtech.multiblock.miner.silk_touch_mode"; - default -> "gregtech.multiblock.miner.both_modes"; - }); - } - @Override public boolean onScrewdriverClick(EntityPlayer playerIn, EnumHand hand, EnumFacing facing, CuboidRayTraceResult hitResult) { @@ -550,7 +536,7 @@ public List getDataInfo() { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiSmelter.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiSmelter.java index 71fca7ba8d4..49aaee4e946 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiSmelter.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityMultiSmelter.java @@ -6,9 +6,9 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.ParallelLogicType; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; @@ -19,8 +19,7 @@ import gregtech.api.recipes.machines.RecipeMapFurnace; import gregtech.api.recipes.properties.RecipePropertyStorage; import gregtech.api.util.GTUtility; -import gregtech.api.util.TextComponentUtil; -import gregtech.api.util.TextFormattingUtil; +import gregtech.api.util.KeyUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.blocks.BlockMetalCasing.MetalCasingType; @@ -31,15 +30,13 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.api.drawable.IKey; import org.jetbrains.annotations.NotNull; -import java.util.List; - import static gregtech.api.recipes.logic.OverclockingLogic.standardOC; public class MetaTileEntityMultiSmelter extends RecipeMapMultiblockController { @@ -58,46 +55,39 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) - .addEnergyUsageLine(recipeMapWorkable.getEnergyContainer()) + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) + .addEnergyUsageLine(getEnergyContainer()) .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage())) - .addCustom(tl -> { - if (isStructureFormed()) { - // Heating coil discount - if (heatingCoilDiscount > 1) { - ITextComponent coilDiscount = TextComponentUtil.stringWithColor( - TextFormatting.AQUA, - TextFormattingUtil.formatNumbers(100.0 / heatingCoilDiscount) + "%"); - - ITextComponent base = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.multi_furnace.heating_coil_discount", - coilDiscount); - - ITextComponent hoverText = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.multi_furnace.heating_coil_discount_hover"); - - TextComponentUtil.setHover(base, hoverText); - tl.add(base); - } - - // Custom parallels line so we can have a hover text - if (recipeMapWorkable.getParallelLimit() > 1) { - ITextComponent parallels = TextComponentUtil.stringWithColor( - TextFormatting.DARK_PURPLE, - TextFormattingUtil.formatNumbers(recipeMapWorkable.getParallelLimit())); - ITextComponent bodyText = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.parallel", - parallels); - ITextComponent hoverText = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.multi_furnace.parallel_hover"); - tl.add(TextComponentUtil.setHover(bodyText, hoverText)); - } + .addCustom(richText -> { + if (!isStructureFormed()) return; + + if (heatingCoilDiscount > 1) { + IKey coilDiscount = KeyUtil.number(TextFormatting.AQUA, + (long) (100.0 / heatingCoilDiscount), "%"); + + IKey base = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.multi_furnace.heating_coil_discount", + coilDiscount); + + IKey hoverText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.multi_furnace.heating_coil_discount_hover"); + + richText.add(KeyUtil.setHover(base, hoverText)); + } + + if (recipeMapWorkable.getParallelLimit() > 0) { + IKey parallels = KeyUtil.number(TextFormatting.DARK_PURPLE, + recipeMapWorkable.getParallelLimit()); + + IKey bodyText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.parallel", + parallels); + + IKey hoverText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.multi_furnace.parallel_hover"); + + richText.add(KeyUtil.setHover(bodyText, hoverText)); } }) .addWorkingStatusLine() @@ -107,14 +97,9 @@ protected void addDisplayText(List textList) { @Override protected void formStructure(PatternMatchContext context) { super.formStructure(context); - Object coilType = context.get("CoilType"); - if (coilType instanceof IHeatingCoilBlockStats) { - this.heatingCoilLevel = ((IHeatingCoilBlockStats) coilType).getLevel(); - this.heatingCoilDiscount = ((IHeatingCoilBlockStats) coilType).getEnergyDiscount(); - } else { - this.heatingCoilLevel = CoilType.CUPRONICKEL.getLevel(); - this.heatingCoilDiscount = CoilType.CUPRONICKEL.getEnergyDiscount(); - } + IHeatingCoilBlockStats coilType = context.getOrDefault("CoilType", CoilType.CUPRONICKEL); + this.heatingCoilLevel = coilType.getLevel(); + this.heatingCoilDiscount = coilType.getEnergyDiscount(); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java index fc49827d51b..82b7b150416 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityNetworkSwitch.java @@ -8,11 +8,11 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; @@ -23,7 +23,6 @@ import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; @@ -145,9 +144,8 @@ public void addInformation(ItemStack stack, @Nullable World world, @NotNull List } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(true, isActive() && isWorkingEnabled()) // transform into two-state system for display + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(true, isActive() && isWorkingEnabled()) // transform into two-state system for display .setWorkingStatusKeys( "gregtech.multiblock.idling", "gregtech.multiblock.idling", @@ -158,13 +156,13 @@ protected void addDisplayText(List textList) { } @Override - protected void addWarningText(List textList) { - super.addWarningText(textList); - if (isStructureFormed() && computationHandler.hasNonBridgingConnections()) { - textList.add(TextComponentUtil.translationWithColor( - TextFormatting.YELLOW, - "gregtech.multiblock.computation.non_bridging.detailed")); - } + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + super.configureWarningText(builder); + builder.addCustom(list -> { + if (isStructureFormed() && computationHandler.hasNonBridgingConnections()) { + list.add(KeyUtil.lang(TextFormatting.YELLOW, "gregtech.multiblock.computation.non_bridging.detailed")); + } + }); } /** Handles computation load across multiple receivers and to multiple transmitters. */ diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPowerSubstation.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPowerSubstation.java index abf7a3d31d4..95644a32095 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPowerSubstation.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPowerSubstation.java @@ -11,17 +11,19 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IBatteryData; import gregtech.api.metatileentity.multiblock.IMultiblockPart; -import gregtech.api.metatileentity.multiblock.IProgressBarMultiblock; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; +import gregtech.api.metatileentity.multiblock.ProgressBarMultiblock; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.sync.BigIntegerSyncValue; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.MultiblockShapeInfo; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.pattern.TraceabilityPredicate; import gregtech.api.util.BlockInfo; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; @@ -40,8 +42,6 @@ import net.minecraft.network.PacketBuffer; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; @@ -51,6 +51,9 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.widgets.ProgressWidget; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.VisibleForTesting; @@ -67,7 +70,7 @@ import static gregtech.api.util.RelativeDirection.*; public class MetaTileEntityPowerSubstation extends MultiblockWithDisplayBase - implements IControllable, IProgressBarMultiblock { + implements IControllable, ProgressBarMultiblock { // Structure Constants public static final int MAX_BATTERY_LAYERS = 18; @@ -232,7 +235,7 @@ public void setWorkingEnabled(boolean isWorkingAllowed) { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } @@ -339,112 +342,95 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(true, isActive() && isWorkingEnabled()) // transform into two-state system for display - .setWorkingStatusKeys( - "gregtech.multiblock.idling", - "gregtech.multiblock.idling", - "gregtech.machine.active_transformer.routing") - .addCustom(tl -> { - if (isStructureFormed() && energyBank != null) { - BigInteger energyStored = energyBank.getStored(); - BigInteger energyCapacity = energyBank.getCapacity(); - - // Stored EU line - ITextComponent storedFormatted = TextComponentUtil.stringWithColor( - TextFormatting.GOLD, - TextFormattingUtil.formatNumbers(energyStored) + " EU"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.stored", - storedFormatted)); - - // EU Capacity line - ITextComponent capacityFormatted = TextComponentUtil.stringWithColor( - TextFormatting.GOLD, - TextFormattingUtil.formatNumbers(energyCapacity) + " EU"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.capacity", - capacityFormatted)); - - // Passive Drain line - ITextComponent passiveDrain = TextComponentUtil.stringWithColor( - TextFormatting.DARK_RED, - TextFormattingUtil.formatNumbers(getPassiveDrain()) + " EU/t"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.passive_drain", - passiveDrain)); - - // Average EU IN line - ITextComponent avgValue = TextComponentUtil.stringWithColor( - TextFormatting.GREEN, - TextFormattingUtil.formatNumbers(averageInLastSec) + " EU/t"); - ITextComponent base = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.average_in", - avgValue); - ITextComponent hover = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.average_in_hover"); - tl.add(TextComponentUtil.setHover(base, hover)); - - // Average EU OUT line - avgValue = TextComponentUtil.stringWithColor( - TextFormatting.RED, - TextFormattingUtil.formatNumbers(averageOutLastSec) + " EU/t"); - base = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.average_out", - avgValue); - hover = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.average_out_hover"); - tl.add(TextComponentUtil.setHover(base, hover)); - - // Time to fill/drain line - if (averageInLastSec > averageOutLastSec) { - ITextComponent timeToFill = getTimeToFillDrainText(energyCapacity.subtract(energyStored) - .divide(BigInteger.valueOf((averageInLastSec - averageOutLastSec) * 20))); - TextComponentUtil.setColor(timeToFill, TextFormatting.GREEN); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.time_to_fill", - timeToFill)); - } else if (averageInLastSec < averageOutLastSec) { - ITextComponent timeToDrain = getTimeToFillDrainText( - energyStored.divide(BigInteger.valueOf( - (averageOutLastSec - averageInLastSec) * 20))); - TextComponentUtil.setColor(timeToDrain, TextFormatting.RED); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.power_substation.time_to_drain", - timeToDrain)); - } - } - }) - .addWorkingStatusLine(); + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.structureFormed(isStructureFormed()); + builder.setWorkingStatus(true, isActive() && isWorkingEnabled()); // transform into two-state system for display + builder.setWorkingStatusKeys("gregtech.multiblock.idling", "gregtech.multiblock.idling", + "gregtech.machine.active_transformer.routing"); + builder.addCustom(list -> { + if (isStructureFormed() && energyBank != null) { + BigInteger energyStored = energyBank.getStored(); + BigInteger energyCapacity = energyBank.getCapacity(); + + // Stored EU line + IKey storedFormatted = KeyUtil.string( + TextFormattingUtil.formatNumbers(energyStored) + " EU"); + + IKey truncated = KeyUtil.string(TextFormatting.GOLD, + TextFormattingUtil.formatBigIntToCompactString(energyStored, 7) + " EU"); + + IKey bodyStored = (KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.stored", + truncated)); + + list.add(KeyUtil.setHover(bodyStored, storedFormatted)); + + // EU Capacity line + IKey capacityFormatted = KeyUtil.string( + TextFormattingUtil.formatNumbers(energyCapacity) + " EU"); + + IKey capCompact = KeyUtil.string(TextFormatting.GOLD, + TextFormattingUtil.formatBigIntToCompactString(energyCapacity, 7) + " EU"); + + IKey bodyCap = KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.capacity", + capCompact); + + list.add(KeyUtil.setHover(bodyCap, capacityFormatted)); + + // Passive Drain line + IKey passiveDrain = KeyUtil.string(TextFormatting.DARK_RED, + TextFormattingUtil.formatNumbers(getPassiveDrain()) + " EU/t"); + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.passive_drain", + passiveDrain)); + + // Average EU IN line + IKey avgValue = KeyUtil.string(TextFormatting.GREEN, + TextFormattingUtil.formatNumbers(averageInLastSec) + " EU/t"); + IKey base = KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.average_in", + avgValue); + IKey hover = KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.average_in_hover"); + list.add(KeyUtil.setHover(base, hover)); + + // Average EU OUT line + avgValue = KeyUtil.string(TextFormatting.RED, + TextFormattingUtil.formatNumbers(averageOutLastSec) + " EU/t"); + base = KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.average_out", avgValue); + hover = KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.average_out_hover"); + list.add(KeyUtil.setHover(base, hover)); + + // Time to fill/drain line + if (averageInLastSec > averageOutLastSec) { + IKey timeToFill = getTimeToFillDrainText(energyCapacity.subtract(energyStored) + .divide(BigInteger.valueOf((averageInLastSec - averageOutLastSec) * 20))); + timeToFill.style(TextFormatting.GREEN); + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.time_to_fill", + timeToFill)); + } else if (averageInLastSec < averageOutLastSec) { + IKey timeToDrain = getTimeToFillDrainText( + energyStored.divide(BigInteger.valueOf((averageOutLastSec - averageInLastSec) * 20))); + timeToDrain.style(TextFormatting.RED); + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.power_substation.time_to_drain", + timeToDrain)); + } + } + }); + builder.addWorkingStatusLine(); } @Override - protected void addWarningText(List textList) { - super.addWarningText(textList); - if (isStructureFormed()) { - if (averageInLastSec < averageOutLastSec) { // decreasing + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addCustom(list -> { + if (isStructureFormed() && averageInLastSec < averageOutLastSec) { BigInteger timeToDrainSeconds = energyBank.getStored() .divide(BigInteger.valueOf((averageOutLastSec - averageInLastSec) * 20)); if (timeToDrainSeconds.compareTo(BigInteger.valueOf(60 * 60)) < 0) { // less than 1 hour left - textList.add(TextComponentUtil.translationWithColor( - TextFormatting.YELLOW, + list.add(KeyUtil.lang(TextFormatting.YELLOW, "gregtech.multiblock.power_substation.under_one_hour_left")); } } - } + }); } - private static ITextComponent getTimeToFillDrainText(BigInteger timeToFillSeconds) { + private static IKey getTimeToFillDrainText(BigInteger timeToFillSeconds) { if (timeToFillSeconds.compareTo(BIG_INTEGER_MAX_LONG) > 0) { // too large to represent in a java Duration timeToFillSeconds = BIG_INTEGER_MAX_LONG; @@ -469,10 +455,10 @@ private static ITextComponent getTimeToFillDrainText(BigInteger timeToFillSecond fillTime = duration.toDays() / 365; key = "gregtech.multiblock.power_substation.time_years"; } else { - return new TextComponentTranslation("gregtech.multiblock.power_substation.time_forever"); + return KeyUtil.lang("gregtech.multiblock.power_substation.time_forever"); } - return new TextComponentTranslation(key, TextFormattingUtil.formatNumbers(fillTime)); + return KeyUtil.lang(key, TextFormattingUtil.formatNumbers(fillTime)); } @Override @@ -579,23 +565,32 @@ public long getAverageOutLastSec() { } @Override - public double getFillPercentage(int index) { - if (energyBank == null) return 0; - return energyBank.getStored().doubleValue() / energyBank.getCapacity().doubleValue(); + public int getProgressBarCount() { + return 1; } @Override - public void addBarHoverText(List hoverList, int index) { - String stored = energyBank != null ? TextFormattingUtil.formatNumbers(energyBank.getStored()) : "0"; - String capacity = energyBank != null ? TextFormattingUtil.formatNumbers(energyBank.getCapacity()) : "0"; - - ITextComponent energyInfo = TextComponentUtil.stringWithColor( - TextFormatting.YELLOW, - stored + " / " + capacity + " EU"); - hoverList.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.energy_stored", - energyInfo)); + public @NotNull ProgressWidget createProgressBar(@NotNull PanelSyncManager panelSyncManager, int index) { + BigIntegerSyncValue energyStoredValue = new BigIntegerSyncValue( + () -> energyBank == null ? BigInteger.ZERO : energyBank.getStored(), null); + BigIntegerSyncValue energyCapacityValue = new BigIntegerSyncValue( + () -> energyBank == null ? BigInteger.ZERO : energyBank.getCapacity(), null); + panelSyncManager.syncValue("energy_stored", energyStoredValue); + panelSyncManager.syncValue("energy_capacity", energyCapacityValue); + + return new ProgressWidget() + .progress( + () -> energyStoredValue.getValue().doubleValue() / energyCapacityValue.getValue().doubleValue()) + .texture(GTGuiTextures.PROGRESS_BAR_MULTI_ENERGY_YELLOW, MultiblockUIFactory.Bars.FULL_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + t.addLine(IKey.lang("gregtech.multiblock.energy_stored", energyStoredValue.getValue(), + energyCapacityValue.getValue())); + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); } public static class PowerStationEnergyBank { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityProcessingArray.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityProcessingArray.java index 0a06b0fb546..84a3a1ee556 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityProcessingArray.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityProcessingArray.java @@ -14,8 +14,8 @@ import gregtech.api.metatileentity.multiblock.ICleanroomReceiver; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; @@ -26,7 +26,7 @@ import gregtech.api.recipes.logic.OCResult; import gregtech.api.recipes.properties.RecipePropertyStorage; import gregtech.api.util.GTUtility; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; @@ -41,14 +41,13 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.items.IItemHandlerModifiable; +import com.cleanroommc.modularui.api.drawable.IKey; import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -115,61 +114,60 @@ public ICubeRenderer getBaseTexture(IMultiblockPart sourcePart) { } @Override - protected void addDisplayText(List textList) { + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { ProcessingArrayWorkable logic = (ProcessingArrayWorkable) recipeMapWorkable; - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) - .addEnergyUsageLine(recipeMapWorkable.getEnergyContainer()) - .addEnergyTierLine(logic.currentMachineStack == ItemStack.EMPTY ? -1 : logic.machineTier) - .addCustom(tl -> { - if (isStructureFormed()) { - - // Machine mode text - // Shared text components for both states - ITextComponent maxMachinesText = TextComponentUtil.stringWithColor(TextFormatting.DARK_PURPLE, - Integer.toString(getMachineLimit())); - maxMachinesText = TextComponentUtil.translationWithColor(TextFormatting.GRAY, - "gregtech.machine.machine_hatch.machines_max", maxMachinesText); - - if (logic.activeRecipeMap == null) { - // No machines in hatch - ITextComponent noneText = TextComponentUtil.translationWithColor(TextFormatting.YELLOW, - "gregtech.machine.machine_hatch.machines_none"); - ITextComponent bodyText = TextComponentUtil.translationWithColor(TextFormatting.GRAY, - "gregtech.machine.machine_hatch.machines", noneText); - ITextComponent hoverText1 = TextComponentUtil.translationWithColor(TextFormatting.GRAY, - "gregtech.machine.machine_hatch.machines_none_hover"); - tl.add(TextComponentUtil.setHover(bodyText, hoverText1, maxMachinesText)); - } else { - // Some amount of machines in hatch - String key = logic.getMachineStack().getTranslationKey(); - ITextComponent mapText = TextComponentUtil.translationWithColor(TextFormatting.DARK_PURPLE, - key + ".name"); - mapText = TextComponentUtil.translationWithColor( - TextFormatting.DARK_PURPLE, - "%sx %s", - logic.getParallelLimit(), mapText); - ITextComponent bodyText = TextComponentUtil.translationWithColor(TextFormatting.GRAY, - "gregtech.machine.machine_hatch.machines", mapText); - ITextComponent voltageName = new TextComponentString(GTValues.VNF[logic.machineTier]); - int amps = logic.getMachineStack().getCount(); - String energyFormatted = TextFormattingUtil - .formatNumbers(GTValues.V[logic.machineTier] * amps); - ITextComponent hoverText = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.machine.machine_hatch.machines_max_eut", - energyFormatted, amps, voltageName); - tl.add(TextComponentUtil.setHover(bodyText, hoverText, maxMachinesText)); - } - - // Hatch locked status - if (isActive()) { - tl.add(TextComponentUtil.translationWithColor(TextFormatting.DARK_RED, - "gregtech.machine.machine_hatch.locked")); - } + builder.setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) + .addEnergyUsageLine(this.getEnergyContainer()) + .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage())) + .addCustom(richText -> { + if (!isStructureFormed()) return; + + // Machine mode text + // Shared text components for both states + IKey maxMachinesText = KeyUtil.string(TextFormatting.DARK_PURPLE, + Integer.toString(getMachineLimit())); + maxMachinesText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.machine.machine_hatch.machines_max", maxMachinesText); + + if (logic.activeRecipeMap == null) { + // No machines in hatch + IKey noneText = KeyUtil.lang(TextFormatting.YELLOW, + "gregtech.machine.machine_hatch.machines_none"); + IKey bodyText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.machine.machine_hatch.machines", noneText); + IKey hoverText1 = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.machine.machine_hatch.machines_none_hover"); + richText.add(KeyUtil.setHover(bodyText, hoverText1, maxMachinesText)); + } else { + // Some amount of machines in hatch + String key = logic.getMachineStack().getTranslationKey(); + IKey mapText = KeyUtil.lang(TextFormatting.DARK_PURPLE, + key + ".name"); + mapText = KeyUtil.string( + TextFormatting.DARK_PURPLE, + "%sx %s", + logic.getParallelLimit(), mapText); + IKey bodyText = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.machine.machine_hatch.machines", mapText); + String voltageName = GTValues.VNF[logic.machineTier]; + int amps = logic.getMachineStack().getCount(); + String energyFormatted = TextFormattingUtil + .formatNumbers(GTValues.V[logic.machineTier] * amps); + IKey hoverText = KeyUtil.lang( + TextFormatting.GRAY, + "gregtech.machine.machine_hatch.machines_max_eut", + energyFormatted, amps, voltageName); + richText.add(KeyUtil.setHover(bodyText, hoverText, maxMachinesText)); + } + + // Hatch locked status + if (isActive()) { + richText.add(KeyUtil.lang(TextFormatting.DARK_RED, + "gregtech.machine.machine_hatch.locked")); } }) + .addParallelsLine(recipeMapWorkable.getParallelLimit()) .addWorkingStatusLine() .addProgressLine(recipeMapWorkable.getProgressPercent()); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPyrolyseOven.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPyrolyseOven.java index b4715563582..62942115eb3 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPyrolyseOven.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityPyrolyseOven.java @@ -5,8 +5,8 @@ import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; @@ -14,7 +14,7 @@ import gregtech.api.recipes.logic.OCResult; import gregtech.api.recipes.properties.RecipePropertyStorage; import gregtech.api.util.GTUtility; -import gregtech.api.util.TextComponentUtil; +import gregtech.api.util.KeyUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.blocks.BlockMachineCasing.MachineCasingType; @@ -26,12 +26,12 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.api.drawable.IKey; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -97,36 +97,6 @@ protected void formStructure(PatternMatchContext context) { this.coilTier = 0; } - @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) - .addEnergyUsageLine(recipeMapWorkable.getEnergyContainer()) - .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage())) - .addCustom(tl -> { - if (isStructureFormed()) { - int processingSpeed = coilTier == 0 ? 75 : 50 * (coilTier + 1); - ITextComponent speedIncrease = TextComponentUtil.stringWithColor( - getSpeedColor(processingSpeed), - processingSpeed + "%"); - - ITextComponent base = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.pyrolyse_oven.speed", - speedIncrease); - - ITextComponent hover = TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.pyrolyse_oven.speed_hover"); - - tl.add(TextComponentUtil.setHover(base, hover)); - } - }) - .addParallelsLine(recipeMapWorkable.getParallelLimit()) - .addWorkingStatusLine() - .addProgressLine(recipeMapWorkable.getProgressPercent()); - } - private TextFormatting getSpeedColor(int speed) { if (speed < 100) { return TextFormatting.RED; @@ -139,6 +109,28 @@ private TextFormatting getSpeedColor(int speed) { } } + @Override + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) + .addEnergyUsageLine(this.getEnergyContainer()) + .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage())) + .addCustom(textList -> { + if (!isStructureFormed()) return; + + int processingSpeed = coilTier == 0 ? 75 : 50 * (coilTier + 1); + IKey speed = KeyUtil.number(() -> getSpeedColor(processingSpeed), processingSpeed, "%"); + + IKey body = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.pyrolyse_oven.speed", speed); + IKey hover = KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.pyrolyse_oven.speed_hover"); + textList.add(KeyUtil.setHover(body, hover)); + }) + .addParallelsLine(recipeMapWorkable.getParallelLimit()) + .addWorkingStatusLine() + .addProgressLine(recipeMapWorkable.getProgressPercent()); + } + @Override public void addInformation(ItemStack stack, @Nullable World player, List tooltip, boolean advanced) { super.addInformation(stack, player, tooltip, advanced); diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java index 50923590e11..aeaebb3357a 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/MetaTileEntityResearchStation.java @@ -11,8 +11,8 @@ import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.MultiblockShapeInfo; @@ -33,7 +33,6 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.EnumFacing; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.ITextComponent; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; @@ -201,7 +200,7 @@ protected ICubeRenderer getFrontOverlay() { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } @@ -223,14 +222,13 @@ public void addInformation(ItemStack stack, @Nullable World world, @NotNull List } @Override - protected void addDisplayText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.setWorkingStatus(recipeMapWorkable.isWorkingEnabled(), recipeMapWorkable.isActive()) .setWorkingStatusKeys( "gregtech.multiblock.idling", "gregtech.multiblock.work_paused", "gregtech.machine.research_station.researching") - .addEnergyUsageLine(recipeMapWorkable.getEnergyContainer()) + .addEnergyUsageLine(this.getEnergyContainer()) .addEnergyTierLine(GTUtility.getTierByVoltage(recipeMapWorkable.getMaxVoltage())) .addComputationUsageExactLine(getRecipeMapWorkable().getCurrentDrawnCWUt()) .addParallelsLine(recipeMapWorkable.getParallelLimit()) @@ -239,9 +237,8 @@ protected void addDisplayText(List textList) { } @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addLowPowerLine(recipeMapWorkable.isHasNotEnoughEnergy()) + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addLowPowerLine(recipeMapWorkable.isHasNotEnoughEnergy()) .addLowComputationLine(getRecipeMapWorkable().isHasNotEnoughComputation()) .addMaintenanceProblemLines(getMaintenanceProblems()); } diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java index 4deeabb9a9f..718bc1c26d4 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/centralmonitor/MetaTileEntityCentralMonitor.java @@ -7,8 +7,6 @@ import gregtech.api.cover.Cover; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; -import gregtech.api.gui.Widget; -import gregtech.api.gui.widgets.AdvancedTextWidget; import gregtech.api.gui.widgets.WidgetGroup; import gregtech.api.metatileentity.IFastRenderMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; @@ -16,12 +14,14 @@ import gregtech.api.metatileentity.multiblock.IMultiblockPart; import gregtech.api.metatileentity.multiblock.MultiblockAbility; import gregtech.api.metatileentity.multiblock.MultiblockWithDisplayBase; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.pipenet.tile.IPipeTile; import gregtech.api.pipenet.tile.TileEntityPipeBase; import gregtech.api.util.FacingPos; +import gregtech.api.util.KeyUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.client.utils.RenderUtil; @@ -49,9 +49,7 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.text.ITextComponent; -import net.minecraft.util.text.TextComponentString; -import net.minecraft.util.text.TextComponentTranslation; +import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.fml.relauncher.Side; @@ -60,6 +58,9 @@ import codechicken.lib.render.CCRenderState; import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.widgets.ButtonWidget; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL11; @@ -70,7 +71,7 @@ public class MetaTileEntityCentralMonitor extends MultiblockWithDisplayBase implements IFastRenderMetaTileEntity { - private final static long ENERGY_COST = -ConfigHolder.machines.centralMonitorEuCost; + private final static long ENERGY_COST = ConfigHolder.machines.centralMonitorEuCost; public final static int MAX_HEIGHT = 9; public final static int MAX_WIDTH = 14; // run-time data @@ -278,33 +279,55 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, } @Override - protected void addDisplayText(List textList) { - super.addDisplayText(textList); - textList.add(new TextComponentTranslation("gregtech.multiblock.central_monitor.height", this.height)); - if (!isStructureFormed()) { - ITextComponent buttonText = new TextComponentTranslation( - "gregtech.multiblock.central_monitor.height_modify", height); - buttonText.appendText(" "); - buttonText.appendSibling(AdvancedTextWidget.withButton(new TextComponentString("[-]"), "sub")); - buttonText.appendText(" "); - buttonText.appendSibling(AdvancedTextWidget.withButton(new TextComponentString("[+]"), "add")); - textList.add(buttonText); - } else { - textList.add(new TextComponentTranslation("gregtech.multiblock.central_monitor.width", this.width)); - textList.add(new TextComponentTranslation("gregtech.multiblock.central_monitor.low_power")); - } + protected MultiblockUIFactory createUIFactory() { + return super.createUIFactory() + .createFlexButton((posGuiData, panelSyncManager) -> { + IntSyncValue intSync = new IntSyncValue(() -> height, this::setHeight); + panelSyncManager.syncValue("height", intSync); + + return new ButtonWidget<>() + .addTooltipLine(IKey.lang("gregtech.multiblock.central_monitor.button_tooltip")) + .onMousePressed(mouseData -> { + int currentHeight = intSync.getIntValue(); + + if (mouseData == 0 && currentHeight < MAX_HEIGHT) { + intSync.setIntValue(currentHeight + 1); + return true; + } else if (mouseData == 1 && currentHeight > 3) { + intSync.setIntValue(currentHeight - 1); + return true; + } else if (mouseData == 2) { + intSync.setIntValue(3); + } + + return false; + }); + }); } @Override - protected boolean shouldShowVoidingModeButton() { - return false; + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + builder.addCustom(list -> { + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.central_monitor.height", this.height)); + + if (isStructureFormed()) { + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.central_monitor.width", this.width)); + } + }); } @Override - protected void handleDisplayClick(String componentData, Widget.ClickData clickData) { - super.handleDisplayClick(componentData, clickData); - int modifier = componentData.equals("add") ? 1 : -1; - setHeight(this.height + modifier); + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addCustom(list -> { + if (isStructureFormed() && !drainEnergy(true)) { + list.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.central_monitor.low_power")); + } + }); + } + + @Override + public boolean shouldShowVoidingModeButton() { + return false; } @Override @@ -370,8 +393,7 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity metaTileEntityHol @Override protected void updateFormedValid() { if (this.getOffsetTimer() % 20 == 0) { - setActive(inputEnergy.changeEnergy(ENERGY_COST * this.getMultiblockParts().size()) == - ENERGY_COST * this.getMultiblockParts().size()); + setActive(drainEnergy(false)); if (checkCovers()) { this.getMultiblockParts().forEach(part -> { Set covers = getAllCovers(); @@ -384,6 +406,20 @@ protected void updateFormedValid() { } } + /** + * @return if the Central Monitor was able to drain enough energy. + */ + private boolean drainEnergy(boolean simulate) { + long energyToDrain = ENERGY_COST * this.getMultiblockParts().size(); + long resultEnergy = inputEnergy.getEnergyStored() - energyToDrain; + if (resultEnergy >= 0L && resultEnergy <= inputEnergy.getEnergyCapacity()) { + if (!simulate) + inputEnergy.changeEnergy(-energyToDrain); + return true; + } + return false; + } + public Set getAllCovers() { Set allCovers = new HashSet<>(); if (netCovers != null) { @@ -630,7 +666,7 @@ public void addInformation(ItemStack stack, @Nullable World player, List tooltip.add(I18n.format("gregtech.multiblock.central_monitor.tooltip.1")); tooltip.add(I18n.format("gregtech.multiblock.central_monitor.tooltip.2", MAX_WIDTH, MAX_HEIGHT)); tooltip.add(I18n.format("gregtech.multiblock.central_monitor.tooltip.3")); - tooltip.add(I18n.format("gregtech.multiblock.central_monitor.tooltip.4", -ENERGY_COST)); + tooltip.add(I18n.format("gregtech.multiblock.central_monitor.tooltip.4", ENERGY_COST)); } @Override diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeCombustionEngine.java b/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeCombustionEngine.java index 5bdd31eafc8..5eb691f3dea 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeCombustionEngine.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeCombustionEngine.java @@ -6,24 +6,23 @@ import gregtech.api.capability.IMultipleTankHandler; import gregtech.api.capability.impl.MultiblockFuelRecipeLogic; import gregtech.api.fluids.store.FluidStorageKeys; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.resources.TextureArea; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; +import gregtech.api.metatileentity.multiblock.*; import gregtech.api.metatileentity.multiblock.FuelMultiblockController; import gregtech.api.metatileentity.multiblock.IMultiblockPart; -import gregtech.api.metatileentity.multiblock.IProgressBarMultiblock; import gregtech.api.metatileentity.multiblock.MultiblockAbility; -import gregtech.api.metatileentity.multiblock.MultiblockDisplayText; import gregtech.api.metatileentity.multiblock.RecipeMapMultiblockController; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.sync.FixedIntArraySyncValue; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.recipes.RecipeMaps; import gregtech.api.unification.material.Materials; +import gregtech.api.util.KeyUtil; import gregtech.api.util.RelativeDirection; -import gregtech.api.util.TextComponentUtil; -import gregtech.api.util.TextFormattingUtil; import gregtech.client.renderer.ICubeRenderer; import gregtech.client.renderer.texture.Textures; import gregtech.common.blocks.BlockMetalCasing.MetalCasingType; @@ -36,23 +35,29 @@ import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.value.sync.BooleanSyncValue; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widgets.ProgressWidget; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -public class MetaTileEntityLargeCombustionEngine extends FuelMultiblockController implements IProgressBarMultiblock { +public class MetaTileEntityLargeCombustionEngine extends FuelMultiblockController implements ProgressBarMultiblock { private final int tier; private final boolean isExtreme; private boolean boostAllowed; + private boolean hasLubricant; public MetaTileEntityLargeCombustionEngine(ResourceLocation metaTileEntityId, int tier) { super(metaTileEntityId, RecipeMaps.COMBUSTION_GENERATOR_FUELS, tier); @@ -68,11 +73,10 @@ public MetaTileEntity createMetaTileEntity(IGregTechTileEntity tileEntity) { } @Override - protected void addDisplayText(List textList) { - LargeCombustionEngineWorkableHandler recipeLogic = ((LargeCombustionEngineWorkableHandler) recipeMapWorkable); + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { + var recipeLogic = (LargeCombustionEngineWorkableHandler) recipeMapWorkable; - MultiblockDisplayText.Builder builder = MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()); + builder.setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()); if (isExtreme) { builder.addEnergyProductionLine(GTValues.V[tier + 1], recipeLogic.getRecipeEUt()); @@ -81,34 +85,36 @@ protected void addDisplayText(List textList) { } builder.addFuelNeededLine(recipeLogic.getRecipeFluidInputInfo(), recipeLogic.getPreviousRecipeDuration()) - .addCustom(tl -> { + .addCustom(richText -> { if (isStructureFormed() && recipeLogic.isOxygenBoosted) { - String key = isExtreme ? "gregtech.multiblock.large_combustion_engine.liquid_oxygen_boosted" : + String key = isExtreme ? + "gregtech.multiblock.large_combustion_engine.liquid_oxygen_boosted" : "gregtech.multiblock.large_combustion_engine.oxygen_boosted"; - tl.add(TextComponentUtil.translationWithColor(TextFormatting.AQUA, key)); + richText.add(KeyUtil.lang(TextFormatting.AQUA, key)); } }) .addWorkingStatusLine(); } @Override - protected void addErrorText(List textList) { - super.addErrorText(textList); - if (isStructureFormed()) { + protected void configureErrorText(MultiblockUIFactory.Builder builder) { + var recipeLogic = (LargeCombustionEngineWorkableHandler) recipeMapWorkable; + + builder.addCustom(keyList -> { + if (!isStructureFormed()) return; + if (checkIntakesObstructed()) { - textList.add(TextComponentUtil.translationWithColor(TextFormatting.RED, + keyList.add(KeyUtil.lang(TextFormatting.RED, "gregtech.multiblock.large_combustion_engine.obstructed")); - textList.add(TextComponentUtil.translationWithColor(TextFormatting.GRAY, + keyList.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.large_combustion_engine.obstructed.desc")); } - FluidStack lubricantStack = getInputFluidInventory().drain(Materials.Lubricant.getFluid(Integer.MAX_VALUE), - false); - if (lubricantStack == null || lubricantStack.amount == 0) { - textList.add(TextComponentUtil.translationWithColor(TextFormatting.RED, + if (!recipeLogic.checkLubricant()) { + keyList.add(KeyUtil.lang(TextFormatting.RED, "gregtech.multiblock.large_combustion_engine.no_lubricant")); } - } + }); } @Override @@ -126,7 +132,7 @@ public void addInformation(ItemStack stack, @Nullable World player, List } @Override - protected BlockPattern createStructurePattern() { + protected @NotNull BlockPattern createStructurePattern() { return FactoryBlockPattern.start() .aisle("XXX", "XDX", "XXX") .aisle("XCX", "CGC", "XCX") @@ -216,7 +222,7 @@ private boolean checkIntakesObstructed() { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } @@ -225,107 +231,137 @@ public boolean isBoostAllowed() { } @Override - public int getNumProgressBars() { + public int getProgressBarCount() { return 3; } @Override - public double getFillPercentage(int index) { - if (index == 0) { - int[] fuelAmount = new int[2]; - if (getInputFluidInventory() != null) { - MultiblockFuelRecipeLogic recipeLogic = (MultiblockFuelRecipeLogic) recipeMapWorkable; - if (recipeLogic.getInputFluidStack() != null) { - FluidStack testStack = recipeLogic.getInputFluidStack().copy(); - testStack.amount = Integer.MAX_VALUE; - fuelAmount = getTotalFluidAmount(testStack, getInputFluidInventory()); - } + public @NotNull ProgressWidget createProgressBar(PanelSyncManager panelSyncManager, int index) { + return switch (index) { + case 0 -> { + FixedIntArraySyncValue fuelValue = new FixedIntArraySyncValue(this::getFuelAmount, null); + StringSyncValue fuelNameValue = new StringSyncValue(() -> { + FluidStack stack = ((MultiblockFuelRecipeLogic) recipeMapWorkable).getInputFluidStack(); + if (stack == null) { + return null; + } + Fluid fluid = stack.getFluid(); + if (fluid == null) { + return null; + } + return fluid.getName(); + }); + panelSyncManager.syncValue("fuel_amount", fuelValue); + panelSyncManager.syncValue("fuel_name", fuelNameValue); + + yield new ProgressWidget() + .progress(() -> fuelValue.getValue(1) == 0 ? 0 : + 1.0 * fuelValue.getValue(0) / fuelValue.getValue(1)) + .texture(GTGuiTextures.PROGRESS_BAR_LCE_FUEL, MultiblockUIFactory.Bars.THIRD_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> createFuelTooltip(t, fuelValue, fuelNameValue)); } - return fuelAmount[1] != 0 ? 1.0 * fuelAmount[0] / fuelAmount[1] : 0; - } else if (index == 1) { - int[] lubricantAmount = new int[2]; - if (getInputFluidInventory() != null) { - lubricantAmount = getTotalFluidAmount(Materials.Lubricant.getFluid(Integer.MAX_VALUE), - getInputFluidInventory()); + case 1 -> { + FixedIntArraySyncValue lubricantValue = new FixedIntArraySyncValue(this::getLubricantAmount, null); + panelSyncManager.syncValue("lubricant_amount", lubricantValue); + + yield new ProgressWidget() + .progress(() -> lubricantValue.getValue(1) == 0 ? 0 : + 1.0 * lubricantValue.getValue(0) / lubricantValue.getValue(1)) + .texture(GTGuiTextures.PROGRESS_BAR_LCE_LUBRICANT, MultiblockUIFactory.Bars.THIRD_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + if (lubricantValue.getValue(0) == 0) { + t.addLine(IKey.lang("gregtech.multiblock.large_combustion_engine.no_lubricant")); + } else { + t.addLine(IKey.lang("gregtech.multiblock.large_combustion_engine.lubricant_amount", + lubricantValue.getValue(0), lubricantValue.getValue(0))); + } + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); } - return lubricantAmount[1] != 0 ? 1.0 * lubricantAmount[0] / lubricantAmount[1] : 0; - } else { - int[] oxygenAmount = new int[2]; - if (getInputFluidInventory() != null) { - if (isBoostAllowed()) { - FluidStack oxygenStack = isExtreme ? - Materials.Oxygen.getFluid(FluidStorageKeys.LIQUID, Integer.MAX_VALUE) : - Materials.Oxygen.getFluid(Integer.MAX_VALUE); - oxygenAmount = getTotalFluidAmount(oxygenStack, getInputFluidInventory()); - } + case 2 -> { + FixedIntArraySyncValue oxygenValue = new FixedIntArraySyncValue(this::getOxygenAmount, null); + BooleanSyncValue boostValue = new BooleanSyncValue(this::isBoostAllowed); + panelSyncManager.syncValue("oxygen_amount", oxygenValue); + panelSyncManager.syncValue("boost_allowed", boostValue); + + yield new ProgressWidget() + .progress(() -> oxygenValue.getValue(1) == 0 ? 0 : + 1.0 * oxygenValue.getValue(0) / oxygenValue.getValue(1)) + .texture(GTGuiTextures.PROGRESS_BAR_LCE_OXYGEN, MultiblockUIFactory.Bars.THIRD_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + if (boostValue.getBoolValue()) { + if (oxygenValue.getValue(0) == 0) { + t.addLine(IKey.lang("gregtech.multiblock.large_combustion_engine.oxygen_none")); + } else if (isExtreme) { + t.addLine(IKey.lang( + "gregtech.multiblock.large_combustion_engine.liquid_oxygen_amount", + oxygenValue.getValue(0), oxygenValue.getValue(0))); + } else { + t.addLine(IKey.lang("gregtech.multiblock.large_combustion_engine.oxygen_amount", + oxygenValue.getValue(0), oxygenValue.getValue(1))); + } + } else if (isExtreme) { + t.addLine(IKey.lang( + "gregtech.multiblock.large_combustion_engine.liquid_oxygen_boost_disallowed")); + } else { + t.addLine(IKey.lang( + "gregtech.multiblock.large_combustion_engine.oxygen_boost_disallowed")); + } + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); } - return oxygenAmount[1] != 0 ? 1.0 * oxygenAmount[0] / oxygenAmount[1] : 0; - } + default -> throw new IllegalStateException("Invalid index received " + index); + }; } - @Override - public TextureArea getProgressBarTexture(int index) { - if (index == 0) { - return GuiTextures.PROGRESS_BAR_LCE_FUEL; - } else if (index == 1) { - return GuiTextures.PROGRESS_BAR_LCE_LUBRICANT; - } else { - return GuiTextures.PROGRESS_BAR_LCE_OXYGEN; + /** + * @return an array of [fuel stored, fuel capacity] + */ + private int[] getFuelAmount() { + if (getInputFluidInventory() != null) { + MultiblockFuelRecipeLogic recipeLogic = (MultiblockFuelRecipeLogic) recipeMapWorkable; + if (recipeLogic.getInputFluidStack() != null) { + FluidStack testStack = recipeLogic.getInputFluidStack().copy(); + testStack.amount = Integer.MAX_VALUE; + return getTotalFluidAmount(testStack, getInputFluidInventory()); + } } + return new int[2]; } - @Override - public void addBarHoverText(List hoverList, int index) { - if (index == 0) { - addFuelText(hoverList); - } else if (index == 1) { - // Lubricant - int lubricantStored = 0; - int lubricantCapacity = 0; - if (isStructureFormed() && getInputFluidInventory() != null) { - // Hunt for tanks with lubricant in them - int[] lubricantAmount = getTotalFluidAmount(Materials.Lubricant.getFluid(Integer.MAX_VALUE), - getInputFluidInventory()); - lubricantStored = lubricantAmount[0]; - lubricantCapacity = lubricantAmount[1]; - } + /** + * @return an array of [lubricant stored, lubricant capacity] + */ + private int[] getLubricantAmount() { + if (getInputFluidInventory() != null) { + return getTotalFluidAmount(Materials.Lubricant.getFluid(Integer.MAX_VALUE), + getInputFluidInventory()); + } + return new int[2]; + } - ITextComponent lubricantInfo = TextComponentUtil.stringWithColor( - TextFormatting.GOLD, - TextFormattingUtil.formatNumbers(lubricantStored) + " / " + - TextFormattingUtil.formatNumbers(lubricantCapacity) + " L"); - hoverList.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.large_combustion_engine.lubricant_amount", - lubricantInfo)); - } else { - // Oxygen/LOX + /** + * @return an array of [oxygen stored, oxygen capacity] + */ + private int[] getOxygenAmount() { + if (getInputFluidInventory() != null) { if (isBoostAllowed()) { - int oxygenStored = 0; - int oxygenCapacity = 0; - if (isStructureFormed() && getInputFluidInventory() != null) { - // Hunt for tanks with Oxygen or LOX (depending on tier) in them - FluidStack oxygenStack = isExtreme ? - Materials.Oxygen.getFluid(FluidStorageKeys.LIQUID, Integer.MAX_VALUE) : - Materials.Oxygen.getFluid(Integer.MAX_VALUE); - int[] oxygenAmount = getTotalFluidAmount(oxygenStack, getInputFluidInventory()); - oxygenStored = oxygenAmount[0]; - oxygenCapacity = oxygenAmount[1]; - } - - ITextComponent oxygenInfo = TextComponentUtil.stringWithColor( - TextFormatting.AQUA, - TextFormattingUtil.formatNumbers(oxygenStored) + " / " + - TextFormattingUtil.formatNumbers(oxygenCapacity) + " L"); - String key = isExtreme ? "gregtech.multiblock.large_combustion_engine.liquid_oxygen_amount" : - "gregtech.multiblock.large_combustion_engine.oxygen_amount"; - hoverList.add(TextComponentUtil.translationWithColor(TextFormatting.GRAY, key, oxygenInfo)); - } else { - String key = isExtreme ? "gregtech.multiblock.large_combustion_engine.liquid_oxygen_boost_disallowed" : - "gregtech.multiblock.large_combustion_engine.oxygen_boost_disallowed"; - hoverList.add(TextComponentUtil.translationWithColor(TextFormatting.YELLOW, key)); + FluidStack oxygenStack = isExtreme ? + Materials.Oxygen.getFluid(FluidStorageKeys.LIQUID, Integer.MAX_VALUE) : + Materials.Oxygen.getFluid(Integer.MAX_VALUE); + return getTotalFluidAmount(oxygenStack, getInputFluidInventory()); } } + return new int[2]; } private static class LargeCombustionEngineWorkableHandler extends MultiblockFuelRecipeLogic { diff --git a/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java b/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java index 16522799167..dc0ed78b477 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java +++ b/src/main/java/gregtech/common/metatileentities/multi/electric/generator/MetaTileEntityLargeTurbine.java @@ -4,39 +4,44 @@ import gregtech.api.capability.IRotorHolder; import gregtech.api.capability.impl.FluidTankList; import gregtech.api.capability.impl.MultiblockFuelRecipeLogic; -import gregtech.api.gui.GuiTextures; -import gregtech.api.gui.resources.TextureArea; import gregtech.api.metatileentity.ITieredMetaTileEntity; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; import gregtech.api.metatileentity.multiblock.*; +import gregtech.api.metatileentity.multiblock.ui.MultiblockUIFactory; +import gregtech.api.mui.GTGuiTextures; +import gregtech.api.mui.sync.FixedIntArraySyncValue; import gregtech.api.pattern.BlockPattern; import gregtech.api.pattern.FactoryBlockPattern; import gregtech.api.pattern.PatternMatchContext; import gregtech.api.recipes.RecipeMap; -import gregtech.api.util.TextComponentUtil; -import gregtech.api.util.TextFormattingUtil; +import gregtech.api.util.KeyUtil; import gregtech.client.renderer.ICubeRenderer; import net.minecraft.block.state.IBlockState; import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; -import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextFormatting; import net.minecraft.world.World; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; import net.minecraftforge.fluids.capability.IFluidHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; +import com.cleanroommc.modularui.api.drawable.IKey; +import com.cleanroommc.modularui.value.sync.IntSyncValue; +import com.cleanroommc.modularui.value.sync.PanelSyncManager; +import com.cleanroommc.modularui.value.sync.StringSyncValue; +import com.cleanroommc.modularui.widgets.ProgressWidget; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; public class MetaTileEntityLargeTurbine extends FuelMultiblockController - implements ITieredMetaTileEntity, IProgressBarMultiblock { + implements ITieredMetaTileEntity, ProgressBarMultiblock { public final int tier; @@ -114,66 +119,66 @@ protected long getMaxVoltage() { } @Override - protected void addDisplayText(List textList) { + protected void configureDisplayText(MultiblockUIFactory.Builder builder) { MultiblockFuelRecipeLogic recipeLogic = (MultiblockFuelRecipeLogic) recipeMapWorkable; - - MultiblockDisplayText.builder(textList, isStructureFormed()) - .setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()) + builder.setWorkingStatus(recipeLogic.isWorkingEnabled(), recipeLogic.isActive()) .addEnergyProductionLine(getMaxVoltage(), recipeLogic.getRecipeEUt()) - .addCustom(tl -> { - if (isStructureFormed()) { - IRotorHolder rotorHolder = getRotorHolder(); - if (rotorHolder.getRotorEfficiency() > 0) { - ITextComponent efficiencyInfo = TextComponentUtil.stringWithColor( - TextFormatting.AQUA, - TextFormattingUtil.formatNumbers(rotorHolder.getTotalEfficiency()) + "%"); - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.turbine.efficiency", - efficiencyInfo)); - } + .addCustom(keyList -> { + if (!isStructureFormed()) return; + if (getRotorHolder() == null) return; + + int rotorEfficiency = getRotorHolder().getRotorEfficiency(); + int totalEfficiency = getRotorHolder().getTotalEfficiency(); + + if (rotorEfficiency > 0) { + IKey efficiencyInfo = KeyUtil.number(TextFormatting.AQUA, + totalEfficiency, "%"); + keyList.add(KeyUtil.lang(TextFormatting.GRAY, + "gregtech.multiblock.turbine.efficiency", + efficiencyInfo)); } }) + // todo fix prev duration being 0 on first ui open .addFuelNeededLine(recipeLogic.getRecipeFluidInputInfo(), recipeLogic.getPreviousRecipeDuration()) .addWorkingStatusLine(); } @Override - protected void addWarningText(List textList) { - MultiblockDisplayText.builder(textList, isStructureFormed(), false) - .addCustom(tl -> { - if (isStructureFormed()) { - IRotorHolder rotorHolder = getRotorHolder(); - if (rotorHolder.getRotorEfficiency() > 0) { - if (rotorHolder.getRotorDurabilityPercent() <= MIN_DURABILITY_TO_WARN) { - tl.add(TextComponentUtil.translationWithColor( - TextFormatting.YELLOW, - "gregtech.multiblock.turbine.rotor_durability_low")); - } - } - } - }) - .addLowDynamoTierLine(isDynamoTierTooLow()) - .addMaintenanceProblemLines(getMaintenanceProblems()); + protected void configureWarningText(MultiblockUIFactory.Builder builder) { + builder.addCustom(keyList -> { + if (!isStructureFormed() || getRotorHolder() == null) + return; + + int rotorEfficiency = getRotorHolder().getRotorEfficiency(); + int rotorDurability = getRotorHolder().getRotorDurabilityPercent(); + + if (rotorEfficiency > 0 && rotorDurability <= MIN_DURABILITY_TO_WARN) { + keyList.add(KeyUtil.lang(TextFormatting.YELLOW, + "gregtech.multiblock.turbine.rotor_durability_low")); + } + }); + super.configureWarningText(builder); } @Override - protected void addErrorText(List textList) { - super.addErrorText(textList); - if (isStructureFormed()) { + protected void configureErrorText(MultiblockUIFactory.Builder builder) { + builder.addCustom(keyList -> { + if (!isStructureFormed() || getRotorHolder() == null) + return; + if (!isRotorFaceFree()) { - textList.add(TextComponentUtil.translationWithColor(TextFormatting.RED, + keyList.add(KeyUtil.lang(TextFormatting.RED, "gregtech.multiblock.turbine.obstructed")); - textList.add(TextComponentUtil.translationWithColor(TextFormatting.GRAY, + keyList.add(KeyUtil.lang(TextFormatting.GRAY, "gregtech.multiblock.turbine.obstructed.desc")); } + int rotorEfficiency = getRotorHolder().getRotorEfficiency(); - IRotorHolder rotorHolder = getRotorHolder(); - if (rotorHolder.getRotorEfficiency() <= 0) { - textList.add(TextComponentUtil.translationWithColor(TextFormatting.RED, + if (rotorEfficiency <= 0) { + keyList.add(KeyUtil.lang(TextFormatting.RED, "gregtech.multiblock.turbine.no_rotor")); } - } + }); } @Override @@ -256,114 +261,153 @@ public boolean canVoidRecipeFluidOutputs() { } @Override - protected boolean shouldShowVoidingModeButton() { + public boolean shouldShowVoidingModeButton() { return false; } @Override - public int getNumProgressBars() { + public int getProgressBarCount() { return 3; } @Override - public double getFillPercentage(int index) { - if (index == 0) { - int[] fuelAmount = new int[2]; - if (getInputFluidInventory() != null) { - MultiblockFuelRecipeLogic recipeLogic = (MultiblockFuelRecipeLogic) recipeMapWorkable; - if (recipeLogic.getInputFluidStack() != null) { - FluidStack testStack = recipeLogic.getInputFluidStack().copy(); - testStack.amount = Integer.MAX_VALUE; - fuelAmount = getTotalFluidAmount(testStack, getInputFluidInventory()); - } + public @NotNull ProgressWidget createProgressBar(PanelSyncManager panelSyncManager, int index) { + return switch (index) { + case 0 -> { + FixedIntArraySyncValue fuelValue = new FixedIntArraySyncValue(this::getFuelAmount, null); + StringSyncValue fuelNameValue = new StringSyncValue(() -> { + FluidStack stack = ((MultiblockFuelRecipeLogic) recipeMapWorkable).getInputFluidStack(); + if (stack == null) { + return null; + } + Fluid fluid = stack.getFluid(); + if (fluid == null) { + return null; + } + return fluid.getName(); + }); + panelSyncManager.syncValue("fuel_amount", fuelValue); + panelSyncManager.syncValue("fuel_name", fuelNameValue); + + yield new ProgressWidget() + .progress(() -> fuelValue.getValue(1) == 0 ? 0 : + 1.0 * fuelValue.getValue(0) / fuelValue.getValue(1)) + .texture(GTGuiTextures.PROGRESS_BAR_LCE_FUEL, MultiblockUIFactory.Bars.THIRD_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> createFuelTooltip(t, fuelValue, fuelNameValue)); } - return fuelAmount[1] != 0 ? 1.0 * fuelAmount[0] / fuelAmount[1] : 0; - } else if (index == 1) { - IRotorHolder rotorHolder = getRotorHolder(); - return rotorHolder != null ? 1.0 * rotorHolder.getRotorSpeed() / rotorHolder.getMaxRotorHolderSpeed() : 0; - } else { - IRotorHolder rotorHolder = getRotorHolder(); - return rotorHolder != null ? 1.0 * rotorHolder.getRotorDurabilityPercent() / 100 : 0; - } - } - - @Override - public TextureArea getProgressBarTexture(int index) { - if (index == 0) { - return GuiTextures.PROGRESS_BAR_LCE_FUEL; - } else if (index == 1) { - return GuiTextures.PROGRESS_BAR_TURBINE_ROTOR_SPEED; - } else { - return GuiTextures.PROGRESS_BAR_TURBINE_ROTOR_DURABILITY; - } - } + case 1 -> { + IntSyncValue rotorSpeedValue = new IntSyncValue(() -> { + IRotorHolder rotorHolder = getRotorHolder(); + if (rotorHolder == null) { + return 0; + } + return rotorHolder.getRotorSpeed(); + }); - @Override - public void addBarHoverText(List hoverList, int index) { - if (index == 0) { - // Fuel - addFuelText(hoverList); - } else if (index == 1) { - // Rotor speed - IRotorHolder rotorHolder = getRotorHolder(); - if (rotorHolder == null || rotorHolder.getRotorEfficiency() <= 0) { - hoverList.add(TextComponentUtil.translationWithColor(TextFormatting.YELLOW, - "gregtech.multiblock.turbine.no_rotor")); - } else { - int rotorSpeed = rotorHolder.getRotorSpeed(); - int rotorMaxSpeed = rotorHolder.getMaxRotorHolderSpeed(); - ITextComponent rpmTranslated = TextComponentUtil.translationWithColor( - getRotorSpeedColor(rotorSpeed, rotorMaxSpeed), - "gregtech.multiblock.turbine.rotor_rpm_unit_name"); - ITextComponent rotorInfo = TextComponentUtil.translationWithColor( - getRotorSpeedColor(rotorSpeed, rotorMaxSpeed), - "%s / %s %s", - TextFormattingUtil.formatNumbers(rotorSpeed), - TextFormattingUtil.formatNumbers(rotorMaxSpeed), - rpmTranslated); - hoverList.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.turbine.rotor_speed", - rotorInfo)); + IntSyncValue rotorMaxSpeedValue = new IntSyncValue(() -> { + IRotorHolder rotorHolder = getRotorHolder(); + if (rotorHolder == null) { + return 0; + } + return rotorHolder.getMaxRotorHolderSpeed(); + }); + + panelSyncManager.syncValue("rotor_speed", rotorSpeedValue); + panelSyncManager.syncValue("rotor_max_speed", rotorMaxSpeedValue); + + yield new ProgressWidget() + .progress(() -> rotorMaxSpeedValue.getIntValue() == 0 ? 0 : + 1.0 * rotorSpeedValue.getIntValue() / rotorMaxSpeedValue.getIntValue()) + .texture(GTGuiTextures.PROGRESS_BAR_TURBINE_ROTOR_SPEED, MultiblockUIFactory.Bars.THIRD_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + int speed = rotorSpeedValue.getIntValue(); + int maxSpeed = rotorMaxSpeedValue.getIntValue(); + + t.addLine(KeyUtil.lang("gregtech.multiblock.turbine.rotor_speed", + getSpeedFormat(maxSpeed, speed), speed, maxSpeed)); + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); } - } else { - // Rotor durability - IRotorHolder rotorHolder = getRotorHolder(); - if (rotorHolder == null || rotorHolder.getRotorEfficiency() <= 0) { - // No rotor found - hoverList.add(TextComponentUtil.translationWithColor(TextFormatting.YELLOW, - "gregtech.multiblock.turbine.no_rotor")); - } else { - int rotorDurability = rotorHolder.getRotorDurabilityPercent(); - ITextComponent rotorInfo = TextComponentUtil.stringWithColor( - getRotorDurabilityColor(rotorDurability), - rotorDurability + "%"); - hoverList.add(TextComponentUtil.translationWithColor( - TextFormatting.GRAY, - "gregtech.multiblock.turbine.rotor_durability", - rotorInfo)); + case 2 -> { + IntSyncValue durabilityValue = new IntSyncValue(() -> { + IRotorHolder rotorHolder = getRotorHolder(); + if (rotorHolder == null) { + return 0; + } + return rotorHolder.getRotorDurabilityPercent(); + }); + IntSyncValue efficiencyValue = new IntSyncValue(() -> { + IRotorHolder rotorHolder = getRotorHolder(); + if (rotorHolder == null) { + return 0; + } + return rotorHolder.getRotorEfficiency(); + }); + + panelSyncManager.syncValue("rotor_durability", durabilityValue); + panelSyncManager.syncValue("rotor_efficiency", efficiencyValue); + + yield new ProgressWidget() + .progress(() -> durabilityValue.getIntValue() / 100.0) + .texture(GTGuiTextures.PROGRESS_BAR_TURBINE_ROTOR_DURABILITY, + MultiblockUIFactory.Bars.THIRD_WIDTH) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> { + if (isStructureFormed()) { + if (efficiencyValue.getIntValue() <= 0) { + t.addLine(IKey.lang("gregtech.multiblock.turbine.no_rotor")); + } else { + int durability = durabilityValue.getIntValue(); + // TODO working dynamic color substitutions into IKey.lang + if (durability > 40) { + t.addLine(IKey.lang("gregtech.multiblock.turbine.rotor_durability.high", + durability)); + } else if (durability > MIN_DURABILITY_TO_WARN) { + t.addLine(IKey.lang("gregtech.multiblock.turbine.rotor_durability.medium", + durability)); + } else { + t.addLine(IKey.lang("gregtech.multiblock.turbine.rotor_durability.low", + durability)); + } + } + } else { + t.addLine(IKey.lang("gregtech.multiblock.invalid_structure")); + } + }); } - } + default -> throw new IllegalStateException("Invalid index received " + index); + }; } - private TextFormatting getRotorDurabilityColor(int durability) { - if (durability > 40) { - return TextFormatting.GREEN; - } else if (durability > MIN_DURABILITY_TO_WARN) { - return TextFormatting.YELLOW; - } else { - return TextFormatting.RED; - } - } + private @NotNull TextFormatting getSpeedFormat(int maxSpeed, int speed) { + float percent = maxSpeed == 0 ? 0 : 1.0f * speed / maxSpeed; - private TextFormatting getRotorSpeedColor(int rotorSpeed, int maxRotorSpeed) { - double speedRatio = 1.0 * rotorSpeed / maxRotorSpeed; - if (speedRatio < 0.4) { + if (percent < 0.4) { return TextFormatting.RED; - } else if (speedRatio < 0.8) { + } else if (percent < 0.8) { return TextFormatting.YELLOW; } else { return TextFormatting.GREEN; } } + + /** + * @return an array of [fuel stored, fuel capacity] + */ + private int[] getFuelAmount() { + if (getInputFluidInventory() != null) { + MultiblockFuelRecipeLogic recipeLogic = (MultiblockFuelRecipeLogic) recipeMapWorkable; + if (recipeLogic.getInputFluidStack() != null) { + FluidStack testStack = recipeLogic.getInputFluidStack().copy(); + testStack.amount = Integer.MAX_VALUE; + return getTotalFluidAmount(testStack, getInputFluidInventory()); + } + } + return new int[2]; + } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityItemBus.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityItemBus.java index 37c145eab75..9d63999c234 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityItemBus.java @@ -40,10 +40,8 @@ import codechicken.lib.render.pipeline.IVertexOperation; import codechicken.lib.vec.Matrix4; import com.cleanroommc.modularui.api.drawable.IKey; -import com.cleanroommc.modularui.api.widget.IWidget; import com.cleanroommc.modularui.factory.PosGuiData; import com.cleanroommc.modularui.screen.ModularPanel; -import com.cleanroommc.modularui.value.BoolValue; import com.cleanroommc.modularui.value.sync.BooleanSyncValue; import com.cleanroommc.modularui.value.sync.PanelSyncManager; import com.cleanroommc.modularui.value.sync.SyncHandlers; @@ -269,40 +267,19 @@ public boolean usesMui2() { } @Override - public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager) { + public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager panelSyncManager) { int rowSize = (int) Math.sqrt(getInventorySize()); - guiSyncManager.registerSlotGroup("item_inv", rowSize); + panelSyncManager.registerSlotGroup("item_inv", rowSize); int backgroundWidth = Math.max( 9 * 18 + 18 + 14 + 5, // Player Inv width rowSize * 18 + 14); // Bus Inv width int backgroundHeight = 18 + 18 * rowSize + 94; - List> widgets = new ArrayList<>(); - for (int i = 0; i < rowSize; i++) { - widgets.add(new ArrayList<>()); - for (int j = 0; j < rowSize; j++) { - int index = i * rowSize + j; - IItemHandlerModifiable handler = isExportHatch ? exportItems : importItems; - widgets.get(i) - .add(new ItemSlot() - .slot(SyncHandlers.itemSlot(handler, index) - .slotGroup("item_inv") - .changeListener((newItem, onlyAmountChanged, client, init) -> { - if (onlyAmountChanged && - handler instanceof GTItemStackHandler gtHandler) { - gtHandler.onContentsChanged(index); - } - }) - .accessibility(!isExportHatch, true))); - } - } - BooleanSyncValue workingStateValue = new BooleanSyncValue(() -> workingEnabled, val -> workingEnabled = val); - guiSyncManager.syncValue("working_state", workingStateValue); BooleanSyncValue collapseStateValue = new BooleanSyncValue(() -> autoCollapse, val -> autoCollapse = val); - guiSyncManager.syncValue("collapse_state", collapseStateValue); + IItemHandlerModifiable handler = isExportHatch ? exportItems : importItems; boolean hasGhostCircuit = hasGhostCircuitInventory() && this.circuitInventory != null; return GTGuis.createPanel(this, backgroundWidth, backgroundHeight) @@ -313,33 +290,40 @@ public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager) .minElementMargin(0, 0) .minColWidth(18).minRowHeight(18) .alignX(0.5f) - .matrix(widgets)) + .mapTo(rowSize, rowSize * rowSize, index -> new ItemSlot() + .slot(SyncHandlers.itemSlot(handler, index) + .slotGroup("item_inv") + .changeListener((newItem, onlyAmountChanged, client, init) -> { + if (onlyAmountChanged && + handler instanceof GTItemStackHandler gtHandler) { + gtHandler.onContentsChanged(index); + } + }) + .accessibility(!isExportHatch, true)))) .child(Flow.column() .pos(backgroundWidth - 7 - 18, backgroundHeight - 18 * 4 - 7 - 5) .width(18).height(18 * 4 + 5) .child(GTGuiTextures.getLogo(getUITheme()).asWidget().size(17).top(18 * 3 + 5)) .child(new ToggleButton() .top(18 * 2) - .value(new BoolValue.Dynamic(workingStateValue::getBoolValue, - workingStateValue::setBoolValue)) + .value(workingStateValue) .overlay(GTGuiTextures.BUTTON_ITEM_OUTPUT) - .tooltipBuilder(t -> t.setAutoUpdate(true) - .addLine(isExportHatch ? - (workingStateValue.getBoolValue() ? - IKey.lang("gregtech.gui.item_auto_output.tooltip.enabled") : - IKey.lang("gregtech.gui.item_auto_output.tooltip.disabled")) : - (workingStateValue.getBoolValue() ? - IKey.lang("gregtech.gui.item_auto_input.tooltip.enabled") : - IKey.lang("gregtech.gui.item_auto_input.tooltip.disabled"))))) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> t.addLine(isExportHatch ? + (workingStateValue.getBoolValue() ? + IKey.lang("gregtech.gui.item_auto_output.tooltip.enabled") : + IKey.lang("gregtech.gui.item_auto_output.tooltip.disabled")) : + (workingStateValue.getBoolValue() ? + IKey.lang("gregtech.gui.item_auto_input.tooltip.enabled") : + IKey.lang("gregtech.gui.item_auto_input.tooltip.disabled"))))) .child(new ToggleButton() .top(18) - .value(new BoolValue.Dynamic(collapseStateValue::getBoolValue, - collapseStateValue::setBoolValue)) + .value(collapseStateValue) .overlay(GTGuiTextures.BUTTON_AUTO_COLLAPSE) - .tooltipBuilder(t -> t.setAutoUpdate(true) - .addLine(collapseStateValue.getBoolValue() ? - IKey.lang("gregtech.gui.item_auto_collapse.tooltip.enabled") : - IKey.lang("gregtech.gui.item_auto_collapse.tooltip.disabled")))) + .tooltipAutoUpdate(true) + .tooltipBuilder(t -> t.addLine(collapseStateValue.getBoolValue() ? + IKey.lang("gregtech.gui.item_auto_collapse.tooltip.enabled") : + IKey.lang("gregtech.gui.item_auto_collapse.tooltip.disabled")))) .childIf(hasGhostCircuit, new GhostCircuitSlotWidget() .slot(SyncHandlers.itemSlot(circuitInventory, 0)) .background(GTGuiTextures.SLOT, GTGuiTextures.INT_CIRCUIT_OVERLAY)) diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityMufflerHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityMufflerHatch.java index 3788ac57732..f3954e39dbb 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityMufflerHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityMufflerHatch.java @@ -1,6 +1,7 @@ package gregtech.common.metatileentities.multi.multiblockpart; import gregtech.api.GTValues; +import gregtech.api.capability.GregtechDataCodes; import gregtech.api.capability.IMufflerHatch; import gregtech.api.items.itemhandlers.GTItemStackHandler; import gregtech.api.metatileentity.ITieredMetaTileEntity; @@ -21,6 +22,7 @@ import net.minecraft.client.resources.I18n; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.network.PacketBuffer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -49,6 +51,7 @@ public class MetaTileEntityMufflerHatch extends MetaTileEntityMultiblockPart implements IMultiblockAbilityPart, ITieredMetaTileEntity, IMufflerHatch { + private static final int MUFFLER_OBSTRUCTED = GregtechDataCodes.assignId(); private final int recoveryChance; private final GTItemStackHandler inventory; @@ -71,8 +74,13 @@ public void update() { super.update(); if (!getWorld().isRemote) { - if (getOffsetTimer() % 10 == 0) - this.frontFaceFree = checkFrontFaceFree(); + if (getOffsetTimer() % 10 == 0) { + boolean frontFaceFree = checkFrontFaceFree(); + if (frontFaceFree != this.frontFaceFree) { + this.frontFaceFree = frontFaceFree; + writeCustomData(MUFFLER_OBSTRUCTED, buffer -> buffer.writeBoolean(this.frontFaceFree)); + } + } } if (getWorld().isRemote && getController() instanceof MultiblockWithDisplayBase controller && @@ -120,6 +128,26 @@ private boolean checkFrontFaceFree() { return blockState.getBlock().isAir(blockState, getWorld(), frontPos) || GTUtility.isBlockSnow(blockState); } + @Override + public void writeInitialSyncData(PacketBuffer buf) { + super.writeInitialSyncData(buf); + buf.writeBoolean(this.frontFaceFree); + } + + @Override + public void receiveInitialSyncData(PacketBuffer buf) { + super.receiveInitialSyncData(buf); + this.frontFaceFree = buf.readBoolean(); + } + + @Override + public void receiveCustomData(int dataId, PacketBuffer buf) { + super.receiveCustomData(dataId, buf); + if (dataId == MUFFLER_OBSTRUCTED) { + this.frontFaceFree = buf.readBoolean(); + } + } + /** @deprecated No longer needed. Multiblock controller sets the particle type. */ @Deprecated @ApiStatus.ScheduledForRemoval(inVersion = "2.9") diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCABridge.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCABridge.java index 9af74c4227b..f49e6f19287 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCABridge.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCABridge.java @@ -5,11 +5,14 @@ import gregtech.api.gui.resources.TextureArea; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; +import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; import net.minecraft.util.ResourceLocation; +import com.cleanroommc.modularui.drawable.UITexture; + public class MetaTileEntityHPCABridge extends MetaTileEntityHPCAComponent { public MetaTileEntityHPCABridge(ResourceLocation metaTileEntityId) { @@ -41,6 +44,11 @@ public TextureArea getComponentIcon() { return GuiTextures.HPCA_ICON_BRIDGE_COMPONENT; } + @Override + public UITexture getComponentIcon2() { + return GTGuiTextures.HPCA_ICON_BRIDGE_COMPONENT; + } + @Override public SimpleOverlayRenderer getFrontActiveOverlay() { return Textures.HPCA_BRIDGE_ACTIVE_OVERLAY; diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCAComputation.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCAComputation.java index a27376901c9..2c9eadb5ff8 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCAComputation.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCAComputation.java @@ -6,11 +6,14 @@ import gregtech.api.gui.resources.TextureArea; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; +import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; import net.minecraft.util.ResourceLocation; +import com.cleanroommc.modularui.drawable.UITexture; + public class MetaTileEntityHPCAComputation extends MetaTileEntityHPCAComponent implements IHPCAComputationProvider { private final boolean advanced; @@ -46,6 +49,16 @@ public TextureArea getComponentIcon() { GuiTextures.HPCA_ICON_COMPUTATION_COMPONENT; } + @Override + public UITexture getComponentIcon2() { + if (isDamaged()) { + return advanced ? GTGuiTextures.HPCA_ICON_DAMAGED_ADVANCED_COMPUTATION_COMPONENT : + GTGuiTextures.HPCA_ICON_DAMAGED_COMPUTATION_COMPONENT; + } + return advanced ? GTGuiTextures.HPCA_ICON_ADVANCED_COMPUTATION_COMPONENT : + GTGuiTextures.HPCA_ICON_COMPUTATION_COMPONENT; + } + @Override public SimpleOverlayRenderer getFrontActiveOverlay() { if (isDamaged()) diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCACooler.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCACooler.java index 90d00239f88..fe5aa72cbd9 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCACooler.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/hpca/MetaTileEntityHPCACooler.java @@ -6,11 +6,14 @@ import gregtech.api.gui.resources.TextureArea; import gregtech.api.metatileentity.MetaTileEntity; import gregtech.api.metatileentity.interfaces.IGregTechTileEntity; +import gregtech.api.mui.GTGuiTextures; import gregtech.client.renderer.texture.Textures; import gregtech.client.renderer.texture.cube.SimpleOverlayRenderer; import net.minecraft.util.ResourceLocation; +import com.cleanroommc.modularui.drawable.UITexture; + public class MetaTileEntityHPCACooler extends MetaTileEntityHPCAComponent implements IHPCACoolantProvider { private final boolean advanced; @@ -40,6 +43,11 @@ public TextureArea getComponentIcon() { return advanced ? GuiTextures.HPCA_ICON_ACTIVE_COOLER_COMPONENT : GuiTextures.HPCA_ICON_HEAT_SINK_COMPONENT; } + @Override + public UITexture getComponentIcon2() { + return advanced ? GTGuiTextures.HPCA_ICON_ACTIVE_COOLER_COMPONENT : GTGuiTextures.HPCA_ICON_HEAT_SINK_COMPONENT; + } + @Override public SimpleOverlayRenderer getFrontActiveOverlay() { return advanced ? Textures.HPCA_ACTIVE_COOLER_ACTIVE_OVERLAY : getFrontOverlay(); diff --git a/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamItemBus.java b/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamItemBus.java index 56b15d8c93f..cf20e2dedd3 100644 --- a/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamItemBus.java +++ b/src/main/java/gregtech/common/metatileentities/steam/multiblockpart/MetaTileEntitySteamItemBus.java @@ -86,8 +86,8 @@ public void renderMetaTileEntity(CCRenderState renderState, Matrix4 translation, } @Override - public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager) { - guiSyncManager.registerSlotGroup("item_inv", 2); + public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager panelSyncManager) { + panelSyncManager.registerSlotGroup("item_inv", 2); List> widgets = new ArrayList<>(); for (int i = 0; i < 2; i++) { diff --git a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java index 1f00f06818b..6b2468f5836 100644 --- a/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java +++ b/src/main/java/gregtech/common/metatileentities/storage/MetaTileEntityCrate.java @@ -140,8 +140,8 @@ public boolean usesMui2() { } @Override - public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager guiSyncManager) { - guiSyncManager.registerSlotGroup("item_inv", rowSize); + public ModularPanel buildUI(PosGuiData guiData, PanelSyncManager panelSyncManager) { + panelSyncManager.registerSlotGroup("item_inv", rowSize); int rows = inventorySize / rowSize; List> widgets = new ArrayList<>(); diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 56a674d293b..934cc7407a0 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -4866,13 +4866,8 @@ gregtech.machine.miner.multi.production=Produces §f3x§7 more crushed ore than gregtech.machine.miner.fluid_usage=Uses §f%,d L/t §7of §f%s§7, doubled per overclock. gregtech.machine.miner.multi.description=A multiblock mining machine that covers a large area and produces huge quantity of ore. gregtech.machine.miner.multi.needsfluid=No Drilling Fluid! - -gregtech.machine.miner.startx=sX: %d -gregtech.machine.miner.starty=sY: %d -gregtech.machine.miner.startz=sZ: %d -gregtech.machine.miner.minex=mX: %d -gregtech.machine.miner.miney=mY: %d -gregtech.machine.miner.minez=mZ: %d +gregtech.machine.miner.mining_at=Currently mining at: +gregtech.machine.miner.mining_pos=X: %s Y: %s Z: %s gregtech.machine.miner.radius=Radius: %d gregtech.machine.miner.working_area=Working Area: %dx%d blocks gregtech.machine.miner.working_area_chunks=Working Area: %dx%d chunks @@ -4964,13 +4959,14 @@ gregtech.multiblock.high_performance_computing_array.description=The High Perfor gregtech.machine.central_monitor.name=Central Monitor gregtech.multiblock.central_monitor.low_power=Low Power -gregtech.multiblock.central_monitor.height=Screen Height: +gregtech.multiblock.central_monitor.height=Screen Height: %d gregtech.multiblock.central_monitor.width=Screen Width: %d gregtech.multiblock.central_monitor.height_modify=Modify Height: %d gregtech.multiblock.central_monitor.tooltip.1=This is a machine that monitors machines proxied by the Digital Interface Cover. You can easily monitor the Fluids, Items, Energy, and States of machines proxied in Energy Network. gregtech.multiblock.central_monitor.tooltip.2=You can build the central monitor screen from 3X2 to %dX%d (width X height). gregtech.multiblock.central_monitor.tooltip.3=The default height is 3. You can adjust the screen height in the GUI before the structure is formed. gregtech.multiblock.central_monitor.tooltip.4=Energy consumption: %d EU/s for each screen. +gregtech.multiblock.central_monitor.button_tooltip=Left click to increase height, right click to decrease height. Middle click to reset gregtech.multiblock.monitor_screen.tooltip.1=The GUI can be opened with a right-click of a screwdriver. gregtech.multiblock.monitor_screen.tooltip.2=The proxy mode of Digital Interface Cover can delegate machines' capabilities and GUI. (Yes, you can connect pipes directly on the screen.) gregtech.multiblock.monitor_screen.tooltip.3=The screen also supports plugins. @@ -5596,10 +5592,10 @@ gregtech.gui.fluid_voiding.tooltip.enabled=Excess Fluid Voiding Enabled gregtech.gui.fluid_voiding.tooltip.disabled=Excess Fluid Voiding Disabled gregtech.gui.item_voiding.tooltip.enabled=Excess Item Voiding Enabled gregtech.gui.item_voiding.tooltip.disabled=Excess Item Voiding Disabled -gregtech.gui.multiblock_item_voiding=Voiding Mode/n§7Voiding §6Items -gregtech.gui.multiblock_fluid_voiding=Voiding Mode/n§7Voiding §9Fluids -gregtech.gui.multiblock_item_fluid_voiding=Voiding Mode/n§7Voiding §6Items §7and §9Fluids -gregtech.gui.multiblock_no_voiding=Voiding Mode/n§7Voiding Nothing +gregtech.gui.multiblock_item_voiding=Voiding Mode\n§7Voiding §6Items +gregtech.gui.multiblock_fluid_voiding=Voiding Mode\n§7Voiding §9Fluids +gregtech.gui.multiblock_item_fluid_voiding=Voiding Mode\n§7Voiding §6Items §7and §9Fluids +gregtech.gui.multiblock_no_voiding=Voiding Mode\n§7Voiding Nothing gregtech.gui.multiblock_voiding_not_supported=This Multiblock does not support Voiding Mode gregtech.gui.me_network.online=Network Status: §2Online§r gregtech.gui.me_network.offline=Network Status: §4Offline§r @@ -5735,7 +5731,7 @@ gregtech.multiblock.idling=Idling. gregtech.multiblock.not_enough_energy=Machine needs more energy! gregtech.multiblock.not_enough_energy_output=Energy Dynamo Tier Too Low! gregtech.multiblock.progress=Progress: %s%% -gregtech.multiblock.invalid_structure=Invalid structure. +gregtech.multiblock.invalid_structure=§cInvalid structure. gregtech.multiblock.invalid_structure.tooltip=This block is a controller of the multiblock structure. For building help, see structure template in JEI. gregtech.multiblock.validation_failed=Invalid amount of inputs/outputs. gregtech.multiblock.max_energy_per_tick=Max EU/t: %s (%s) @@ -5755,16 +5751,17 @@ gregtech.multiblock.universal.problem.wire_cutter=Wires burned out. (Wire Cutter gregtech.multiblock.universal.problem.crowbar=That doesn't belong there. (Crowbar) gregtech.multiblock.universal.muffler_obstructed=Muffler Hatch is Obstructed! gregtech.multiblock.universal.muffler_obstructed_desc=Muffler Hatch must have a block of airspace in front of it. -gregtech.multiblock.universal.distinct_enabled=Distinct Buses: §aEnabled§r/nEach Item Input Bus will be treated separately for recipe lookup. Useful for things like Programmed Circuits, Extruder Shapes, etc. -gregtech.multiblock.universal.distinct_disabled=Distinct Buses: §cDisabled§r/nEach Item Input Bus will be treated as a combined input for recipe lookup. +gregtech.multiblock.universal.distinct_enabled=Distinct Buses: §aEnabled§r\nEach Item Input Bus will be treated separately for recipe lookup. Useful for things like Programmed Circuits, Extruder Shapes, etc. +gregtech.multiblock.universal.distinct_disabled=Distinct Buses: §cDisabled§r\nEach Item Input Bus will be treated as a combined input for recipe lookup. gregtech.multiblock.universal.distinct_not_supported=This Multiblock does not support Distinct Buses gregtech.multiblock.universal.no_flex_button=This Multiblock has no additional functionality with this Button. gregtech.multiblock.parallel=Max Parallels: %s gregtech.multiblock.multiple_recipemaps.header=Machine Mode: +gregtech.multiblock.multiple_recipemaps.value=Machine Mode: %s gregtech.multiblock.multiple_recipemaps.tooltip=Screwdriver the controller to change which machine mode to use. gregtech.multiblock.multiple_recipemaps_recipes.tooltip=Machine Modes: §e%s§r gregtech.multiblock.multiple_recipemaps.switch_message=The machine must be off to switch modes! -gregtech.multiblock.energy_stored=Energy: %s +gregtech.multiblock.energy_stored=§7Energy: §e%,d / %,d EU gregtech.multiblock.preview.zoom=Use mousewheel or right-click + drag to zoom gregtech.multiblock.preview.rotate=Click and drag to rotate @@ -5794,15 +5791,17 @@ gregtech.multiblock.multi_furnace.heating_coil_discount_hover=Energy usage modif gregtech.multiblock.multi_furnace.parallel_hover=Multi Smelter Parallels, determined by coil tier gregtech.multiblock.distillation_tower.distilling_fluid=Distilling %s -gregtech.multiblock.large_combustion_engine.fuel_amount=Fuel: %s -gregtech.multiblock.large_combustion_engine.no_lubricant=No Lubricant! -gregtech.multiblock.large_combustion_engine.lubricant_amount=Lubricant: %s -gregtech.multiblock.large_combustion_engine.oxygen_amount=Oxygen: %s -gregtech.multiblock.large_combustion_engine.liquid_oxygen_amount=Liquid Oxygen: %s +gregtech.multiblock.large_combustion_engine.fuel_none=§cNo Fuel! +gregtech.multiblock.large_combustion_engine.fuel_amount=§7Fuel: %,d / %,d L (§6%s§7) +gregtech.multiblock.large_combustion_engine.no_lubricant=§cNo Lubricant! +gregtech.multiblock.large_combustion_engine.lubricant_amount=§7Lubricant: §6%,d / %,d L +gregtech.multiblock.large_combustion_engine.oxygen_none=§cNo Booster! +gregtech.multiblock.large_combustion_engine.oxygen_amount=Oxygen: §b%,d / %,d L +gregtech.multiblock.large_combustion_engine.liquid_oxygen_amount=Liquid Oxygen: §b%,d / %,d L gregtech.multiblock.large_combustion_engine.oxygen_boosted=Oxygen boosted. gregtech.multiblock.large_combustion_engine.liquid_oxygen_boosted=Liquid Oxygen boosted. -gregtech.multiblock.large_combustion_engine.oxygen_boost_disallowed=Upgrade the Dynamo Hatch to enable Oxygen Boosting. -gregtech.multiblock.large_combustion_engine.liquid_oxygen_boost_disallowed=Upgrade the Dynamo Hatch to enable Liquid Oxygen Boosting. +gregtech.multiblock.large_combustion_engine.oxygen_boost_disallowed=§eUpgrade the Dynamo Hatch to enable Oxygen Boosting. +gregtech.multiblock.large_combustion_engine.liquid_oxygen_boost_disallowed=§eUpgrade the Dynamo Hatch to enable Liquid Oxygen Boosting. gregtech.multiblock.large_combustion_engine.supply_oxygen_to_boost=Supply Oxygen to boost. gregtech.multiblock.large_combustion_engine.supply_liquid_oxygen_to_boost=Supply Liquid Oxygen to boost. gregtech.multiblock.large_combustion_engine.obstructed=Engine Intakes Obstructed! @@ -5810,11 +5809,11 @@ gregtech.multiblock.large_combustion_engine.obstructed.desc=Engine Intakes must gregtech.multiblock.turbine.fuel_amount=Fuel: %sL %s gregtech.multiblock.turbine.fuel_needed=Consumes %s per %s ticks -gregtech.multiblock.turbine.rotor_speed=Rotor Speed: %s -gregtech.multiblock.turbine.rotor_rpm_unit_name=RPM -gregtech.multiblock.turbine.rotor_durability=Rotor Durability: %s -gregtech.multiblock.turbine.rotor_durability_low=Rotor durability low! -gregtech.multiblock.turbine.no_rotor=No Rotor in Rotor Holder! +gregtech.multiblock.turbine.rotor_speed=§7Rotor Speed: %s%,d / %,d RPM +gregtech.multiblock.turbine.rotor_durability.high=§7Rotor Durability: §a%,d%% +gregtech.multiblock.turbine.rotor_durability.medium=§7Rotor Durability: §e%,d%% +gregtech.multiblock.turbine.rotor_durability.low=§cRotor durability low! +gregtech.multiblock.turbine.no_rotor=§eNo Rotor in Rotor Holder! gregtech.multiblock.turbine.efficiency=Turbine Efficiency: %s gregtech.multiblock.turbine.energy_per_tick=Output EU/t: %s (%s) gregtech.multiblock.turbine.obstructed=Turbine Face Obstructed! @@ -5824,14 +5823,15 @@ gregtech.multiblock.turbine.efficiency_tooltip=Each Rotor Holder above %s§7 add gregtech.multiblock.large_boiler.efficiency=Efficiency: %s gregtech.multiblock.large_boiler.steam_output=Steam Output: %s gregtech.multiblock.large_boiler.throttle=Throttle: %s +gregtech.multiblock.large_boiler.throttle.title=Boiler Throttle gregtech.multiblock.large_boiler.throttle.tooltip=Boiler can output less Steam and consume less fuel (efficiency is not lost, does not affect heat-up time) gregtech.multiblock.large_boiler.throttle_increment=Increase throttle by §a+5%%§r/n§7Boiler can output less Steam and consume less fuel (efficiency is not lost, does not affect heat-up time) gregtech.multiblock.large_boiler.throttle_decrement=Decrease throttle by §c-5%%§r/n§7Boiler can output less Steam and consume less fuel (efficiency is not lost, does not affect heat-up time) gregtech.multiblock.large_boiler.rate_tooltip=§7Produces §f%d L §7of Steam with §f1 Coal gregtech.multiblock.large_boiler.heat_time_tooltip=§7Takes §f%,d seconds §7to heat up gregtech.multiblock.large_boiler.explosion_tooltip=Will explode if provided Fuel with no Water -gregtech.multiblock.large_boiler.water_bar_hover=Water: %s -gregtech.multiblock.large_boiler.no_water=No Water! +gregtech.multiblock.large_boiler.water_bar_hover=§7Water: §9%,d / %,d L +gregtech.multiblock.large_boiler.no_water=§eNo Water! gregtech.machine.miner.done=Done! gregtech.machine.miner.working=Working... @@ -5849,8 +5849,10 @@ gregtech.multiblock.miner.both_modes=Chunk Mode: §aEnabled§r/nSilk Touch Mode: gregtech.multiblock.fluid_rig.drilled_fluid=Fluid: %s gregtech.multiblock.fluid_rig.no_fluid_in_area=None in Area. gregtech.multiblock.fluid_rig.fluid_amount=Pumping Rate: %s -gregtech.multiblock.fluid_rig.vein_depletion=Vein Size: %s -gregtech.multiblock.fluid_rig.vein_depleted=Vein Depleted. +gregtech.multiblock.fluid_rig.vein_depletion.high=§7Vein Size: §a%,d%% +gregtech.multiblock.fluid_rig.vein_depletion.medium=§7Vein Size: §e%,d%% +gregtech.multiblock.fluid_rig.vein_depletion.low=§7Vein Size: §c%,d%% +gregtech.multiblock.fluid_rig.vein_depleted=§cVein Depleted. gregtech.multiblock.miner.drilling=Drilling. gregtech.multiblock.pyrolyse_oven.speed=Processing Speed: %s @@ -5885,9 +5887,11 @@ gregtech.multiblock.power_substation.under_one_hour_left=Less than 1 hour until gregtech.multiblock.data_bank.providing=Providing data. -gregtech.multiblock.hpca.computation=Providing: %s +gregtech.multiblock.hpca.computation=§7Providing: §b%,d / %,d CWU/t gregtech.multiblock.hpca.energy=Using: %s / %s EU/t (%s) -gregtech.multiblock.hpca.temperature=Temperature: %s +gregtech.multiblock.hpca.temperature.high=§7Temperature: §c%,d°C +gregtech.multiblock.hpca.temperature.medium=§7Temperature: §e%,d°C +gregtech.multiblock.hpca.temperature.low=§7Temperature: §a%,d°C gregtech.multiblock.hpca.hover_for_info=Hover for details gregtech.multiblock.hpca.error_damaged=Damaged component in structure! gregtech.multiblock.hpca.error_temperature=Temperature above 100C, components may be damaged! diff --git a/src/main/resources/assets/gregtech/textures/gui/progress_bar/fusion_diagram/stitched.png b/src/main/resources/assets/gregtech/textures/gui/progress_bar/fusion_diagram/stitched.png new file mode 100644 index 00000000000..8ba66f3caca Binary files /dev/null and b/src/main/resources/assets/gregtech/textures/gui/progress_bar/fusion_diagram/stitched.png differ