aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorefefury <69400149+efefury@users.noreply.github.com>2022-10-30 00:50:56 +0200
committerGitHub <noreply@github.com>2022-10-30 00:50:56 +0200
commit0ff09b9032d2f1a9c5a8cab3c876037702445af6 (patch)
tree077d51d1bbaa0cada6c93447767416e34ee807ab
parentf0bbd5a9f2efcea16131f9b3688302d61b5757c2 (diff)
downloadNotEnoughUpdates-0ff09b9032d2f1a9c5a8cab3c876037702445af6.tar.gz
NotEnoughUpdates-0ff09b9032d2f1a9c5a8cab3c876037702445af6.tar.bz2
NotEnoughUpdates-0ff09b9032d2f1a9c5a8cab3c876037702445af6.zip
Croesus profit overlay (#368)
Co-authored-by: Lulonaut <lulonaut@tutanota.de> Co-authored-by: nopo <nopotheemail@gmail.com>
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NEUOverlay.java4
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/NotEnoughUpdates.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/auction/APIManager.java7
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/ItemTooltipRngListener.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/listener/RenderListener.java17
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/DungeonNpcProfitOverlay.java391
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/mixins/MixinGuiContainer.java2
-rw-r--r--src/main/java/io/github/moulberry/notenoughupdates/options/seperateSections/Dungeons.java37
8 files changed, 445 insertions, 17 deletions
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<String, String> 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 <https://www.gnu.org/licenses/>.
+ */
+
+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(
+ "^§.(?<essenceType>\\w+) Essence §.x(?<essenceAmount>\\d+)$");
+ private static final Pattern enchantedBookPattern = Pattern.compile("^§.Enchanted Book \\((?<enchantName>.*)\\)");
+ private static List<DungeonChest> chestProfits;
+ private static List<Slot> 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<Slot> 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<Slot> 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<String> lore = ItemUtils.getLore(stack);
+ if ("§7Contents".equals(lore.get(0))) {
+ dungeonChest.name = stack.getDisplayName();
+ List<SkyblockItem> 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<DungeonChest> 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
+ * <p>
+ * This includes:
+ * <ul>
+ * <li>The items, represented as a SkyblockItem</li>
+ * <li>The cost to open the chest</li>
+ * </ul>
+ *
+ * @see SkyblockItem
+ */
+ private static class DungeonChest {
+ private List<SkyblockItem> items = new ArrayList<>();
+ private List<String> 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
+ * <p>
+ * This includes:
+ * <ul>
+ * <li>The internal name of the item</li>
+ * <li>The amount</li>
+ * </ul>
+ *
+ * @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.
+ * <p>
+ * This involves checking for:
+ * <ul>
+ * <li>Enchanted books</li>
+ * <li>Dungeon essence</li>
+ * <li>Normal items that can appear in dungeon chests</li>
+ * </ul>
+ *
+ * @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<String, JsonObject> 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<String, JsonObject> 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;
+
}