/* * Copyright (C) 2022-2024 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.miscgui; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import io.github.moulberry.notenoughupdates.NEUManager; import io.github.moulberry.notenoughupdates.NEUOverlay; import io.github.moulberry.notenoughupdates.NotEnoughUpdates; import io.github.moulberry.notenoughupdates.auction.APIManager; import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe; import io.github.moulberry.notenoughupdates.core.util.ArrowPagesUtils; import io.github.moulberry.notenoughupdates.events.ButtonExclusionZoneEvent; import io.github.moulberry.notenoughupdates.mixins.AccessorGuiContainer; import io.github.moulberry.notenoughupdates.options.NEUConfig; import io.github.moulberry.notenoughupdates.profileviewer.GuiProfileViewer; import io.github.moulberry.notenoughupdates.profileviewer.PlayerStats; import io.github.moulberry.notenoughupdates.util.Constants; import io.github.moulberry.notenoughupdates.util.ItemUtils; import io.github.moulberry.notenoughupdates.util.Rectangle; import io.github.moulberry.notenoughupdates.util.Utils; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.gui.inventory.GuiChest; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.RenderHelper; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.inventory.ContainerChest; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.util.EnumChatFormatting; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.lwjgl.input.Keyboard; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; import java.awt.*; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import static io.github.moulberry.notenoughupdates.util.GuiTextures.accessory_bag_overlay; @NEUAutoSubscribe public class AccessoryBagOverlay { private enum Tabs { TAB_BASIC, TAB_TOTAL, TAB_DUP, TAB_MISSING } public static final AccessoryBagOverlay INSTANCE = new AccessoryBagOverlay(); // Arrow pages variables private static int statsPageActive = 0; private static int statsPagesTotal = 0; private static int dupePageActive = 0; private static int dupePagesTotal = 0; private static int missingPageActive = 0; private static int missingPagesTotal = 0; // Page-specific button variables private static boolean dupe_highlight = true; private static boolean dupe_showPersonal = false; private static boolean missing_showAllTiers = true; private static boolean missing_useMP = true; private static List tooltipToDisplay = null; private static boolean offsetButtons = false; @SubscribeEvent public void onButtonExclusionZones(ButtonExclusionZoneEvent event) { if (isInAccessoryBag()) { event.blockArea( new Rectangle( event.getGuiBaseRect().getRight(), event.getGuiBaseRect().getTop(), 168 /*pane*/ + (offsetButtons ? 24 : 0) /*tabs*/ + 5 /*space*/, 128 ), ButtonExclusionZoneEvent.PushDirection.TOWARDS_RIGHT ); } } private static final ItemStack[] TAB_STACKS = new ItemStack[]{ Utils.createItemStack(Items.dye, EnumChatFormatting.DARK_AQUA + "Basic Information", 10, EnumChatFormatting.GREEN + "- Talis count by rarity" ), Utils.createItemStack(Items.diamond_sword, EnumChatFormatting.DARK_AQUA + "Total Stat Bonuses", 0 ), Utils.createItemStack(Items.dye, EnumChatFormatting.DARK_AQUA + "Duplicates", 8 ), Utils.createItemStack(Item.getItemFromBlock(Blocks.barrier), EnumChatFormatting.DARK_AQUA + "Missing", 0 ) }; private static Tabs currentTab = Tabs.TAB_BASIC; public static boolean mouseClick() { if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; ContainerChest cc = (ContainerChest) eventGui.inventorySlots; String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); if (!containerName.trim().startsWith("Accessory Bag")) { return false; } } else { return false; } if (!Mouse.getEventButtonState()) return false; try { AccessorGuiContainer accessor = (AccessorGuiContainer) Minecraft.getMinecraft().currentScreen; int xSize = accessor.getXSize(); int guiLeft = accessor.getGuiLeft(); int guiTop = accessor.getGuiTop(); if (mouseX() < guiLeft + xSize + 3 || mouseX() > guiLeft + xSize + 168 + 28) return false; if (mouseY() < guiTop || mouseY() > guiTop + 128) return false; if (mouseX() > guiLeft + xSize + 168 + 3 && mouseY() < guiTop + 20 * Tabs.values().length + 22) { int tabClicked = (mouseY() - guiTop) / 20; tabClicked = Math.min(Math.max(0, tabClicked), Tabs.values().length - 1); currentTab = Tabs.values()[tabClicked]; playPressSound(); } if (currentTab == Tabs.TAB_TOTAL) { if (statsPagesTotal > 1) ArrowPagesUtils.onPageSwitchMouse( guiLeft + xSize + 3, guiTop, new int[]{60, 110}, statsPageActive, statsPagesTotal, integer -> statsPageActive = integer ); } if (currentTab == Tabs.TAB_DUP) { if (dupePagesTotal > 1) ArrowPagesUtils.onPageSwitchMouse( guiLeft + xSize + 3, guiTop, new int[]{60, 110}, dupePageActive, dupePagesTotal, integer -> dupePageActive = integer ); if (new Rectangle(guiLeft + xSize + 3 + 120, guiTop + 108, 16, 16).contains(mouseX(), mouseY())) { dupe_highlight = !dupe_highlight; playPressSound(); } if (new Rectangle(guiLeft + xSize + 3 + 141, guiTop + 108, 16, 16).contains(mouseX(), mouseY())) { dupe_showPersonal = !dupe_showPersonal; playPressSound(); } } if (currentTab == Tabs.TAB_MISSING) { if (missingPagesTotal > 1) ArrowPagesUtils.onPageSwitchMouse( guiLeft + xSize + 3, guiTop, new int[]{60, 110}, missingPageActive, missingPagesTotal, integer -> missingPageActive = integer ); if (new Rectangle(guiLeft + xSize + 3 + 120, guiTop + 108, 16, 16).contains(mouseX(), mouseY())) { missing_useMP = !missing_useMP; missing = null; playPressSound(); } if (new Rectangle(guiLeft + xSize + 3 + 141, guiTop + 108, 16, 16).contains(mouseX(), mouseY())) { missing_showAllTiers = !missing_showAllTiers; missing = null; playPressSound(); } } return true; } catch (Exception e) { return false; } } public static void resetCache() { accessoryStacks = new HashSet<>(); pagesVisited = new HashSet<>(); talismanCountRarity = null; totalStats = null; duplicates = null; missing = null; } private static Set accessoryStacks = new HashSet<>(); private static Set pagesVisited = new HashSet<>(); public static void renderVisitOverlay(int x, int y) { Utils.drawStringCenteredScaledMaxWidth("Please visit all", x + 80, y + 60, true, 140, -1); Utils.drawStringCenteredScaledMaxWidth("pages of the bag", x + 80, y + 72, true, 140, -1); } private static TreeMap talismanCountRarity = null; public static void renderBasicOverlay(int x, int y) { if (talismanCountRarity == null) { talismanCountRarity = new TreeMap<>(); for (ItemStack stack : accessoryStacks) { int rarity = getRarity(stack); if (rarity >= 0) { talismanCountRarity.put(rarity, talismanCountRarity.getOrDefault(rarity, 0) + 1); } } } drawTitle(x, y, "Total Counts By Rarity"); int yIndex = 0; for (Map.Entry entry : talismanCountRarity.descendingMap().entrySet()) { String rarityName = Utils.rarityArrC[entry.getKey()]; Utils.renderAlignedString( rarityName, EnumChatFormatting.WHITE.toString() + entry.getValue(), x + 34, y + 20 + 11 * yIndex, 100 ); yIndex++; } NEUConfig.HiddenProfileSpecific profileSpecific = NotEnoughUpdates.INSTANCE.config.getProfileSpecific(); int mp = 0; if (profileSpecific != null) mp = profileSpecific.magicalPower; Utils.renderAlignedString( EnumChatFormatting.AQUA + "Magical Power", mp != 0 ? EnumChatFormatting.WHITE.toString() + mp : EnumChatFormatting.RED + "NO DATA, DO /PV", x + 20, y + 25 + 88, 130 ); } private static PlayerStats.Stats totalStats = null; public static void renderTotalStatsOverlay(int x, int y) { if (totalStats == null) { totalStats = new PlayerStats.Stats(); for (ItemStack stack : accessoryStacks) { if (stack != null) totalStats.add(getStatForItem(stack, PlayerStats.STAT_PATTERN_MAP, true)); } } drawTitle(x, y, "Total Stats"); int yIndex = 0; List> statPairs = new ArrayList<>(); for (int i = 0; i < PlayerStats.defaultStatNames.length; i++) { String statName = PlayerStats.defaultStatNames[i]; String statNamePretty = PlayerStats.defaultStatNamesPretty[i]; int val = Math.round(totalStats.get(statName)); if (Math.abs(val) >= 1E-5) statPairs.add(new ImmutablePair<>(statNamePretty, val)); } statsPageActive = Math.min(statsPageActive, (statPairs.size() / 8)); for (Pair pair : statPairs.subList(statsPageActive * 8, statPairs.size())) { Utils.renderAlignedString( pair.getKey(), EnumChatFormatting.WHITE.toString() + pair.getValue(), x + 6, y + 20 + 11 * yIndex, 158 ); if (yIndex++ >= 7 && statPairs.size() > 9) break; } statsPagesTotal = (int) Math.ceil(statPairs.size() / 8.0); if (statPairs.size() > 9) { GlStateManager.color(1f, 1f, 1f, 1f); ArrowPagesUtils.onDraw(x, y, new int[]{60, 110}, statsPageActive, statsPagesTotal); } } private static Set duplicates = null; public static void renderDuplicatesOverlay(int x, int y) { if (duplicates == null) { JsonObject misc = Constants.MISC; if (misc == null) { drawTitle(x, y, "Duplicates: REPO ERROR"); Utils.showOutdatedRepoNotification("misc.json"); return; } } if (duplicates.isEmpty()) { drawTitle(x, y, "No Duplicates"); } else { drawTitle(x, y, "Duplicates: " + duplicates.size()); int yIndex = 0; List sortedDupes = duplicates.stream().sorted((Comparator.comparing(ItemStack::getDisplayName))).collect(Collectors.toList()); dupePageActive = Math.min(dupePageActive, (duplicates.size() / 8)); for (ItemStack duplicate : sortedDupes.subList(dupePageActive * 8, sortedDupes.size())) { String s = duplicate.getDisplayName(); Utils.renderShadowedString(s.substring(0, Math.min(s.length(), 35)), x + 84, y + 20 + 11 * yIndex, 158); if (++yIndex >= 8 && sortedDupes.size() > 9) break; } dupePagesTotal = (int) Math.ceil(sortedDupes.size() / 8.0); if (sortedDupes.size() > 9) { GlStateManager.color(1f, 1f, 1f, 1f); ArrowPagesUtils.onDraw(x, y, new int[]{60, 110}, dupePageActive, dupePagesTotal); } } List highlightTooltip = new ArrayList<>(); if (dupe_highlight) { highlightTooltip.add("§aHighlight dupes"); highlightTooltip.add("§7Will highlight accessories"); highlightTooltip.add("§7you have duplicates of."); } else { highlightTooltip.add("§cDon't highlight dupes"); highlightTooltip.add("§7Will not highlight accessories"); highlightTooltip.add("§7you have duplicates of."); } renderButton( new ItemStack(dupe_highlight ? Items.ender_eye : Items.ender_pearl), x + 120, y + 107, highlightTooltip ); List compDeletorTooltip = new ArrayList<>(); if (dupe_showPersonal) { compDeletorTooltip.add("§aHighlight Compactors & Deletors"); compDeletorTooltip.add("§7Will highlight all duplicates."); } else { compDeletorTooltip.add("§cDon't highlight Compactors & Deletors"); compDeletorTooltip.add("§7Duplicates allow you to specify"); compDeletorTooltip.add("§7more things to compact and delete,"); compDeletorTooltip.add("§7but they do not give more MP!"); } renderButton( NotEnoughUpdates.INSTANCE.manager.createItem(dupe_showPersonal ? "PERSONAL_DELETOR_4000" : "DISPENSER"), x + 141, y + 107, compDeletorTooltip ); } private static List missing = null; public static void renderMissingOverlay(int x, int y) { if (missing == null) { JsonObject misc = Constants.MISC; if (misc == null) { drawTitle(x, y, "Missing: REPO ERROR"); Utils.showOutdatedRepoNotification("misc.json"); return; } JsonElement talisman_upgrades_element = misc.get("talisman_upgrades"); if (talisman_upgrades_element == null) { drawTitle(x, y, "Missing: REPO ERROR"); Utils.showOutdatedRepoNotification("misc.json talisman_upgrades"); return; } JsonObject talisman_upgrades = talisman_upgrades_element.getAsJsonObject(); missing = new ArrayList<>(); List missingInternal = new ArrayList<>(); List ignoredTalisman = new ArrayList<>(); if (misc.has("ignored_talisman")) { for (JsonElement jsonElement : misc.getAsJsonArray("ignored_talisman")) { ignoredTalisman.add(jsonElement.getAsString()); } } for (Map.Entry entry : NotEnoughUpdates.INSTANCE.manager.getItemInformation().entrySet()) { if (ignoredTalisman.contains(entry.getValue().get("internalname").getAsString())) continue; if (entry.getValue().has("lore")) { if (checkItemType( entry.getValue().get("lore").getAsJsonArray(), "ACCESSORY", "HATCESSORY", "DUNGEON ACCESSORY" ) >= 0) { missingInternal.add(entry.getKey()); } } } for (ItemStack stack : accessoryStacks) { String internalname = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withItemStack(stack).resolveInternalName(); missingInternal.remove(internalname); for (Map.Entry talisman_upgrade_element : talisman_upgrades.entrySet()) { JsonArray upgrades = talisman_upgrade_element.getValue().getAsJsonArray(); for (int j = 0; j < upgrades.size(); j++) { String upgrade = upgrades.get(j).getAsString(); if (internalname.equals(upgrade)) { missingInternal.remove(talisman_upgrade_element.getKey()); break; } } } if (internalname.contains("ABICASE")) { missingInternal.removeAll(missingInternal .stream() .filter(s -> s.contains("ABICASE")) .collect(Collectors.toList())); } } missingInternal.sort(getItemComparator(missing_useMP)); Set missingDisplayNames = new HashSet<>(); for (String internal : missingInternal) { boolean hasDup = false; if (talisman_upgrades.has(internal)) { JsonArray upgrades = talisman_upgrades.get(internal).getAsJsonArray(); for (int j = 0; j < upgrades.size(); j++) { String upgrade = upgrades.get(j).getAsString(); if (missingInternal.contains(upgrade)) { hasDup = true; break; } } } ItemStack stack = NotEnoughUpdates.INSTANCE.manager.jsonToStack(NotEnoughUpdates.INSTANCE.manager .getItemInformation() .get(internal), false); if (missingDisplayNames.contains(stack.getDisplayName())) continue; missingDisplayNames.add(stack.getDisplayName()); if (hasDup) { if (!missing_showAllTiers) continue; stack.setStackDisplayName(stack.getDisplayName() + "*"); } missing.add(stack); } } if (missing.isEmpty()) { drawTitle(x, y, "No Missing"); } else { drawTitle(x, y, "Missing: " + missing.size()); int yIndex = 0; missingPageActive = Math.min(missingPageActive, missing.size() / 8); for (ItemStack missingStack : missing.subList(missingPageActive * 8, missing.size())) { String s = missingStack.getDisplayName(); String internal = NotEnoughUpdates.INSTANCE.manager .createItemResolutionQuery() .withItemStack(missingStack) .resolveInternalName(); if (internal.equals("RIFT_PRISM") && hasConsumedRiftPrism()) continue; double price = getItemPrice(internal); Utils.renderAlignedString( s, price != -1 ? "§6" + Utils.shortNumberFormat(price, 0) : "§c" + "NO DATA", x + 5, y + 20 + 11 * yIndex, 158 ); Rectangle rect = new Rectangle(x, y + 20 + 11 * yIndex, 168, 11); renderAccessoryHover(rect, missingStack); if (++yIndex >= 8 && missing.size() > 9) break; } missingPagesTotal = (int) Math.ceil(missing.size() / 8.0); if (missing.size() > 9) { GlStateManager.color(1f, 1f, 1f, 1f); ArrowPagesUtils.onDraw(x, y, new int[]{60, 110}, missingPageActive, missingPagesTotal); } List mpTooltip = new ArrayList<>(); if (missing_useMP) { mpTooltip.add("§bSort by Magical Power"); mpTooltip.add("§7Will sort the accessories"); mpTooltip.add("§7by the best MP gain."); } else { mpTooltip.add("§6Sort by Coins"); mpTooltip.add("§7Will sort the accessories"); mpTooltip.add("§7by the cheapest options."); } renderButton(ItemUtils.getCoinItemStack(missing_useMP ? 10_000_000 : 100_000), x + 120, y + 107, mpTooltip); List tieredTooltip = new ArrayList<>(); if (missing_showAllTiers) { tieredTooltip.add("§aShow all tiers"); tieredTooltip.add("§7Will show all the tiers"); tieredTooltip.add("§7to get the cheapest options."); } else { tieredTooltip.add("§6Show highest tier"); tieredTooltip.add("§7Will show only the highest tier"); tieredTooltip.add("§7to avoid wasting money on lower ones."); } renderButton(new ItemStack(missing_showAllTiers ? Items.coal : Items.diamond), x + 141, y + 107, tieredTooltip); } } private static void drawTitle(int x, int y, String abc) { Utils.drawStringCenteredScaledMaxWidth(abc, x + 84, y + 12, false, 158, gray()); } private static int gray() { return new Color(80, 80, 80).getRGB(); } private static Comparator getItemComparator(boolean accountMP) { return (o1, o2) -> { double cost1 = getItemPrice(o1); double cost2 = getItemPrice(o2); if (accountMP) { cost1 /= cost1 != -1 ? getMagicalPowerForItem(o1) : -1E-99; // Artificially push items with -1 price to the end cost2 /= cost2 != -1 ? getMagicalPowerForItem(o2) : -1E-99; // since they would be put at the start otherwise } if (cost1 == -1 && cost2 == -1) return o1.compareTo(o2); if (cost1 == -1) return 1; if (cost2 == -1) return -1; if (cost1 < cost2) return -1; if (cost1 > cost2) return 1; return o1.compareTo(o2); }; } private static boolean inAccessoryBag = false; public static boolean isInAccessoryBag() { return inAccessoryBag && NotEnoughUpdates.INSTANCE.config.accessoryBag.enableOverlay; } public static void renderOverlay() { inAccessoryBag = false; offsetButtons = false; if (Minecraft.getMinecraft().currentScreen instanceof GuiChest) { GuiChest eventGui = (GuiChest) Minecraft.getMinecraft().currentScreen; ContainerChest cc = (ContainerChest) eventGui.inventorySlots; String containerName = cc.getLowerChestInventory().getDisplayName().getUnformattedText(); if (containerName.trim().startsWith("Accessory Bag") && !containerName.contains("Thaumaturgy") && !containerName.contains("Upgrades")) { inAccessoryBag = true; try { AccessorGuiContainer accessor = (AccessorGuiContainer) Minecraft.getMinecraft().currentScreen; int xSize = accessor.getXSize(); int guiLeft = accessor.getGuiLeft(); int guiTop = accessor.getGuiTop(); if (accessoryStacks.isEmpty()) { for (ItemStack stack : Minecraft.getMinecraft().thePlayer.inventory.mainInventory) { if (stack != null && isAccessory(stack)) { accessoryStacks.add(stack); } } } if (containerName.trim().contains("(")) { String first = containerName.trim().split("\\(")[1].split("/")[0]; Integer currentPageNumber = Integer.parseInt(first); boolean hasStack = false; if (Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) { IInventory inv = ((ContainerChest) Minecraft.getMinecraft().thePlayer.openContainer).getLowerChestInventory(); for (int i = 0; i < inv.getSizeInventory(); i++) { ItemStack stack = inv.getStackInSlot(i); if (stack != null) { hasStack = true; if (isAccessory(stack)) { boolean toAdd = true; for (ItemStack accessoryStack : accessoryStacks) { String s = NEUManager.getUUIDForItem(accessoryStack); String ss = NEUManager.getUUIDForItem(stack); if (ss != null && ss.equals(s)) { toAdd = false; break; } } if (toAdd) accessoryStacks.add(stack); } } } } if (hasStack) pagesVisited.add(currentPageNumber); String second = containerName.trim().split("/")[1].split("\\)")[0]; //System.out.println(second + ":" + pagesVisited.size()); if (Integer.parseInt(second) > pagesVisited.size()) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay); GlStateManager.disableLighting(); Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 168, 128, 0, 168 / 196f, 0, 1f, GL11.GL_NEAREST); renderVisitOverlay(guiLeft + xSize + 3, guiTop); return; } } else if (pagesVisited.isEmpty()) { boolean hasStack = false; if (Minecraft.getMinecraft().thePlayer.openContainer instanceof ContainerChest) { IInventory inv = ((ContainerChest) Minecraft.getMinecraft().thePlayer.openContainer).getLowerChestInventory(); for (int i = 0; i < inv.getSizeInventory(); i++) { ItemStack stack = inv.getStackInSlot(i); if (stack != null) { hasStack = true; if (isAccessory(stack)) { accessoryStacks.add(stack); } } } } if (hasStack) pagesVisited.add(1); } GlStateManager.disableLighting(); offsetButtons = true; for (int i = 0; i <= Tabs.values().length - 1; i++) { if (i != currentTab.ordinal()) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay); Utils.drawTexturedRect(guiLeft + xSize + 168, guiTop + 20 * i, 25, 22, 168 / 196f, 193f / 196f, 0f, 22 / 128f, GL11.GL_NEAREST ); RenderHelper.enableGUIStandardItemLighting(); Utils.drawItemStack(TAB_STACKS[i], guiLeft + xSize + 168 + 5, guiTop + 20 * i + 3); } } GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay); Utils.drawTexturedRect(guiLeft + xSize + 4, guiTop, 168, 128, 0, 168 / 196f, 0, 1f, GL11.GL_NEAREST); if (pagesVisited.isEmpty()) { renderVisitOverlay(guiLeft + xSize + 3, guiTop); return; } Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay); Utils.drawTexturedRect(guiLeft + xSize + 168, guiTop + 20 * currentTab.ordinal(), 28, 22, 168 / 196f, 1f, 22 / 128f, 44 / 128f, GL11.GL_NEAREST ); RenderHelper.enableGUIStandardItemLighting(); Utils.drawItemStack( TAB_STACKS[currentTab.ordinal()], guiLeft + xSize + 168 + 8, guiTop + 20 * currentTab.ordinal() + 3 ); fillDuplicates(); switch (currentTab) { case TAB_BASIC: renderBasicOverlay(guiLeft + xSize + 3, guiTop); break; case TAB_TOTAL: renderTotalStatsOverlay(guiLeft + xSize + 3, guiTop); break; case TAB_DUP: renderDuplicatesOverlay(guiLeft + xSize + 3, guiTop); break; case TAB_MISSING: renderMissingOverlay(guiLeft + xSize + 3, guiTop); } if (dupe_highlight) { highlightDuplicates(); } } catch (Exception e) { e.printStackTrace(); } if (tooltipToDisplay != null) { Utils.drawHoveringText(tooltipToDisplay, mouseX(), mouseY(), eventGui.width, eventGui.height, -1); tooltipToDisplay = null; } } } } private static PlayerStats.Stats getStatForItem( ItemStack stack, HashMap patternMap, boolean addExtras ) { String internalname = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withItemStack(stack).resolveInternalName(); NBTTagCompound tag = stack.getTagCompound(); PlayerStats.Stats stats = new PlayerStats.Stats(); if (internalname == null) { return stats; } if (tag != null) { NBTTagCompound display = tag.getCompoundTag("display"); if (display.hasKey("Lore", 9)) { NBTTagList list = display.getTagList("Lore", 8); for (int i = 0; i < list.tagCount(); i++) { String line = list.getStringTagAt(i); for (Map.Entry entry : patternMap.entrySet()) { Matcher matcher = entry.getValue().matcher(Utils.cleanColour(line)); if (matcher.find()) { float bonus = Float.parseFloat(matcher.group(1)); stats.addStat(entry.getKey(), bonus); } } if (line.startsWith(EnumChatFormatting.GRAY + "Current Bonus: ")) { for (Map.Entry entry : patternMap.entrySet()) { String prettyStatName = Utils.cleanColour( PlayerStats.defaultStatNamesPretty[Arrays .asList(PlayerStats.defaultStatNames) .indexOf(entry.getKey())]); if (line.contains(prettyStatName)) { float bonus = Float.parseFloat( line.split(prettyStatName)[0] .replaceAll("§7Current Bonus: §.", "")); stats.addStat(entry.getKey(), bonus); } } } } } } if (!addExtras) return stats; if (internalname.equals("DAY_CRYSTAL") || internalname.equals("NIGHT_CRYSTAL")) { stats.addStat(PlayerStats.STRENGTH, 2.5f); stats.addStat(PlayerStats.DEFENCE, 2.5f); } return stats; } public static int checkItemType(ItemStack stack, boolean contains, String... typeMatches) { NBTTagCompound tag = stack.getTagCompound(); if (tag != null) { NBTTagCompound display = tag.getCompoundTag("display"); if (display.hasKey("Lore", 9)) { NBTTagList list = display.getTagList("Lore", 8); for (int i = list.tagCount() - 1; i >= 0; i--) { String line = list.getStringTagAt(i); for (String rarity : Utils.rarityArr) { for (int j = 0; j < typeMatches.length; j++) { if (contains) { if (line.trim().contains(rarity + " " + typeMatches[j])) { return j; } else if (line.trim().contains(rarity + " DUNGEON " + typeMatches[j])) { return j; } } else { if (line.trim().endsWith(rarity + " " + typeMatches[j])) { return j; } else if (line.trim().endsWith(rarity + " DUNGEON " + typeMatches[j])) { return j; } } } } } } } return -1; } private static int checkItemType(JsonArray lore, String... typeMatches) { for (int i = lore.size() - 1; i >= 0; i--) { String line = lore.get(i).getAsString(); for (String rarity : Utils.rarityArr) { for (int j = 0; j < typeMatches.length; j++) { if (line.trim().endsWith(rarity + " " + typeMatches[j])) { return j; } } } } return -1; } public static boolean isAccessory(ItemStack stack) { return checkItemType(stack, true, "ACCESSORY", "HATCESSORY") >= 0; } public static int getRarity(ItemStack stack) { NBTTagCompound tag = stack.getTagCompound(); if (tag != null) { NBTTagCompound display = tag.getCompoundTag("display"); if (display.hasKey("Lore", 9)) { NBTTagList list = display.getTagList("Lore", 8); for (int i = list.tagCount(); i >= 0; i--) { String line = list.getStringTagAt(i); for (int j = 0; j < Utils.rarityArrC.length; j++) { if (line.contains(Utils.rarityArrC[j])) { return j; } } } } } return -1; } public static double getItemPrice(String internal) { APIManager.CraftInfo info = NotEnoughUpdates.INSTANCE.manager.auctionManager.getCraftCost(internal); double bin = NotEnoughUpdates.INSTANCE.manager.auctionManager.getLowestBin(internal); if (info == null) return bin; if (bin == -1) return info.craftCost; return Math.min(info.craftCost, bin); } public static ScaledResolution getScaledResolution() { return new ScaledResolution(Minecraft.getMinecraft()); } public static int mouseX() { return Mouse.getX() / getScaledResolution().getScaleFactor(); } public static int mouseY() { return getScaledResolution().getScaledHeight() - Mouse.getY() / getScaledResolution().getScaleFactor(); } public static int getMagicalPowerForItem(String internal) { int abi = 0; JsonObject jsonStack = NotEnoughUpdates.INSTANCE.manager.getJsonForItem( NotEnoughUpdates.INSTANCE.manager. createItemResolutionQuery(). withKnownInternalName(internal). resolveToItemStack()); int rarity = Utils.getRarityFromLore(jsonStack.get("lore").getAsJsonArray()); if (internal.equals("HEGEMONY_ARTIFACT")) { switch (rarity) { case 4: return 16; case 5: return 22; } } if (internal.contains("ABICASE")) { abi = getAbiphoneMagicPower(); } switch (rarity) { case 0: case 6: return abi + 3; case 1: case 7: return abi + 5; case 2: return abi + 8; case 3: return abi + 12; case 4: return abi + 16; case 5: return abi + 22; } return 0; } public static void renderButton(ItemStack stack, int x, int y, List tooltip) { GlStateManager.color(1, 1, 1, 1); Minecraft.getMinecraft().getTextureManager().bindTexture(accessory_bag_overlay); GlStateManager.disableLighting(); Utils.drawTexturedRect(x, y, 17, 17, 168f / 196f, 184f / 196f, 112f / 128f, 1f, GL11.GL_NEAREST); // slot RenderHelper.enableGUIStandardItemLighting(); Minecraft.getMinecraft().getRenderItem().renderItemIntoGUI(stack, x, y); // item if (new Rectangle(x, y, 16, 16).contains(mouseX(), mouseY())) { Utils.drawHoveringText( tooltip, mouseX(), mouseY(), getScaledResolution().getScaledWidth(), getScaledResolution().getScaledHeight(), -1 ); } } public static void highlightDuplicates() { AccessorGuiContainer accessor = (AccessorGuiContainer) Minecraft.getMinecraft().currentScreen; int guiLeft = accessor.getGuiLeft(); int guiTop = accessor.getGuiTop(); for (Slot slot : Minecraft.getMinecraft().thePlayer.openContainer.inventorySlots) { ItemStack stack = slot.getStack(); if (stack != null && isAccessory(stack)) { if (!dupe_showPersonal && NotEnoughUpdates.INSTANCE.manager .createItemResolutionQuery() .withItemStack(stack) .resolveInternalName() .matches("PERSONAL_(DELETOR|COMPACTOR)_[0-9]+")) continue; if (duplicates != null && duplicates .stream() .map(ItemStack::getDisplayName) .collect(Collectors.toList()) .contains(stack.getDisplayName())) { GlStateManager.translate(0, 0, 50); GuiScreen.drawRect( guiLeft + slot.xDisplayPosition, guiTop + slot.yDisplayPosition, guiLeft + slot.xDisplayPosition + 16, guiTop + slot.yDisplayPosition + 16, 0xBBFF0000 ); GlStateManager.translate(0, 0, -50); } } } } public static void fillDuplicates() { if (duplicates != null) return; JsonObject misc = Constants.MISC; JsonElement talisman_upgrades_element = misc.get("talisman_upgrades"); if (talisman_upgrades_element == null) { Utils.showOutdatedRepoNotification("misc.json talisman_upgrades"); return; } JsonObject talisman_upgrades = talisman_upgrades_element.getAsJsonObject(); duplicates = new HashSet<>(); ArrayList duplicatesIDs = new ArrayList<>(); Set prevInternalnames = new HashSet<>(); for (ItemStack stack : accessoryStacks) { String internalname = NotEnoughUpdates.INSTANCE.manager.createItemResolutionQuery().withItemStack(stack).resolveInternalName(); if (prevInternalnames.contains(internalname)) { duplicates.add(stack); duplicatesIDs.add(internalname); continue; } prevInternalnames.add(internalname); if (talisman_upgrades.has(internalname)) { JsonArray upgrades = talisman_upgrades.get(internalname).getAsJsonArray(); for (ItemStack stack2 : accessoryStacks) { if (stack != stack2) { String internalname2 = NotEnoughUpdates.INSTANCE.manager .createItemResolutionQuery() .withItemStack(stack2) .resolveInternalName(); boolean toAdd = false; ArrayList upgradeIDs = new ArrayList<>(); for (int j = 0; j < upgrades.size(); j++) { String upgrade = upgrades.get(j).getAsString(); upgradeIDs.add(upgrade); if (internalname2.equals(upgrade)) { duplicates.add(stack); toAdd = true; } } if (toAdd) duplicatesIDs.addAll(upgradeIDs); } } } } for (ItemStack accessoryStack : accessoryStacks) { String internalID = NotEnoughUpdates.INSTANCE.manager .createItemResolutionQuery() .withItemStack(accessoryStack) .resolveInternalName(); if (duplicatesIDs.contains(internalID)) { duplicates.add(accessoryStack); } } } public static void renderAccessoryHover(Rectangle rect, ItemStack stack) { if (rect.contains(mouseX(), mouseY())) { String internal = NotEnoughUpdates.INSTANCE.manager .createItemResolutionQuery() .withItemStack(stack) .resolveInternalName(); tooltipToDisplay = Arrays.asList( stack.getDisplayName().replace("*", ""), "", "§eClick to learn more!", "§eCtrl+Click to search on ah!" ); handleAccessoryClick(stack, internal); } } public static void handleAccessoryClick(ItemStack stack, String internal) { if (Mouse.isButtonDown(0) && internal != null) { if (!Keyboard.isKeyDown(Keyboard.KEY_LCONTROL)) { if (!NotEnoughUpdates.INSTANCE.manager.displayGuiItemRecipe(internal)) { NEUOverlay.getTextField().setText("id:" + internal); NotEnoughUpdates.INSTANCE.overlay.updateSearch(); NotEnoughUpdates.INSTANCE.overlay.setSearchBarFocus(true); } } else { String displayname = Utils.cleanColour(stack.getDisplayName()); NotEnoughUpdates.INSTANCE.trySendCommand("/ahs " + displayname.replace("*", "")); } } } public static boolean hasConsumedRiftPrism() { NEUConfig.HiddenProfileSpecific profileSpecific = NotEnoughUpdates.INSTANCE.config.getProfileSpecific(); if (profileSpecific == null) return false; try { JsonObject profileInfo = GuiProfileViewer.getSelectedProfile().getProfileJson(); if (profileInfo.has("rift") && profileInfo.getAsJsonObject("rift").has("access")) { profileSpecific.hasConsumedRiftPrism = profileInfo.getAsJsonObject( "rift").getAsJsonObject("access").has("consumed_prism"); } } catch (NullPointerException ignored) { } return profileSpecific.hasConsumedRiftPrism; } public static int getAbiphoneMagicPower() { NEUConfig.HiddenProfileSpecific profileSpecific = NotEnoughUpdates.INSTANCE.config.getProfileSpecific(); if (profileSpecific == null) return 0; try { JsonObject profileInfo = GuiProfileViewer.getSelectedProfile().getProfileJson(); if (profileInfo.has("nether_island_player_data")) { JsonObject data = profileInfo.get("nether_island_player_data").getAsJsonObject(); if (data.has("abiphone") && data.get("abiphone").getAsJsonObject().has("active_contacts")) { // BatChest int contact = data.get("abiphone").getAsJsonObject().get("active_contacts").getAsJsonArray().size(); profileSpecific.abiphoneMagicPower = contact / 2; } } } catch (NullPointerException ignored) { } return profileSpecific.abiphoneMagicPower; } private static void playPressSound() { if (NotEnoughUpdates.INSTANCE.config.misc.guiButtonClicks) Utils.playPressSound(); } }