diff options
Diffstat (limited to 'src/main/java/de/hysky/skyblocker')
-rw-r--r-- | src/main/java/de/hysky/skyblocker/SkyblockerMod.java | 2 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java | 14 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java | 4 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java | 31 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/mixin/ClientPlayerEntityMixin.java | 2 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java | 2 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java | 2 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java | 230 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonChestProfit.java | 170 | ||||
-rw-r--r-- | src/main/java/de/hysky/skyblocker/skyblock/item/HotbarSlotLock.java (renamed from src/main/java/de/hysky/skyblocker/skyblock/HotbarSlotLock.java) | 2 |
10 files changed, 282 insertions, 177 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index cbe82667..ac19542a 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -98,7 +98,7 @@ public class SkyblockerMod implements ClientModInitializer { DungeonMap.init(); DungeonSecrets.init(); DungeonBlaze.init(); - DungeonChestProfit.init(); + ChestValue.init(); TheRift.init(); TitleContainer.init(); ScreenMaster.init(); diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java index 1c6bb394..3c8e6739 100644 --- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java +++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java @@ -207,6 +207,9 @@ public class SkyblockerConfig { public WikiLookup wikiLookup = new WikiLookup(); @SerialEntry + public ChestValue chestValue = new ChestValue(); + + @SerialEntry public SpecialEffects specialEffects = new SpecialEffects(); @SerialEntry @@ -547,6 +550,17 @@ public class SkyblockerConfig { public boolean officialWiki = false; } + public static class ChestValue { + @SerialEntry + public boolean enableChestValue = true; + + @SerialEntry + public Formatting color = Formatting.DARK_GREEN; + + @SerialEntry + public Formatting incompleteColor = Formatting.BLUE; + } + public static class SpecialEffects { @SerialEntry public boolean rareDungeonDropEffects = true; diff --git a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java index 7bb6414c..37f268b0 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java @@ -204,8 +204,8 @@ public class DungeonsCategory { .controller(EnumDropdownControllerBuilder.getFactory(ConfigUtils.FORMATTING_TO_STRING)) .build()) .option(Option.<Formatting>createBuilder() - .name(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.incompleteColor")) - .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.dungeons.dungeonChestProfit.incompleteColor.@Tooltip"))) + .name(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue.incompleteColor")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue.incompleteColor.@Tooltip"))) .binding(defaults.locations.dungeons.dungeonChestProfit.incompleteColor, () -> config.locations.dungeons.dungeonChestProfit.incompleteColor, newValue -> config.locations.dungeons.dungeonChestProfit.incompleteColor = newValue) 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 be5f0665..8d8c6f46 100644 --- a/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java +++ b/src/main/java/de/hysky/skyblocker/config/categories/GeneralCategory.java @@ -2,6 +2,7 @@ package de.hysky.skyblocker.config.categories; import de.hysky.skyblocker.config.ConfigUtils; import de.hysky.skyblocker.config.SkyblockerConfig; +import de.hysky.skyblocker.config.controllers.EnumDropdownControllerBuilder; import de.hysky.skyblocker.skyblock.shortcut.ShortcutsConfigScreen; import de.hysky.skyblocker.utils.render.title.TitleContainerConfigScreen; import de.hysky.skyblocker.utils.waypoint.Waypoint; @@ -11,6 +12,7 @@ import dev.isxander.yacl3.api.controller.FloatSliderControllerBuilder; import dev.isxander.yacl3.api.controller.IntegerSliderControllerBuilder; import net.minecraft.client.MinecraftClient; import net.minecraft.text.Text; +import net.minecraft.util.Formatting; public class GeneralCategory { @@ -455,6 +457,35 @@ public class GeneralCategory { .build()) .build()) + //Chest Value + .group(OptionGroup.createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue")) + .collapsed(true) + .option(Option.<Boolean>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue.enableChestValue")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue.enableChestValue.@Tooltip"))) + .binding(defaults.general.chestValue.enableChestValue, + () -> config.general.chestValue.enableChestValue, + newValue -> config.general.chestValue.enableChestValue = newValue) + .controller(ConfigUtils::createBooleanController) + .build()) + .option(Option.<Formatting>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue.color")) + .binding(defaults.general.chestValue.color, + () -> config.general.chestValue.color, + newValue -> config.general.chestValue.color = newValue) + .controller(EnumDropdownControllerBuilder.getFactory(ConfigUtils.FORMATTING_TO_STRING)) + .build()) + .option(Option.<Formatting>createBuilder() + .name(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue.incompleteColor")) + .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue.incompleteColor.@Tooltip"))) + .binding(defaults.general.chestValue.incompleteColor, + () -> config.general.chestValue.incompleteColor, + newValue -> config.general.chestValue.incompleteColor = newValue) + .controller(EnumDropdownControllerBuilder.getFactory(ConfigUtils.FORMATTING_TO_STRING)) + .build()) + .build()) + //Special Effects .group(OptionGroup.createBuilder() .name(Text.translatable("text.autoconfig.skyblocker.option.general.specialEffects")) diff --git a/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerEntityMixin.java b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerEntityMixin.java index 37ae92e8..6813d654 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerEntityMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/ClientPlayerEntityMixin.java @@ -3,7 +3,7 @@ package de.hysky.skyblocker.mixin; import com.mojang.authlib.GameProfile; import dev.cbyrne.betterinject.annotations.Inject; -import de.hysky.skyblocker.skyblock.HotbarSlotLock; +import de.hysky.skyblocker.skyblock.item.HotbarSlotLock; import de.hysky.skyblocker.skyblock.item.ItemProtection; import de.hysky.skyblocker.skyblock.rift.HealingMelonIndicator; import de.hysky.skyblocker.utils.Utils; diff --git a/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java b/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java index 1b6d62d4..0ee7b528 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/InGameHudMixin.java @@ -5,7 +5,7 @@ import com.llamalad7.mixinextras.sugar.Local; import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.skyblock.FancyStatusBars; -import de.hysky.skyblocker.skyblock.HotbarSlotLock; +import de.hysky.skyblocker.skyblock.item.HotbarSlotLock; import de.hysky.skyblocker.skyblock.item.ItemCooldowns; import de.hysky.skyblocker.skyblock.dungeon.DungeonMap; import de.hysky.skyblocker.skyblock.item.ItemRarityBackgrounds; diff --git a/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java b/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java index 066490d5..29889c28 100644 --- a/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java +++ b/src/main/java/de/hysky/skyblocker/mixin/MinecraftClientMixin.java @@ -1,6 +1,6 @@ package de.hysky.skyblocker.mixin; -import de.hysky.skyblocker.skyblock.HotbarSlotLock; +import de.hysky.skyblocker.skyblock.item.HotbarSlotLock; import de.hysky.skyblocker.utils.Utils; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; diff --git a/src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java b/src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java new file mode 100644 index 00000000..8833a8d9 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java @@ -0,0 +1,230 @@ +package de.hysky.skyblocker.skyblock; + +import com.google.gson.JsonObject; +import de.hysky.skyblocker.config.SkyblockerConfig; +import de.hysky.skyblocker.config.SkyblockerConfigManager; +import de.hysky.skyblocker.mixin.accessor.HandledScreenAccessor; +import de.hysky.skyblocker.mixin.accessor.ScreenAccessor; +import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip; +import de.hysky.skyblocker.skyblock.item.tooltip.TooltipInfoType; +import de.hysky.skyblocker.utils.Utils; +import it.unimi.dsi.fastutil.ints.IntBooleanPair; +import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; +import net.fabricmc.fabric.api.client.screen.v1.Screens; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; +import net.minecraft.client.gui.tooltip.Tooltip; +import net.minecraft.client.gui.widget.ButtonWidget; +import net.minecraft.client.item.TooltipContext; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.GenericContainerScreenHandler; +import net.minecraft.screen.slot.Slot; +import net.minecraft.text.Text; +import net.minecraft.util.Formatting; +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.text.DecimalFormat; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ChestValue { + private static final Logger LOGGER = LoggerFactory.getLogger(ChestValue.class); + private static final Set<String> DUNGEON_CHESTS = Set.of("Wood Chest", "Gold Chest", "Diamond Chest", "Emerald Chest", "Obsidian Chest", "Bedrock Chest"); + private static final Pattern ESSENCE_PATTERN = Pattern.compile("(?<type>[A-Za-z]+) Essence x(?<amount>[0-9]+)"); + private static final DecimalFormat FORMATTER = new DecimalFormat("#,###"); + + public static void init() { + ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> { + if (Utils.isOnSkyblock() && screen instanceof GenericContainerScreen genericContainerScreen) { + Text title = screen.getTitle(); + String titleString = title.getString(); + if (DUNGEON_CHESTS.contains(titleString)) { + if (SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit.enableProfitCalculator) { + ScreenEvents.afterTick(screen).register(screen_ -> + ((ScreenAccessor) screen).setTitle(getDungeonChestProfit(genericContainerScreen.getScreenHandler(), title, titleString, client)) + ); + } + } else if (SkyblockerConfigManager.get().general.chestValue.enableChestValue && !titleString.equals("SkyBlock Menu")) { + Screens.getButtons(screen).add(ButtonWidget + .builder(Text.literal("$"), buttonWidget -> { + Screens.getButtons(screen).remove(buttonWidget); + ScreenEvents.afterTick(screen).register(screen_ -> + ((ScreenAccessor) screen).setTitle(getChestValue(genericContainerScreen.getScreenHandler(), title, titleString)) + ); + }) + .dimensions(((HandledScreenAccessor) genericContainerScreen).getX() + ((HandledScreenAccessor) genericContainerScreen).getBackgroundWidth() - 16, ((HandledScreenAccessor) genericContainerScreen).getY() + 4, 12, 12) + .tooltip(Tooltip.of(Text.translatable("text.autoconfig.skyblocker.option.general.chestValue.@Tooltip"))) + .build() + ); + } + } + }); + } + + private static Text getDungeonChestProfit(GenericContainerScreenHandler handler, Text title, String titleString, MinecraftClient client) { + try { + int profit = 0; + boolean hasIncompleteData = false, usedKismet = false; + List<Slot> slots = handler.slots.subList(0, handler.getRows() * 9); + + //If the item stack for the "Open Reward Chest" button or the kismet button hasn't been sent to the client yet + if (slots.get(31).getStack().isEmpty() || slots.get(50).getStack().isEmpty()) return title; + + for (Slot slot : slots) { + ItemStack stack = slot.getStack(); + if (stack.isEmpty()) { + continue; + } + + String name = stack.getName().getString(); + String id = ItemTooltip.getInternalNameFromNBT(stack, false); + + //Regular item price + if (id != null) { + IntBooleanPair priceData = getItemPrice(id); + + if (!priceData.rightBoolean()) hasIncompleteData = true; + + //Add the item price to the profit + profit += priceData.leftInt() * stack.getCount(); + + continue; + } + + //Essence price + if (name.contains("Essence") && SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit.includeEssence) { + Matcher matcher = ESSENCE_PATTERN.matcher(name); + + if (matcher.matches()) { + String type = matcher.group("type"); + int amount = Integer.parseInt(matcher.group("amount")); + + IntBooleanPair priceData = getItemPrice(("ESSENCE_" + type).toUpperCase()); + + if (!priceData.rightBoolean()) hasIncompleteData = true; + + //Add the price of the essence to the profit + profit += priceData.leftInt() * amount; + + continue; + } + } + + //Determine the cost of the chest + if (name.contains("Open Reward Chest")) { + String foundString = searchLoreFor(stack, client, "Coins"); + + //Incase we're searching the free chest + if (!StringUtils.isBlank(foundString)) { + profit -= Integer.parseInt(foundString.replaceAll("[^0-9]", "")); + } + + continue; + } + + //Determine if a kismet was used or not + if (name.contains("Reroll Chest")) { + usedKismet = !StringUtils.isBlank(searchLoreFor(stack, client, "You already rerolled a chest!")); + } + } + + if (SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit.includeKismet && usedKismet) { + IntBooleanPair kismetPriceData = getItemPrice("KISMET_FEATHER"); + + if (!kismetPriceData.rightBoolean()) hasIncompleteData = true; + + profit -= kismetPriceData.leftInt(); + } + + return Text.literal(titleString).append(getProfitText(profit, hasIncompleteData)); + } catch (Exception e) { + LOGGER.error("[Skyblocker Profit Calculator] Failed to calculate dungeon chest profit! ", e); + } + + return title; + } + + private static Text getChestValue(GenericContainerScreenHandler handler, Text title, String titleString) { + try { + int value = 0; + boolean hasIncompleteData = false; + List<Slot> slots = handler.slots.subList(0, handler.getRows() * 9); + + for (Slot slot : slots) { + ItemStack stack = slot.getStack(); + if (stack.isEmpty()) { + continue; + } + + String id = ItemTooltip.getInternalNameFromNBT(stack, false); + + if (id != null) { + IntBooleanPair priceData = getItemPrice(id); + + if (!priceData.rightBoolean()) hasIncompleteData = true; + + value += priceData.leftInt() * stack.getCount(); + } + } + + return Text.literal(titleString).append(getValueText(value, hasIncompleteData)); + } catch (Exception e) { + LOGGER.error("[Skyblocker Value Calculator] Failed to calculate dungeon chest value! ", e); + } + + return title; + } + + /** + * @return An {@link IntBooleanPair} with the {@code left int} representing the item's price, and the {@code right boolean} indicating if the price + * was based on complete data. + */ + private static IntBooleanPair getItemPrice(String id) { + JsonObject bazaarPrices = TooltipInfoType.BAZAAR.getData(); + JsonObject lbinPrices = TooltipInfoType.LOWEST_BINS.getData(); + + if (bazaarPrices == null || lbinPrices == null) return IntBooleanPair.of(0, false); + + if (bazaarPrices.has(id)) { + JsonObject item = bazaarPrices.get(id).getAsJsonObject(); + boolean isPriceNull = item.get("sellPrice").isJsonNull(); + + return IntBooleanPair.of(isPriceNull ? 0 : (int) item.get("sellPrice").getAsDouble(), !isPriceNull); + } + + if (lbinPrices.has(id)) { + return IntBooleanPair.of((int) lbinPrices.get(id).getAsDouble(), true); + } + + return IntBooleanPair.of(0, false); + } + + /** + * Searches for a specific string of characters in the name and lore of an item + */ + private static String searchLoreFor(ItemStack stack, MinecraftClient client, String searchString) { + return stack.getTooltip(client.player, TooltipContext.BASIC).stream().map(Text::getString).filter(line -> line.contains(searchString)).findAny().orElse(null); + } + + private static Text getProfitText(int profit, boolean hasIncompleteData) { + SkyblockerConfig.DungeonChestProfit config = SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit; + return getProfitText(profit, hasIncompleteData, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor); + } + + static Text getProfitText(int profit, boolean hasIncompleteData, int neutralThreshold, Formatting neutralColor, Formatting profitColor, Formatting lossColor, Formatting incompleteColor) { + return Text.literal((profit > 0 ? " +" : ' ') + FORMATTER.format(profit) + " Coins").formatted(hasIncompleteData ? incompleteColor : (Math.abs(profit) < neutralThreshold) ? neutralColor : (profit > 0) ? profitColor : lossColor); + } + + private static Text getValueText(int value, boolean hasIncompleteData) { + SkyblockerConfig.ChestValue config = SkyblockerConfigManager.get().general.chestValue; + return getValueText(value, hasIncompleteData, config.color, config.incompleteColor); + } + + static Text getValueText(int value, boolean hasIncompleteData, Formatting color, Formatting incompleteColor) { + return Text.literal(' ' + FORMATTER.format(value) + " Coins").formatted(hasIncompleteData ? incompleteColor : color); + } +} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonChestProfit.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonChestProfit.java deleted file mode 100644 index 1e889af3..00000000 --- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonChestProfit.java +++ /dev/null @@ -1,170 +0,0 @@ -package de.hysky.skyblocker.skyblock.dungeon; - -import com.google.gson.JsonObject; -import de.hysky.skyblocker.config.SkyblockerConfig; -import de.hysky.skyblocker.config.SkyblockerConfigManager; -import de.hysky.skyblocker.mixin.accessor.ScreenAccessor; -import de.hysky.skyblocker.skyblock.item.tooltip.ItemTooltip; -import de.hysky.skyblocker.skyblock.item.tooltip.TooltipInfoType; -import de.hysky.skyblocker.utils.Utils; -import it.unimi.dsi.fastutil.ints.IntBooleanPair; -import net.fabricmc.fabric.api.client.screen.v1.ScreenEvents; -import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; -import net.minecraft.client.item.TooltipContext; -import net.minecraft.item.ItemStack; -import net.minecraft.screen.GenericContainerScreenHandler; -import net.minecraft.screen.ScreenHandlerType; -import net.minecraft.screen.slot.Slot; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import org.apache.commons.lang3.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.text.DecimalFormat; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class DungeonChestProfit { - private static final Logger LOGGER = LoggerFactory.getLogger(DungeonChestProfit.class); - private static final Pattern ESSENCE_PATTERN = Pattern.compile("(?<type>[A-Za-z]+) Essence x(?<amount>[0-9]+)"); - private static final DecimalFormat FORMATTER = new DecimalFormat("#,###"); - - public static void init() { - ScreenEvents.AFTER_INIT.register((client, screen, scaledWidth, scaledHeight) -> ScreenEvents.afterTick(screen).register(screen1 -> { - if (Utils.isOnSkyblock() && screen instanceof GenericContainerScreen genericContainerScreen && genericContainerScreen.getScreenHandler().getType() == ScreenHandlerType.GENERIC_9X6) { - ((ScreenAccessor) screen).setTitle(getChestProfit(genericContainerScreen.getScreenHandler(), screen.getTitle(), client)); - } - })); - } - - public static Text getChestProfit(GenericContainerScreenHandler handler, Text title, MinecraftClient client) { - try { - if (SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit.enableProfitCalculator && isDungeonChest(title.getString())) { - int profit = 0; - boolean hasIncompleteData = false, usedKismet = false; - List<Slot> slots = handler.slots.subList(0, handler.getRows() * 9); - - //If the item stack for the "Open Reward Chest" button or the kismet button hasn't been sent to the client yet - if (slots.get(31).getStack().isEmpty() || slots.get(50).getStack().isEmpty()) return title; - - for (Slot slot : slots) { - ItemStack stack = slot.getStack(); - - if (!stack.isEmpty()) { - String name = stack.getName().getString(); - String id = ItemTooltip.getInternalNameFromNBT(stack, false); - - //Regular item price - if (id != null) { - IntBooleanPair priceData = getItemPrice(id); - - if (!priceData.rightBoolean()) hasIncompleteData = true; - - //Add the item price to the profit - profit += priceData.leftInt(); - - continue; - } - - //Essence price - if (name.contains("Essence") && SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit.includeEssence) { - Matcher matcher = ESSENCE_PATTERN.matcher(name); - - if (matcher.matches()) { - String type = matcher.group("type"); - int amount = Integer.parseInt(matcher.group("amount")); - - IntBooleanPair priceData = getItemPrice(("ESSENCE_" + type).toUpperCase()); - - if (!priceData.rightBoolean()) hasIncompleteData = true; - - //Add the price of the essence to the profit - profit += priceData.leftInt() * amount; - - continue; - } - } - - //Determine the cost of the chest - if (name.contains("Open Reward Chest")) { - String foundString = searchLoreFor(stack, client, "Coins"); - - //Incase we're searching the free chest - if (!StringUtils.isBlank(foundString)) { - profit -= Integer.parseInt(foundString.replaceAll("[^0-9]", "")); - } - - continue; - } - - //Determine if a kismet was used or not - if (name.contains("Reroll Chest")) { - usedKismet = !StringUtils.isBlank(searchLoreFor(stack, client, "You already rerolled a chest!")); - } - } - } - - if (SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit.includeKismet && usedKismet) { - IntBooleanPair kismetPriceData = getItemPrice("KISMET_FEATHER"); - - if (!kismetPriceData.rightBoolean()) hasIncompleteData = true; - - profit -= kismetPriceData.leftInt(); - } - - return Text.literal(title.getString()).append(getProfitText(profit, hasIncompleteData)); - } - } catch (Exception e) { - LOGGER.error("[Skyblocker Profit Calculator] Failed to calculate dungeon chest profit! ", e); - } - - return title; - } - - /** - * @return An {@link IntBooleanPair} with the {@code left int} representing the item's price, and the {@code right boolean} indicating if the price - * was based on complete data. - */ - private static IntBooleanPair getItemPrice(String id) { - JsonObject bazaarPrices = TooltipInfoType.BAZAAR.getData(); - JsonObject lbinPrices = TooltipInfoType.LOWEST_BINS.getData(); - - if (bazaarPrices == null || lbinPrices == null) return IntBooleanPair.of(0, false); - - if (bazaarPrices.has(id)) { - JsonObject item = bazaarPrices.get(id).getAsJsonObject(); - boolean isPriceNull = item.get("sellPrice").isJsonNull(); - - return IntBooleanPair.of(isPriceNull ? 0 : (int) item.get("sellPrice").getAsDouble(), !isPriceNull); - } - - if (lbinPrices.has(id)) { - return IntBooleanPair.of((int) lbinPrices.get(id).getAsDouble(), true); - } - - return IntBooleanPair.of(0, false); - } - - /** - * Searches for a specific string of characters in the name and lore of an item - */ - private static String searchLoreFor(ItemStack stack, MinecraftClient client, String searchString) { - return stack.getTooltip(client.player, TooltipContext.BASIC).stream().map(Text::getString).filter(line -> line.contains(searchString)).findAny().orElse(null); - } - - private static boolean isDungeonChest(String name) { - return name.equals("Wood Chest") || name.equals("Gold Chest") || name.equals("Diamond Chest") || name.equals("Emerald Chest") || name.equals("Obsidian Chest") || name.equals("Bedrock Chest"); - } - - private static Text getProfitText(int profit, boolean hasIncompleteData) { - SkyblockerConfig.DungeonChestProfit config = SkyblockerConfigManager.get().locations.dungeons.dungeonChestProfit; - return getProfitText(profit, hasIncompleteData, config.neutralThreshold, config.neutralColor, config.profitColor, config.lossColor, config.incompleteColor); - } - - static Text getProfitText(int profit, boolean hasIncompleteData, int neutralThreshold, Formatting neutralColor, Formatting profitColor, Formatting lossColor, Formatting incompleteColor) { - return Text.literal((profit > 0 ? " +" : " ") + FORMATTER.format(profit)).formatted(hasIncompleteData ? incompleteColor : (Math.abs(profit) < neutralThreshold) ? neutralColor : (profit > 0) ? profitColor : lossColor); - } -} diff --git a/src/main/java/de/hysky/skyblocker/skyblock/HotbarSlotLock.java b/src/main/java/de/hysky/skyblocker/skyblock/item/HotbarSlotLock.java index 13f09ec6..069a030d 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/HotbarSlotLock.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/item/HotbarSlotLock.java @@ -1,4 +1,4 @@ -package de.hysky.skyblocker.skyblock; +package de.hysky.skyblocker.skyblock.item; import de.hysky.skyblocker.config.SkyblockerConfigManager; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; |