From cc2b9c92404ed03661778aaae5477444a146ee9f Mon Sep 17 00:00:00 2001 From: Cow Date: Sun, 11 Apr 2021 15:03:58 +0200 Subject: Added order (sort) functionality to Bazaar 'Sell All' tooltip - also increased decimal places for AH: price each - also added Bestiary Overview mini-'tutorial' --- CHANGELOG.md | 1 + .../de/cowtipper/cowlection/config/MooConfig.java | 7 ++ .../listener/skyblock/SkyBlockListener.java | 77 +++++++++++++++++++++- .../java/de/cowtipper/cowlection/util/Utils.java | 13 +++- .../resources/assets/cowlection/lang/en_US.lang | 2 + 5 files changed, 98 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2308919..b082f69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - only works on enchanted books with *one* enchantment - enabled for all ultimate and Turbo-crop enchantments - additional enchantments can be added via `/moo config` *(Keep in mind that not all high-level enchantments can be created by combining lower level books!)* +- Bazaar: Added order (sort) functionality to 'Sell Inventory/Sacks Now' tooltips - SkyBlock Dungeon Party Finder additions: - new `/moo config` option: `Minimum "Dungeon level required"` - SkyBlock Dwarven Mines update: diff --git a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java index 5a9750d..22db2c2 100644 --- a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java +++ b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java @@ -80,6 +80,7 @@ public class MooConfig { private static String tooltipAuctionHousePriceEach; public static String[] tooltipAuctionHousePriceEachEnchantments; private static String auctionHouseMarkEndedAuctions; + public static String bazaarSellAllOrder; private static String bazaarConnectGraphsNodes; public static int bazaarConnectGraphsLineWidth; public static String bestiaryOverviewOrder; @@ -417,6 +418,10 @@ public class MooConfig { Property propAuctionHouseMarkEndedAuctions = subCat.addConfigEntry(cfg.get(configCat.getConfigName(), "auctionHouseMarkEndedAuctions", "a letter", "Mark ended auctions", new String[]{"a letter", "a word", "disabled"})); + Property propBazaarSellAllOrder = subCat.addConfigEntry(cfg.get(configCat.getConfigName(), + "bazaarSellAllOrder", "price (sum)", "Bazaar: sell all order", new String[]{"price (sum)", "item amount", "unordered", "price (each)"}), + new MooConfigPreview(MooConfigPreview.createDemoItem("chest", "§aSell Inventory Now", new String[]{"§7Instantly sell anything in", "§7your inventory that can be", "§7sold on the Bazaar.", "", " §a1§7x §aEnchanted Leather §7for §65,263.1 coins", " §a42§7x §fLeather §7for §6436.8 coins", " §a2§7x §fRabbit Hide §7for §642.0 coins", " §a79§7x §fRaw Beef §7for §6450.3 coins", " §a16§7x §aEnchanted Raw Beef §7for §69,867.2 coins", "", "§7You earn: §615,698 coins", "", "§eClick to sell!"}, Collections.emptyMap()))); + MooConfigPreview bazaarGraphPreview = new MooConfigPreview(MooConfigPreview.createDemoItem("paper", "§aBuy Price §731d §77d §e24h", new String[]{ "§7The price at which buy orders have been filled.", "", "§r┌----------------------------------------------┐", "§r│§66. 1k§r+§bxxxxxx§8·································§bxx§r│", @@ -630,6 +635,7 @@ public class MooConfig { tooltipAuctionHousePriceEach = propTooltipAuctionHousePriceEach.getString(); tooltipAuctionHousePriceEachEnchantments = propTooltipAuctionHousePriceEachEnchantments.getStringList(); auctionHouseMarkEndedAuctions = propAuctionHouseMarkEndedAuctions.getString(); + bazaarSellAllOrder = propBazaarSellAllOrder.getString(); bazaarConnectGraphsNodes = propBazaarConnectGraphsNodes.getString(); bazaarConnectGraphsLineWidth = propBazaarConnectGraphsLineWidth.getInt(); bestiaryOverviewOrder = propBestiaryOverviewOrder.getString(); @@ -706,6 +712,7 @@ public class MooConfig { propTooltipAuctionHousePriceEach.set(tooltipAuctionHousePriceEach); propTooltipAuctionHousePriceEachEnchantments.set(tooltipAuctionHousePriceEachEnchantments); propAuctionHouseMarkEndedAuctions.set(auctionHouseMarkEndedAuctions); + propBazaarSellAllOrder.set(bazaarSellAllOrder); propBazaarConnectGraphsNodes.set(bazaarConnectGraphsNodes); propBazaarConnectGraphsLineWidth.set(bazaarConnectGraphsLineWidth); propBestiaryOverviewOrder.set(bestiaryOverviewOrder); diff --git a/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java b/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java index 09a8152..35acf43 100644 --- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java +++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java @@ -1,5 +1,7 @@ package de.cowtipper.cowlection.listener.skyblock; +import com.google.common.collect.Ordering; +import com.google.common.collect.TreeMultimap; import com.mojang.realmsclient.util.Pair; import de.cowtipper.cowlection.Cowlection; import de.cowtipper.cowlection.config.MooConfig; @@ -68,6 +70,8 @@ public class SkyBlockListener { private static final Pattern ITEM_COUNT_SUFFIXED_PATTERN = Pattern.compile(" (?:§[0-9a-fl-or])*x[\\d]+$"); private static final Pattern PET_NAME_PATTERN = Pattern.compile("^§7\\[Lvl (\\d+)] (§[0-9a-f])"); private static final Pattern TIER_SUFFIX_PATTERN = Pattern.compile(" [IVX0-9]+$"); + // example: " §a42§7x §fLeather §7for §6436.8 coins" + private static final Pattern BAZAAR_SELL_ALL_PATTERN = Pattern.compile("^(?:§[0-9a-fl-or])* (?:§[0-9a-fl-or])+([0-9,]+)(?:§[0-9a-fl-or])+x (?:§[0-9a-fl-or])+[A-Za-z ]+ (?:§[0-9a-fl-or])+for (?:§[0-9a-fl-or])+([0-9,.]+) coins$"); List bestiaryOverview = null; private final NumberFormat numberFormatter; private final Cowlection main; @@ -325,7 +329,15 @@ public class SkyBlockListener { // either use cached bestiary overview or generate overview if trigger item is different boolean isDifferentTriggerItem = BestiaryEntry.isDifferentTriggerItem(e.itemStack); GuiScreen currentScreen = Minecraft.getMinecraft().currentScreen; - if (currentScreen instanceof GuiChest && isBestiaryOverviewVisible && isBestiaryGui((GuiChest) currentScreen, e.itemStack)) { + if (currentScreen instanceof GuiChest && isBestiaryOverviewVisible && isBestiaryMainGui((GuiChest) currentScreen, e.itemStack)) { + e.toolTip.add(""); + e.toolTip.add("" + EnumChatFormatting.GOLD + EnumChatFormatting.BOLD + EnumChatFormatting.UNDERLINE + "Cowlection: Bestiary overview"); + e.toolTip.add(EnumChatFormatting.GRAY + "Select an area below, then hover"); + e.toolTip.add(EnumChatFormatting.GRAY + "over the area icon at the top to see"); + e.toolTip.add(EnumChatFormatting.GRAY + "the " + bestiaryOverviewOrder + " left to the next bestiary tier."); + e.toolTip.add(EnumChatFormatting.DARK_GRAY + "(Hypixel's bestiary shows " + EnumChatFormatting.ITALIC + "progress"); + e.toolTip.add(EnumChatFormatting.DARK_GRAY + " & Cowlection tooltip shows kills " + EnumChatFormatting.ITALIC + "left" + EnumChatFormatting.RESET + EnumChatFormatting.DARK_GRAY + "!)"); + } else if (currentScreen instanceof GuiChest && isBestiaryOverviewVisible && isBestiaryGui((GuiChest) currentScreen, e.itemStack)) { if (isDifferentTriggerItem) { BestiaryEntry.reinitialize(e.itemStack); bestiaryOverview = new ArrayList<>(); @@ -401,6 +413,62 @@ public class SkyBlockListener { } } + // bazaar: sort "Sell Now" + if ((e.itemStack.getItem() == Items.cauldron || e.itemStack.getItem() == Item.getItemFromBlock(Blocks.chest)) && !"unordered".equals(MooConfig.bazaarSellAllOrder)) { + String hoveredItemName = EnumChatFormatting.getTextWithoutFormattingCodes(e.itemStack.getDisplayName()); + if ("Sell Inventory Now".equals(hoveredItemName) || "Sell Sacks Now".equals(hoveredItemName)) { + NumberFormat numberFormatter = NumberFormat.getNumberInstance(Locale.US); + numberFormatter.setMaximumFractionDigits(1); + List toolTip = e.toolTip; + int startIndex = 1337; + TreeMultimap sellEntries = TreeMultimap.create(Ordering.natural().reverse(), Ordering.natural()); + for (int i = 0; i < toolTip.size(); i++) { + Matcher bazaarSellMatcher = BAZAAR_SELL_ALL_PATTERN.matcher(toolTip.get(i)); + if (bazaarSellMatcher.matches()) { + if (i < startIndex) { + startIndex = i; + } + String amountStr = bazaarSellMatcher.group(1); + String priceStr = bazaarSellMatcher.group(2); + try { + double key; + String suffix = ""; + switch (MooConfig.bazaarSellAllOrder) { + case "price (sum)": + key = numberFormatter.parse(priceStr).doubleValue(); + break; + case "item amount": + key = numberFormatter.parse(amountStr).intValue(); + break; + case "price (each)": + key = numberFormatter.parse(priceStr).doubleValue() / numberFormatter.parse(amountStr).doubleValue(); + suffix = EnumChatFormatting.DARK_GRAY + " (" + numberFormatter.format(key) + " each)"; + break; + default: + // invalid value, abort! + return; + } + sellEntries.put(key, toolTip.get(i) + suffix); + } catch (ParseException ex) { + // abort + return; + } + } else if (startIndex < 1337) { + // startIndex has been set; lore line no longer matches regex: reached end of tooltip's 'sell all'-section + break; + } + } + if (sellEntries.size() > 1) { + int sellEntryIndex = 0; + for (String sellEntry : sellEntries.values()) { + e.toolTip.set(startIndex + sellEntryIndex, sellEntry); + ++sellEntryIndex; + } + e.toolTip.add(startIndex + sellEntryIndex, EnumChatFormatting.DARK_GRAY + " » ordered by " + MooConfig.bazaarSellAllOrder); + } + } + } + // for auction house: show price for each item if multiple items are sold at once or if higher tier ultimate enchantment books are sold MooConfig.Setting tooltipAuctionHousePriceEachDisplay = MooConfig.getTooltipAuctionHousePriceEachDisplay(); if ((tooltipAuctionHousePriceEachDisplay == MooConfig.Setting.ALWAYS || tooltipAuctionHousePriceEachDisplay == MooConfig.Setting.SPECIAL && MooConfig.isTooltipToggleKeyBindingPressed()) @@ -612,6 +680,13 @@ public class SkyBlockListener { } } + private boolean isBestiaryMainGui(GuiChest guiChest, ItemStack hoveredItem) { + IInventory inventory = guiChest.inventorySlots.getSlot(0).inventory; + String inventoryName = (inventory.hasCustomName() ? EnumChatFormatting.getTextWithoutFormattingCodes(inventory.getDisplayName().getUnformattedTextForChat()) : inventory.getName()); + String hoveredItemName = EnumChatFormatting.getTextWithoutFormattingCodes(hoveredItem.getDisplayName()); + return ("Bestiary".equals(inventoryName) && "Bestiary".equals(hoveredItemName) && hoveredItem.getItem() == Items.writable_book); + } + private boolean isBestiaryGui(GuiChest guiChest, ItemStack hoveredItem) { IInventory inventory = guiChest.inventorySlots.getSlot(0).inventory; String inventoryName = (inventory.hasCustomName() ? EnumChatFormatting.getTextWithoutFormattingCodes(inventory.getDisplayName().getUnformattedTextForChat()) : inventory.getName()); diff --git a/src/main/java/de/cowtipper/cowlection/util/Utils.java b/src/main/java/de/cowtipper/cowlection/util/Utils.java index bfeef4b..47eb356 100644 --- a/src/main/java/de/cowtipper/cowlection/util/Utils.java +++ b/src/main/java/de/cowtipper/cowlection/util/Utils.java @@ -121,7 +121,18 @@ public final class Utils { Double divideBy = e.getKey(); Character suffix = e.getValue(); - DecimalFormat df = new DecimalFormat("#,##0.#"); + String amountOfDecimals; + switch (suffix) { + case 'k': + amountOfDecimals = "#"; + break; + case 'm': + amountOfDecimals = "##"; + break; + default: + amountOfDecimals = "###"; + } + DecimalFormat df = new DecimalFormat("#,##0." + amountOfDecimals); return df.format(number / divideBy) + suffix; } diff --git a/src/main/resources/assets/cowlection/lang/en_US.lang b/src/main/resources/assets/cowlection/lang/en_US.lang index d23b7f4..63217da 100644 --- a/src/main/resources/assets/cowlection/lang/en_US.lang +++ b/src/main/resources/assets/cowlection/lang/en_US.lang @@ -58,6 +58,8 @@ cowlection.config.tooltipAuctionHousePriceEachEnchantments=§7AH: §rprice per l cowlection.config.tooltipAuctionHousePriceEachEnchantments.tooltip=Breaks down the price of enchanted books with one higher-tiered enchantment into their potential level 1 book prices.\n§d§lUltimate§r and §eTurbo-Crop §renchantments are always included. Enchantments set in this config option get broken down additionally.\n§7Keep in mind that not all high-level enchantments can be created by combining lower level books! cowlection.config.auctionHouseMarkEndedAuctions=§7AH: §rmark sold/ended/expired auctions with... cowlection.config.auctionHouseMarkEndedAuctions.tooltip=Add indicators to auctions that...\n ‣ sold: §aSold §ror §aS\n ‣ ended: §aEnded §ror §aE\n ‣ expired: §cExpired §ror §cE +cowlection.config.bazaarSellAllOrder=§7Bazaar: §rOrder 'Sell Inventory/Sacks Now' by... +cowlection.config.bazaarSellAllOrder.tooltip=Order the Sell All tooltip inside the Bazaar by...\n ‣ price (sum)\n ‣ price (each)\n ‣ item amount\n ‣ or keep it unorderd cowlection.config.bazaarConnectGraphsNodes=§7Bazaar: §rconnect the graph nodes cowlection.config.bazaarConnectGraphsNodes.tooltip=Draw a line through the nodes of the bazaar graphs?\n§7§oThis also (tries to) fix the graphs when using the MC unicode font. cowlection.config.bazaarConnectGraphsLineWidth=§7Bazaar: §rline width -- cgit