From 0ff09b9032d2f1a9c5a8cab3c876037702445af6 Mon Sep 17 00:00:00 2001 From: efefury <69400149+efefury@users.noreply.github.com> Date: Sun, 30 Oct 2022 00:50:56 +0200 Subject: Croesus profit overlay (#368) Co-authored-by: Lulonaut Co-authored-by: nopo --- .../moulberry/notenoughupdates/NEUOverlay.java | 4 +- .../notenoughupdates/NotEnoughUpdates.java | 2 + .../notenoughupdates/auction/APIManager.java | 7 +- .../listener/ItemTooltipRngListener.java | 2 +- .../notenoughupdates/listener/RenderListener.java | 17 +- .../miscfeatures/DungeonNpcProfitOverlay.java | 391 +++++++++++++++++++++ .../notenoughupdates/mixins/MixinGuiContainer.java | 2 + .../options/seperateSections/Dungeons.java | 37 +- 8 files changed, 445 insertions(+), 17 deletions(-) create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java index 2f55c338..87ce915b 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java @@ -1219,8 +1219,8 @@ public class NEUOverlay extends Gui { String internal1 = o1.get("internalname").getAsString(); String internal2 = o2.get("internalname").getAsString(); - double cost1 = manager.auctionManager.getBazaarOrBin(internal1); - double cost2 = manager.auctionManager.getBazaarOrBin(internal2); + double cost1 = manager.auctionManager.getBazaarOrBin(internal1, false); + double cost2 = manager.auctionManager.getBazaarOrBin(internal2, false); if (cost1 < cost2) return mult; if (cost1 > cost2) return -mult; diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java index 8d4abc7d..b514e419 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java @@ -45,6 +45,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.CrystalOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalWishingCompassSolver; import io.github.moulberry.notenoughupdates.miscfeatures.CustomItemEffects; import io.github.moulberry.notenoughupdates.miscfeatures.CustomSkulls; +import io.github.moulberry.notenoughupdates.miscfeatures.DungeonNpcProfitOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.DwarvenMinesWaypoints; import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.miscfeatures.FairySouls; @@ -296,6 +297,7 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(new DwarvenMinesWaypoints()); MinecraftForge.EVENT_BUS.register(new FuelBar()); MinecraftForge.EVENT_BUS.register(new AuctionProfit()); + MinecraftForge.EVENT_BUS.register(new DungeonNpcProfitOverlay()); MinecraftForge.EVENT_BUS.register(XPInformation.getInstance()); MinecraftForge.EVENT_BUS.register(OverlayManager.petInfoOverlay); MinecraftForge.EVENT_BUS.register(OverlayManager.timersOverlay); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java index 1b6896db..755e53f5 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java @@ -822,10 +822,11 @@ public class APIManager { return keys; } - public double getBazaarOrBin(String internalName) { + public double getBazaarOrBin(String internalName, boolean useSellingPrice) { + String curr = (useSellingPrice ? "curr_sell" : "curr_buy"); JsonObject bazaarInfo = manager.auctionManager.getBazaarInfo(internalName); - if (bazaarInfo != null && bazaarInfo.get("curr_buy") != null) { - return bazaarInfo.get("curr_buy").getAsFloat(); + if (bazaarInfo != null && bazaarInfo.get(curr) != null) { + return bazaarInfo.get(curr).getAsFloat(); } else { return manager.auctionManager.getLowestBin(internalName); } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java index fdae53ea..2b7a9bef 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java @@ -139,7 +139,7 @@ public class ItemTooltipRngListener { private String getFormatCoinsPer(ItemStack stack, int needed, int multiplier, String label) { String internalName = neu.manager.createItemResolutionQuery().withItemStack(stack).resolveInternalName(); - double profit = neu.manager.auctionManager.getBazaarOrBin(internalName); + double profit = neu.manager.auctionManager.getBazaarOrBin(internalName, false); if (profit <= 0) return null; //ask hypixel nicely to release a 'chest price api' with 4 dimensions for us. the 4 dimensions needed are: item name, floor, normal/mm, s/s+ diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java index 2eb4c23a..949358ad 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java @@ -40,6 +40,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning; import io.github.moulberry.notenoughupdates.miscfeatures.AuctionProfit; import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver; +import io.github.moulberry.notenoughupdates.miscfeatures.DungeonNpcProfitOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.miscfeatures.StorageManager; import io.github.moulberry.notenoughupdates.miscgui.AccessoryBagOverlay; @@ -136,6 +137,8 @@ public class RenderListener { public static long lastGuiClosed = 0; public static boolean inventoryLoaded = false; private final NotEnoughUpdates neu; + private final NumberFormat format = new DecimalFormat("#,##0.#", new DecimalFormatSymbols(Locale.US)); + private final Pattern ESSENCE_PATTERN = Pattern.compile("§d(.+) Essence §8x([\\d,]+)"); ScheduledExecutorService ses = Executors.newScheduledThreadPool(1); JsonObject essenceJson = new JsonObject(); private boolean hoverInv = false; @@ -150,9 +153,6 @@ public class RenderListener { private boolean typing; private HashMap cachedDefinitions; private boolean inDungeonPage = false; - private final NumberFormat format = new DecimalFormat("#,##0.#", new DecimalFormatSymbols(Locale.US)); - - private final Pattern ESSENCE_PATTERN = Pattern.compile("§d(.+) Essence §8x([\\d,]+)"); public RenderListener(NotEnoughUpdates neu) { this.neu = neu; @@ -458,7 +458,6 @@ public class RenderListener { return; } - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); boolean customAhActive = @@ -559,7 +558,7 @@ public class RenderListener { x -= 25; } } - if (inDungeonPage) { + if (inDungeonPage || DungeonNpcProfitOverlay.isRendering()) { if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 100) { x += 185; @@ -694,7 +693,7 @@ public class RenderListener { } } - if (inDungeonPage) { + if (inDungeonPage || DungeonNpcProfitOverlay.isRendering()) { if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 100) { x += 185; @@ -812,7 +811,7 @@ public class RenderListener { if (bazaarPrice < 5000000 && internal.equals("RECOMBOBULATOR_3000")) bazaarPrice = 5000000; double worth = -1; - boolean isOnBz = false; + boolean isOnBz = false; if (bazaarPrice >= 0) { worth = bazaarPrice; isOnBz = true; @@ -1086,7 +1085,6 @@ public class RenderListener { return; } - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); boolean customAhActive = @@ -1176,7 +1174,7 @@ public class RenderListener { x -= 25; } } - if (inDungeonPage) { + if (inDungeonPage || DungeonNpcProfitOverlay.isRendering()) { if (x + 10 > guiLeft + xSize && x + 18 < guiLeft + xSize + 4 + 28 + 20 && y > guiTop - 180 && y < guiTop + 100) { x += 185; @@ -1564,7 +1562,6 @@ public class RenderListener { return; } - boolean tradeWindowActive = TradeWindow.tradeWindowActive(containerName); boolean storageOverlayActive = StorageManager.getInstance().shouldRenderStorageOverlay(containerName); boolean customAhActive = diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java new file mode 100644 index 00000000..7caa4d6b --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2022 NotEnoughUpdates contributors + * + * This file is part of NotEnoughUpdates. + * + * NotEnoughUpdates is free software: you can redistribute it + * and/or modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * NotEnoughUpdates is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with NotEnoughUpdates. If not, see . + */ + +package io.github.moulberry.notenoughupdates.miscfeatures; + +import com.google.gson.JsonArray; +import com.google.gson.JsonObject; +import io.github.moulberry.notenoughupdates.NotEnoughUpdates; +import io.github.moulberry.notenoughupdates.core.util.StringUtils; +import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; +import io.github.moulberry.notenoughupdates.util.ItemUtils; +import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Items; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class DungeonNpcProfitOverlay { + + private static final ResourceLocation dungeonProfitResource = + new ResourceLocation("notenoughupdates:dungeon_chest_worth.png"); + + private static final Pattern chestNamePattern = Pattern.compile(".+ Catacombs - Floor .+"); + private static final Pattern essencePattern = Pattern.compile( + "^§.(?\\w+) Essence §.x(?\\d+)$"); + private static final Pattern enchantedBookPattern = Pattern.compile("^§.Enchanted Book \\((?.*)\\)"); + private static List chestProfits; + private static List previousSlots; + + /** + * Check the current status for the overlay + * + * @return if the overlay is rendering right now + */ + public static boolean isRendering() { + return NotEnoughUpdates.INSTANCE.config.dungeons.croesusProfitOverlay && chestProfits != null; + } + + /** + * Highlight the slot that is being drawn if applicable. Called by MixinGuiContainer + * + * @param slot the slot to be checked + * @see io.github.moulberry.notenoughupdates.mixins.MixinGuiContainer#drawSlotRet(Slot, CallbackInfo) + */ + public static void onDrawSlot(Slot slot) { + if (isRendering() && NotEnoughUpdates.INSTANCE.config.dungeons.croesusHighlightHighestProfit) { + for (DungeonChest chestProfit : chestProfits) { + if (chestProfit.shouldHighlight) { + if (slot.slotNumber == chestProfit.slot) { + Gui.drawRect( + slot.xDisplayPosition, + slot.yDisplayPosition, + slot.xDisplayPosition + 16, + slot.yDisplayPosition + 16, + Color.GREEN.getRGB() + ); + } + } + } + } + } + + @SubscribeEvent + public void onDrawBackground(GuiScreenEvent.BackgroundDrawnEvent event) { + if (!NotEnoughUpdates.INSTANCE.config.dungeons.croesusProfitOverlay || !(event.gui instanceof GuiChest)) { + chestProfits = null; + previousSlots = null; + return; + } + + String lastOpenChestName = SBInfo.getInstance().lastOpenChestName; + Matcher matcher = chestNamePattern.matcher(lastOpenChestName); + if (!matcher.matches()) { + chestProfits = null; + previousSlots = null; + return; + } + GuiChest guiChest = (GuiChest) event.gui; + List slots = guiChest.inventorySlots.inventorySlots; + + if (chestProfits == null || chestProfits.isEmpty() || !slots.equals(previousSlots)) { + updateDungeonChests(slots); + } + previousSlots = guiChest.inventorySlots.inventorySlots; + + render(guiChest); + } + + /** + * Update the profit applicable for the chests currently visible + * + * @param inventorySlots list of Slots from the GUI containing the dungeon chest previews + */ + private void updateDungeonChests(List inventorySlots) { + chestProfits = new ArrayList<>(); + //loop through the upper chest + for (int i = 0; i < 27; i++) { + Slot inventorySlot = inventorySlots.get(i); + if (inventorySlot == null) { + continue; + } + + ItemStack stack = inventorySlot.getStack(); + if (stack != null && stack.getItem() != null && stack.getItem() == Items.skull) { + //each item is a DungeonChest + DungeonChest dungeonChest = new DungeonChest(); + dungeonChest.slot = i; + + List lore = ItemUtils.getLore(stack); + if ("§7Contents".equals(lore.get(0))) { + dungeonChest.name = stack.getDisplayName(); + List items = new ArrayList<>(); + for (String s : lore) { + //check if this line is showing the cost of opening the Chest + if (s.endsWith(" Coins")) { + String coinString = StringUtils.cleanColour(s); + int whitespace = coinString.indexOf(' '); + if (whitespace != -1) { + String amountString = coinString.substring(0, whitespace).replace(",", ""); + dungeonChest.costToOpen = Integer.parseInt(amountString); + continue; + } + } else if (s.equals("§aFREE")) { + dungeonChest.costToOpen = 0; + } + + //check if the line can be converted to a SkyblockItem + SkyblockItem skyblockItem = SkyblockItem.createFromLoreEntry(s); + if (skyblockItem != null) { + items.add(skyblockItem); + } + } + dungeonChest.items = items; + if (dungeonChest.costToOpen != -1) { + dungeonChest.calculateProfitAndBuildLore(); + chestProfits.add(dungeonChest); + } + } + } + } + + if (NotEnoughUpdates.INSTANCE.config.dungeons.croesusSortByProfit) { + chestProfits.sort(Comparator.comparing(DungeonChest::getProfit).reversed()); + } + + if (NotEnoughUpdates.INSTANCE.config.dungeons.croesusHighlightHighestProfit && chestProfits.size() >= 1) { + List copiedList = new ArrayList<>(chestProfits); + copiedList.sort(Comparator.comparing(DungeonChest::getProfit).reversed()); + + copiedList.get(0).shouldHighlight = true; + } + } + + public void render(GuiChest guiChest) { + int xSize = ((AccessorGuiContainer) guiChest).getXSize(); + int guiLeft = ((AccessorGuiContainer) guiChest).getGuiLeft(); + int guiTop = ((AccessorGuiContainer) guiChest).getGuiTop(); + Minecraft.getMinecraft().getTextureManager().bindTexture(dungeonProfitResource); + GL11.glColor4f(1, 1, 1, 1); + GlStateManager.disableLighting(); + Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 180, 101, 0, 180 / 256f, 0, 101 / 256f, GL11.GL_NEAREST); + + for (int i = 0; i < chestProfits.size(); i++) { + DungeonChest chestProfit = chestProfits.get(i); + int x = guiLeft + xSize + 14; + int y = guiTop + 6 + (i * 10); + Utils.renderAlignedString( + chestProfit.name, + (chestProfit.profit > 0 + ? EnumChatFormatting.GREEN.toString() + : EnumChatFormatting.RED) + Utils.shortNumberFormat(chestProfit.profit, 0), + x, + y, + 160 + ); + + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + int width = scaledResolution.getScaledWidth(); + int height = scaledResolution.getScaledHeight(); + + int mouseX = Utils.getMouseX(); + int mouseY = Utils.getMouseY(); + + if (Utils.isWithinRect(mouseX, mouseY, x, y, 160, 10)) + Utils.drawHoveringText( + chestProfit.lore, + mouseX, + mouseY, + width, + height, + -1, + Minecraft.getMinecraft().fontRendererObj + ); + } + + } + + /** + * Dataclass holding info on a single Dungeon Chest Preview + *

+ * This includes: + *

    + *
  • The items, represented as a SkyblockItem
  • + *
  • The cost to open the chest
  • + *
+ * + * @see SkyblockItem + */ + private static class DungeonChest { + private List items = new ArrayList<>(); + private List lore; + private int costToOpen = -1; + private String name; + private int slot; + private boolean shouldHighlight; + private double profit; + + public double getProfit() { + return profit; + } + + public void calculateProfitAndBuildLore() { + profit = 0d; + lore = new ArrayList<>(); + lore.add(name); + for (SkyblockItem item : items) { + double cost = item.calculateCost(); + profit += cost; + lore.add( + EnumChatFormatting.AQUA + " - " + item.getDisplayName() + EnumChatFormatting.RESET + " " + + EnumChatFormatting.GREEN + + Utils.shortNumberFormat(cost, 0)); + } + lore.add(""); + profit -= costToOpen; + lore.add( + EnumChatFormatting.AQUA + "Cost to open: " + EnumChatFormatting.RED + Utils.shortNumberFormat(costToOpen, 0)); + lore.add( + EnumChatFormatting.AQUA + "Total profit: " + (profit > 0 ? EnumChatFormatting.GREEN : EnumChatFormatting.RED) + + Utils.shortNumberFormat(profit, 0)); + } + } + + /** + * Dataclass holding info on a single skyblock item which is part of a DungeonChest + *

+ * This includes: + *

    + *
  • The internal name of the item
  • + *
  • The amount
  • + *
+ * + * @see DungeonChest + */ + private static class SkyblockItem { + private final String internalName; + private final int amount; + + private SkyblockItem(String internalName, int amount) { + this.internalName = internalName; + this.amount = amount; + } + + /** + * Try to create a SkyblockItem from the given lore line. + *

+ * This involves checking for: + *

    + *
  • Enchanted books
  • + *
  • Dungeon essence
  • + *
  • Normal items that can appear in dungeon chests
  • + *
+ * + * @param line the line to be parsed + * @return a new SkyblockItem if possible, otherwise null + */ + public static @Nullable SkyblockItem createFromLoreEntry(String line) { + Matcher essenceMatcher = essencePattern.matcher(line); + Matcher enchantedBookMatcher = enchantedBookPattern.matcher(line); + + if (enchantedBookMatcher.matches()) { + String enchant = StringUtils.cleanColour(enchantedBookMatcher.group("enchantName")); + + for (Map.Entry entry : NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .entrySet()) { + String displayName = StringUtils.cleanColour(entry.getValue().get("displayname").getAsString()); + if (displayName.equals("Enchanted Book")) { + JsonArray lore = entry.getValue().get("lore").getAsJsonArray(); + String enchantName = StringUtils.cleanColour(lore.get(0).getAsString()); + if (enchant.equals(enchantName)) { + return new SkyblockItem(entry.getKey(), 1); + } + } + } + } else if (essenceMatcher.matches()) { + String essenceType = essenceMatcher.group("essenceType"); + String essenceAmount = essenceMatcher.group("essenceAmount"); + if (essenceType == null || essenceAmount == null) { + return null; + } + + String internalName = "ESSENCE_" + essenceType.toUpperCase(Locale.ROOT); + if (!NotEnoughUpdates.INSTANCE.manager.isValidInternalName(internalName)) { + return null; + } + + //this can only be an integer if the regex matches + int amount = Integer.parseInt(essenceAmount); + return new SkyblockItem(internalName, amount); + } else { + String s = StringUtils.cleanColour(line.trim()); + for (Map.Entry entries : NotEnoughUpdates.INSTANCE.manager + .getItemInformation() + .entrySet()) { + String displayName = entries.getValue().get("displayname").getAsString(); + String cleanDisplayName = StringUtils.cleanColour(displayName); + if (s.equals(cleanDisplayName)) { + return new SkyblockItem(entries.getKey(), 1); + } + } + } + return null; + } + + /** + * Calculate the price of this item, factoring in the amount + * + * @return total price + */ + public double calculateCost() { + double price = NotEnoughUpdates.INSTANCE.manager.auctionManager.getBazaarOrBin(internalName, true); + if (price != -1) { + return price * amount; + } + return 0d; + } + + public String getDisplayName() { + JsonObject entry = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withKnownInternalName( + internalName).resolveToItemListJson(); + if (entry != null) { + String displayName = entry.get("displayname").getAsString(); + String cleanedDisplayName = StringUtils.cleanColour(displayName); + if ("Enchanted Book".equals(cleanedDisplayName)) { + return entry.get("lore").getAsJsonArray().get(0).getAsString(); + } else { + return entry.get("displayname").getAsString(); + } + } + return "ERROR"; + } + } +} diff --git a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java index 81918939..cb4cfa6c 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java @@ -27,6 +27,7 @@ import io.github.moulberry.notenoughupdates.miscfeatures.AbiphoneWarning; import io.github.moulberry.notenoughupdates.miscfeatures.AuctionBINWarning; import io.github.moulberry.notenoughupdates.miscfeatures.AuctionSortModeWarning; import io.github.moulberry.notenoughupdates.miscfeatures.BetterContainers; +import io.github.moulberry.notenoughupdates.miscfeatures.DungeonNpcProfitOverlay; import io.github.moulberry.notenoughupdates.miscfeatures.EnchantingSolvers; import io.github.moulberry.notenoughupdates.miscfeatures.SlotLocking; import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant; @@ -72,6 +73,7 @@ public abstract class MixinGuiContainer extends GuiScreen { @Inject(method = "drawSlot", at = @At("RETURN")) public void drawSlotRet(Slot slotIn, CallbackInfo ci) { SlotLocking.getInstance().drawSlot(slotIn); + DungeonNpcProfitOverlay.onDrawSlot(slotIn); } @Inject(method = "drawSlot", at = @At("HEAD"), cancellable = true) diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java index cf5635ec..9179c6ea 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java @@ -130,7 +130,7 @@ public class Dungeons { ) @ConfigEditorBoolean @ConfigAccordionId(id = 1) - public boolean shouldWarningDerpy = true; + public boolean shouldWarningDerpy = true; @ConfigOption( name = "Dungeon Win Overlay", @@ -168,6 +168,7 @@ public class Dungeons { @ConfigEditorAccordion(id = 2) public boolean dungeonBlocksAccordion = false; + @ConfigOption( name = "\u00A7cWarning", desc = "You need Fast Render and Antialiasing off for these settings to work\n" + @@ -281,4 +282,38 @@ public class Dungeons { @ConfigAccordionId(id = 2) public String dungBatColour = "0:255:12:255:0"; + @ConfigOption( + name = "Croesus Overlay", + desc = "" + ) + @ConfigEditorAccordion(id = 4) + public boolean croesusAccordion = false; + + @Expose + @ConfigOption( + name = "Enable Croesus Overlay", + desc = "Shows a profit overlay next to your inventory when viewing chest previews at the Croesus NPC" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 4) + public boolean croesusProfitOverlay = true; + + @Expose + @ConfigOption( + name = "Sort by profit", + desc = "Lists the chest by profit (descending)" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 4) + public boolean croesusSortByProfit = true; + + @Expose + @ConfigOption( + name = "Highlight highest profit", + desc = "Highlight the chest which has the most profit" + ) + @ConfigEditorBoolean + @ConfigAccordionId(id = 4) + public boolean croesusHighlightHighestProfit = true; + } -- cgit