diff --git a/src/main/java/net/asodev/islandutils/mixins/ItemBarMixin.java b/src/main/java/net/asodev/islandutils/mixins/ItemBarMixin.java new file mode 100644 index 00000000..9077a8fb --- /dev/null +++ b/src/main/java/net/asodev/islandutils/mixins/ItemBarMixin.java @@ -0,0 +1,223 @@ +package net.asodev.islandutils.mixins; + +import net.asodev.islandutils.modules.cosmetics.CosmeticChroma; +import net.asodev.islandutils.options.IslandOptions; +import net.asodev.islandutils.util.BarInfo; +import net.asodev.islandutils.util.Utils; +import net.minecraft.network.chat.Component; +import net.minecraft.util.ARGB; +import net.minecraft.util.Mth; +import net.minecraft.world.item.ItemStack; +import org.apache.commons.lang3.math.Fraction; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import java.util.ArrayList; +import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +@Mixin(ItemStack.class) +public class ItemBarMixin { + @Unique + private static final String BAR_SEGMENT_SPACE = "\\uE001"; + @Unique + private static final String BAR_SEGMENT_EMPTY = "\\uE27C"; + @Unique + private static final String BAR_SEGMENT_HALF = "\\uE282"; + @Unique + private static final String BAR_SEGMENT_FULL = "\\uE27F"; + @Unique + private static final Pattern PROGRESS_REGEX = Pattern.compile(".*\\n[" + BAR_SEGMENT_SPACE + BAR_SEGMENT_EMPTY + BAR_SEGMENT_HALF + BAR_SEGMENT_FULL + "]* (\\d+)%.*"); + @Unique + private static final Pattern PROGRESS_TRUE_ZERO_REGEX = Pattern.compile(".*\\n[" + BAR_SEGMENT_SPACE + BAR_SEGMENT_EMPTY + "]* 0%.*"); + @Unique + private static final String PROGRESS_COSMETIC_LABEL = "Left-Click to Equip\n"; + @Unique + private static final String PROGRESS_COSMETIC_LABEL_2 = "Left-Click to Unequip\n"; + @Unique + private static final String PROGRESS_BADGE_EARNED_LABEL = "Click to Display on Profile"; + @Unique + private static final String PROGRESS_BADGE_INCOMPLETE_LABEL = "\n\nStage incomplete\n\n"; + @Unique + private static final String PROGRESS_BADGE_PINNED_LABEL = "Shift-Click to Unpin"; + @Unique + private static final String PROGRESS_BADGE_LOCKED_LABEL = "\nUnlock this slot by reaching the below\namount of Skill Trophies.\n"; + @Unique + private static final String PROGRESS_OUTFIT_LOCKED_LABEL = "Locked Outfit Slot\n\nSave a loadout of cosmetics and their"; + @Unique + private static final String PROGRESS_QUEST_LABEL = "\nComplete any of the below tasks to\nfinish the quest.\n"; + @Unique + private static final String PROGRESS_TOOL_USES_LABEL = "\nUses Remaining: "; + @Unique + private static final String PROGRESS_TOOL_LINE_LABEL = "\nYour equipped line adds to your\n"; + @Unique + private static final String PROGRESS_TOOL_REPAIRABLE_LABEL = "\nThis item is out of uses! You can Repair\nit to restore all its uses, you can only\ndo this once per item.\n"; + @Unique + private static final String PROGRESS_TOOL_REPAIRED_LABEL = "\nThis item has previously been repaired.\n"; + @Unique + private static final String PROGRESS_TOOL_BROKEN_LABEL = "\nThis item is out of uses! You've already\nrepaired it once, so cannot do so\nagain."; + + @Unique + private static final Pattern REPUTATION_REGEX = Pattern.compile(".*\\nRoyal Donations: (\\d+)/(\\d+)\\n.*"); + + @Unique + private static final String CHROMA_LABEL = "\nChromas Unlocked:\n"; + @Unique + private static final String STYLE_TROPHY_ICON = "\\uE34D"; + @Unique + private static final Pattern CHROMA_REGEX = Pattern.compile(".*\\n(" + CosmeticChroma.CHAR_REGEX + "{5}) - (\\d+)" + STYLE_TROPHY_ICON + "\\n.*"); + + @Unique + private static final int REPAIRABLE_BAR_COLOR = ARGB.colorFromFloat(1.0F, 1.0F, 0.33F, 0.33F); + + @Unique + private static final int REPUTATION_BAR_COLOR = ARGB.colorFromFloat(1.0F, 0.66F, 0.33F, 1.0F); + + @Unique + private static final int CHROMA_BAR_COLOR_SPEED_MS = 2000; + + @Unique + private Optional getProgressBar(String lore) { + if (!IslandOptions.getMisc().isShowProgressBar()) return Optional.empty(); + + var isCosmetic = lore.contains(PROGRESS_COSMETIC_LABEL) || lore.contains(PROGRESS_COSMETIC_LABEL_2); + var isNonEarnedBadge = lore.contains(PROGRESS_BADGE_INCOMPLETE_LABEL) && !lore.contains(PROGRESS_BADGE_EARNED_LABEL); + var isProfileBadge = lore.contains(PROGRESS_BADGE_PINNED_LABEL) || lore.contains(PROGRESS_BADGE_LOCKED_LABEL); + var isOutfitSlot = lore.contains(PROGRESS_OUTFIT_LOCKED_LABEL); + if (isCosmetic || isNonEarnedBadge || isProfileBadge || isOutfitSlot) return Optional.empty(); + + var isBrokenTool = lore.contains(PROGRESS_TOOL_BROKEN_LABEL); + if (isBrokenTool) return Optional.of(new BarInfo(Fraction.ZERO, ARGB.alpha(0))); + + var isRepairableTool = lore.contains(PROGRESS_TOOL_REPAIRABLE_LABEL); + if (isRepairableTool) return Optional.of(new BarInfo(Fraction.ONE_HALF, REPAIRABLE_BAR_COLOR)); + + var progresses = getProgresses(lore); + if (progresses.isEmpty()) return Optional.empty(); + + var isQuest = lore.contains(PROGRESS_QUEST_LABEL); + var fraction = isQuest ? progresses.stream().max(Fraction::compareTo) : progresses.stream().findFirst(); + + var isNonBrokenTool = lore.contains(PROGRESS_TOOL_USES_LABEL); + if (isNonBrokenTool) { + return fraction.map(f -> { + var canRepairTool = !lore.contains(PROGRESS_TOOL_LINE_LABEL); + if (canRepairTool) { + var isRepairedTool = lore.contains(PROGRESS_TOOL_REPAIRED_LABEL); + f = (isRepairedTool ? f : f.add(Fraction.ONE)).divideBy(Fraction.getFraction(2, 1)); + } + var color = Mth.hsvToRgb(f.floatValue() / 3.0F, 1.0F, 1.0F); + return new BarInfo(f, color); + }); + } + + return fraction.map(f -> new BarInfo(f, IslandOptions.getMisc().getProgressBarColorARGB())); + } + + @Unique + private static @NotNull ArrayList getProgresses(String lore) { + var matcher = PROGRESS_REGEX.matcher(lore); + var progresses = new ArrayList(); + while (matcher.find()) { + var percentage = Integer.parseInt(matcher.group(1)); + if (percentage == 0) { + var trueZeroMatcher = PROGRESS_TRUE_ZERO_REGEX.matcher(matcher.group(0)); + if (!trueZeroMatcher.matches()) { + percentage = 1; + } + } + + var fraction = Fraction.getFraction(percentage, 100); + progresses.add(fraction); + } + return progresses; + } + + @Unique + private Optional getReputationBar(String lore) { + if (!IslandOptions.getCosmetics().isShowReputationBar()) return Optional.empty(); + + var matcher = REPUTATION_REGEX.matcher(lore); + if (!matcher.find()) return Optional.empty(); + + var level = Integer.parseInt(matcher.group(1)); + var max = Integer.parseInt(matcher.group(2)); + + try { + var fraction = Fraction.getFraction(level, max); + return Optional.of(new BarInfo(fraction, REPUTATION_BAR_COLOR)); + } catch (ArithmeticException e) { + return Optional.empty(); + } + } + + @Unique + private Optional getChromaBar(String lore) { + if (!IslandOptions.getCosmetics().isShowChromaBar()) return Optional.empty(); + + if (!lore.contains(CHROMA_LABEL)) return Optional.empty(); + + var matcher = CHROMA_REGEX.matcher(lore); + if (!matcher.find()) return Optional.empty(); + var chromaChars = Optional.of(matcher.group(1).chars().mapToObj(c -> (char) c).toList()); + + return chromaChars.map(charList -> + charList.stream() + .map(CosmeticChroma::fromChar) + .filter(Optional::isPresent) + .map(Optional::get) + .toList() + ).map(chromas -> { + var fraction = CosmeticChroma.toFraction(chromas); + + var color = 0; + if (!chromas.isEmpty()) { + var currentChromaIdx = (int) ((System.currentTimeMillis() / CHROMA_BAR_COLOR_SPEED_MS) % chromas.size()); + var nextChromaIdx = (currentChromaIdx + 1) % chromas.size(); + + var currentChromaColor = chromas.get(currentChromaIdx).toColor(); + var nextChromaColor = chromas.get(nextChromaIdx).toColor(); + + var interpolatedProgress = (float) (System.currentTimeMillis() % CHROMA_BAR_COLOR_SPEED_MS) / CHROMA_BAR_COLOR_SPEED_MS; + color = ARGB.lerp(interpolatedProgress, currentChromaColor, nextChromaColor); + } + + return new BarInfo(fraction, color); + }); + } + + @Unique + private Optional getItemBar() { + var itemStack = (ItemStack)(Object)this; + var lore = Utils.getTooltipLines(itemStack); + if (lore == null) return Optional.empty(); + + var loreStr = lore.stream().map(Component::getString).collect(Collectors.joining("\n")); + + return this.getChromaBar(loreStr) + .or(() -> this.getReputationBar(loreStr)) + .or(() -> this.getProgressBar(loreStr)); + } + + @Inject(method = "isBarVisible", at = @At("RETURN"), cancellable = true) + private void injectBarVisibility(CallbackInfoReturnable cir) { + if (this.getItemBar().isPresent()) { + cir.setReturnValue(true); + } + } + + @Inject(method = "getBarWidth", at = @At("RETURN"), cancellable = true) + private void injectBarWidth(CallbackInfoReturnable cir) { + this.getItemBar().ifPresent(barInfo -> cir.setReturnValue(barInfo.getBarWidth())); + } + + @Inject(method = "getBarColor", at = @At("RETURN"), cancellable = true) + private void injectBarColor(CallbackInfoReturnable cir) { + this.getItemBar().ifPresent(barInfo -> cir.setReturnValue(barInfo.color())); + } +} diff --git a/src/main/java/net/asodev/islandutils/mixins/ItemIDMixin.java b/src/main/java/net/asodev/islandutils/mixins/ItemIDMixin.java index 86cbf971..35c546ef 100644 --- a/src/main/java/net/asodev/islandutils/mixins/ItemIDMixin.java +++ b/src/main/java/net/asodev/islandutils/mixins/ItemIDMixin.java @@ -20,7 +20,11 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.component.ItemLore; +import org.apache.commons.lang3.StringEscapeUtils; import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -28,10 +32,18 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; @Mixin(ItemStack.class) public abstract class ItemIDMixin implements DataComponentHolder { + @Unique + private static final Logger LOGGER = LoggerFactory.getLogger("IslandUtils"); + + @Unique + private int itemPrintCounter = -1; + @Inject( method = "getTooltipLines", at = @At( @@ -42,8 +54,14 @@ public abstract class ItemIDMixin implements DataComponentHolder { ) private void addTooltipLines(Item.TooltipContext tooltipContext, @Nullable Player player, TooltipFlag tooltipFlag, CallbackInfoReturnable> cir, @Local List list) { if (!MccIslandState.isOnline() || !IslandOptions.getMisc().isDebugMode()) return; - if (!InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), InputConstants.KEY_LCONTROL)) - return; + + var window = Minecraft.getInstance().getWindow().getWindow(); + + var itemPrintHotkeyHeld = InputConstants.isKeyDown(window, InputConstants.KEY_F3) && InputConstants.isKeyDown(window, InputConstants.KEY_Z); + itemPrintCounter = (itemPrintHotkeyHeld) ? itemPrintCounter + 1 : -1; + if (itemPrintCounter == 0) printItemInfo(); + + if (!InputConstants.isKeyDown(window, InputConstants.KEY_LCONTROL)) return; MutableComponent toAppend = Component.empty(); if (this.has(DataComponents.CUSTOM_DATA)) tryAddCustomItemID(toAppend); // Append MCCI Custom Item ID @@ -62,15 +80,46 @@ private void tryAddCustomItemID(MutableComponent toAppend) { } @Unique - private void tryAddSlotNumber(MutableComponent toAppend) { + private Optional getHoveredSlot() { ItemStack me = (ItemStack) (Object) this; Screen screen = Minecraft.getInstance().screen; - if (!(screen instanceof AbstractContainerScreen containerScreen)) return; + if (screen == null) return Optional.empty(); + if (!(screen instanceof AbstractContainerScreen containerScreen)) return Optional.empty(); Slot hoveredSlot = ((ContainerScreenAccessor) containerScreen).getHoveredSlot(); - if (hoveredSlot == null || !hoveredSlot.hasItem() || hoveredSlot.getItem() != me) return; - Component component = Component.literal(" (" + hoveredSlot.getContainerSlot() + ")").withStyle(ChatFormatting.GRAY); - toAppend.append(component); + if (hoveredSlot == null || !hoveredSlot.hasItem()) return Optional.empty(); + if (hoveredSlot.getItem() != me) return Optional.empty(); + return Optional.of(hoveredSlot); + } + + @Unique + private void tryAddSlotNumber(MutableComponent toAppend) { + getHoveredSlot().ifPresent(hoveredSlot -> { + Component component = Component.literal(" (" + hoveredSlot.getContainerSlot() + ")").withStyle(ChatFormatting.GRAY); + toAppend.append(component); + }); + } + + @Unique + private void printItemInfo() { + getHoveredSlot().ifPresent(hoveredSlot -> { + LOGGER.info("-----"); + LOGGER.info("Printing components of {}", hoveredSlot.getItem().getItem().getDescriptionId()); + LOGGER.info("-----"); + hoveredSlot.getItem().getComponents().forEach(component -> { + if (component.value() instanceof Component) { + LOGGER.info("{}=>\"{}\"", component.type(), ((Component) component.value()).getString()); + } else if (component.value() instanceof ItemLore) { + var lines = ((ItemLore) component.value()).lines(); + var lineStrings = lines.stream().map(Component::getString).map(StringEscapeUtils::escapeJava); + var fullString = lineStrings.collect(Collectors.joining("\\n")); + LOGGER.info("{}=>\"{}\"", component.type(), fullString); + } else { + LOGGER.info(component.toString()); + } + }); + LOGGER.info("-----"); + }); } } diff --git a/src/main/java/net/asodev/islandutils/modules/cosmetics/CosmeticChroma.java b/src/main/java/net/asodev/islandutils/modules/cosmetics/CosmeticChroma.java new file mode 100644 index 00000000..7ee68165 --- /dev/null +++ b/src/main/java/net/asodev/islandutils/modules/cosmetics/CosmeticChroma.java @@ -0,0 +1,54 @@ +package net.asodev.islandutils.modules.cosmetics; + +import com.google.common.collect.EnumHashBiMap; +import com.google.common.collect.ImmutableMap; +import net.minecraft.util.ARGB; +import org.apache.commons.lang3.math.Fraction; + +import java.util.List; +import java.util.Optional; + +public enum CosmeticChroma { + MECHANICAL, + NATURAL, + OCEANIC, + MAGICAL, + GRAYSCALE; + + private static final char EMPTY_CHAR = '\uE02A'; + private static final EnumHashBiMap CHARS = EnumHashBiMap.create( + ImmutableMap.of( + MECHANICAL, '\uE02E', + NATURAL, '\uE02F', + OCEANIC, '\uE02C', + MAGICAL, '\uE02D', + GRAYSCALE, '\uE02B' + ) + ); + public static final String CHAR_REGEX = + "[" + EMPTY_CHAR + String.join("", CHARS.values().stream().map(String::valueOf).toList()) + "]"; + + public static final int COUNT = CHARS.size(); + + public final char toChar() { + return Optional.ofNullable(CHARS.get(this)).orElse(EMPTY_CHAR); + } + + public static Optional fromChar(char c) { + return Optional.ofNullable(CHARS.inverse().get(c)); + } + + public int toColor() { + return switch (this) { + case MECHANICAL -> ARGB.colorFromFloat(1.0f, 1.0f, 0.33f, 0.0f); + case NATURAL -> ARGB.colorFromFloat(1.0f, 0.0f, 0.66f, 0.33f); + case OCEANIC -> ARGB.colorFromFloat(1.0f, 0.0f, 0.5f, 1.0f); + case MAGICAL -> ARGB.colorFromFloat(1.0f, 0.5f, 0.0f, 1.0f); + case GRAYSCALE -> ARGB.colorFromFloat(1.0f, 0.5f, 0.5f, 0.5f); + }; + } + + public static Fraction toFraction(List chromas) { + return Fraction.getFraction(chromas.size(), COUNT); + } +} diff --git a/src/main/java/net/asodev/islandutils/options/categories/CosmeticsOptions.java b/src/main/java/net/asodev/islandutils/options/categories/CosmeticsOptions.java index ecff30e9..746a81d1 100644 --- a/src/main/java/net/asodev/islandutils/options/categories/CosmeticsOptions.java +++ b/src/main/java/net/asodev/islandutils/options/categories/CosmeticsOptions.java @@ -13,6 +13,8 @@ public class CosmeticsOptions implements OptionsCategory { boolean showPlayerPreview = true; boolean showOnHover = true; boolean showOnOnlyCosmeticMenus = true; + boolean showReputationBar = false; + boolean showChromaBar = false; public boolean isShowPlayerPreview() { return showPlayerPreview; @@ -26,6 +28,14 @@ public boolean isShowOnOnlyCosmeticMenus() { return showOnOnlyCosmeticMenus; } + public boolean isShowReputationBar() { + return showReputationBar; + } + + public boolean isShowChromaBar() { + return showChromaBar; + } + @Override public ConfigCategory getCategory() { Option showPreviewOption = Option.createBuilder() @@ -38,16 +48,28 @@ public ConfigCategory getCategory() { .controller(TickBoxControllerBuilder::create) .binding(defaults.showOnHover, () -> showOnHover, value -> this.showOnHover = value) .build(); - Option showInOnlyCosmeticMenu = Option.createBuilder() + Option showOnlyCosmeticMenusOption = Option.createBuilder() .name(Component.translatable("text.autoconfig.islandutils.option.showOnOnlyCosmeticMenus")) .controller(TickBoxControllerBuilder::create) .binding(defaults.showOnOnlyCosmeticMenus, () -> showOnOnlyCosmeticMenus, value -> this.showOnOnlyCosmeticMenus = value) .build(); + Option showReputationBarOption = Option.createBuilder() + .name(Component.translatable("text.autoconfig.islandutils.option.showReputationBar")) + .controller(TickBoxControllerBuilder::create) + .binding(defaults.showReputationBar, () -> showReputationBar, value -> this.showReputationBar = value) + .build(); + Option showChromaBarOption = Option.createBuilder() + .name(Component.translatable("text.autoconfig.islandutils.option.showChromaBar")) + .controller(TickBoxControllerBuilder::create) + .binding(defaults.showChromaBar, () -> showChromaBar, value -> this.showChromaBar = value) + .build(); return ConfigCategory.createBuilder() .name(Component.translatable("text.autoconfig.islandutils.category.cosmetics")) .option(showPreviewOption) .option(showHoverOption) - .option(showInOnlyCosmeticMenu) + .option(showOnlyCosmeticMenusOption) + .option(showReputationBarOption) + .option(showChromaBarOption) .build(); } } diff --git a/src/main/java/net/asodev/islandutils/options/categories/MiscOptions.java b/src/main/java/net/asodev/islandutils/options/categories/MiscOptions.java index a8ac72d0..79813073 100644 --- a/src/main/java/net/asodev/islandutils/options/categories/MiscOptions.java +++ b/src/main/java/net/asodev/islandutils/options/categories/MiscOptions.java @@ -4,10 +4,14 @@ import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.OptionDescription; import dev.isxander.yacl3.api.OptionGroup; +import dev.isxander.yacl3.api.controller.ColorControllerBuilder; import dev.isxander.yacl3.api.controller.TickBoxControllerBuilder; import net.asodev.islandutils.options.saving.Ignore; import net.asodev.islandutils.util.Utils; import net.minecraft.network.chat.Component; +import net.minecraft.util.ARGB; + +import java.awt.*; public class MiscOptions implements OptionsCategory { @Ignore @@ -19,8 +23,10 @@ public class MiscOptions implements OptionsCategory { boolean silverPreview = true; boolean channelSwitchers = true; boolean showFishingUpgradeIcon = true; + boolean showProgressBar = true; boolean enableConfigButton = true; boolean debugMode = false; + int progressBarColorARGB = ARGB.opaque(Color.WHITE.getRGB()); public boolean isPauseConfirm() { return pauseConfirm; @@ -44,6 +50,12 @@ public boolean showChannelSwitchers() { public boolean isShowFishingUpgradeIcon() { return showFishingUpgradeIcon; } + public boolean isShowProgressBar() { + return showProgressBar; + } + public int getProgressBarColorARGB() { + return progressBarColorARGB; + } public boolean isDebugMode() { return debugMode && !Utils.isLunarClient(); @@ -83,7 +95,6 @@ public ConfigCategory getCategory() { .build(); Option fishingUpgradeOption = Option.createBuilder() .name(Component.translatable("text.autoconfig.islandutils.option.showFishingUpgradeIcon")) - .description(OptionDescription.of(Component.translatable("text.autoconfig.islandutils.option.showFishingUpgradeIcon.@Tooltip"))) .controller(TickBoxControllerBuilder::create) .binding(defaults.showFishingUpgradeIcon, () -> showFishingUpgradeIcon, value -> this.showFishingUpgradeIcon = value) .build(); @@ -93,6 +104,21 @@ public ConfigCategory getCategory() { .controller(TickBoxControllerBuilder::create) .binding(defaults.enableConfigButton, () -> enableConfigButton, value -> this.enableConfigButton = value) .build(); + Option progressBarOption = Option.createBuilder() + .name(Component.translatable("text.autoconfig.islandutils.option.showProgressBar")) + .description(OptionDescription.of(Component.translatable("text.autoconfig.islandutils.option.showProgressBar.@Tooltip"))) + .controller(TickBoxControllerBuilder::create) + .binding(defaults.showProgressBar, () -> showProgressBar, value -> this.showProgressBar = value) + .build(); + Option progressBarColorOption = Option.createBuilder() + .name(Component.translatable("text.autoconfig.islandutils.option.progressBarColor")) + .controller(ColorControllerBuilder::create) + .binding( + new Color(defaults.progressBarColorARGB & 0xFFFFFF), + () -> new Color(progressBarColorARGB & 0xFFFFFF), + value -> this.progressBarColorARGB = ARGB.opaque(value.getRGB()) + ) + .build(); Option debugOption = Option.createBuilder() .name(Component.translatable("text.autoconfig.islandutils.option.debugMode")) .description(OptionDescription.of(Component.translatable("text.autoconfig.islandutils.option.debugMode.@Tooltip"))) @@ -114,6 +140,8 @@ public ConfigCategory getCategory() { .option(channelsOption) .option(fishingUpgradeOption) .option(buttonOption) + .option(progressBarOption) + .option(progressBarColorOption) .group(OptionGroup.createBuilder() .name(Component.translatable("text.autoconfig.islandutils.group.debugOptions")) .collapsed(true) diff --git a/src/main/java/net/asodev/islandutils/util/BarInfo.java b/src/main/java/net/asodev/islandutils/util/BarInfo.java new file mode 100644 index 00000000..5f5d41a6 --- /dev/null +++ b/src/main/java/net/asodev/islandutils/util/BarInfo.java @@ -0,0 +1,14 @@ +package net.asodev.islandutils.util; + +import net.minecraft.util.Mth; +import org.apache.commons.lang3.math.Fraction; + +public record BarInfo(Fraction fraction, int color) { + public int getBarWidth() { + if (fraction.compareTo(Fraction.ZERO) > 0) { + return Math.min(1 + Mth.mulAndTruncate(fraction, 12), 13); + } else { + return Math.min(Mth.mulAndTruncate(fraction, 13), 13); + } + } +} diff --git a/src/main/resources/assets/island/lang/en_us.json b/src/main/resources/assets/island/lang/en_us.json index 8d533ad0..84273b72 100644 --- a/src/main/resources/assets/island/lang/en_us.json +++ b/src/main/resources/assets/island/lang/en_us.json @@ -24,6 +24,8 @@ "text.autoconfig.islandutils.option.showPlayerPreview": "Show Cosmetic Previews", "text.autoconfig.islandutils.option.showOnHover": "Preview cosmetics on hover", "text.autoconfig.islandutils.option.showOnOnlyCosmeticMenus": "Show cosmetic preview only in Cosmetic Menus", + "text.autoconfig.islandutils.option.showReputationBar": "Show reputation bar", + "text.autoconfig.islandutils.option.showChromaBar": "Show chroma bar", "text.autoconfig.islandutils.category.discord": "Discord Presence", "text.autoconfig.islandutils.group.presenceDisplayOptions": "Presence Display Options", @@ -81,6 +83,9 @@ "text.autoconfig.islandutils.option.silverPreview.@Tooltip": "Shows all the items you'll earn in the Scavenging menu", "text.autoconfig.islandutils.option.channelSwitchers": "Show chat channel buttons", "text.autoconfig.islandutils.option.channelSwitchers.@Tooltip": "Shows the chat channel switcher buttons above the chat box", + "text.autoconfig.islandutils.option.showProgressBar": "Show progress bars", + "text.autoconfig.islandutils.option.showProgressBar.@Tooltip": "Adds an progress bar to inventories for menu items with progress in their tooltip, such as quests or fishing islands", + "text.autoconfig.islandutils.option.progressBarColor": "Color for progress bars on items", "text.autoconfig.islandutils.option.hideSliders": "Hide Sound Sliders if not Online", "text.autoconfig.islandutils.option.hideSliders.@Tooltip": "Hides the Music Sliders if you're not on MCC Island", "text.autoconfig.islandutils.option.showFishingUpgradeIcon": "Show fishing upgrade icons", diff --git a/src/main/resources/islandutils.mixins.json b/src/main/resources/islandutils.mixins.json index f586508d..5f973c7e 100644 --- a/src/main/resources/islandutils.mixins.json +++ b/src/main/resources/islandutils.mixins.json @@ -9,6 +9,7 @@ "accessors.WalkAnimStateAccessor", "cosmetics.ChestScreenMixin", "cosmetics.PreviewTutorialMixin", + "ItemBarMixin", "discord.ConnectionMixin", "discord.ScoreDisplayMixin", "fontloader.FontLoaderMixin",