From 351d5d3e8da348d48cac36a5cc4a784f288d7656 Mon Sep 17 00:00:00 2001 From: UpFault Date: Tue, 28 May 2024 16:34:10 -0500 Subject: [PATCH 1/6] Added EssenceShopPrice Feature, moved concatenate methods from ChocolateFactorySolver to Utils as they most likely will be used many times --- .../de/hysky/skyblocker/SkyblockerMod.java | 1 + .../categories/UIAndVisualsCategory.java | 7 + .../config/configs/UIAndVisualsConfig.java | 3 + .../skyblocker/skyblock/EssenceShopPrice.java | 87 ++++++++++++ .../ChocolateFactorySolver.java | 134 +++++++++++++----- .../java/de/hysky/skyblocker/utils/Utils.java | 23 ++- .../assets/skyblocker/lang/en_us.json | 2 + 7 files changed, 223 insertions(+), 34 deletions(-) create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/EssenceShopPrice.java diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index 8dd1419d66..ad3ccc1f3a 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -200,6 +200,7 @@ public void onInitializeClient() { EggFinder.init(); TimeTowerReminder.init(); SkyblockTime.init(); + new EssenceShopPrice(); JerryTimer.init(); TooltipManager.init(); SlotTextManager.init(); diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java index 889b253a94..d8b4311a35 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java @@ -75,6 +75,13 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig newValue -> config.uiAndVisuals.showEquipmentInInventory = newValue) .controller(ConfigUtils::createBooleanController) .build()) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.uiAndVisuals.showEssenceCost")) + .binding(defaults.uiAndVisuals.showEssenceCost, + () -> config.uiAndVisuals.showEssenceCost, + newValue -> config.uiAndVisuals.showEssenceCost = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) //Chest Value FIXME change dropdown to color controller .group(OptionGroup.createBuilder() diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index 80bdb1c924..6537c99cb9 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -66,6 +66,9 @@ public class UIAndVisualsConfig { @SerialEntry public CompactDamage compactDamage = new CompactDamage(); + @SerialEntry + public boolean showEssenceCost = false; + public static class ChestValue { @SerialEntry public boolean enableChestValue = true; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/EssenceShopPrice.java b/src/main/java/de/hysky/skyblocker/skyblock/EssenceShopPrice.java new file mode 100644 index 0000000000..63c4cbdea7 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/EssenceShopPrice.java @@ -0,0 +1,87 @@ +package de.hysky.skyblocker.skyblock; + +import com.google.gson.JsonObject; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.tooltip.TooltipInfoType; +import de.hysky.skyblocker.utils.RegexUtils; +import de.hysky.skyblocker.utils.Utils; +import it.unimi.dsi.fastutil.longs.LongBooleanPair; +import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; +import net.minecraft.client.item.TooltipType; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.List; +import java.util.Locale; +import java.util.OptionalLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class EssenceShopPrice { + private static final Logger LOGGER = LoggerFactory.getLogger(EssenceShopPrice.class); + private static final Pattern ESSENCE_PATTERN = Pattern.compile("Cost (?[0-9,]+) (?[A-Za-z]+) Essence"); + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,###.#", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); + + public EssenceShopPrice() { + ItemTooltipCallback.EVENT.register(EssenceShopPrice::handleTooltip); + } + + //TODO: maybe move the price value right after the essence amount ex: "1,500 Wither Essence (645k coins)" + private static void handleTooltip(ItemStack stack, Item.TooltipContext tooltipContext, TooltipType tooltipType, List lines) { + if (!SkyblockerConfigManager.get().uiAndVisuals.showEssenceCost) return; + if (!(MinecraftClient.getInstance().currentScreen instanceof GenericContainerScreen screen) || !screen.getTitle().getString().contains("Essence Shop")) return; + String lore = Utils.concatenateLore(lines); + Matcher essenceMatcher = ESSENCE_PATTERN.matcher(lore); + OptionalLong cost = RegexUtils.getLongFromMatcher(essenceMatcher); + long costValue = 0; + if (cost.isPresent()) { + String type = essenceMatcher.group("type"); + int amount = Integer.parseInt(essenceMatcher.group("amount").replace(",", "")); + + LongBooleanPair priceData = getItemPrice(("ESSENCE_" + type).toUpperCase()); + + priceData.rightBoolean(); + + costValue += priceData.leftLong() * amount; + addPriceInfoToLore(lines, costValue); + } + } + + private static void addPriceInfoToLore(List lines, long cost) { + lines.add(Text.empty() + .append(Text.literal("Price: ").formatted(Formatting.GRAY)) + .append(Text.literal(DECIMAL_FORMAT.format(cost) + " coins").formatted(Formatting.GOLD))); + } + + /** + * @return An {@link LongBooleanPair} with the {@code left long} representing the item's price, and the {@code right boolean} indicating if the price + * was based on complete data. + */ + private static LongBooleanPair getItemPrice(String id) { + JsonObject bazaarPrices = TooltipInfoType.BAZAAR.getData(); + JsonObject lbinPrices = TooltipInfoType.LOWEST_BINS.getData(); + + if (bazaarPrices == null || lbinPrices == null) return LongBooleanPair.of(0L, false); + + if (bazaarPrices.has(id)) { + JsonObject item = bazaarPrices.get(id).getAsJsonObject(); + boolean isPriceNull = item.get("sellPrice").isJsonNull(); + + return LongBooleanPair.of(isPriceNull ? 0L : (long) item.get("sellPrice").getAsDouble(), !isPriceNull); + } + + if (lbinPrices.has(id)) { + return LongBooleanPair.of((long) lbinPrices.get(id).getAsDouble(), true); + } + + return LongBooleanPair.of(0L, false); + } +} 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 db81382c6e..9d1a4ce03d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java @@ -5,6 +5,7 @@ import de.hysky.skyblocker.skyblock.item.tooltip.adders.LineSmoothener; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.RegexUtils; +import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.gui.ColorHighlight; import de.hysky.skyblocker.utils.render.gui.ContainerSolver; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -150,15 +151,14 @@ private static void updateFactoryInfo(Int2ObjectMap slots) { RegexUtils.getLongFromMatcher(CHOCOLATE_PATTERN.matcher(slots.get(CHOCOLATE_SLOT).getName().getString())).ifPresent(l -> totalChocolate = l); //Cps item (cocoa bean) is in slot 45 - String cpsItemLore = getConcatenatedLore(slots.get(CPS_SLOT)); + String cpsItemLore = Utils.getConcatenatedLore(slots.get(45)); Matcher cpsMatcher = CPS_PATTERN.matcher(cpsItemLore); RegexUtils.getDoubleFromMatcher(cpsMatcher).ifPresent(d -> totalCps = d); Matcher multiplierMatcher = TOTAL_MULTIPLIER_PATTERN.matcher(cpsItemLore); RegexUtils.getDoubleFromMatcher(multiplierMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0).ifPresent(d -> totalCpsMultiplier = d); //Prestige item is in slot 28 - String prestigeLore = getConcatenatedLore(slots.get(PRESTIGE_SLOT)); - Matcher prestigeMatcher = PRESTIGE_REQUIREMENT_PATTERN.matcher(prestigeLore); + Matcher prestigeMatcher = PRESTIGE_REQUIREMENT_PATTERN.matcher(Utils.getConcatenatedLore(slots.get(28))); OptionalLong currentChocolate = RegexUtils.getLongFromMatcher(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 @@ -177,12 +177,9 @@ private static void updateFactoryInfo(Int2ObjectMap slots) { } //Time Tower is in slot 39 - isTimeTowerMaxed = StringUtils.substringAfterLast(slots.get(TIME_TOWER_SLOT).getName().getString(), ' ').equals("XV"); - String timeTowerLore = getConcatenatedLore(slots.get(TIME_TOWER_SLOT)); - Matcher timeTowerMultiplierMatcher = TIME_TOWER_MULTIPLIER_PATTERN.matcher(timeTowerLore); - RegexUtils.getDoubleFromMatcher(timeTowerMultiplierMatcher).ifPresent(d -> timeTowerMultiplier = d); - Matcher timeTowerStatusMatcher = TIME_TOWER_STATUS_PATTERN.matcher(timeTowerLore); - if (timeTowerStatusMatcher.find(timeTowerMultiplierMatcher.hasMatch() ? timeTowerMultiplierMatcher.end() : 0)) { + timeTowerMultiplier = romanToDecimal(StringUtils.substringAfterLast(slots.get(39).getName().getString(), ' ')) / 10.0; //The name holds the level, which is multiplier * 10 in roman numerals + Matcher timeTowerStatusMatcher = TIME_TOWER_STATUS_PATTERN.matcher(Utils.getConcatenatedLore(slots.get(39))); + if (timeTowerStatusMatcher.find()) { isTimeTowerActive = timeTowerStatusMatcher.group(1).equals("ACTIVE"); } @@ -293,13 +290,11 @@ public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List //It should be set to true if there's any information added, false otherwise. boolean shouldAddLine = false; - String lore = concatenateLore(lines); - Matcher costMatcher = COST_PATTERN.matcher(lore); - OptionalLong cost = RegexUtils.getLongFromMatcher(costMatcher); - //Available on all items with a chocolate cost - if (cost.isPresent()) shouldAddLine |= addUpgradeTimerToLore(lines, cost.getAsLong()); - - int index = focusedSlot.id; + String lore = Utils.concatenateLore(lines); + Matcher costMatcher = COST_PATTERN.matcher(lore); + OptionalLong cost = RegexUtils.getLongFromMatcher(costMatcher); + //Available on all items with a chocolate cost + if (cost.isPresent()) shouldAddLine = addUpgradeTimerToLore(lines, cost.getAsLong()); //Prestige item if (index == PRESTIGE_SLOT) { @@ -391,23 +386,96 @@ private 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()).formatted(Formatting.GOLD); + 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); + } + + private static Optional getCoach(ItemStack coachItem) { + if (!coachItem.isOf(Items.PLAYER_HEAD)) return Optional.empty(); + String coachLore = Utils.getConcatenatedLore(coachItem); + + if (totalCpsMultiplier == -1.0) return Optional.empty(); //We need the total multiplier to calculate the increase in cps. + + Matcher multiplierIncreaseMatcher = MULTIPLIER_INCREASE_PATTERN.matcher(coachLore); + OptionalDouble currentCpsMultiplier = RegexUtils.getDoubleFromMatcher(multiplierIncreaseMatcher); + if (currentCpsMultiplier.isEmpty()) return Optional.empty(); + + OptionalDouble nextCpsMultiplier = RegexUtils.getDoubleFromMatcher(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. + } + + Matcher costMatcher = COST_PATTERN.matcher(coachLore); + OptionalInt cost = RegexUtils.getIntFromMatcher(costMatcher, multiplierIncreaseMatcher.hasMatch() ? multiplierIncreaseMatcher.end() : 0); //Cost comes after the multiplier line + if (cost.isEmpty()) return Optional.empty(); + + return Optional.of(new Rabbit(totalCps / totalCpsMultiplier * (nextCpsMultiplier.getAsDouble() - currentCpsMultiplier.getAsDouble()), cost.getAsInt(), 42, coachItem)); + } + + private static Optional getRabbit(ItemStack item, int slot) { + String lore = Utils.getConcatenatedLore(item); + Matcher cpsMatcher = CPS_INCREASE_PATTERN.matcher(lore); + OptionalInt currentCps = RegexUtils.getIntFromMatcher(cpsMatcher); + if (currentCps.isEmpty()) return Optional.empty(); + OptionalInt nextCps = RegexUtils.getIntFromMatcher(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); + OptionalInt cost = RegexUtils.getIntFromMatcher(costMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0); //Cost comes after the cps line + if (cost.isEmpty()) return Optional.empty(); + return Optional.of(new Rabbit(nextCps.getAsInt() - currentCps.getAsInt(), cost.getAsInt(), slot, item)); + } + + private static Optional getPrestigeHighlight(ItemStack item) { + List loreList = ItemUtils.getLore(item); + if (loreList.isEmpty()) return Optional.empty(); + + String lore = loreList.getLast().getString(); //The last line holds the text we're looking for + if (lore.equals("Click to prestige!")) return Optional.of(ColorHighlight.green(28)); + return Optional.of(ColorHighlight.red(28)); + } + + private record Rabbit(double cpsIncrease, int cost, int slot, ItemStack itemStack) { + } + + //Perhaps the part below can go to a separate file later on, but I couldn't find a proper name for the class, so they're staying here. + private static final Map romanMap = Map.of( + 'I', 1, + 'V', 5, + 'X', 10, + 'L', 50, + 'C', 100, + 'D', 500, + 'M', 1000 + ); + + public static int romanToDecimal(String romanNumeral) { + int decimal = 0; + int lastNumber = 0; + for (int i = romanNumeral.length() - 1; i >= 0; i--) { + char ch = romanNumeral.charAt(i); + decimal = romanMap.get(ch) >= lastNumber ? decimal + romanMap.get(ch) : decimal - romanMap.get(ch); + lastNumber = romanMap.get(ch); } + return decimal; } } diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java index bbeb11b582..0a8c7c8046 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Utils.java +++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java @@ -21,6 +21,7 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.PlayerListEntry; +import net.minecraft.item.ItemStack; import net.minecraft.scoreboard.*; import net.minecraft.text.MutableText; import net.minecraft.text.Text; @@ -158,7 +159,7 @@ public static Location getLocation() { /** * Can be used to restrict features to being active only on the Alpha network. - * + * * @return the current environment parsed from the Mod API. */ @NotNull @@ -554,6 +555,26 @@ public static void sendMessageToBypassEvents(Text message) { client.getNarratorManager().narrateSystemMessage(message); } + /** + * Utility method. + */ + public static String getConcatenatedLore(ItemStack item) { + return concatenateLore(ItemUtils.getLore(item)); + } + + /** + * Concatenates the lore of an item into one string. + * This is useful in case some pattern we're looking for is split into multiple lines, which would make it harder to regex. + */ + public static String concatenateLore(List lore) { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < lore.size(); i++) { + stringBuilder.append(lore.get(i).getString()); + if (i != lore.size() - 1) stringBuilder.append(" "); + } + return stringBuilder.toString(); + } + public static String getUndashedUuid() { return UndashedUuid.toString(MinecraftClient.getInstance().getSession().getUuidOrNull()); } diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index ecdae5e03c..2fd610d14f 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -596,6 +596,8 @@ "skyblocker.config.uiAndVisuals.compactDamage.critDamageGradientStart": "Crit Damage Gradient Start Color", "skyblocker.config.uiAndVisuals.compactDamage.critDamageGradientEnd": "Crit Damage Gradient End Color", + "skyblocker.config.uiAndVisuals.showEssenceCost": "Show Essence Cost", + "skyblocker.config.uiAndVisuals.compactorDeletorPreview": "Enable Compactor/Deletor Preview", "skyblocker.config.uiAndVisuals.dontStripSkinAlphaValues": "Correct Transparent Skin Pixels", From 8676cb7d4948ea4627de06d5527f589dba821b05 Mon Sep 17 00:00:00 2001 From: UpFault Date: Wed, 29 May 2024 02:09:25 -0500 Subject: [PATCH 2/6] Moved Show Essence Cost value from UIAndVisualsCategory to GeneralCategory --- .../skyblocker/config/categories/GeneralCategory.java | 7 +++++++ .../skyblocker/config/categories/UIAndVisualsCategory.java | 7 ------- .../de/hysky/skyblocker/config/configs/GeneralConfig.java | 3 +++ .../skyblocker/config/configs/UIAndVisualsConfig.java | 2 -- src/main/resources/assets/skyblocker/lang/en_us.json | 3 +-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java index 96bb226d96..eac77d2c55 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -222,6 +222,13 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .controller(ConfigUtils::createBooleanController) .build()) .build()) + .option(Option.createBuilder() + .name(Text.translatable("skyblocker.config.general.itemTooltip.showEssenceCost")) + .binding(defaults.general.showEssenceCost, + () -> config.general.showEssenceCost, + newValue -> config.general.showEssenceCost = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) //Item Info Display .group(OptionGroup.createBuilder() diff --git a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java index d8b4311a35..889b253a94 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/UIAndVisualsCategory.java @@ -75,13 +75,6 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig newValue -> config.uiAndVisuals.showEquipmentInInventory = newValue) .controller(ConfigUtils::createBooleanController) .build()) - .option(Option.createBuilder() - .name(Text.translatable("skyblocker.config.uiAndVisuals.showEssenceCost")) - .binding(defaults.uiAndVisuals.showEssenceCost, - () -> config.uiAndVisuals.showEssenceCost, - newValue -> config.uiAndVisuals.showEssenceCost = newValue) - .controller(ConfigUtils::createBooleanController) - .build()) //Chest Value FIXME change dropdown to color controller .group(OptionGroup.createBuilder() diff --git a/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java index 754e15f152..786eac84a7 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java @@ -51,6 +51,9 @@ public class GeneralConfig { @SerialEntry public List lockedSlots = new ArrayList<>(); + @SerialEntry + public boolean showEssenceCost = false; + //maybe put this 5 somewhere else @SerialEntry public ObjectOpenHashSet protectedItems = new ObjectOpenHashSet<>(); diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index 6537c99cb9..465db24d07 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -66,8 +66,6 @@ public class UIAndVisualsConfig { @SerialEntry public CompactDamage compactDamage = new CompactDamage(); - @SerialEntry - public boolean showEssenceCost = false; public static class ChestValue { @SerialEntry diff --git a/src/main/resources/assets/skyblocker/lang/en_us.json b/src/main/resources/assets/skyblocker/lang/en_us.json index 2fd610d14f..9cb5ea2933 100644 --- a/src/main/resources/assets/skyblocker/lang/en_us.json +++ b/src/main/resources/assets/skyblocker/lang/en_us.json @@ -263,6 +263,7 @@ "skyblocker.config.general.itemTooltip.enableMuseumInfo.@Tooltip": "If this item is donatable to the museum, then the item's category in the musuem is displayed. It also displays a marker indicating whether you've donated that item to your musuem or not (freebies not yet supported).\n\nMake sure to enable your Museum API for accurate information!", "skyblocker.config.general.itemTooltip.enableNPCPrice": "Enable NPC Price", "skyblocker.config.general.itemTooltip.enableObtainedDate": "Enable Obtained Date", + "skyblocker.config.general.itemTooltip.showEssenceCost": "Show Essence Cost", "skyblocker.config.general.quiverWarning": "Quiver Warning", "skyblocker.config.general.quiverWarning.enableQuiverWarning": "Enable Quiver Warning", @@ -596,8 +597,6 @@ "skyblocker.config.uiAndVisuals.compactDamage.critDamageGradientStart": "Crit Damage Gradient Start Color", "skyblocker.config.uiAndVisuals.compactDamage.critDamageGradientEnd": "Crit Damage Gradient End Color", - "skyblocker.config.uiAndVisuals.showEssenceCost": "Show Essence Cost", - "skyblocker.config.uiAndVisuals.compactorDeletorPreview": "Enable Compactor/Deletor Preview", "skyblocker.config.uiAndVisuals.dontStripSkinAlphaValues": "Correct Transparent Skin Pixels", From d934e0ad6807ed1c55cb0d62e3a0e979cb7c5080 Mon Sep 17 00:00:00 2001 From: UpFault <76474308+UpFault@users.noreply.github.com> Date: Sat, 1 Jun 2024 23:31:24 -0500 Subject: [PATCH 3/6] Update GeneralCategory.java --- .../hysky/skyblocker/config/categories/GeneralCategory.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java index eac77d2c55..2c989b8422 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -224,9 +224,9 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .build()) .option(Option.createBuilder() .name(Text.translatable("skyblocker.config.general.itemTooltip.showEssenceCost")) - .binding(defaults.general.showEssenceCost, - () -> config.general.showEssenceCost, - newValue -> config.general.showEssenceCost = newValue) + .binding(defaults.general.itemTooltip.showEssenceCost, + () -> config.general.itemTooltip.showEssenceCost, + newValue -> config.general.itemTooltip.showEssenceCost = newValue) .controller(ConfigUtils::createBooleanController) .build()) From 54cf91a921f562658a94703b3c6325fc8ce11392 Mon Sep 17 00:00:00 2001 From: Rime <81419447+Emirlol@users.noreply.github.com> Date: Sun, 14 Jul 2024 18:08:47 +0300 Subject: [PATCH 4/6] Rebase onto master and clean up code --- .../de/hysky/skyblocker/SkyblockerMod.java | 9 +- .../config/categories/GeneralCategory.java | 6 +- .../config/configs/UIAndVisualsConfig.java | 5 +- .../skyblocker/skyblock/EssenceShopPrice.java | 87 ---------- .../ChocolateFactorySolver.java | 164 ++++-------------- .../item/tooltip/TooltipInfoType.java | 3 +- .../skyblock/item/tooltip/TooltipManager.java | 15 +- .../item/tooltip/adders/EssenceShopPrice.java | 72 ++++++++ .../de/hysky/skyblocker/utils/ItemUtils.java | 20 +++ .../java/de/hysky/skyblocker/utils/Utils.java | 21 --- 10 files changed, 149 insertions(+), 253 deletions(-) delete mode 100644 src/main/java/de/hysky/skyblocker/skyblock/EssenceShopPrice.java create mode 100644 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/EssenceShopPrice.java diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index ad3ccc1f3a..08b0915a57 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -27,8 +27,8 @@ import de.hysky.skyblocker.skyblock.end.EnderNodes; import de.hysky.skyblocker.skyblock.end.TheEnd; import de.hysky.skyblocker.skyblock.entity.MobBoundingBoxes; -import de.hysky.skyblocker.skyblock.fancybars.FancyStatusBars; import de.hysky.skyblocker.skyblock.events.EventNotifications; +import de.hysky.skyblocker.skyblock.fancybars.FancyStatusBars; import de.hysky.skyblocker.skyblock.garden.FarmingHud; import de.hysky.skyblocker.skyblock.garden.LowerSensitivity; import de.hysky.skyblocker.skyblock.garden.VisitorHelper; @@ -48,11 +48,7 @@ import de.hysky.skyblocker.skyblock.tabhud.TabHud; import de.hysky.skyblocker.skyblock.tabhud.screenbuilder.ScreenMaster; import de.hysky.skyblocker.skyblock.tabhud.util.PlayerListMgr; -import de.hysky.skyblocker.skyblock.waypoint.FairySouls; -import de.hysky.skyblocker.skyblock.waypoint.MythologicalRitual; -import de.hysky.skyblocker.skyblock.waypoint.OrderedWaypoints; -import de.hysky.skyblocker.skyblock.waypoint.Relics; -import de.hysky.skyblocker.skyblock.waypoint.Waypoints; +import de.hysky.skyblocker.skyblock.waypoint.*; import de.hysky.skyblocker.utils.*; import de.hysky.skyblocker.utils.chat.ChatMessageListener; import de.hysky.skyblocker.utils.discord.DiscordRPCManager; @@ -200,7 +196,6 @@ public void onInitializeClient() { EggFinder.init(); TimeTowerReminder.init(); SkyblockTime.init(); - new EssenceShopPrice(); JerryTimer.init(); TooltipManager.init(); SlotTextManager.init(); diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java index 2c989b8422..0f9cd0f36a 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -224,9 +224,9 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig .build()) .option(Option.createBuilder() .name(Text.translatable("skyblocker.config.general.itemTooltip.showEssenceCost")) - .binding(defaults.general.itemTooltip.showEssenceCost, - () -> config.general.itemTooltip.showEssenceCost, - newValue -> config.general.itemTooltip.showEssenceCost = newValue) + .binding(defaults.uiAndVisuals.showEssenceCost, + () -> config.uiAndVisuals.showEssenceCost, + newValue -> config.uiAndVisuals.showEssenceCost = newValue) .controller(ConfigUtils::createBooleanController) .build()) diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index 465db24d07..3d3548ae4b 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -8,7 +8,7 @@ import java.util.ArrayList; import java.util.List; -public class UIAndVisualsConfig { +public class UIAndVisualsConfig { @SerialEntry public boolean compactorDeletorPreview = true; @@ -30,6 +30,9 @@ public class UIAndVisualsConfig { @SerialEntry public boolean showEquipmentInInventory = true; + @SerialEntry + public boolean showEssenceCost = true; + @SerialEntry public ChestValue chestValue = new ChestValue(); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/EssenceShopPrice.java b/src/main/java/de/hysky/skyblocker/skyblock/EssenceShopPrice.java deleted file mode 100644 index 63c4cbdea7..0000000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/EssenceShopPrice.java +++ /dev/null @@ -1,87 +0,0 @@ -package de.hysky.skyblocker.skyblock; - -import com.google.gson.JsonObject; -import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.skyblock.item.tooltip.TooltipInfoType; -import de.hysky.skyblocker.utils.RegexUtils; -import de.hysky.skyblocker.utils.Utils; -import it.unimi.dsi.fastutil.longs.LongBooleanPair; -import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; -import net.minecraft.client.item.TooltipType; -import net.minecraft.item.Item; -import net.minecraft.item.ItemStack; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; -import java.util.List; -import java.util.Locale; -import java.util.OptionalLong; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class EssenceShopPrice { - private static final Logger LOGGER = LoggerFactory.getLogger(EssenceShopPrice.class); - private static final Pattern ESSENCE_PATTERN = Pattern.compile("Cost (?[0-9,]+) (?[A-Za-z]+) Essence"); - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,###.#", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); - - public EssenceShopPrice() { - ItemTooltipCallback.EVENT.register(EssenceShopPrice::handleTooltip); - } - - //TODO: maybe move the price value right after the essence amount ex: "1,500 Wither Essence (645k coins)" - private static void handleTooltip(ItemStack stack, Item.TooltipContext tooltipContext, TooltipType tooltipType, List lines) { - if (!SkyblockerConfigManager.get().uiAndVisuals.showEssenceCost) return; - if (!(MinecraftClient.getInstance().currentScreen instanceof GenericContainerScreen screen) || !screen.getTitle().getString().contains("Essence Shop")) return; - String lore = Utils.concatenateLore(lines); - Matcher essenceMatcher = ESSENCE_PATTERN.matcher(lore); - OptionalLong cost = RegexUtils.getLongFromMatcher(essenceMatcher); - long costValue = 0; - if (cost.isPresent()) { - String type = essenceMatcher.group("type"); - int amount = Integer.parseInt(essenceMatcher.group("amount").replace(",", "")); - - LongBooleanPair priceData = getItemPrice(("ESSENCE_" + type).toUpperCase()); - - priceData.rightBoolean(); - - costValue += priceData.leftLong() * amount; - addPriceInfoToLore(lines, costValue); - } - } - - private static void addPriceInfoToLore(List lines, long cost) { - lines.add(Text.empty() - .append(Text.literal("Price: ").formatted(Formatting.GRAY)) - .append(Text.literal(DECIMAL_FORMAT.format(cost) + " coins").formatted(Formatting.GOLD))); - } - - /** - * @return An {@link LongBooleanPair} with the {@code left long} representing the item's price, and the {@code right boolean} indicating if the price - * was based on complete data. - */ - private static LongBooleanPair getItemPrice(String id) { - JsonObject bazaarPrices = TooltipInfoType.BAZAAR.getData(); - JsonObject lbinPrices = TooltipInfoType.LOWEST_BINS.getData(); - - if (bazaarPrices == null || lbinPrices == null) return LongBooleanPair.of(0L, false); - - if (bazaarPrices.has(id)) { - JsonObject item = bazaarPrices.get(id).getAsJsonObject(); - boolean isPriceNull = item.get("sellPrice").isJsonNull(); - - return LongBooleanPair.of(isPriceNull ? 0L : (long) item.get("sellPrice").getAsDouble(), !isPriceNull); - } - - if (lbinPrices.has(id)) { - return LongBooleanPair.of((long) lbinPrices.get(id).getAsDouble(), true); - } - - return LongBooleanPair.of(0L, false); - } -} 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 9d1a4ce03d..cd4db72725 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java @@ -5,7 +5,6 @@ import de.hysky.skyblocker.skyblock.item.tooltip.adders.LineSmoothener; import de.hysky.skyblocker.utils.ItemUtils; import de.hysky.skyblocker.utils.RegexUtils; -import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.render.gui.ColorHighlight; import de.hysky.skyblocker.utils.render.gui.ContainerSolver; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; @@ -94,7 +93,7 @@ public ChocolateFactorySolver() { private static void onTick(MinecraftClient client) { if (ding != StraySound.NONE) { - dingTick = (++dingTick) % (ding == StraySound.NORMAL ? 5 : 3); + dingTick = (++dingTick) % (ding == StraySound.NORMAL ? 5 : 3); if (dingTick == 0) { client.getSoundManager().play(PositionedSoundInstance.master(ding == StraySound.NORMAL ? SoundEvents.BLOCK_NOTE_BLOCK_PLING.value() : SoundEvents.BLOCK_NOTE_BLOCK_HARP.value(), 1.f, 1.f)); } @@ -151,14 +150,15 @@ private static void updateFactoryInfo(Int2ObjectMap slots) { RegexUtils.getLongFromMatcher(CHOCOLATE_PATTERN.matcher(slots.get(CHOCOLATE_SLOT).getName().getString())).ifPresent(l -> totalChocolate = l); //Cps item (cocoa bean) is in slot 45 - String cpsItemLore = Utils.getConcatenatedLore(slots.get(45)); + String cpsItemLore = ItemUtils.getConcatenatedLore(slots.get(CPS_SLOT)); Matcher cpsMatcher = CPS_PATTERN.matcher(cpsItemLore); RegexUtils.getDoubleFromMatcher(cpsMatcher).ifPresent(d -> totalCps = d); Matcher multiplierMatcher = TOTAL_MULTIPLIER_PATTERN.matcher(cpsItemLore); RegexUtils.getDoubleFromMatcher(multiplierMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0).ifPresent(d -> totalCpsMultiplier = d); //Prestige item is in slot 28 - Matcher prestigeMatcher = PRESTIGE_REQUIREMENT_PATTERN.matcher(Utils.getConcatenatedLore(slots.get(28))); + String prestigeLore = ItemUtils.getConcatenatedLore(slots.get(PRESTIGE_SLOT)); + Matcher prestigeMatcher = PRESTIGE_REQUIREMENT_PATTERN.matcher(prestigeLore); OptionalLong currentChocolate = RegexUtils.getLongFromMatcher(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 @@ -177,9 +177,12 @@ private static void updateFactoryInfo(Int2ObjectMap slots) { } //Time Tower is in slot 39 - timeTowerMultiplier = romanToDecimal(StringUtils.substringAfterLast(slots.get(39).getName().getString(), ' ')) / 10.0; //The name holds the level, which is multiplier * 10 in roman numerals - Matcher timeTowerStatusMatcher = TIME_TOWER_STATUS_PATTERN.matcher(Utils.getConcatenatedLore(slots.get(39))); - if (timeTowerStatusMatcher.find()) { + 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); + Matcher timeTowerStatusMatcher = TIME_TOWER_STATUS_PATTERN.matcher(timeTowerLore); + if (timeTowerStatusMatcher.find(timeTowerMultiplierMatcher.hasMatch() ? timeTowerMultiplierMatcher.end() : 0)) { isTimeTowerActive = timeTowerStatusMatcher.group(1).equals("ACTIVE"); } @@ -187,29 +190,9 @@ private static void updateFactoryInfo(Int2ObjectMap slots) { cpsIncreaseFactors.sort(Comparator.comparingDouble(rabbit -> rabbit.cost() / rabbit.cpsIncrease())); //Ascending order, lower = better } - /** - * Utility method. - */ - private static String getConcatenatedLore(ItemStack item) { - return concatenateLore(ItemUtils.getLore(item)); - } - - /** - * Concatenates the lore of an item into one string. - * This is useful in case some pattern we're looking for is split into multiple lines, which would make it harder to regex. - */ - private static String concatenateLore(List lore) { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < lore.size(); i++) { - stringBuilder.append(lore.get(i).getString()); - if (i != lore.size() - 1) stringBuilder.append(" "); - } - return stringBuilder.toString(); - } - private static Optional getCoach(ItemStack coachItem) { if (!coachItem.isOf(Items.PLAYER_HEAD)) return Optional.empty(); - String coachLore = getConcatenatedLore(coachItem); + String coachLore = ItemUtils.getConcatenatedLore(coachItem); if (totalCps < 0 || totalCpsMultiplier < 0) return Optional.empty(); //We need these 2 to calculate the increase in cps. @@ -231,7 +214,7 @@ private static Optional getCoach(ItemStack coachItem) { } private static Optional getRabbit(ItemStack item, int slot) { - String lore = getConcatenatedLore(item); + String lore = ItemUtils.getConcatenatedLore(item); Matcher cpsMatcher = CPS_INCREASE_PATTERN.matcher(lore); OptionalInt currentCps = RegexUtils.getIntFromMatcher(cpsMatcher); if (currentCps.isEmpty()) return Optional.empty(); @@ -244,7 +227,7 @@ private static Optional getRabbit(ItemStack item, int slot) { Matcher costMatcher = COST_PATTERN.matcher(lore); OptionalLong cost = RegexUtils.getLongFromMatcher(costMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0); //Cost comes after the cps line if (cost.isEmpty()) return Optional.empty(); - return Optional.of(new Rabbit((nextCps.getAsInt() - currentCps.getAsInt())*(totalCpsMultiplier < 0 ? 1 : totalCpsMultiplier), cost.getAsLong(), slot)); + return Optional.of(new Rabbit((nextCps.getAsInt() - currentCps.getAsInt()) * (totalCpsMultiplier < 0 ? 1 : totalCpsMultiplier), cost.getAsLong(), slot)); } private static Optional getPrestigeHighlight() { @@ -268,7 +251,7 @@ private static List getStrayRabbitHighlight(Int2ObjectMap //It should be set to true if there's any information added, false otherwise. boolean shouldAddLine = false; - String lore = Utils.concatenateLore(lines); - Matcher costMatcher = COST_PATTERN.matcher(lore); - OptionalLong cost = RegexUtils.getLongFromMatcher(costMatcher); - //Available on all items with a chocolate cost - if (cost.isPresent()) shouldAddLine = addUpgradeTimerToLore(lines, cost.getAsLong()); + String lore = ItemUtils.concatenateLore(lines); + Matcher costMatcher = COST_PATTERN.matcher(lore); + OptionalLong cost = RegexUtils.getLongFromMatcher(costMatcher); + //Available on all items with a chocolate cost + if (cost.isPresent()) shouldAddLine |= addUpgradeTimerToLore(lines, cost.getAsLong()); + + int index = focusedSlot.id; //Prestige item if (index == PRESTIGE_SLOT) { @@ -386,96 +371,23 @@ private 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()).formatted(Formatting.GOLD); - } - - private static Optional getCoach(ItemStack coachItem) { - if (!coachItem.isOf(Items.PLAYER_HEAD)) return Optional.empty(); - String coachLore = Utils.getConcatenatedLore(coachItem); - - if (totalCpsMultiplier == -1.0) return Optional.empty(); //We need the total multiplier to calculate the increase in cps. - - Matcher multiplierIncreaseMatcher = MULTIPLIER_INCREASE_PATTERN.matcher(coachLore); - OptionalDouble currentCpsMultiplier = RegexUtils.getDoubleFromMatcher(multiplierIncreaseMatcher); - if (currentCpsMultiplier.isEmpty()) return Optional.empty(); - - OptionalDouble nextCpsMultiplier = RegexUtils.getDoubleFromMatcher(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. - } - - Matcher costMatcher = COST_PATTERN.matcher(coachLore); - OptionalInt cost = RegexUtils.getIntFromMatcher(costMatcher, multiplierIncreaseMatcher.hasMatch() ? multiplierIncreaseMatcher.end() : 0); //Cost comes after the multiplier line - if (cost.isEmpty()) return Optional.empty(); - - return Optional.of(new Rabbit(totalCps / totalCpsMultiplier * (nextCpsMultiplier.getAsDouble() - currentCpsMultiplier.getAsDouble()), cost.getAsInt(), 42, coachItem)); - } - - private static Optional getRabbit(ItemStack item, int slot) { - String lore = Utils.getConcatenatedLore(item); - Matcher cpsMatcher = CPS_INCREASE_PATTERN.matcher(lore); - OptionalInt currentCps = RegexUtils.getIntFromMatcher(cpsMatcher); - if (currentCps.isEmpty()) return Optional.empty(); - OptionalInt nextCps = RegexUtils.getIntFromMatcher(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); - OptionalInt cost = RegexUtils.getIntFromMatcher(costMatcher, cpsMatcher.hasMatch() ? cpsMatcher.end() : 0); //Cost comes after the cps line - if (cost.isEmpty()) return Optional.empty(); - return Optional.of(new Rabbit(nextCps.getAsInt() - currentCps.getAsInt(), cost.getAsInt(), slot, item)); - } - - private static Optional getPrestigeHighlight(ItemStack item) { - List loreList = ItemUtils.getLore(item); - if (loreList.isEmpty()) return Optional.empty(); - - String lore = loreList.getLast().getString(); //The last line holds the text we're looking for - if (lore.equals("Click to prestige!")) return Optional.of(ColorHighlight.green(28)); - return Optional.of(ColorHighlight.red(28)); - } - - private record Rabbit(double cpsIncrease, int cost, int slot, ItemStack itemStack) { - } - - //Perhaps the part below can go to a separate file later on, but I couldn't find a proper name for the class, so they're staying here. - private static final Map romanMap = Map.of( - 'I', 1, - 'V', 5, - 'X', 10, - 'L', 50, - 'C', 100, - 'D', 500, - 'M', 1000 - ); - - public static int romanToDecimal(String romanNumeral) { - int decimal = 0; - int lastNumber = 0; - for (int i = romanNumeral.length() - 1; i >= 0; i--) { - char ch = romanNumeral.charAt(i); - decimal = romanMap.get(ch) >= lastNumber ? decimal + romanMap.get(ch) : decimal - romanMap.get(ch); - lastNumber = romanMap.get(ch); + 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 decimal; } } diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java index 92adf49dce..389cfa69c7 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java @@ -4,6 +4,7 @@ import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.config.configs.GeneralConfig; +import de.hysky.skyblocker.skyblock.item.tooltip.adders.EssenceShopPrice; import de.hysky.skyblocker.utils.Http; import de.hysky.skyblocker.utils.Utils; import org.jetbrains.annotations.Nullable; @@ -16,7 +17,7 @@ public enum TooltipInfoType implements Runnable { NPC("https://hysky.de/api/npcprice", itemTooltip -> itemTooltip.enableNPCPrice, true), - BAZAAR("https://hysky.de/api/bazaar", itemTooltip -> itemTooltip.enableBazaarPrice || itemTooltip.enableCraftingCost.getOrder() != null || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableBazaarPrice, false), + BAZAAR("https://hysky.de/api/bazaar", itemTooltip -> itemTooltip.enableBazaarPrice || itemTooltip.enableCraftingCost.getOrder() != null || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableBazaarPrice, false, EssenceShopPrice::refreshEssencePrices), LOWEST_BINS("https://hysky.de/api/auctions/lowestbins", itemTooltip -> itemTooltip.enableLowestBIN || itemTooltip.enableCraftingCost.getOrder() != null || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableLowestBIN, false), ONE_DAY_AVERAGE("https://hysky.de/api/auctions/lowestbins/average/1day.json", itemTooltip -> itemTooltip.enableAvgBIN, false), THREE_DAY_AVERAGE("https://hysky.de/api/auctions/lowestbins/average/3day.json", itemTooltip -> itemTooltip.enableAvgBIN || SkyblockerConfigManager.get().uiAndVisuals.searchOverlay.enableAuctionHouse, itemTooltip -> itemTooltip.enableAvgBIN, false), diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipManager.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipManager.java index bd06acba51..c3399b58f7 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipManager.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipManager.java @@ -30,13 +30,14 @@ public class TooltipManager { new BazaarPriceTooltip(2), new LBinTooltip(3), new AvgBinTooltip(4), - new CraftPriceTooltip(5), - new DungeonQualityTooltip(6), - new MotesTooltip(7), - new ObtainedDateTooltip(8), - new MuseumTooltip(9), - new ColorTooltip(10), - new AccessoryTooltip(11), + new EssenceShopPrice(5), + new CraftPriceTooltip(6), + new DungeonQualityTooltip(7), + new MotesTooltip(8), + new ObtainedDateTooltip(9), + new MuseumTooltip(10), + new ColorTooltip(11), + new AccessoryTooltip(12), }; private static final ArrayList currentScreenAdders = new ArrayList<>(); 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 new file mode 100644 index 0000000000..a2efa1af17 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/EssenceShopPrice.java @@ -0,0 +1,72 @@ +package de.hysky.skyblocker.skyblock.item.tooltip.adders; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.skyblock.item.tooltip.TooltipAdder; +import de.hysky.skyblocker.utils.ItemUtils; +import de.hysky.skyblocker.utils.RegexUtils; +import it.unimi.dsi.fastutil.objects.Object2LongArrayMap; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DecimalFormat; +import java.text.DecimalFormatSymbols; +import java.util.List; +import java.util.Locale; +import java.util.OptionalLong; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class EssenceShopPrice extends TooltipAdder { + private static final Logger LOGGER = LoggerFactory.getLogger(EssenceShopPrice.class); + private static final Pattern ESSENCE_PATTERN = Pattern.compile("Cost (?[\\d,]+) (?[A-Za-z]+) Essence"); + private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,###.#", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); + private static final String[] ESSENCE_TYPES = {"WITHER", "SPIDER", "UNDEAD", "DRAGON", "GOLD", "DIAMOND", "ICE", "CRIMSON"}; + private static final Object2LongArrayMap ESSENCE_PRICES = new Object2LongArrayMap<>(ESSENCE_TYPES, new long[8]); + + public EssenceShopPrice(int priority) { + super("\\S+ Essence Shop", priority); + } + + public static void refreshEssencePrices(JsonObject data) { + for (String essenceType : ESSENCE_TYPES) { + JsonElement price = data.get("ESSENCE_" + essenceType); + if (price == null || !price.isJsonObject()) continue; + JsonElement sellPrice = price.getAsJsonObject().get("sellPrice"); + if (sellPrice == null) continue; + if (sellPrice.isJsonPrimitive()) { + ESSENCE_PRICES.put(essenceType, sellPrice.getAsLong()); + } + } + LOGGER.info("[Skyblocker] Refreshed essence prices."); + } + + //Todo: maybe move the price value right after the essence amount ex: "1,500 Wither Essence (645k coins)" + @Override + public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List lines) { + if (!SkyblockerConfigManager.get().uiAndVisuals.showEssenceCost) return; + + String lore = ItemUtils.concatenateLore(lines); + Matcher essenceMatcher = ESSENCE_PATTERN.matcher(lore); + OptionalLong cost = RegexUtils.getLongFromMatcher(essenceMatcher); + if (cost.isEmpty()) return; + + String type = essenceMatcher.group("type"); + long priceData = ESSENCE_PRICES.getLong(type.toUpperCase(Locale.ROOT)); + if (priceData == 0) return; //Default value for getLong is 0 if no value exists for that key + + lines.add(Text.empty() + .append(Text.literal("Essence Cost: ").formatted(Formatting.AQUA)) + .append(Text.literal(DECIMAL_FORMAT.format(priceData * cost.getAsLong()) + " coins").formatted(Formatting.DARK_AQUA)) + .append(Text.literal(" (").formatted(Formatting.GRAY)) + .append(Text.literal(DECIMAL_FORMAT.format(priceData) + " each").formatted(Formatting.GRAY)) + .append(Text.literal(")").formatted(Formatting.GRAY)) + ); + } +} diff --git a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java index 658078868e..894ef8ecd2 100644 --- a/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java +++ b/src/main/java/de/hysky/skyblocker/utils/ItemUtils.java @@ -283,4 +283,24 @@ public static Matcher getLoreLineIfContainsMatch(ItemStack stack, Pattern patter throw new RuntimeException(e); } } + + /** + * Utility method. + */ + public static @NotNull String getConcatenatedLore(@NotNull ItemStack item) { + return concatenateLore(getLore(item)); + } + + /** + * Concatenates the lore of an item into one string. + * This is useful in case some pattern we're looking for is split into multiple lines, which would make it harder to regex. + */ + public static @NotNull String concatenateLore(@NotNull List lore) { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < lore.size(); i++) { + stringBuilder.append(lore.get(i).getString()); + if (i != lore.size() - 1) stringBuilder.append(" "); + } + return stringBuilder.toString(); + } } diff --git a/src/main/java/de/hysky/skyblocker/utils/Utils.java b/src/main/java/de/hysky/skyblocker/utils/Utils.java index 0a8c7c8046..042095d1dd 100644 --- a/src/main/java/de/hysky/skyblocker/utils/Utils.java +++ b/src/main/java/de/hysky/skyblocker/utils/Utils.java @@ -21,7 +21,6 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; import net.minecraft.client.network.PlayerListEntry; -import net.minecraft.item.ItemStack; import net.minecraft.scoreboard.*; import net.minecraft.text.MutableText; import net.minecraft.text.Text; @@ -555,26 +554,6 @@ public static void sendMessageToBypassEvents(Text message) { client.getNarratorManager().narrateSystemMessage(message); } - /** - * Utility method. - */ - public static String getConcatenatedLore(ItemStack item) { - return concatenateLore(ItemUtils.getLore(item)); - } - - /** - * Concatenates the lore of an item into one string. - * This is useful in case some pattern we're looking for is split into multiple lines, which would make it harder to regex. - */ - public static String concatenateLore(List lore) { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < lore.size(); i++) { - stringBuilder.append(lore.get(i).getString()); - if (i != lore.size() - 1) stringBuilder.append(" "); - } - return stringBuilder.toString(); - } - public static String getUndashedUuid() { return UndashedUuid.toString(MinecraftClient.getInstance().getSession().getUuidOrNull()); } From 58911a1e08ea209fa3f14375422489e2f496cee2 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:01:42 +0800 Subject: [PATCH 5/6] Refactor essence shop price --- .../config/categories/GeneralCategory.java | 8 +++---- .../config/configs/GeneralConfig.java | 6 +++--- .../config/configs/UIAndVisualsConfig.java | 6 +----- .../item/tooltip/adders/EssenceShopPrice.java | 21 +++++++------------ 4 files changed, 16 insertions(+), 25 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java index 0f9cd0f36a..ab674b185b 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -221,14 +221,14 @@ public static ConfigCategory create(SkyblockerConfig defaults, SkyblockerConfig newValue -> config.general.itemTooltip.dungeonQuality = newValue) .controller(ConfigUtils::createBooleanController) .build()) - .build()) .option(Option.createBuilder() .name(Text.translatable("skyblocker.config.general.itemTooltip.showEssenceCost")) - .binding(defaults.uiAndVisuals.showEssenceCost, - () -> config.uiAndVisuals.showEssenceCost, - newValue -> config.uiAndVisuals.showEssenceCost = newValue) + .binding(defaults.general.itemTooltip.showEssenceCost, + () -> config.general.itemTooltip.showEssenceCost, + newValue -> config.general.itemTooltip.showEssenceCost = newValue) .controller(ConfigUtils::createBooleanController) .build()) + .build()) //Item Info Display .group(OptionGroup.createBuilder() diff --git a/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java index 786eac84a7..691e6f794b 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/GeneralConfig.java @@ -51,9 +51,6 @@ public class GeneralConfig { @SerialEntry public List lockedSlots = new ArrayList<>(); - @SerialEntry - public boolean showEssenceCost = false; - //maybe put this 5 somewhere else @SerialEntry public ObjectOpenHashSet protectedItems = new ObjectOpenHashSet<>(); @@ -134,6 +131,9 @@ public static class ItemTooltip { @SerialEntry public boolean dungeonQuality = true; + + @SerialEntry + public boolean showEssenceCost = false; } public enum Average { diff --git a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java index 3d3548ae4b..80bdb1c924 100644 --- a/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java @@ -8,7 +8,7 @@ import java.util.ArrayList; import java.util.List; -public class UIAndVisualsConfig { +public class UIAndVisualsConfig { @SerialEntry public boolean compactorDeletorPreview = true; @@ -30,9 +30,6 @@ public class UIAndVisualsConfig { @SerialEntry public boolean showEquipmentInInventory = true; - @SerialEntry - public boolean showEssenceCost = true; - @SerialEntry public ChestValue chestValue = new ChestValue(); @@ -69,7 +66,6 @@ public class UIAndVisualsConfig { @SerialEntry public CompactDamage compactDamage = new CompactDamage(); - public static class ChestValue { @SerialEntry public boolean enableChestValue = true; 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 a2efa1af17..5a7051d3cf 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 @@ -12,11 +12,8 @@ import net.minecraft.text.Text; import net.minecraft.util.Formatting; import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import java.text.DecimalFormat; -import java.text.DecimalFormatSymbols; +import java.text.NumberFormat; import java.util.List; import java.util.Locale; import java.util.OptionalLong; @@ -24,9 +21,8 @@ import java.util.regex.Pattern; public class EssenceShopPrice extends TooltipAdder { - private static final Logger LOGGER = LoggerFactory.getLogger(EssenceShopPrice.class); private static final Pattern ESSENCE_PATTERN = Pattern.compile("Cost (?[\\d,]+) (?[A-Za-z]+) Essence"); - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("#,###.#", DecimalFormatSymbols.getInstance(Locale.ENGLISH)); + private static final NumberFormat DECIMAL_FORMAT = NumberFormat.getInstance(Locale.US); private static final String[] ESSENCE_TYPES = {"WITHER", "SPIDER", "UNDEAD", "DRAGON", "GOLD", "DIAMOND", "ICE", "CRIMSON"}; private static final Object2LongArrayMap ESSENCE_PRICES = new Object2LongArrayMap<>(ESSENCE_TYPES, new long[8]); @@ -44,13 +40,12 @@ public static void refreshEssencePrices(JsonObject data) { ESSENCE_PRICES.put(essenceType, sellPrice.getAsLong()); } } - LOGGER.info("[Skyblocker] Refreshed essence prices."); } //Todo: maybe move the price value right after the essence amount ex: "1,500 Wither Essence (645k coins)" @Override public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List lines) { - if (!SkyblockerConfigManager.get().uiAndVisuals.showEssenceCost) return; + if (!SkyblockerConfigManager.get().general.itemTooltip.showEssenceCost) return; String lore = ItemUtils.concatenateLore(lines); Matcher essenceMatcher = ESSENCE_PATTERN.matcher(lore); @@ -62,11 +57,11 @@ public void addToTooltip(@Nullable Slot focusedSlot, ItemStack stack, List if (priceData == 0) return; //Default value for getLong is 0 if no value exists for that key lines.add(Text.empty() - .append(Text.literal("Essence Cost: ").formatted(Formatting.AQUA)) - .append(Text.literal(DECIMAL_FORMAT.format(priceData * cost.getAsLong()) + " coins").formatted(Formatting.DARK_AQUA)) - .append(Text.literal(" (").formatted(Formatting.GRAY)) - .append(Text.literal(DECIMAL_FORMAT.format(priceData) + " each").formatted(Formatting.GRAY)) - .append(Text.literal(")").formatted(Formatting.GRAY)) + .append(Text.literal("Essence Cost: ").formatted(Formatting.AQUA)) + .append(Text.literal(DECIMAL_FORMAT.format(priceData * cost.getAsLong()) + " coins").formatted(Formatting.DARK_AQUA)) + .append(Text.literal(" (").formatted(Formatting.GRAY)) + .append(Text.literal(DECIMAL_FORMAT.format(priceData) + " each").formatted(Formatting.GRAY)) + .append(Text.literal(")").formatted(Formatting.GRAY)) ); } } From e1543a69ba3ed4b10a0cdbbdeeefc8ff8a017743 Mon Sep 17 00:00:00 2001 From: Kevinthegreat <92656833+kevinthegreat1@users.noreply.github.com> Date: Thu, 18 Jul 2024 15:59:48 +0800 Subject: [PATCH 6/6] Refactor TooltipInfoType --- .../item/tooltip/TooltipInfoType.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java index 389cfa69c7..46f4cb589f 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipInfoType.java @@ -17,7 +17,7 @@ public enum TooltipInfoType implements Runnable { NPC("https://hysky.de/api/npcprice", itemTooltip -> itemTooltip.enableNPCPrice, true), - BAZAAR("https://hysky.de/api/bazaar", itemTooltip -> itemTooltip.enableBazaarPrice || itemTooltip.enableCraftingCost.getOrder() != null || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableBazaarPrice, false, EssenceShopPrice::refreshEssencePrices), + BAZAAR("https://hysky.de/api/bazaar", itemTooltip -> itemTooltip.enableBazaarPrice || itemTooltip.enableCraftingCost.getOrder() != null || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue || itemTooltip.showEssenceCost, itemTooltip -> itemTooltip.enableBazaarPrice, false, EssenceShopPrice::refreshEssencePrices), LOWEST_BINS("https://hysky.de/api/auctions/lowestbins", itemTooltip -> itemTooltip.enableLowestBIN || itemTooltip.enableCraftingCost.getOrder() != null || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.enableProfitCalculator || SkyblockerConfigManager.get().dungeons.dungeonChestProfit.croesusProfit || SkyblockerConfigManager.get().uiAndVisuals.chestValue.enableChestValue, itemTooltip -> itemTooltip.enableLowestBIN, false), ONE_DAY_AVERAGE("https://hysky.de/api/auctions/lowestbins/average/1day.json", itemTooltip -> itemTooltip.enableAvgBIN, false), THREE_DAY_AVERAGE("https://hysky.de/api/auctions/lowestbins/average/3day.json", itemTooltip -> itemTooltip.enableAvgBIN || SkyblockerConfigManager.get().uiAndVisuals.searchOverlay.enableAuctionHouse, itemTooltip -> itemTooltip.enableAvgBIN, false), @@ -30,10 +30,10 @@ public enum TooltipInfoType implements Runnable { private final String address; private final Predicate dataEnabled; private final Predicate tooltipEnabled; - private JsonObject data; + private @Nullable JsonObject data; private final boolean cacheable; private long hash; - private final Consumer callback; + private final @Nullable Consumer callback; /** * Use this for when you're adding tooltip info that has no data associated with it @@ -46,19 +46,19 @@ public enum TooltipInfoType implements Runnable { * @param address the address to download the data from * @param enabled the predicate to check if the data should be downloaded and the tooltip should be shown * @param cacheable whether the data should be cached - * @param callback called when the {@code data} is refreshed */ - TooltipInfoType(String address, Predicate enabled, boolean cacheable, Consumer callback) { - this(address, enabled, enabled, cacheable, callback); + TooltipInfoType(String address, Predicate enabled, boolean cacheable) { + this(address, enabled, enabled, cacheable, null); } /** * @param address the address to download the data from * @param enabled the predicate to check if the data should be downloaded and the tooltip should be shown * @param cacheable whether the data should be cached + * @param callback called when the {@code data} is refreshed */ - TooltipInfoType(String address, Predicate enabled, boolean cacheable) { - this(address, enabled, enabled, cacheable, null); + TooltipInfoType(String address, Predicate enabled, boolean cacheable, Consumer callback) { + this(address, enabled, enabled, cacheable, callback); } /** @@ -100,7 +100,7 @@ public boolean isTooltipEnabled() { return tooltipEnabled.test(ItemTooltip.config); } - public JsonObject getData() { + public @Nullable JsonObject getData() { return data; } @@ -161,14 +161,14 @@ public void run() { } String response = Http.sendGetRequest(address); if (response.trim().startsWith("