From a503b7d90787fa2450d4b0005a9f851de3434ac6 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:10:27 -0400 Subject: [PATCH 1/8] Refactor format time --- .../ChocolateFactorySolver.java | 22 ++-------------- .../skyblock/events/EventToast.java | 4 +-- .../skyblock/itemlist/UpcomingEventsTab.java | 6 ++--- .../hysky/skyblocker/utils/SkyblockTime.java | 26 +++++++++++++++++++ .../java/de/hysky/skyblocker/utils/Utils.java | 20 +------------- .../utils/config/DurationController.java | 4 +-- 6 files changed, 36 insertions(+), 46 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java index 087d16630f..da0f66c717 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java @@ -6,6 +6,7 @@ import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.RegexUtils; import de.hysky.skyblocker.utils.RomanNumerals; +import de.hysky.skyblocker.utils.SkyblockTime; import de.hysky.skyblocker.utils.container.SimpleContainerSolver; import de.hysky.skyblocker.utils.container.SlotTextAdder; import de.hysky.skyblocker.utils.container.TooltipAdder; @@ -364,26 +365,7 @@ private boolean addRabbitStatsToLore(List lines, int slot) { } private MutableText formatTime(double seconds) { - seconds = Math.ceil(seconds); - if (seconds <= 0) return Text.literal("Now").formatted(Formatting.GREEN); - - StringBuilder builder = new StringBuilder(); - if (seconds >= 86400) { - builder.append((int) (seconds / 86400)).append("d "); - seconds %= 86400; - } - if (seconds >= 3600) { - builder.append((int) (seconds / 3600)).append("h "); - seconds %= 3600; - } - if (seconds >= 60) { - builder.append((int) (seconds / 60)).append("m "); - seconds %= 60; - } - if (seconds >= 1) { - builder.append((int) seconds).append("s"); - } - return Text.literal(builder.toString()).formatted(Formatting.GOLD); + return SkyblockTime.formatTime(seconds).formatted(Formatting.GOLD); } @Override diff --git a/src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java b/src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java index 48ea05c4a7..16bd52729d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java @@ -1,7 +1,7 @@ package de.hysky.skyblocker.skyblock.events; import de.hysky.skyblocker.SkyblockerMod; -import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.SkyblockTime; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.DrawContext; @@ -71,7 +71,7 @@ protected void drawTimer(DrawContext context, int x, int y) { started = timeTillEvent < 0; if (started) return; - Text time = Utils.getDurationText(timeTillEvent); + Text time = SkyblockTime.formatTime(timeTillEvent); TextRenderer textRenderer = MinecraftClient.getInstance().textRenderer; context.drawText(textRenderer, time, x, y, Colors.LIGHT_YELLOW, false); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/UpcomingEventsTab.java b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/UpcomingEventsTab.java index 9552ae87e5..5b46f56891 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/itemlist/UpcomingEventsTab.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/itemlist/UpcomingEventsTab.java @@ -3,7 +3,7 @@ import de.hysky.skyblocker.mixins.accessors.DrawContextInvoker; import de.hysky.skyblocker.skyblock.events.EventNotifications; import de.hysky.skyblocker.skyblock.tabhud.widget.JacobsContestWidget; -import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.SkyblockTime; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; @@ -105,10 +105,10 @@ public void render(DrawContext context, int x, int y, int mouseX, int mouseY) { if (events.isEmpty()) { context.drawText(textRenderer, Text.literal(" ").append(Text.translatable("skyblocker.events.tab.noMore")), x, y + textRenderer.fontHeight, Colors.GRAY, false); } else if (events.peekFirst().start() > time) { - MutableText formatted = Text.literal(" ").append(Text.translatable("skyblocker.events.tab.startsIn", Utils.getDurationText((int) (events.peekFirst().start() - time)))).formatted(Formatting.YELLOW); + MutableText formatted = Text.literal(" ").append(Text.translatable("skyblocker.events.tab.startsIn", SkyblockTime.formatTime((int) (events.peekFirst().start() - time)))).formatted(Formatting.YELLOW); context.drawText(textRenderer, formatted, x, y + textRenderer.fontHeight, -1, true); } else { - MutableText formatted = Text.literal(" ").append(Text.translatable( "skyblocker.events.tab.endsIn", Utils.getDurationText((int) (events.peekFirst().start() + events.peekFirst().duration() - time)))).formatted(Formatting.GREEN); + MutableText formatted = Text.literal(" ").append(Text.translatable( "skyblocker.events.tab.endsIn", SkyblockTime.formatTime((int) (events.peekFirst().start() + events.peekFirst().duration() - time)))).formatted(Formatting.GREEN); context.drawText(textRenderer, formatted, x, y + textRenderer.fontHeight, -1, true); } diff --git a/src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java b/src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java index 3f6025f059..3c9a51fd10 100644 --- a/src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java +++ b/src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java @@ -4,6 +4,9 @@ import de.hysky.skyblocker.utils.scheduler.Scheduler; import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.text.MutableText; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -122,6 +125,29 @@ private static void updateTime() { LOGGER.info("[Skyblocker Time] Skyblock time updated to Year {}, Season {}, Month {}, Day {}, Hour {}", year, season, month, day, hour); } + public static MutableText formatTime(double seconds) { + seconds = Math.ceil(seconds); + if (seconds <= 0) return Text.literal("Now").formatted(Formatting.GREEN); + + StringBuilder builder = new StringBuilder(); + if (seconds >= 86400) { + builder.append((int) (seconds / 86400)).append("d "); + seconds %= 86400; + } + if (seconds >= 3600) { + builder.append((int) (seconds / 3600)).append("h "); + seconds %= 3600; + } + if (seconds >= 60) { + builder.append((int) (seconds / 60)).append("m "); + seconds %= 60; + } + if (seconds >= 1) { + builder.append((int) seconds).append("s"); + } + return Text.literal(builder.toString()); + } + public enum Season { SPRING, SUMMER, FALL, WINTER } diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java index aa795d68e2..53be6f87df 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Utils.java +++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java @@ -28,7 +28,6 @@ import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.PlayerListEntry; import net.minecraft.scoreboard.*; -import net.minecraft.text.MutableText; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Util; @@ -353,24 +352,7 @@ private static void updateScoreboard(MinecraftClient client) { } } - // TODO: Combine with `ChocolateFactorySolver.formatTime` and move into `SkyblockTime`. - public static Text getDurationText(int timeInSeconds) { - int seconds = timeInSeconds % 60; - int minutes = (timeInSeconds / 60) % 60; - int hours = (timeInSeconds / 3600); - - MutableText time = Text.empty(); - if (hours > 0) { - time.append(hours + "h").append(" "); - } - if (hours > 0 || minutes > 0) { - time.append(minutes + "m").append(" "); - } - time.append(seconds + "s"); - return time; - } - - private static void updateFromPlayerList(MinecraftClient client) { + private static void updateFromPlayerList(MinecraftClient client) { if (client.getNetworkHandler() == null) { return; } diff --git a/src/main/java/de/hysky/skyblocker/utils/config/DurationController.java b/src/main/java/de/hysky/skyblocker/utils/config/DurationController.java index 09edcf3c91..00046475d9 100644 --- a/src/main/java/de/hysky/skyblocker/utils/config/DurationController.java +++ b/src/main/java/de/hysky/skyblocker/utils/config/DurationController.java @@ -1,6 +1,6 @@ package de.hysky.skyblocker.utils.config; -import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.SkyblockTime; import dev.isxander.yacl3.api.Option; import dev.isxander.yacl3.api.utils.Dimension; import dev.isxander.yacl3.gui.AbstractWidget; @@ -18,7 +18,7 @@ public record DurationController(Option option) implements IStringContr @Override public String getString() { - return Utils.getDurationText(option.pendingValue()).getString(); + return SkyblockTime.formatTime(option.pendingValue()).getString(); } From 45610fffbbaaf4efa4122da89b3e48c1a9ce4167 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sat, 21 Sep 2024 21:53:07 -0400 Subject: [PATCH 2/8] Update pet tier parsing --- .../hysky/skyblocker/skyblock/PetCache.java | 6 ++---- .../skyblock/item/SkyblockItemRarity.java | 20 +++++++++---------- .../skyblock/quicknav/QuickNavButton.java | 7 +++++-- .../hysky/skyblocker/utils/ItemUtilsTest.java | 4 ++++ 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java b/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java index 39516dc250..01c7fada93 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/PetCache.java @@ -7,6 +7,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.annotations.Init; +import de.hysky.skyblocker.skyblock.item.SkyblockItemRarity; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.Utils; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; @@ -137,9 +138,6 @@ public static PetInfo getCurrentPet() { } public record PetInfo(String type, double exp, String tier, Optional uuid, Optional item, Optional skin) { - // TODO: Combine with SkyblockItemRarity - private static final String[] TIER_INDEX = {"COMMON", "UNCOMMON", "RARE", "EPIC", "LEGENDARY", "MYTHIC"}; - public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.STRING.fieldOf("type").forGetter(PetInfo::type), Codec.DOUBLE.fieldOf("exp").forGetter(PetInfo::exp), @@ -153,7 +151,7 @@ public record PetInfo(String type, double exp, String tier, Optional uui ).xmap(Object2ObjectOpenHashMap::new, Object2ObjectOpenHashMap::new); public int tierIndex() { - return ArrayUtils.indexOf(TIER_INDEX, tier); + return SkyblockItemRarity.valueOf(tier).ordinal(); } } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java b/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java index 60bda97662..b21b587876 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java @@ -3,17 +3,17 @@ import net.minecraft.util.Formatting; public enum SkyblockItemRarity { - ADMIN(Formatting.DARK_RED), - ULTIMATE(Formatting.DARK_RED), - VERY_SPECIAL(Formatting.RED), - SPECIAL(Formatting.RED), - DIVINE(Formatting.AQUA), - MYTHIC(Formatting.LIGHT_PURPLE), - LEGENDARY(Formatting.GOLD), - EPIC(Formatting.DARK_PURPLE), - RARE(Formatting.BLUE), + COMMON(Formatting.WHITE), UNCOMMON(Formatting.GREEN), - COMMON(Formatting.WHITE); + RARE(Formatting.BLUE), + EPIC(Formatting.DARK_PURPLE), + LEGENDARY(Formatting.GOLD), + MYTHIC(Formatting.LIGHT_PURPLE), + DIVINE(Formatting.AQUA), + SPECIAL(Formatting.RED), + VERY_SPECIAL(Formatting.RED), + ULTIMATE(Formatting.DARK_RED), + ADMIN(Formatting.DARK_RED); public final int color; public final float r; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java index 1873111b84..75e486a15a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java @@ -98,8 +98,11 @@ public void onClick(double mouseX, double mouseY) { if (!this.temporaryToggled) { this.temporaryToggled = true; this.toggleTime = System.currentTimeMillis(); - MessageScheduler.INSTANCE.sendMessageAfterCooldown(command); - // TODO : add null check with log error + if (command == null || command.isEmpty()) { + MinecraftClient.getInstance().player.sendMessage(Text.literal("Quick Nav button index " + index + " has no command"), false); + } else { + MessageScheduler.INSTANCE.sendMessageAfterCooldown(command); + } this.alpha = 0.5f; } } diff --git a/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java b/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java index 8ce54392c3..4f8b111cc5 100644 --- a/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java +++ b/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java @@ -32,6 +32,7 @@ public class ItemUtilsTest { private final ItemStack CRIMSON_CHESTPLATE = create("{\"id\":\"minecraft:leather_chestplate\",\"count\":1,\"components\":{\"minecraft:attribute_modifiers\":{\"modifiers\":[],\"show_in_tooltip\":false},\"minecraft:unbreakable\":{\"show_in_tooltip\":false},\"minecraft:lore\":[\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Strength: \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+65 \\\"},{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"(+35)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Crit Chance: \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+15% \\\"},{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"(+15%)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Crit Damage: \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+53% \\\"},{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"(+33%)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Health: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+367 \\\"},{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"(+40) \\\"},{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"(+7)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Defense: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+117 \\\"},{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"(+20) \\\"},{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"(+7)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Intelligence: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+30 \\\"},{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"(+25)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"True Defense: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+5\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Farming Fortune: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+1\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Health Regen: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+10\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Bonus Pest Chance: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+2%\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[\\\" \\\",{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"[\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"⚔\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"] \\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"[\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"⚔\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"]\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"Growth VI\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"Pesterminator I\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"Protection VI\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"Rejuvenate V\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"Thorns III\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"True Protection I\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"Magic Find X ✖\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Grants \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"+5✯ Magic Find\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"Veteran X ✖\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Grants \\\"},{\\\"color\\\":\\\"dark_aqua\\\",\\\"text\\\":\\\"+7.5☯ Combat Wisdom\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"Tiered Bonus: Dominus (0/4)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"For every melee kill gain \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"1 \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"stack of \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Dominus\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"ᝐ\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Each \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Dominus ᝐ \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"stack grants \\\"},{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"+0.1Ⓢ Swing\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"Range\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"At \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"10 \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"stacks also \\\"},{\\\"color\\\":\\\"light_purple\\\",\\\"text\\\":\\\"swipe \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"in a random\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"direction hitting every enemy in the path of\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"the swipe.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Lose 1 stack after \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"4s \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"of not gaining a stack.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"Ancient Bonus\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Grants \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+1 \\\"},{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"☠ Crit Damage \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"per\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"Catacombs \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"level.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"bold\\\":true,\\\"color\\\":\\\"light_purple\\\",\\\"obfuscated\\\":true,\\\"text\\\":\\\"a\\\"},\\\"\\\",{\\\"bold\\\":false,\\\"extra\\\":[\\\" \\\"],\\\"italic\\\":false,\\\"obfuscated\\\":false,\\\"strikethrough\\\":false,\\\"text\\\":\\\"\\\",\\\"underlined\\\":false},{\\\"bold\\\":true,\\\"color\\\":\\\"light_purple\\\",\\\"text\\\":\\\"\\\"},{\\\"bold\\\":true,\\\"color\\\":\\\"light_purple\\\",\\\"text\\\":\\\"MYTHIC CHESTPLATE \\\"},{\\\"bold\\\":true,\\\"color\\\":\\\"light_purple\\\",\\\"obfuscated\\\":true,\\\"text\\\":\\\"a\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"strikethrough\\\":true,\\\"text\\\":\\\"-----------------\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Seller: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"[VIP] Kalokro\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Buy it now: \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"839,500,000 coins\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Ends in: \\\"},{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"10d\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"Click to inspect!\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\"],\"minecraft:hide_additional_tooltip\":{},\"minecraft:custom_name\":\"{\\\"extra\\\":[{\\\"color\\\":\\\"white\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"white\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"light_purple\\\",\\\"text\\\":\\\"Ancient Crimson Chestplate\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"minecraft:custom_data\":{\"rarity_upgrades\":1,\"hot_potato_count\":10,\"modifier\":\"ancient\",\"attributes\":{\"veteran\":10,\"magic_find\":10},\"id\":\"CRIMSON_CHESTPLATE\",\"boss_tier\":4,\"enchantments\":{\"rejuvenate\":5,\"protection\":6,\"growth\":6,\"thorns\":3,\"true_protection\":1,\"pesterminator\":1},\"uuid\":\"520b4ccb-20cb-4bc5-b460-84373e158552\",\"timestamp\":1721846560121},\"minecraft:dyed_color\":{\"rgb\":16740108,\"show_in_tooltip\":false}}}"); private final ItemStack AURORA_CHESTPLATE = create("{\"id\":\"minecraft:leather_chestplate\",\"count\":1,\"components\":{\"minecraft:attribute_modifiers\":{\"modifiers\":[],\"show_in_tooltip\":false},\"minecraft:unbreakable\":{\"show_in_tooltip\":false},\"minecraft:lore\":[\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Health: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+230\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Defense: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+65\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Intelligence: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+125\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[\\\" \\\",{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"[\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"⚔\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"] \\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"[\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"⚔\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"]\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"Mana Pool X\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Grants \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"+200✎ Intelligence\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"Mana Regeneration X ✖\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Increases your mana regeneration\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"by \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"10%\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"Tiered Bonus: Arcane Vision (0/4)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Gives you the ability to see the runic\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"affinity of enemies.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Using the proper \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"Rune \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"when casting spells\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"from \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"Runic Items \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"grants 1 stack of \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Arcane\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Vision Ѫ\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Each \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Arcane Vision Ѫ \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"stack grants you \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+2%\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"damage on your \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"Runic Spells\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"At \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"10 \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"stacks, the spells also explode on hit.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Lose 1 stack after \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"4s \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"of not gaining a stack.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"This item can be reforged!\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"bold\\\":true,\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"LEGENDARY CHESTPLATE\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"strikethrough\\\":true,\\\"text\\\":\\\"-----------------\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Seller: \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"[MVP\\\"},{\\\"color\\\":\\\"dark_green\\\",\\\"text\\\":\\\"+\\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"] Generic_Hero\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Buy it now: \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"870,000,000 coins\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Ends in: \\\"},{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"3d\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"Click to inspect!\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\"],\"minecraft:hide_additional_tooltip\":{},\"minecraft:custom_name\":\"{\\\"extra\\\":[{\\\"color\\\":\\\"white\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"white\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Aurora Chestplate\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"minecraft:custom_data\":{\"attributes\":{\"mana_regeneration\":10,\"mana_pool\":10},\"id\":\"AURORA_CHESTPLATE\",\"boss_tier\":4,\"uuid\":\"e7c13be1-519f-42bb-aae7-302408132d78\",\"timestamp\":1721222564305},\"minecraft:dyed_color\":{\"rgb\":2638321,\"show_in_tooltip\":false}}}"); private final ItemStack TERROR_CHESTPLATE = create("{\"id\":\"minecraft:leather_chestplate\",\"count\":1,\"components\":{\"minecraft:attribute_modifiers\":{\"modifiers\":[],\"show_in_tooltip\":false},\"minecraft:unbreakable\":{\"show_in_tooltip\":false},\"minecraft:lore\":[\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Crit Damage: \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+50%\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Health: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+230\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Defense: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+65\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Speed: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+12\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Intelligence: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+5\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[\\\" \\\",{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"[\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"⚔\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"] \\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"[\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"⚔\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"]\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"Lifeline VII ✖\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"When under \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"20% \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"maximum HP, your \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"❁\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"Damage \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"and \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"❈ Defense \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"increase by\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"17.5%\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"Mana Pool VII\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Grants \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"+140✎ Intelligence\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"Tiered Bonus: Hydra Strike (0/4)\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Successful arrow hits grant \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"1 \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"stack of\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Hydra Strike ⁑\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\".\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Each \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Hydra Strike ⁑ \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"stack makes your\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"arrows fly \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"30% \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"faster, and deal \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+10% \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"more\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"damage.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"At \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"10 \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"stacks your bow fires \\\"},{\\\"color\\\":\\\"light_purple\\\",\\\"text\\\":\\\"2 \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"extra arrows.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Lose 1 stack after \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"4s \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"of not gaining a stack.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"This item can be reforged!\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"bold\\\":true,\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"LEGENDARY CHESTPLATE\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"strikethrough\\\":true,\\\"text\\\":\\\"-----------------\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Seller: \\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"[MVP\\\"},{\\\"color\\\":\\\"white\\\",\\\"text\\\":\\\"+\\\"},{\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"] Eradication\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Buy it now: \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"190,000,000 coins\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Ends in: \\\"},{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"7d\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"Click to inspect!\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\"],\"minecraft:hide_additional_tooltip\":{},\"minecraft:custom_name\":\"{\\\"extra\\\":[{\\\"color\\\":\\\"white\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"white\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Terror Chestplate\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"minecraft:custom_data\":{\"attributes\":{\"mana_pool\":7,\"lifeline\":7},\"id\":\"TERROR_CHESTPLATE\",\"boss_tier\":4,\"uuid\":\"e2f24f7e-12dd-4b8e-a177-4a3160335192\",\"timestamp\":1721455900078},\"minecraft:dyed_color\":{\"rgb\":4064687,\"show_in_tooltip\":false}}}"); + private final ItemStack WITHER_SKELETON_PET = create("{\"id\":\"minecraft:player_head\",\"count\":1,\"components\":{\"minecraft:lore\":[\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"Mining Pet\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Defense: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+25\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Strength: \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+25\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Intelligence: \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"+25\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Crit Chance: \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+5%\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Crit Damage: \\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"+25%\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Stronger Bones\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Take \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"30% \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"less damage from skeletons\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Wither Blood\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Deal \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"125% \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"more damage to wither\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"mobs\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Death\\u0027s Touch\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Upon hitting an enemy inflict the\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"wither effect for \\\"},{\\\"color\\\":\\\"green\\\",\\\"text\\\":\\\"200% \\\"},{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"damage over\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"3 seconds\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"Does not stack\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Held Item: \\\"},{\\\"color\\\":\\\"blue\\\",\\\"text\\\":\\\"Dwarf Turtle Shelmet\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"Makes the pet\\u0027s owner immune to\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"knockback.\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"bold\\\":true,\\\"color\\\":\\\"aqua\\\",\\\"text\\\":\\\"MAX LEVEL\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"dark_gray\\\",\\\"text\\\":\\\"▸ 29,079,797 XP\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"red\\\",\\\"text\\\":\\\"Click to despawn!\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"\\\"},{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"Shift Left-click to toggle as favorite!\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"{\\\"extra\\\":[{\\\"color\\\":\\\"yellow\\\",\\\"text\\\":\\\"Right-click to convert to an item!\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\"],\"minecraft:custom_name\":\"{\\\"extra\\\":[{\\\"color\\\":\\\"gray\\\",\\\"text\\\":\\\"[Lvl 100] \\\"},{\\\"color\\\":\\\"gold\\\",\\\"text\\\":\\\"Wither Skeleton\\\"}],\\\"italic\\\":false,\\\"text\\\":\\\"\\\"}\",\"minecraft:profile\":{\"name\":\"61eebdb5acf149e9\",\"id\":[1643036085,-1393473047,-1459445539,-328222031],\"properties\":[{\"name\":\"textures\",\"value\":\"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjVlYzk2NDY0NWE4ZWZhYzc2YmUyZjE2MGQ3Yzk5NTYzNjJmMzJiNjUxNzM5MGM1OWMzMDg1MDM0ZjA1MGNmZiJ9fX0\\u003d\"}]},\"minecraft:custom_data\":{\"petInfo\":\"{\\\"type\\\":\\\"WITHER_SKELETON\\\",\\\"active\\\":true,\\\"exp\\\":2.907979704591799E7,\\\"tier\\\":\\\"LEGENDARY\\\",\\\"hideInfo\\\":false,\\\"heldItem\\\":\\\"DWARF_TURTLE_SHELMET\\\",\\\"candyUsed\\\":0,\\\"uuid\\\":\\\"dcc730ef-2936-461c-b7ec-45a087baa44d\\\",\\\"uniqueId\\\":\\\"7e7270ec-0ff5-460d-8d14-430ea48b596f\\\",\\\"hideRightClick\\\":false,\\\"noMove\\\":false}\",\"uuid\":\"dcc730ef-2936-461c-b7ec-45a087baa44d\",\"id\":\"PET\"}}}"); public ItemStack create(String itemStackJson) { return ItemStack.CODEC.parse(JSON_OPS, JsonParser.parseString(itemStackJson)).getOrThrow(); @@ -65,6 +66,7 @@ void testGetItemId() { Assertions.assertEquals("CRIMSON_CHESTPLATE", ItemUtils.getItemId(CRIMSON_CHESTPLATE)); Assertions.assertEquals("AURORA_CHESTPLATE", ItemUtils.getItemId(AURORA_CHESTPLATE)); Assertions.assertEquals("TERROR_CHESTPLATE", ItemUtils.getItemId(TERROR_CHESTPLATE)); + Assertions.assertEquals("WITHER_SKELETON", ItemUtils.getItemId(WITHER_SKELETON_PET)); } @Test @@ -88,6 +90,7 @@ void testGetSkyblockApiId() { Assertions.assertEquals("CRIMSON_CHESTPLATE-MAGIC_FIND-VETERAN", CRIMSON_CHESTPLATE.getSkyblockApiId()); Assertions.assertEquals("AURORA_CHESTPLATE-MANA_POOL-MANA_REGENERATION", AURORA_CHESTPLATE.getSkyblockApiId()); Assertions.assertEquals("TERROR_CHESTPLATE-LIFELINE-MANA_POOL", TERROR_CHESTPLATE.getSkyblockApiId()); + Assertions.assertEquals("LVL_1_LEGENDARY_WITHER_SKELETON", WITHER_SKELETON_PET.getSkyblockApiId()); } @Test @@ -104,6 +107,7 @@ void testGetNeuId() { Assertions.assertEquals("CRIMSON_CHESTPLATE", CRIMSON_CHESTPLATE.getNeuName()); Assertions.assertEquals("AURORA_CHESTPLATE", AURORA_CHESTPLATE.getNeuName()); Assertions.assertEquals("TERROR_CHESTPLATE", TERROR_CHESTPLATE.getNeuName()); + Assertions.assertEquals("WITHER_SKELETON;4", WITHER_SKELETON_PET.getNeuName()); } @Test From ed40e076dd50b9440545ca9e187081136b09a347 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sat, 21 Sep 2024 22:03:39 -0400 Subject: [PATCH 3/8] Update quick nav empty command message --- .../de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java | 4 +++- .../de/hysky/skyblocker/utils/scheduler/MessageScheduler.java | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java index 75e486a15a..3f38bf74ef 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java @@ -5,6 +5,7 @@ import com.mojang.serialization.JsonOps; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.mixins.accessors.HandledScreenAccessor; +import de.hysky.skyblocker.utils.Constants; import de.hysky.skyblocker.utils.scheduler.MessageScheduler; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -18,6 +19,7 @@ import net.minecraft.item.ItemStack; import net.minecraft.text.Text; import net.minecraft.text.TextCodecs; +import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import java.time.Duration; @@ -99,7 +101,7 @@ public void onClick(double mouseX, double mouseY) { this.temporaryToggled = true; this.toggleTime = System.currentTimeMillis(); if (command == null || command.isEmpty()) { - MinecraftClient.getInstance().player.sendMessage(Text.literal("Quick Nav button index " + index + " has no command"), false); + MinecraftClient.getInstance().player.sendMessage(Constants.PREFIX.get().append(Text.literal("Quick Nav button index " + (index + 1) + " has no command!").formatted(Formatting.RED)), false); } else { MessageScheduler.INSTANCE.sendMessageAfterCooldown(command); } diff --git a/src/main/java/de/hysky/skyblocker/utils/scheduler/MessageScheduler.java b/src/main/java/de/hysky/skyblocker/utils/scheduler/MessageScheduler.java index 04596960ee..a1fe7f5afc 100644 --- a/src/main/java/de/hysky/skyblocker/utils/scheduler/MessageScheduler.java +++ b/src/main/java/de/hysky/skyblocker/utils/scheduler/MessageScheduler.java @@ -46,10 +46,11 @@ private void sendMessage(String message, boolean hide) { return; } message = StringHelper.truncateChat(StringUtils.normalizeSpace(message.trim())); + + if (!hide) client.inGameHud.getChatHud().addToMessageHistory(message); if (message.startsWith("/")) { client.player.networkHandler.sendCommand(message.substring(1)); } else { - if (!hide) client.inGameHud.getChatHud().addToMessageHistory(message); client.player.networkHandler.sendChatMessage(message); } } From 4bb2e49763aff58007da720f79bb50a77bd3066a Mon Sep 17 00:00:00 2001 From: Kevin <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 22 Sep 2024 10:09:48 +0800 Subject: [PATCH 4/8] Update pet id test --- src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java b/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java index 4f8b111cc5..101815ac47 100644 --- a/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java +++ b/src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java @@ -66,7 +66,7 @@ void testGetItemId() { Assertions.assertEquals("CRIMSON_CHESTPLATE", ItemUtils.getItemId(CRIMSON_CHESTPLATE)); Assertions.assertEquals("AURORA_CHESTPLATE", ItemUtils.getItemId(AURORA_CHESTPLATE)); Assertions.assertEquals("TERROR_CHESTPLATE", ItemUtils.getItemId(TERROR_CHESTPLATE)); - Assertions.assertEquals("WITHER_SKELETON", ItemUtils.getItemId(WITHER_SKELETON_PET)); + Assertions.assertEquals("PET", ItemUtils.getItemId(WITHER_SKELETON_PET)); } @Test From 0ef339b506839c641df5e47bcecebc697fd4a09e Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 22 Sep 2024 12:58:52 -0400 Subject: [PATCH 5/8] Update health and speed bar --- .../skyblocker/skyblock/StatusBarTracker.java | 285 +++++++++--------- .../ChocolateFactorySolver.java | 26 +- .../item/tooltip/adders/EssenceShopPrice.java | 2 +- .../de/hysky/skyblocker/utils/RegexUtils.java | 28 +- 4 files changed, 177 insertions(+), 164 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java b/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java index 5938f76e1b..18448ea50a 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java @@ -2,10 +2,11 @@ import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Location; +import de.hysky.skyblocker.utils.RegexUtils; import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.scheduler.Scheduler; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.text.Text; @@ -13,143 +14,147 @@ import java.util.regex.Pattern; public class StatusBarTracker { - private static final Pattern STATUS_HEALTH = Pattern.compile("§[6c](\\d+(,\\d\\d\\d)*)/(\\d+(,\\d\\d\\d)*)❤(?:(\\+§c(\\d+(,\\d\\d\\d)*). *)| *)"); - private static final Pattern DEFENSE_STATUS = Pattern.compile("§a(\\d+(,\\d\\d\\d)*)§a❈ Defense *"); - private static final Pattern MANA_USE = Pattern.compile("§b-(\\d+(,\\d\\d\\d)*) Mana \\(§\\S+(?:\\s\\S+)* *"); - private static final Pattern MANA_STATUS = Pattern.compile("§b(\\d+(,\\d\\d\\d)*)/(\\d+(,\\d\\d\\d)*)✎ (?:Mana|§3(\\d+(,\\d\\d\\d)*)ʬ) *"); - - private Resource health = new Resource(100, 100, 0); - private Resource mana = new Resource(100, 100, 0); - private Resource speed = new Resource(100, 400, 0); - private int defense = 0; - - public void init() { - ClientReceiveMessageEvents.ALLOW_GAME.register(this::allowOverlayMessage); - ClientReceiveMessageEvents.MODIFY_GAME.register(this::onOverlayMessage); - } - - public Resource getHealth() { - return this.health; - } - - public Resource getMana() { - return this.mana; - } - - public int getDefense() { - return this.defense; - } - - public Resource getSpeed() { - updateSpeed(); - return this.speed; - } - - private int parseInt(Matcher m, int group) { - return Integer.parseInt(m.group(group).replace(",", "")); - } - - private void updateMana(Matcher m) { - int value = parseInt(m, 1); - int max = parseInt(m, 3); - int overflow = m.group(5) == null ? 0 : parseInt(m, 5); - this.mana = new Resource(value, max, overflow); - } - - private void updateSpeed() { - // Black cat and racing helm are untested - I don't have the money to test atm, but no reason why they shouldn't work - var player = MinecraftClient.getInstance().player; - int value = (int) (player.isSprinting() ? (player.getMovementSpeed() / 1.3f) * 1000 : player.getMovementSpeed() * 1000); - int max = 400; // hardcoded limit (except for with cactus knife, black cat, snail, racing helm, young drag) - if (player.getMainHandStack().getName().getString().contains("Cactus Knife") && Utils.getLocation() == Location.GARDEN) { - max = 500; - } - Iterable armor = player.getArmorItems(); - int youngDragCount = 0; - for (ItemStack armorPiece : armor) { - if (armorPiece.getName().getString().contains("Racing Helmet")) { - max = 500; - } else if (armorPiece.getName().getString().contains("Young Dragon")) { - youngDragCount++; - } - } - if (youngDragCount == 4) { - max = 500; - } - - PetCache.PetInfo pet = PetCache.getCurrentPet(); - if (pet != null) { - if (pet.type().contains("BLACK_CAT")) { - max = 500; - } else if (pet.type().contains("SNAIL")) { - max = 100; - } - } - this.speed = new Resource(value, max, 0); - } - - private void updateHealth(Matcher m) { - int value = parseInt(m, 1); - int max = parseInt(m, 3); - int overflow = Math.max(0, value - max); - if (MinecraftClient.getInstance() != null && MinecraftClient.getInstance().player != null) { - ClientPlayerEntity player = MinecraftClient.getInstance().player; - value = (int) (player.getHealth() * max / player.getMaxHealth()); - overflow = (int) (player.getAbsorptionAmount() * max / player.getMaxHealth()); - } - this.health = new Resource(Math.min(value, max), max, Math.min(overflow, max)); - } - - private String reset(String str, Matcher m) { - str = str.substring(m.end()); - m.reset(str); - return str; - } - - private boolean allowOverlayMessage(Text text, boolean overlay) { - onOverlayMessage(text, overlay); - return true; - } - - private Text onOverlayMessage(Text text, boolean overlay) { - if (!overlay || !Utils.isOnSkyblock() || !SkyblockerConfigManager.get().uiAndVisuals.bars.enableBars || Utils.isInTheRift()) { - return text; - } - return Text.of(update(text.getString(), SkyblockerConfigManager.get().chat.hideMana)); - } - - public String update(String actionBar, boolean filterManaUse) { - var sb = new StringBuilder(); - Matcher matcher = STATUS_HEALTH.matcher(actionBar); - if (!matcher.lookingAt()) - return actionBar; - updateHealth(matcher); - if (matcher.group(5) != null) { - sb.append("§c❤"); - sb.append(matcher.group(5)); - } - actionBar = reset(actionBar, matcher); - if (matcher.usePattern(MANA_STATUS).lookingAt()) { - defense = 0; - updateMana(matcher); - actionBar = reset(actionBar, matcher); - } else { - if (matcher.usePattern(DEFENSE_STATUS).lookingAt()) { - defense = parseInt(matcher, 1); - actionBar = reset(actionBar, matcher); - } else if (filterManaUse && matcher.usePattern(MANA_USE).lookingAt()) { - actionBar = reset(actionBar, matcher); - } - if (matcher.usePattern(MANA_STATUS).find()) { - updateMana(matcher); - matcher.appendReplacement(sb, ""); - } - } - matcher.appendTail(sb); - String res = sb.toString().trim(); - return res.isEmpty() ? null : res; - } - - public record Resource(int value, int max, int overflow) { - } + private static final Pattern STATUS_HEALTH = Pattern.compile("§[6c](?[0-9,]+)/(?[0-9,]+)❤ *(?\\+§c([0-9,]+). *)?"); + private static final Pattern DEFENSE_STATUS = Pattern.compile("§a(\\d+(,\\d\\d\\d)*)§a❈ Defense *"); + private static final Pattern MANA_USE = Pattern.compile("§b-(\\d+(,\\d\\d\\d)*) Mana \\(§\\S+(?:\\s\\S+)* *"); + private static final Pattern MANA_STATUS = Pattern.compile("§b(\\d+(,\\d\\d\\d)*)/(\\d+(,\\d\\d\\d)*)✎ (?:Mana|§3(\\d+(,\\d\\d\\d)*)ʬ) *"); + + private final MinecraftClient client = MinecraftClient.getInstance(); + private Resource health = new Resource(100, 100, 0); + private Resource mana = new Resource(100, 100, 0); + private Resource speed = new Resource(100, 400, 0); + private int defense = 0; + + public void init() { + ClientReceiveMessageEvents.ALLOW_GAME.register(this::allowOverlayMessage); + ClientReceiveMessageEvents.MODIFY_GAME.register(this::onOverlayMessage); + Scheduler.INSTANCE.scheduleCyclic(this::tick, 1); + } + + public Resource getHealth() { + return this.health; + } + + public Resource getMana() { + return this.mana; + } + + public int getDefense() { + return this.defense; + } + + public Resource getSpeed() { + return this.speed; + } + + private void tick() { + if (client == null || client.player == null) return; + updateHealth(health.value, health.max, health.overflow); + updateSpeed(); + } + + private void updateMana(Matcher m) { + int value = RegexUtils.parseIntFromMatcher(m, 1); + int max = RegexUtils.parseIntFromMatcher(m, 3); + int overflow; + overflow = m.group(5) == null ? 0 : RegexUtils.parseIntFromMatcher(m, 5); + this.mana = new Resource(value, max, overflow); + } + + private void updateSpeed() { + // Black cat and racing helm are untested - I don't have the money to test atm, but no reason why they shouldn't work + assert client.player != null; + int value = (int) (client.player.isSprinting() ? (client.player.getMovementSpeed() / 1.3f) * 1000 : client.player.getMovementSpeed() * 1000); + int max = 400; // hardcoded limit (except for with cactus knife, black cat, snail, racing helm, young drag) + if (client.player.getMainHandStack().getName().getString().contains("Cactus Knife") && Utils.getLocation() == Location.GARDEN) { + max = 500; + } + Iterable armor = client.player.getArmorItems(); + int youngDragCount = 0; + for (ItemStack armorPiece : armor) { + if (armorPiece.getName().getString().contains("Racing Helmet")) { + max = 500; + } else if (armorPiece.getName().getString().contains("Young Dragon")) { + youngDragCount++; + } + } + if (youngDragCount == 4) { + max = 500; + } + + PetCache.PetInfo pet = PetCache.getCurrentPet(); + if (pet != null) { + if (pet.type().contains("BLACK_CAT")) { + max = 500; + } else if (pet.type().contains("SNAIL")) { + max = 100; + } + } + this.speed = new Resource(value, max, 0); + } + + private void updateHealth(Matcher matcher) { + int health = RegexUtils.parseIntFromMatcher(matcher, "health"); + int max = RegexUtils.parseIntFromMatcher(matcher, "max"); + updateHealth(health, max, Math.max(0, health - max)); + } + + private void updateHealth(int value, int max, int overflow) { + if (client != null && client.player != null) { + value = (int) (client.player.getHealth() * max / client.player.getMaxHealth()); + overflow = (int) (client.player.getAbsorptionAmount() * max / client.player.getMaxHealth()); + } + health = new Resource(Math.min(value, max), max, Math.min(overflow, max)); + } + + private String reset(String str, Matcher m) { + str = str.substring(m.end()); + m.reset(str); + return str; + } + + private boolean allowOverlayMessage(Text text, boolean overlay) { + onOverlayMessage(text, overlay); + return true; + } + + private Text onOverlayMessage(Text text, boolean overlay) { + if (!overlay || !Utils.isOnSkyblock() || !SkyblockerConfigManager.get().uiAndVisuals.bars.enableBars || Utils.isInTheRift()) { + return text; + } + return Text.of(update(text.getString(), SkyblockerConfigManager.get().chat.hideMana)); + } + + public String update(String actionBar, boolean filterManaUse) { + var sb = new StringBuilder(); + Matcher matcher = STATUS_HEALTH.matcher(actionBar); + if (!matcher.lookingAt()) return actionBar; + updateHealth(matcher); + if (matcher.group("healing") != null) { + sb.append("§c❤"); + sb.append(matcher.group("healing")); + } + actionBar = reset(actionBar, matcher); + if (matcher.usePattern(MANA_STATUS).lookingAt()) { + defense = 0; + updateMana(matcher); + actionBar = reset(actionBar, matcher); + } else { + if (matcher.usePattern(DEFENSE_STATUS).lookingAt()) { + defense = RegexUtils.parseIntFromMatcher(matcher, 1); + actionBar = reset(actionBar, matcher); + } else if (filterManaUse && matcher.usePattern(MANA_USE).lookingAt()) { + actionBar = reset(actionBar, matcher); + } + if (matcher.usePattern(MANA_STATUS).find()) { + updateMana(matcher); + matcher.appendReplacement(sb, ""); + } + } + matcher.appendTail(sb); + String res = sb.toString().trim(); + return res.isEmpty() ? null : res; + } + + public record Resource(int value, int max, int overflow) {} } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java index da0f66c717..9bc4567065 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java @@ -145,19 +145,19 @@ private void updateFactoryInfo(Int2ObjectMap slots) { getCoach(slots.get(COACH_SLOT)).ifPresent(cpsIncreaseFactors::add); //The clickable chocolate is in slot 13, holds the total chocolate - RegexUtils.getLongFromMatcher(CHOCOLATE_PATTERN.matcher(slots.get(CHOCOLATE_SLOT).getName().getString())).ifPresent(l -> totalChocolate = l); + RegexUtils.findLongFromMatcher(CHOCOLATE_PATTERN.matcher(slots.get(CHOCOLATE_SLOT).getName().getString())).ifPresent(l -> totalChocolate = l); //Cps item (cocoa bean) is in slot 45 String cpsItemLore = ItemUtils.getConcatenatedLore(slots.get(CPS_SLOT)); Matcher cpsMatcher = CPS_PATTERN.matcher(cpsItemLore); - RegexUtils.getDoubleFromMatcher(cpsMatcher).ifPresent(d -> totalCps = d); + RegexUtils.findDoubleFromMatcher(cpsMatcher).ifPresent(d -> totalCps = d); Matcher multiplierMatcher = TOTAL_MULTIPLIER_PATTERN.matcher(cpsItemLore); - RegexUtils.getDoubleFromMatcher(multiplierMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0).ifPresent(d -> totalCpsMultiplier = d); + RegexUtils.findDoubleFromMatcher(multiplierMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0).ifPresent(d -> totalCpsMultiplier = d); //Prestige item is in slot 28 String prestigeLore = ItemUtils.getConcatenatedLore(slots.get(PRESTIGE_SLOT)); Matcher prestigeMatcher = PRESTIGE_REQUIREMENT_PATTERN.matcher(prestigeLore); - OptionalLong currentChocolate = RegexUtils.getLongFromMatcher(prestigeMatcher); + OptionalLong currentChocolate = RegexUtils.findLongFromMatcher(prestigeMatcher); if (currentChocolate.isPresent()) { String requirement = prestigeMatcher.group(2); //If the first one matched, we can assume the 2nd one is also matched since it's one whole regex //Since the last character is either M or B we can just try to replace both characters. Only the correct one will actually replace anything. @@ -178,7 +178,7 @@ private void updateFactoryInfo(Int2ObjectMap slots) { isTimeTowerMaxed = StringUtils.substringAfterLast(slots.get(TIME_TOWER_SLOT).getName().getString(), ' ').equals("XV"); String timeTowerLore = ItemUtils.getConcatenatedLore(slots.get(TIME_TOWER_SLOT)); Matcher timeTowerMultiplierMatcher = TIME_TOWER_MULTIPLIER_PATTERN.matcher(timeTowerLore); - RegexUtils.getDoubleFromMatcher(timeTowerMultiplierMatcher).ifPresent(d -> timeTowerMultiplier = d); + RegexUtils.findDoubleFromMatcher(timeTowerMultiplierMatcher).ifPresent(d -> timeTowerMultiplier = d); Matcher timeTowerStatusMatcher = TIME_TOWER_STATUS_PATTERN.matcher(timeTowerLore); if (timeTowerStatusMatcher.find(timeTowerMultiplierMatcher.hasMatch() ? timeTowerMultiplierMatcher.end() : 0)) { isTimeTowerActive = timeTowerStatusMatcher.group(1).equals("ACTIVE"); @@ -199,10 +199,10 @@ private Optional getCoach(ItemStack coachItem) { if (totalCps < 0 || totalCpsMultiplier < 0) return Optional.empty(); //We need these 2 to calculate the increase in cps. Matcher multiplierIncreaseMatcher = MULTIPLIER_INCREASE_PATTERN.matcher(coachLore); - OptionalDouble currentCpsMultiplier = RegexUtils.getDoubleFromMatcher(multiplierIncreaseMatcher); + OptionalDouble currentCpsMultiplier = RegexUtils.findDoubleFromMatcher(multiplierIncreaseMatcher); if (currentCpsMultiplier.isEmpty()) return Optional.empty(); - OptionalDouble nextCpsMultiplier = RegexUtils.getDoubleFromMatcher(multiplierIncreaseMatcher); + OptionalDouble nextCpsMultiplier = RegexUtils.findDoubleFromMatcher(multiplierIncreaseMatcher); if (nextCpsMultiplier.isEmpty()) { //This means that the coach isn't hired yet. nextCpsMultiplier = currentCpsMultiplier; //So the first instance of the multiplier is actually the amount we'll get upon upgrading. currentCpsMultiplier = OptionalDouble.of(0.0); //And so, we can re-assign values to the variables to make the calculation more readable. @@ -210,7 +210,7 @@ private Optional getCoach(ItemStack coachItem) { Matcher costMatcher = COST_PATTERN.matcher(coachLore); Matcher levelMatcher = COACH_LEVEL_PATTERN.matcher(coachItem.getName().getString()); - OptionalLong cost = RegexUtils.getLongFromMatcher(costMatcher, multiplierIncreaseMatcher.hasMatch() ? multiplierIncreaseMatcher.end() : 0); //Cost comes after the multiplier line + OptionalLong cost = RegexUtils.findLongFromMatcher(costMatcher, multiplierIncreaseMatcher.hasMatch() ? multiplierIncreaseMatcher.end() : 0); //Cost comes after the multiplier line int level = -1; if (levelMatcher.find()) { level = RomanNumerals.romanToDecimal(levelMatcher.group(1)); @@ -222,18 +222,18 @@ private Optional getCoach(ItemStack coachItem) { private Optional getRabbit(ItemStack item, int slot) { String lore = ItemUtils.getConcatenatedLore(item); Matcher cpsMatcher = CPS_INCREASE_PATTERN.matcher(lore); - OptionalInt currentCps = RegexUtils.getIntFromMatcher(cpsMatcher); + OptionalInt currentCps = RegexUtils.findIntFromMatcher(cpsMatcher); if (currentCps.isEmpty()) return Optional.empty(); - OptionalInt nextCps = RegexUtils.getIntFromMatcher(cpsMatcher); + OptionalInt nextCps = RegexUtils.findIntFromMatcher(cpsMatcher); if (nextCps.isEmpty()) { nextCps = currentCps; //This means that the rabbit isn't hired yet. currentCps = OptionalInt.of(0); //So the first instance of the cps is actually the amount we'll get upon hiring. } Matcher costMatcher = COST_PATTERN.matcher(lore); - OptionalLong cost = RegexUtils.getLongFromMatcher(costMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0); //Cost comes after the cps line + OptionalLong cost = RegexUtils.findLongFromMatcher(costMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0); //Cost comes after the cps line Matcher levelMatcher = LEVEL_PATTERN.matcher(lore); - int level = RegexUtils.getIntFromMatcher(levelMatcher).orElse(0) - 1; + int level = RegexUtils.findIntFromMatcher(levelMatcher).orElse(0) - 1; if (cost.isEmpty()) return Optional.empty(); return Optional.of(new Rabbit((nextCps.getAsInt() - currentCps.getAsInt()) * (totalCpsMultiplier < 0 ? 1 : totalCpsMultiplier), cost.getAsLong(), slot, level)); } @@ -272,7 +272,7 @@ public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List String lore = ItemUtils.concatenateLore(lines); Matcher costMatcher = COST_PATTERN.matcher(lore); - OptionalLong cost = RegexUtils.getLongFromMatcher(costMatcher); + OptionalLong cost = RegexUtils.findLongFromMatcher(costMatcher); //Available on all items with a chocolate cost if (cost.isPresent()) shouldAddLine |= addUpgradeTimerToLore(lines, cost.getAsLong()); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/EssenceShopPrice.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/EssenceShopPrice.java index 240a30ed94..e4a85ec1dd 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/EssenceShopPrice.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/EssenceShopPrice.java @@ -50,7 +50,7 @@ public static void refreshEssencePrices(Object2ObjectMap public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List lines) { String lore = ItemUtils.concatenateLore(lines); Matcher essenceMatcher = ESSENCE_PATTERN.matcher(lore); - OptionalLong cost = RegexUtils.getLongFromMatcher(essenceMatcher); + OptionalLong cost = RegexUtils.findLongFromMatcher(essenceMatcher); if (cost.isEmpty()) return; String type = essenceMatcher.group("type"); diff --git a/src/main/java/de/hysky/skyblocker/utils/RegexUtils.java b/src/main/java/de/hysky/skyblocker/utils/RegexUtils.java index 5b91a80b3c..3d6b88420d 100644 --- a/src/main/java/de/hysky/skyblocker/utils/RegexUtils.java +++ b/src/main/java/de/hysky/skyblocker/utils/RegexUtils.java @@ -9,14 +9,14 @@ public class RegexUtils { /** * @return An OptionalLong of the first group in the matcher, or an empty OptionalLong if the matcher doesn't find anything. */ - public static OptionalLong getLongFromMatcher(Matcher matcher) { - return getLongFromMatcher(matcher, matcher.hasMatch() ? matcher.end() : 0); + public static OptionalLong findLongFromMatcher(Matcher matcher) { + return findLongFromMatcher(matcher, matcher.hasMatch() ? matcher.end() : 0); } /** * @return An OptionalLong of the first group in the matcher, or an empty OptionalLong if the matcher doesn't find anything. */ - public static OptionalLong getLongFromMatcher(Matcher matcher, int startingIndex) { + public static OptionalLong findLongFromMatcher(Matcher matcher, int startingIndex) { if (!matcher.find(startingIndex)) return OptionalLong.empty(); return OptionalLong.of(Long.parseLong(matcher.group(1).replace(",", ""))); } @@ -24,31 +24,39 @@ public static OptionalLong getLongFromMatcher(Matcher matcher, int startingIndex /** * @return An OptionalInt of the first group in the matcher, or an empty OptionalInt if the matcher doesn't find anything. */ - public static OptionalInt getIntFromMatcher(Matcher matcher) { - return getIntFromMatcher(matcher, matcher.hasMatch() ? matcher.end() : 0); + public static OptionalInt findIntFromMatcher(Matcher matcher) { + return findIntFromMatcher(matcher, matcher.hasMatch() ? matcher.end() : 0); } /** * @return An OptionalInt of the first group in the matcher, or an empty OptionalInt if the matcher doesn't find anything. */ - public static OptionalInt getIntFromMatcher(Matcher matcher, int startingIndex) { + public static OptionalInt findIntFromMatcher(Matcher matcher, int startingIndex) { if (!matcher.find(startingIndex)) return OptionalInt.empty(); - return OptionalInt.of(Integer.parseInt(matcher.group(1).replace(",", ""))); + return OptionalInt.of(parseIntFromMatcher(matcher, 1)); + } + + public static int parseIntFromMatcher(Matcher matcher, int group) { + return Integer.parseInt(matcher.group(group).replace(",", "")); + } + + public static int parseIntFromMatcher(Matcher matcher, String group) { + return Integer.parseInt(matcher.group(group).replace(",", "")); } /** * @return An OptionalDouble of the first group in the matcher, or an empty OptionalDouble if the matcher doesn't find anything. * @implNote Assumes the decimal separator is `.` */ - public static OptionalDouble getDoubleFromMatcher(Matcher matcher) { - return getDoubleFromMatcher(matcher, matcher.hasMatch() ? matcher.end() : 0); + public static OptionalDouble findDoubleFromMatcher(Matcher matcher) { + return findDoubleFromMatcher(matcher, matcher.hasMatch() ? matcher.end() : 0); } /** * @return An OptionalDouble of the first group in the matcher, or an empty OptionalDouble if the matcher doesn't find anything. * @implNote Assumes the decimal separator is `.` */ - public static OptionalDouble getDoubleFromMatcher(Matcher matcher, int startingIndex) { + public static OptionalDouble findDoubleFromMatcher(Matcher matcher, int startingIndex) { if (!matcher.find(startingIndex)) return OptionalDouble.empty(); return OptionalDouble.of(Double.parseDouble(matcher.group(1).replace(",", ""))); } From f8665b96427e382808295f6664886ef56a45d2f2 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:04:56 -0400 Subject: [PATCH 6/8] Refactor bars updating --- .../skyblocker/skyblock/StatusBarTracker.java | 122 +++++++++--------- 1 file changed, 59 insertions(+), 63 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java b/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java index 18448ea50a..ebf052f77c 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java @@ -53,6 +53,65 @@ private void tick() { updateSpeed(); } + private boolean allowOverlayMessage(Text text, boolean overlay) { + onOverlayMessage(text, overlay); + return true; + } + + private Text onOverlayMessage(Text text, boolean overlay) { + if (!overlay || !Utils.isOnSkyblock() || !SkyblockerConfigManager.get().uiAndVisuals.bars.enableBars || Utils.isInTheRift()) { + return text; + } + return Text.of(update(text.getString(), SkyblockerConfigManager.get().chat.hideMana)); + } + + public String update(String actionBar, boolean filterManaUse) { + var sb = new StringBuilder(); + + // Match health and don't add it to the string builder + // Append healing to the string builder if there is any healing + Matcher matcher = STATUS_HEALTH.matcher(actionBar); + if (!matcher.find()) return actionBar; + updateHealth(matcher); + if (matcher.group("healing") != null) { + sb.append("§c❤"); + } + matcher.appendReplacement(sb, "$3"); + + // Match defense or mana use and don't add it to the string builder + if (matcher.usePattern(DEFENSE_STATUS).find()) { + defense = RegexUtils.parseIntFromMatcher(matcher, 1); + matcher.appendReplacement(sb, ""); + } else if (filterManaUse && matcher.usePattern(MANA_USE).find()) { + matcher.appendReplacement(sb, ""); + } + + // Match mana and don't add it to the string builder + if (matcher.usePattern(MANA_STATUS).find()) { + updateMana(matcher); + matcher.appendReplacement(sb, ""); + } + + // Append the rest of the message to the string builder + matcher.appendTail(sb); + String res = sb.toString().trim(); + return res.isEmpty() ? null : res; + } + + private void updateHealth(Matcher matcher) { + int health = RegexUtils.parseIntFromMatcher(matcher, "health"); + int max = RegexUtils.parseIntFromMatcher(matcher, "max"); + updateHealth(health, max, Math.max(0, health - max)); + } + + private void updateHealth(int value, int max, int overflow) { + if (client != null && client.player != null) { + value = (int) (client.player.getHealth() * max / client.player.getMaxHealth()); + overflow = (int) (client.player.getAbsorptionAmount() * max / client.player.getMaxHealth()); + } + health = new Resource(Math.min(value, max), max, Math.min(overflow, max)); + } + private void updateMana(Matcher m) { int value = RegexUtils.parseIntFromMatcher(m, 1); int max = RegexUtils.parseIntFromMatcher(m, 3); @@ -93,68 +152,5 @@ private void updateSpeed() { this.speed = new Resource(value, max, 0); } - private void updateHealth(Matcher matcher) { - int health = RegexUtils.parseIntFromMatcher(matcher, "health"); - int max = RegexUtils.parseIntFromMatcher(matcher, "max"); - updateHealth(health, max, Math.max(0, health - max)); - } - - private void updateHealth(int value, int max, int overflow) { - if (client != null && client.player != null) { - value = (int) (client.player.getHealth() * max / client.player.getMaxHealth()); - overflow = (int) (client.player.getAbsorptionAmount() * max / client.player.getMaxHealth()); - } - health = new Resource(Math.min(value, max), max, Math.min(overflow, max)); - } - - private String reset(String str, Matcher m) { - str = str.substring(m.end()); - m.reset(str); - return str; - } - - private boolean allowOverlayMessage(Text text, boolean overlay) { - onOverlayMessage(text, overlay); - return true; - } - - private Text onOverlayMessage(Text text, boolean overlay) { - if (!overlay || !Utils.isOnSkyblock() || !SkyblockerConfigManager.get().uiAndVisuals.bars.enableBars || Utils.isInTheRift()) { - return text; - } - return Text.of(update(text.getString(), SkyblockerConfigManager.get().chat.hideMana)); - } - - public String update(String actionBar, boolean filterManaUse) { - var sb = new StringBuilder(); - Matcher matcher = STATUS_HEALTH.matcher(actionBar); - if (!matcher.lookingAt()) return actionBar; - updateHealth(matcher); - if (matcher.group("healing") != null) { - sb.append("§c❤"); - sb.append(matcher.group("healing")); - } - actionBar = reset(actionBar, matcher); - if (matcher.usePattern(MANA_STATUS).lookingAt()) { - defense = 0; - updateMana(matcher); - actionBar = reset(actionBar, matcher); - } else { - if (matcher.usePattern(DEFENSE_STATUS).lookingAt()) { - defense = RegexUtils.parseIntFromMatcher(matcher, 1); - actionBar = reset(actionBar, matcher); - } else if (filterManaUse && matcher.usePattern(MANA_USE).lookingAt()) { - actionBar = reset(actionBar, matcher); - } - if (matcher.usePattern(MANA_STATUS).find()) { - updateMana(matcher); - matcher.appendReplacement(sb, ""); - } - } - matcher.appendTail(sb); - String res = sb.toString().trim(); - return res.isEmpty() ? null : res; - } - public record Resource(int value, int max, int overflow) {} } From f075ae0abb2dbb2a14512702ddaaabaf65eb8753 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:34:43 -0400 Subject: [PATCH 7/8] Update regex --- .../skyblocker/skyblock/StatusBarTracker.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java b/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java index ebf052f77c..c589438c6b 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java @@ -14,10 +14,10 @@ import java.util.regex.Pattern; public class StatusBarTracker { - private static final Pattern STATUS_HEALTH = Pattern.compile("§[6c](?[0-9,]+)/(?[0-9,]+)❤ *(?\\+§c([0-9,]+). *)?"); - private static final Pattern DEFENSE_STATUS = Pattern.compile("§a(\\d+(,\\d\\d\\d)*)§a❈ Defense *"); - private static final Pattern MANA_USE = Pattern.compile("§b-(\\d+(,\\d\\d\\d)*) Mana \\(§\\S+(?:\\s\\S+)* *"); - private static final Pattern MANA_STATUS = Pattern.compile("§b(\\d+(,\\d\\d\\d)*)/(\\d+(,\\d\\d\\d)*)✎ (?:Mana|§3(\\d+(,\\d\\d\\d)*)ʬ) *"); + private static final Pattern STATUS_HEALTH = Pattern.compile("§[6c](?[\\d,]+)/(?[\\d,]+)❤ *(?\\+§c([\\d,]+). *)?"); + private static final Pattern DEFENSE_STATUS = Pattern.compile("§a(?[\\d,]+)§a❈ Defense *"); + private static final Pattern MANA_USE = Pattern.compile("§b-([\\d,]+) Mana \\(§.*?\\) *"); + private static final Pattern MANA_STATUS = Pattern.compile("§b(?[\\d,]+)/(?[\\d,]+)✎ (?:Mana|§3(?[\\d,]+)ʬ) *"); private final MinecraftClient client = MinecraftClient.getInstance(); private Resource health = new Resource(100, 100, 0); @@ -80,7 +80,7 @@ public String update(String actionBar, boolean filterManaUse) { // Match defense or mana use and don't add it to the string builder if (matcher.usePattern(DEFENSE_STATUS).find()) { - defense = RegexUtils.parseIntFromMatcher(matcher, 1); + defense = RegexUtils.parseIntFromMatcher(matcher, "defense"); matcher.appendReplacement(sb, ""); } else if (filterManaUse && matcher.usePattern(MANA_USE).find()) { matcher.appendReplacement(sb, ""); @@ -113,11 +113,10 @@ private void updateHealth(int value, int max, int overflow) { } private void updateMana(Matcher m) { - int value = RegexUtils.parseIntFromMatcher(m, 1); - int max = RegexUtils.parseIntFromMatcher(m, 3); - int overflow; - overflow = m.group(5) == null ? 0 : RegexUtils.parseIntFromMatcher(m, 5); - this.mana = new Resource(value, max, overflow); + int mana = RegexUtils.parseIntFromMatcher(m, "mana"); + int max = RegexUtils.parseIntFromMatcher(m, "max"); + int overflow = m.group("overflow") == null ? 0 : RegexUtils.parseIntFromMatcher(m, "overflow"); + this.mana = new Resource(mana, max, overflow); } private void updateSpeed() { From c1292243286f61aac88fa1421456408b2f1aeebe Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Sun, 22 Sep 2024 14:37:54 -0400 Subject: [PATCH 8/8] Fix BazaarPriceTooltip sack crash --- .../item/tooltip/adders/BazaarPriceTooltip.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/BazaarPriceTooltip.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/BazaarPriceTooltip.java index 6d7d26c521..4e1c0dc303 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/BazaarPriceTooltip.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/BazaarPriceTooltip.java @@ -23,26 +23,26 @@ public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List String skyblockApiId = stack.getSkyblockApiId(); if (TooltipInfoType.BAZAAR.hasOrNullWarning(skyblockApiId)) { - int amount; - if (lines.get(1).getString().endsWith("Sack")) { - //The amount is in the 2nd sibling of the 3rd line of the lore. here V + int count; + if (lines.size() >= 4 && lines.get(3).getSiblings().size() >= 2 && lines.get(1).getString().endsWith("Sack")) { + //The count is in the 2nd sibling of the 3rd line of the lore. here V //Example line: empty[style={color=dark_purple,!italic}, siblings=[literal{Stored: }[style={color=gray}], literal{0}[style={color=dark_gray}], literal{/20k}[style={color=gray}]] String line = lines.get(3).getSiblings().get(1).getString().replace(",", ""); - amount = NumberUtils.isParsable(line) && !line.equals("0") ? Integer.parseInt(line) : stack.getCount(); + count = NumberUtils.isParsable(line) && !line.equals("0") ? Integer.parseInt(line) : stack.getCount(); } else { - amount = stack.getCount(); + count = stack.getCount(); } BazaarProduct product = TooltipInfoType.BAZAAR.getData().get(skyblockApiId); lines.add(Text.literal(String.format("%-18s", "Bazaar buy Price:")) .formatted(Formatting.GOLD) .append(product.buyPrice().isEmpty() ? Text.literal("No data").formatted(Formatting.RED) - : ItemTooltip.getCoinsMessage(product.buyPrice().getAsDouble(), amount))); + : ItemTooltip.getCoinsMessage(product.buyPrice().getAsDouble(), count))); lines.add(Text.literal(String.format("%-19s", "Bazaar sell Price:")) .formatted(Formatting.GOLD) .append(product.sellPrice().isEmpty() ? Text.literal("No data").formatted(Formatting.RED) - : ItemTooltip.getCoinsMessage(product.sellPrice().getAsDouble(), amount))); + : ItemTooltip.getCoinsMessage(product.sellPrice().getAsDouble(), count))); } }