diff --git a/src/main/java/appeng/block/AEBaseItemBlockChargeable.java b/src/main/java/appeng/block/AEBaseItemBlockChargeable.java index 918f4db2998..579f25d384b 100644 --- a/src/main/java/appeng/block/AEBaseItemBlockChargeable.java +++ b/src/main/java/appeng/block/AEBaseItemBlockChargeable.java @@ -21,11 +21,10 @@ import appeng.api.config.AccessRestriction; import appeng.api.config.Actionable; -import appeng.api.config.PowerUnits; import appeng.api.definitions.IBlockDefinition; import appeng.api.implementations.items.IAEItemPowerStorage; import appeng.core.Api; -import appeng.core.localization.GuiText; +import appeng.core.localization.Tooltips; import appeng.util.Platform; import net.minecraft.block.Block; import net.minecraft.client.util.ITooltipFlag; @@ -35,7 +34,6 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import java.text.MessageFormat; import java.util.List; @@ -57,10 +55,7 @@ public void addCheckedInformation(final ItemStack stack, final World world, fina internalCurrentPower = tag.getDouble("internalCurrentPower"); } - final double percent = internalCurrentPower / internalMaxPower; - - lines.add(GuiText.StoredEnergy.getLocal() + ':' + MessageFormat.format(" {0,number,#} ", internalCurrentPower) + Platform - .gui_localize(PowerUnits.AE.unlocalizedName) + " - " + MessageFormat.format(" {0,number,#.##%} ", percent)); + lines.add(Tooltips.energyStorageComponent(internalCurrentPower, internalMaxPower).getFormattedText()); } } diff --git a/src/main/java/appeng/core/api/ApiClientHelper.java b/src/main/java/appeng/core/api/ApiClientHelper.java index 9cbb87203ae..3ee1094bc94 100644 --- a/src/main/java/appeng/core/api/ApiClientHelper.java +++ b/src/main/java/appeng/core/api/ApiClientHelper.java @@ -13,6 +13,7 @@ import appeng.api.util.IClientHelper; import appeng.core.AEConfig; import appeng.core.localization.GuiText; +import appeng.core.localization.Tooltips; import appeng.fluids.items.FluidDummyItem; import appeng.fluids.util.AEFluidStack; import appeng.util.ReadableNumberConverter; @@ -44,10 +45,9 @@ public > void addCellInformation(ICellInventoryHandler final ICellInventory cellInventory = handler.getCellInv(); if (cellInventory != null) { - lines.add(cellInventory.getUsedBytes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalBytes() + ' ' + GuiText.BytesUsed.getLocal()); + lines.add(Tooltips.bytesUsed(cellInventory.getUsedBytes(),cellInventory.getTotalBytes()).getFormattedText()); - lines.add(cellInventory.getStoredItemTypes() + " " + GuiText.Of.getLocal() + ' ' + cellInventory.getTotalItemTypes() + ' ' + GuiText.Types - .getLocal()); + lines.add(Tooltips.typesUsed(cellInventory.getStoredItemTypes(),cellInventory.getTotalItemTypes()).getFormattedText()); } IItemList itemList = cellInventory.getChannel().createList(); diff --git a/src/main/java/appeng/core/localization/GuiText.java b/src/main/java/appeng/core/localization/GuiText.java index d7545a6dd8b..c03fb6d932f 100644 --- a/src/main/java/appeng/core/localization/GuiText.java +++ b/src/main/java/appeng/core/localization/GuiText.java @@ -19,6 +19,8 @@ package appeng.core.localization; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.util.text.translation.I18n; @@ -223,6 +225,10 @@ public String getLocal() { return I18n.translateToLocal(this.getUnlocalized()); } + public ITextComponent getLocalizedWithArgs(Object... args) { + return new TextComponentTranslation(this.getUnlocalized(), args); + } + public String getUnlocalized() { return this.root + '.' + this; } diff --git a/src/main/java/appeng/core/localization/Tooltips.java b/src/main/java/appeng/core/localization/Tooltips.java new file mode 100644 index 00000000000..8a47713351b --- /dev/null +++ b/src/main/java/appeng/core/localization/Tooltips.java @@ -0,0 +1,203 @@ +package appeng.core.localization; + +import appeng.api.config.PowerUnits; +import com.github.bsideup.jabel.Desugar; +import net.minecraft.util.text.*; + +import java.text.DecimalFormat; +import java.text.MessageFormat; +import java.util.Arrays; + +/** + * Static utilities for constructing tooltips in various places. + */ +public final class Tooltips { + + private static final char SEP; + static { + var format = (DecimalFormat) DecimalFormat.getInstance(); + var symbols = format.getDecimalFormatSymbols(); + SEP = symbols.getDecimalSeparator(); + } + + public static final Style UNIT_TEXT = new Style().setColor(TextFormatting.YELLOW).setItalic(false); + public static final Style NORMAL_TOOLTIP_TEXT = new Style().setColor(TextFormatting.GRAY).setItalic(false); + public static final Style NUMBER_TEXT = new Style().setColor(TextFormatting.LIGHT_PURPLE).setItalic(false); + + + public static final String[] units = new String[] { "k", "M", "G", "T", "P", "E" }; + public static final long[] DECIMAL_NUMS = new long[] { 1000L, 1000_000L, 1000_000_000L, 1000_000_000_000L, + 1000_000_000_000_000L, + 1000_000_000_000_000_000L }; + + public static ITextComponent of(ITextComponent... components) { + ITextComponent s = new TextComponentString(""); + for (var c : components) { + s = s.appendSibling(c); + } + return s; + } + + public static ITextComponent of(String s) { + return new TextComponentString(s); + } + + public static ITextComponent ofPercent(double percent) { + return ofPercent(percent,true); + } + + public static ITextComponent ofPercent(double percent, boolean oneIsGreen) { + return new TextComponentString(MessageFormat.format("{0,number,#.##%}", percent)) + .setStyle(colorFromRatio(percent, oneIsGreen)); + } + + public static ITextComponent of(PowerUnits pU) { + return new TextComponentTranslation(pU.unlocalizedName).setStyle(UNIT_TEXT); + } + + public static ITextComponent ofNumber(double number, double max) { + MaxedAmount amount = getMaxedAmount(number, max); + return ofNumber(amount); + } + + public static ITextComponent of(GuiText guiText, Object... args) { + return of(guiText, NORMAL_TOOLTIP_TEXT, args); + } + + public static ITextComponent of(GuiText guiText, Style style, Object... args) { + + if (args.length > 0 && args[0] instanceof Integer) { + return guiText.getLocalizedWithArgs(Arrays.stream(args).map((o) -> ofUnformattedNumber((Integer) o)).toArray()).createCopy() + .setStyle(style); + } else if (args.length > 0 && args[0] instanceof Long) { + return guiText.getLocalizedWithArgs(Arrays.stream(args).map((o) -> ofUnformattedNumber((Long) o)).toArray()).createCopy() + .setStyle(style); + } + return guiText.getLocalizedWithArgs(args).createCopy().setStyle(style); + + } + + public static ITextComponent ofUnformattedNumber(long number) { + return new TextComponentString(String.valueOf(number)).setStyle(NUMBER_TEXT); + } + + public static ITextComponent ofUnformattedNumberWithRatioColor(long number, double ratio, boolean oneIsGreen) { + return new TextComponentString(String.valueOf(number)).setStyle(colorFromRatio(ratio, oneIsGreen)); + } + + private static ITextComponent ofNumber(MaxedAmount number) { + boolean numberUnit = !number.digit().equals("0"); + return new TextComponentString(number.digit() + (numberUnit ? number.unit() : "")).setStyle(NUMBER_TEXT) + .appendSibling(new TextComponentString("/") + .setStyle(NORMAL_TOOLTIP_TEXT)) + .appendText(number.maxDigit() + number.unit()).setStyle(NUMBER_TEXT); + } + @Desugar + public record MaxedAmount(String digit, String maxDigit, String unit) { + } + + @Desugar + public record Amount(String digit, String unit) { + } + + public static Style colorFromRatio(double ratio, boolean oneIsGreen) { + double p = ratio; + + if (!oneIsGreen) { + p = 1 - p; + } + + TextFormatting colorCode = getColorCode(p); + + return new Style().setItalic(false).setColor(colorCode); + } + + public static String getAmount(double amount, long num) { + double fract = amount / num; + String returned; + if (fract < 10) { + returned = String.format("%.3f", fract); + } else if (fract < 100) { + returned = String.format("%.2f", fract); + } else { + returned = String.format("%.1f", fract); + } + while (returned.endsWith("0")) { + returned = returned.substring(0, returned.length() - 1); + } + if (returned.endsWith(String.valueOf(SEP))) { + returned = returned.substring(0, returned.length() - 1); + } + return returned; + + } + + public static Amount getAmount(double amount) { + if (amount < 10000) { + return new Amount(getAmount(amount, 1), ""); + } else { + int i = 0; + while (amount / DECIMAL_NUMS[i] >= 1000) { + i++; + } + return new Amount(getAmount(amount, DECIMAL_NUMS[i]), units[i]); + } + } + + public static MaxedAmount getMaxedAmount(double amount, double max) { + if (max < 10000) { + return new MaxedAmount(getAmount(amount, 1), getAmount(max, 1), ""); + } else { + int i = 0; + while (max / DECIMAL_NUMS[i] >= 1000) { + i++; + } + return new MaxedAmount(getAmount(amount, DECIMAL_NUMS[i]), getAmount(max, DECIMAL_NUMS[i]), units[i]); + } + } + + private static TextFormatting getColorCode(double p) { + if (p < 0.33) { + return TextFormatting.RED; + } else if (p < 0.66) { + return TextFormatting.YELLOW; + } else { + return TextFormatting.GREEN; + } + } + + public static ITextComponent energyStorageComponent(double energy, double max) { + return Tooltips.of( + Tooltips.of(GuiText.StoredEnergy.getLocal()), + Tooltips.of(": "), + Tooltips.ofNumber(energy, max), + Tooltips.of(" "), + Tooltips.of(PowerUnits.AE), + Tooltips.of(" ("), + Tooltips.ofPercent(energy / max), + Tooltips.of(")")); + } + + public static ITextComponent bytesUsed(long bytes, long max) { + return of( + Tooltips.of( + ofUnformattedNumberWithRatioColor(bytes, (double) bytes / max, false), + of(" "), + of(GuiText.Of), + of(" "), + ofUnformattedNumber(max), + of(" "), + of(GuiText.BytesUsed))); + } + + public static ITextComponent typesUsed(long types, long max) { + return Tooltips.of( + ofUnformattedNumberWithRatioColor(types, (double) types / max, false), + of(" "), + of(GuiText.Of), + of(" "), + ofUnformattedNumber(max), + of(" "), + of(GuiText.Types)); + } +} diff --git a/src/main/java/appeng/items/tools/powered/ToolWirelessTerminal.java b/src/main/java/appeng/items/tools/powered/ToolWirelessTerminal.java index 06b995a7dac..d1d97b3456d 100644 --- a/src/main/java/appeng/items/tools/powered/ToolWirelessTerminal.java +++ b/src/main/java/appeng/items/tools/powered/ToolWirelessTerminal.java @@ -20,13 +20,7 @@ import appeng.api.AEApi; -import appeng.api.config.Actionable; -import appeng.api.config.FuzzyMode; -import appeng.api.config.Settings; -import appeng.api.config.SortDir; -import appeng.api.config.SortOrder; -import appeng.api.config.Upgrades; -import appeng.api.config.ViewItems; +import appeng.api.config.*; import appeng.api.features.IWirelessTermHandler; import appeng.api.util.IConfigManager; import appeng.core.AEConfig; @@ -51,7 +45,7 @@ import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.translation.I18n; import net.minecraft.world.World; import net.minecraftforge.fml.common.Optional; @@ -95,9 +89,9 @@ public void addCheckedInformation(final ItemStack stack, final World world, fina final String encKey = tag.getString("encryptionKey"); if (encKey == null || encKey.isEmpty()) { - lines.add(GuiText.Unlinked.getLocal()); + lines.add(TextFormatting.RED + GuiText.Unlinked.getLocal()); } else { - lines.add(GuiText.Linked.getLocal()); + lines.add(TextFormatting.GREEN + GuiText.Linked.getLocal()); } } } else { diff --git a/src/main/java/appeng/items/tools/powered/powersink/AEBasePoweredItem.java b/src/main/java/appeng/items/tools/powered/powersink/AEBasePoweredItem.java index cf80f0430d4..5345d5433b8 100644 --- a/src/main/java/appeng/items/tools/powered/powersink/AEBasePoweredItem.java +++ b/src/main/java/appeng/items/tools/powered/powersink/AEBasePoweredItem.java @@ -21,9 +21,8 @@ import appeng.api.config.AccessRestriction; import appeng.api.config.Actionable; -import appeng.api.config.PowerUnits; import appeng.api.implementations.items.IAEItemPowerStorage; -import appeng.core.localization.GuiText; +import appeng.core.localization.Tooltips; import appeng.items.AEBaseItem; import appeng.util.Platform; import net.minecraft.client.util.ITooltipFlag; @@ -36,7 +35,6 @@ import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; -import java.text.MessageFormat; import java.util.List; @@ -65,10 +63,8 @@ public void addCheckedInformation(final ItemStack stack, final World world, fina internalCurrentPower = tag.getDouble(CURRENT_POWER_NBT_KEY); } - final double percent = internalCurrentPower / internalMaxPower; - - lines.add(GuiText.StoredEnergy.getLocal() + ':' + MessageFormat.format(" {0,number,#} ", internalCurrentPower) + Platform - .gui_localize(PowerUnits.AE.unlocalizedName) + " - " + MessageFormat.format(" {0,number,#.##%} ", percent)); + lines.add( + Tooltips.energyStorageComponent(internalCurrentPower, internalMaxPower).getFormattedText()); } @Override