diff options
24 files changed, 871 insertions, 38 deletions
diff --git a/Update Notes/2.1.1.md b/Update Notes/2.1.1.md index 1f4e0311..988913cc 100644 --- a/Update Notes/2.1.1.md +++ b/Update Notes/2.1.1.md @@ -18,3 +18,8 @@ - Add exponent and percentage to calculator - u9g - Add total trophy fish count to /pv - Vixid - Allow hiding messages below a set skyblock level - nopo + - Add crimson isle quests to todo overlay - Vixid + - Add replace chat social options to both party and guild chat - Vixid + - Add class average to dungeons page in /pv - Vixid + - Add recipe history and fairy soul waypoint distance - Vixid + - Fix buggy cape on player model in /pv - Vixid diff --git a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java index af190244..71aa10b6 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/NEUManager.java @@ -34,6 +34,7 @@ import io.github.moulberry.notenoughupdates.recipes.CraftingOverlay; import io.github.moulberry.notenoughupdates.recipes.CraftingRecipe; import io.github.moulberry.notenoughupdates.recipes.Ingredient; import io.github.moulberry.notenoughupdates.recipes.NeuRecipe; +import io.github.moulberry.notenoughupdates.recipes.RecipeHistory; import io.github.moulberry.notenoughupdates.util.ApiUtil; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.HotmInformation; @@ -113,12 +114,16 @@ public class NEUManager { new KeyBinding("Show usages for item", Keyboard.KEY_U, "NotEnoughUpdates"); public final KeyBinding keybindViewRecipe = new KeyBinding("Show recipe for item", Keyboard.KEY_R, "NotEnoughUpdates"); + public final KeyBinding keybindPreviousRecipe = + new KeyBinding("Show previous recipe", Keyboard.KEY_LBRACKET, "NotEnoughUpdates"); + public final KeyBinding keybindNextRecipe = + new KeyBinding("Show next recipe", Keyboard.KEY_RBRACKET, "NotEnoughUpdates"); public final KeyBinding keybindToggleDisplay = new KeyBinding("Toggle NEU overlay", 0, "NotEnoughUpdates"); public final KeyBinding keybindClosePanes = new KeyBinding("Close NEU panes", 0, "NotEnoughUpdates"); public final KeyBinding keybindItemSelect = new KeyBinding("Select Item", -98 /*middle*/, "NotEnoughUpdates"); public final KeyBinding[] keybinds = new KeyBinding[]{ - keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, - keybindToggleDisplay, keybindClosePanes, keybindItemSelect + keybindGive, keybindFavourite, keybindViewUsages, keybindViewRecipe, keybindPreviousRecipe, + keybindNextRecipe, keybindToggleDisplay, keybindClosePanes, keybindItemSelect }; public String viewItemAttemptID = null; @@ -884,7 +889,6 @@ public class NEUManager { case "viewpotion": neu.sendChatMessage("/viewpotion " + internalName.split(";")[0].toLowerCase(Locale.ROOT)); } - displayGuiItemRecipe(internalName); } public void showRecipe(String internalName) { @@ -988,6 +992,7 @@ public class NEUManager { List<NeuRecipe> usages = getAvailableUsagesFor(internalName); if (usages.isEmpty()) return false; NotEnoughUpdates.INSTANCE.openGui = (new GuiItemRecipe(usages, this)); + RecipeHistory.add(NotEnoughUpdates.INSTANCE.openGui); return true; } @@ -996,6 +1001,7 @@ public class NEUManager { List<NeuRecipe> recipes = getAvailableRecipesFor(internalName); if (recipes.isEmpty()) return false; NotEnoughUpdates.INSTANCE.openGui = (new GuiItemRecipe(recipes, this)); + RecipeHistory.add(NotEnoughUpdates.INSTANCE.openGui); return true; } 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 143033b7..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; @@ -78,6 +79,7 @@ import io.github.moulberry.notenoughupdates.profileviewer.ProfileViewer; import io.github.moulberry.notenoughupdates.recipes.RecipeGenerator; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.SBInfo; +import io.github.moulberry.notenoughupdates.util.TitleUtil; import io.github.moulberry.notenoughupdates.util.Utils; import io.github.moulberry.notenoughupdates.util.XPInformation; import net.minecraft.client.Minecraft; @@ -295,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); @@ -322,6 +325,7 @@ public class NotEnoughUpdates { MinecraftForge.EVENT_BUS.register(MinionHelperManager.getInstance()); MinecraftForge.EVENT_BUS.register(navigation); MinecraftForge.EVENT_BUS.register(new WorldListener(this)); + MinecraftForge.EVENT_BUS.register(TitleUtil.getInstance()); if (Minecraft.getMinecraft().getResourceManager() instanceof IReloadableResourceManager) { IReloadableResourceManager manager = (IReloadableResourceManager) Minecraft.getMinecraft().getResourceManager(); 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/core/util/render/RenderUtils.java b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java index e7ce29c3..d7bd097a 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/core/util/render/RenderUtils.java @@ -378,14 +378,18 @@ public class RenderUtils { } public static void renderWayPoint(List<String> str, Vec3i loc, float partialTicks) { - renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks); + renderWayPoint(str, new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks, false); } public static void renderWayPoint(String str, Vector3f loc, float partialTicks) { - renderWayPoint(Arrays.asList(str), loc, partialTicks); + renderWayPoint(Arrays.asList(str), loc, partialTicks, false); + } + + public static void renderWayPoint(Vec3i loc, float partialTicks) { + renderWayPoint(Arrays.asList(""), new Vector3f(loc.getX(), loc.getY(), loc.getZ()), partialTicks, true); } - public static void renderWayPoint(List<String> lines, Vector3f loc, float partialTicks) { + public static void renderWayPoint(List<String> lines, Vector3f loc, float partialTicks, boolean onlyShowDistance) { GlStateManager.alphaFunc(516, 0.1F); GlStateManager.pushMatrix(); @@ -409,7 +413,7 @@ public class RenderUtils { GlStateManager.translate(x, y, z); GlStateManager.translate(0, viewer.getEyeHeight(), 0); - lines = new ArrayList<>(lines); + lines = onlyShowDistance ? new ArrayList<>() : new ArrayList<>(lines); lines.add(EnumChatFormatting.YELLOW.toString() + Math.round(dist) + "m"); renderNametag(lines); diff --git a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java index a5acd5b4..6a94c0b3 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/ChatListener.java @@ -23,6 +23,7 @@ import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.dungeons.DungeonWin; import io.github.moulberry.notenoughupdates.miscfeatures.CookieWarning; import io.github.moulberry.notenoughupdates.miscfeatures.CrystalMetalDetectorSolver; +import io.github.moulberry.notenoughupdates.miscfeatures.EnderNodes; import io.github.moulberry.notenoughupdates.miscfeatures.StreamerMode; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.overlays.SlayerOverlay; @@ -306,5 +307,9 @@ public class ChatListener { unformatted.equals("You have successfully picked the lock on this chest!") || (unformatted.startsWith("You received +") && unformatted.endsWith(" Powder"))) OverlayManager.powderGrindingOverlay.message(unformatted); + + if (unformatted.equals("ENDER NODE! You found Endermite Nest!")) { + EnderNodes.dispalyEndermiteNotif(); + } } } 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/NEUEventListener.java b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java index 43a1daf9..5b388dea 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/listener/NEUEventListener.java @@ -34,11 +34,13 @@ import io.github.moulberry.notenoughupdates.miscfeatures.ItemCustomizeManager; import io.github.moulberry.notenoughupdates.miscfeatures.NPCRetexturing; import io.github.moulberry.notenoughupdates.miscgui.AccessoryBagOverlay; import io.github.moulberry.notenoughupdates.miscgui.GuiCustomEnchant; +import io.github.moulberry.notenoughupdates.miscgui.GuiItemRecipe; import io.github.moulberry.notenoughupdates.miscgui.hex.GuiCustomHex; import io.github.moulberry.notenoughupdates.miscgui.StorageOverlay; import io.github.moulberry.notenoughupdates.overlays.OverlayManager; import io.github.moulberry.notenoughupdates.overlays.TextOverlay; import io.github.moulberry.notenoughupdates.overlays.TextTabOverlay; +import io.github.moulberry.notenoughupdates.recipes.RecipeHistory; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.NotificationHandler; import io.github.moulberry.notenoughupdates.util.ProfileApiSyncer; @@ -162,6 +164,11 @@ public class NEUEventListener { if (longUpdate) { + + if (!(Minecraft.getMinecraft().currentScreen instanceof GuiItemRecipe)) { + RecipeHistory.clear(); + } + CrystalOverlay.tick(); FairySouls.getInstance().tick(); XPInformation.getInstance().tick(); 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 ? EnumCh |
