From 91975bf22481edb0f74c204a7b847baac3830736 Mon Sep 17 00:00:00 2001 From: Cow Date: Tue, 29 Dec 2020 14:06:37 +0100 Subject: Added quick lookup for item prices and wiki --- CHANGELOG.md | 3 + .../de/cowtipper/cowlection/config/MooConfig.java | 30 ++++- .../cowlection/listener/PlayerListener.java | 2 +- .../listener/skyblock/DungeonsListener.java | 56 +--------- .../listener/skyblock/SkyBlockListener.java | 123 ++++++++++++++++++++- .../de/cowtipper/cowlection/util/GuiHelper.java | 26 ++--- .../java/de/cowtipper/cowlection/util/Utils.java | 66 +++++++++++ .../resources/assets/cowlection/lang/en_US.lang | 8 +- 8 files changed, 236 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ac4e9c..6601a31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - SkyBlock Bazaar graphs improvements: - make graphs easier to read by connecting graphs' nodes - Fix graphs when using the mc unicode font +- Added quick lookup for item prices and wiki: + - wiki: hypixel-skyblock.fandom.com (default key: `I` = info) + - item prices: stonks.gg (default key: `P` = price) ### Changed - Item age: show timestamp in the local timezone instead of "SkyBlock"-timezone (Eastern Time; also fixed the incorrect 12h ↔ 24h clock conversion) diff --git a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java index f8674ed..2adfcb7 100644 --- a/src/main/java/de/cowtipper/cowlection/config/MooConfig.java +++ b/src/main/java/de/cowtipper/cowlection/config/MooConfig.java @@ -74,6 +74,8 @@ public class MooConfig { public static boolean tooltipItemAgeShortened; private static String tooltipItemTimestamp; private static String numeralSystem; + private static int lookupWikiKeyBinding; + private static int lookupPriceKeyBinding; // Category: SkyBlock Dungeons private static String showItemQualityAndFloor; private static String dungItemQualityPos; @@ -351,6 +353,14 @@ public class MooConfig { Property propNumeralSystem = subCat.addConfigEntry(cfg.get(configCat.getConfigName(), "numeralSystem", "Arabic: 1, 4, 10", "Use Roman or Arabic numeral system?", new String[]{"Arabic: 1, 4, 10", "Roman: I, IV, X"})); + // Sub-Category: Item lookup + subCat = configCat.addSubCategory("Item lookup"); + subCat.addExplanations("Lookup item prices or wiki articles for any SkyBlock item in any inventory."); + + Property propLookupWikiKeyBinding = subCat.addConfigEntry(cfg.get(configCat.getConfigName(), + "lookupWikiKeyBinding", Keyboard.KEY_I, "Key to lookup wiki")); + Property propLookupPriceKeyBinding = subCat.addConfigEntry(cfg.get(configCat.getConfigName(), + "lookupPriceKeyBinding", Keyboard.KEY_P, "Key to lookup item price")); // Category: SkyBlock Dungeons configCat = new MooConfigCategory("SkyBlock Dungeons", "skyblockdungeons"); @@ -489,6 +499,8 @@ public class MooConfig { tooltipItemAgeShortened = propTooltipItemAgeShortened.getBoolean(); tooltipItemTimestamp = propTooltipItemTimestamp.getString(); numeralSystem = propNumeralSystem.getString(); + lookupWikiKeyBinding = propLookupWikiKeyBinding.getInt(); + lookupPriceKeyBinding = propLookupPriceKeyBinding.getInt(); // Category: SkyBlock Dungeons showItemQualityAndFloor = propShowItemQualityAndFloor.getString(); dungItemQualityPos = propDungItemQualityPos.getString(); @@ -541,6 +553,8 @@ public class MooConfig { propTooltipItemAgeShortened.set(tooltipItemAgeShortened); propTooltipItemTimestamp.set(tooltipItemTimestamp); propNumeralSystem.set(numeralSystem); + propLookupWikiKeyBinding.set(lookupWikiKeyBinding); + propLookupPriceKeyBinding.set(lookupPriceKeyBinding); // Category: SkyBlock Dungeons propShowItemQualityAndFloor.set(showItemQualityAndFloor); propDungItemQualityPos.set(dungItemQualityPos); @@ -655,7 +669,7 @@ public class MooConfig { // Category: SkyBlock public static Setting getEnableSkyBlockOnlyFeatures() { - return Setting.get(MooConfig.enableSkyBlockOnlyFeatures); + return Setting.get(enableSkyBlockOnlyFeatures); } public static Setting getTooltipAuctionHousePriceEachDisplay() { @@ -679,11 +693,13 @@ public class MooConfig { } public static boolean isTooltipToggleKeyBindingPressed() { - return tooltipToggleKeyBinding > 0 && Keyboard.isKeyDown(MooConfig.tooltipToggleKeyBinding); + return tooltipToggleKeyBinding > 0 && Keyboard.isKeyDown(tooltipToggleKeyBinding); } - - public static boolean isDungeonItemTooltipToggleKeyBindingPressed() { - return dungItemToolTipToggleKeyBinding > 0 && Keyboard.isKeyDown(MooConfig.dungItemToolTipToggleKeyBinding); + public static boolean isLookupWikiKeyBindingPressed() { + return lookupWikiKeyBinding > 0 && Keyboard.isKeyDown(lookupWikiKeyBinding); + } + public static boolean isLookupPriceKeyBindingPressed() { + return lookupPriceKeyBinding > 0 && Keyboard.isKeyDown(lookupPriceKeyBinding); } // Category: SkyBlock Dungeons @@ -695,6 +711,10 @@ public class MooConfig { return dungItemQualityPos.equals("top"); } + public static boolean isDungeonItemTooltipToggleKeyBindingPressed() { + return dungItemToolTipToggleKeyBinding > 0 && Keyboard.isKeyDown(dungItemToolTipToggleKeyBinding); + } + public static Setting getDungPartyFinderPlayerLookupDisplay() { return Setting.get(dungPartyFinderPlayerLookup); } diff --git a/src/main/java/de/cowtipper/cowlection/listener/PlayerListener.java b/src/main/java/de/cowtipper/cowlection/listener/PlayerListener.java index 484b5b7..31d2d73 100644 --- a/src/main/java/de/cowtipper/cowlection/listener/PlayerListener.java +++ b/src/main/java/de/cowtipper/cowlection/listener/PlayerListener.java @@ -241,7 +241,7 @@ public class PlayerListener { public static boolean registerSkyBlockListeners() { if (dungeonsListener == null && skyBlockListener == null) { MinecraftForge.EVENT_BUS.register(dungeonsListener = new DungeonsListener(Cowlection.getInstance())); - MinecraftForge.EVENT_BUS.register(skyBlockListener = new SkyBlockListener()); + MinecraftForge.EVENT_BUS.register(skyBlockListener = new SkyBlockListener(Cowlection.getInstance())); return true; } return false; diff --git a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java index 15a902d..ba48367 100644 --- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java +++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/DungeonsListener.java @@ -1,5 +1,6 @@ package de.cowtipper.cowlection.listener.skyblock; +import com.mojang.realmsclient.util.Pair; import de.cowtipper.cowlection.Cowlection; import de.cowtipper.cowlection.config.MooConfig; import de.cowtipper.cowlection.config.gui.MooConfigGui; @@ -34,7 +35,6 @@ import net.minecraftforge.fml.common.eventhandler.EventPriority; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import net.minecraftforge.fml.relauncher.Side; -import org.apache.commons.lang3.StringUtils; import org.lwjgl.input.Mouse; import java.awt.*; @@ -130,57 +130,9 @@ public class DungeonsListener { if (toggleKeyBindingPressed) { // simplify dungeon armor stats String originalItemName = e.itemStack.getDisplayName(); - StringBuilder modifiedItemName = new StringBuilder(originalItemName); - String grayedOutFormatting = "" + EnumChatFormatting.GRAY + EnumChatFormatting.STRIKETHROUGH; - - if (extraAttributes.hasKey("modifier")) { - // item has been reforged; re-format item name to exclude reforges - reforge = StringUtils.capitalize(extraAttributes.getString("modifier")); - int modifierSuffix = Math.max(reforge.indexOf("_sword"), reforge.indexOf("_bow")); - if (modifierSuffix != -1) { - reforge = reforge.substring(0, modifierSuffix); - } - int reforgeInItemName = originalItemName.indexOf(reforge); - if (reforgeInItemName == -1 && reforge.equals("Light") && extraAttributes.getString("id").startsWith("HEAVY_")) { - // special case: heavy armor with light reforge - reforgeInItemName = originalItemName.indexOf("Heavy"); - } - - if (reforgeInItemName > 0 && !originalItemName.contains(EnumChatFormatting.STRIKETHROUGH.toString())) { - // we have a reforged item! strike through reforge in item name and remove any essence upgrades (✪) - - int reforgeLength = reforge.length(); - String reforgePrefix = null; - // special cases for reforge + item name - if (reforge.equals("Heavy") && extraAttributes.getString("id").startsWith("HEAVY_")) { - reforgePrefix = "Extremely "; - } else if (reforge.equals("Light") && extraAttributes.getString("id").startsWith("HEAVY_")) { - reforgePrefix = "Not So "; - } else if ((reforge.equals("Wise") && extraAttributes.getString("id").startsWith("WISE_DRAGON_")) - || (reforge.equals("Strong") && extraAttributes.getString("id").startsWith("STRONG_DRAGON_"))) { - reforgePrefix = "Very "; - } else if (reforge.equals("Superior") && extraAttributes.getString("id").startsWith("SUPERIOR_DRAGON_")) { - reforgePrefix = "Highly "; - } else if (reforge.equals("Perfect") && extraAttributes.getString("id").startsWith("PERFECT_")) { - reforgePrefix = "Absolutely "; - } - if (reforgePrefix != null) { - reforgeInItemName -= reforgePrefix.length(); - reforgeLength = reforgePrefix.length() - 1; - } - - modifiedItemName.insert(reforgeInItemName, grayedOutFormatting) - .insert(reforgeInItemName + reforgeLength + grayedOutFormatting.length(), originalItemName.substring(0, reforgeInItemName)); - } - } - // remove essence upgrade indicators (✪) - String essenceUpgradeIndicator = EnumChatFormatting.GOLD + "✪"; - int essenceModifier = modifiedItemName.indexOf(essenceUpgradeIndicator); - while (essenceModifier > 0) { - modifiedItemName.replace(essenceModifier, essenceModifier + essenceUpgradeIndicator.length(), grayedOutFormatting + "✪"); - essenceModifier = modifiedItemName.indexOf(essenceUpgradeIndicator); - } - e.toolTip.set(0, modifiedItemName.toString()); // replace item name + Pair sbItemBaseName = Utils.extractSbItemBaseName(originalItemName, extraAttributes, true); + e.toolTip.set(0, sbItemBaseName.first()); // replace item name + reforge = sbItemBaseName.second(); } // add item quality/floor and (if key bind is pressed: subtract stat boosts from reforge and update stats for dungeons) ListIterator tooltipIterator = e.toolTip.listIterator(); 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 3f79154..a8103bf 100644 --- a/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java +++ b/src/main/java/de/cowtipper/cowlection/listener/skyblock/SkyBlockListener.java @@ -1,49 +1,127 @@ package de.cowtipper.cowlection.listener.skyblock; +import com.mojang.realmsclient.util.Pair; +import de.cowtipper.cowlection.Cowlection; import de.cowtipper.cowlection.config.MooConfig; import de.cowtipper.cowlection.config.gui.MooConfigGui; import de.cowtipper.cowlection.util.GuiHelper; import de.cowtipper.cowlection.util.Utils; import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.SoundCategory; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.enchantment.Enchantment; 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.minecraft.util.StatCollector; +import net.minecraftforge.client.event.GuiScreenEvent; import net.minecraftforge.common.util.Constants; import net.minecraftforge.event.entity.player.ItemTooltipEvent; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.apache.commons.lang3.StringUtils; +import org.lwjgl.input.Keyboard; +import java.awt.*; +import java.net.URI; +import java.net.URLEncoder; import java.text.NumberFormat; import java.text.ParseException; import java.time.LocalDateTime; import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; import java.util.List; -import java.util.Locale; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class SkyBlockListener { + private static final Set blackList = new HashSet<>(Arrays.asList("ENCHANTED_BOOK", "RUNE", "PET", "POTION")); // + minions (_GENERATOR_) + private static final Pattern ITEM_COUNT_PREFIXED_PATTERN = Pattern.compile("^(?:§[0-9a-fl-or])*[\\d]+x "); + private static final Pattern ITEM_COUNT_SUFFIXED_PATTERN = Pattern.compile(" (?:§[0-9a-fl-or])*x[\\d]+$"); private final NumberFormat numberFormatter; + private final Cowlection main; - public SkyBlockListener() { + public SkyBlockListener(Cowlection main) { + this.main = main; numberFormatter = NumberFormat.getNumberInstance(Locale.US); numberFormatter.setMaximumFractionDigits(0); } + @SubscribeEvent + public void onItemLookupInGui(GuiScreenEvent.KeyboardInputEvent.Pre e) { + // open item info (wiki, price: bazaar or auction) + ItemLookupType itemLookupType; + if (MooConfig.isLookupWikiKeyBindingPressed()) { + itemLookupType = ItemLookupType.WIKI; + } else if (MooConfig.isLookupPriceKeyBindingPressed()) { + itemLookupType = ItemLookupType.PRICE; + } else { + itemLookupType = ItemLookupType.INVALID; + } + if (itemLookupType != ItemLookupType.INVALID && Keyboard.getEventKeyState() && e.gui instanceof GuiContainer) { + GuiContainer guiContainer = (GuiContainer) e.gui; + Slot hoveredSlot = GuiHelper.getSlotUnderMouse(guiContainer); + if (hoveredSlot != null && hoveredSlot.getHasStack()) { + ItemStack itemStack = hoveredSlot.getStack(); + NBTTagCompound extraAttributes = itemStack.getSubCompound("ExtraAttributes", false); + if (extraAttributes != null && extraAttributes.hasKey("id")) { + // seems to be a SkyBlock item + String sbId = extraAttributes.getString("id"); + if (itemLookupType == ItemLookupType.WIKI || (/* itemLookupType == ItemLookupType.PRICE && */ !blackList.contains(sbId) && !sbId.contains("_GENERATOR_"))) { + // open item price info or open wiki entry + Pair sbItemBaseName = Utils.extractSbItemBaseName(itemStack.getDisplayName(), extraAttributes, false); + String itemBaseName = sbItemBaseName.first(); + + // exceptions: + String querySuffix = ""; + // remove item count (prefixed or suffixed) + Matcher itemCountPrefixMatcher = ITEM_COUNT_PREFIXED_PATTERN.matcher(itemBaseName); + Matcher itemCountSuffixMatcher = ITEM_COUNT_SUFFIXED_PATTERN.matcher(itemBaseName); + if (itemCountPrefixMatcher.find()) { + itemBaseName = itemBaseName.substring(itemCountPrefixMatcher.end()); + } else if (itemCountSuffixMatcher.find()) { + itemBaseName = itemBaseName.substring(0, itemCountSuffixMatcher.start()); + } + // special sb item ids + if ("PET".equals(sbId)) { + int petLevelPrefix = itemBaseName.indexOf("] "); + if (petLevelPrefix > 0) { + itemBaseName = itemBaseName.substring(petLevelPrefix + 2); + } + querySuffix = " Pet"; + } else if ("CAKE_SOUL".equals(sbId)) { + itemBaseName = EnumChatFormatting.LIGHT_PURPLE + "Cake Soul"; + } + + main.getChatHelper().sendMessage(EnumChatFormatting.GREEN, "Opening " + itemLookupType.getDescription() + " for " + itemBaseName); + boolean success = openLink(EnumChatFormatting.getTextWithoutFormattingCodes(itemBaseName).trim() + querySuffix, itemLookupType); + if (!success) { + main.getChatHelper().sendMessage(EnumChatFormatting.RED, "Error: couldn't open your browser"); + Minecraft.getMinecraft().thePlayer.playSound("mob.villager.no", Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.MASTER), 1.4f); + } + } else { + // item is blacklisted from lookup + main.getChatHelper().sendMessage(EnumChatFormatting.RED, "⚠ " + EnumChatFormatting.RESET + itemStack.getDisplayName() + EnumChatFormatting.RED + " (" + Utils.fancyCase(sbId) + ") " + itemLookupType.getDescription() + " cannot be looked up."); + Minecraft.getMinecraft().thePlayer.playSound("mob.villager.no", Minecraft.getMinecraft().gameSettings.getSoundLevel(SoundCategory.MASTER), 1.4f); + } + } + } + } + } + @SubscribeEvent public void onItemTooltip(ItemTooltipEvent e) { - if (e.itemStack == null || e.toolTip == null) { + if (e.itemStack == null || e.toolTip == null || e.entityPlayer == null) { return; } @@ -140,7 +218,7 @@ public class SkyBlockListener { // for auction house: show price for each item if multiple items are sold at once MooConfig.Setting tooltipAuctionHousePriceEachDisplay = MooConfig.getTooltipAuctionHousePriceEachDisplay(); if ((tooltipAuctionHousePriceEachDisplay == MooConfig.Setting.ALWAYS || tooltipAuctionHousePriceEachDisplay == MooConfig.Setting.SPECIAL && MooConfig.isTooltipToggleKeyBindingPressed()) - && e.entityPlayer != null && e.entityPlayer.openContainer instanceof ContainerChest) { + && e.entityPlayer.openContainer instanceof ContainerChest) { int stackSize = e.itemStack.stackSize; if ((stackSize == 1 && !isSubmitBidItem(e.itemStack)) || e.toolTip.size() < 4) { // only 1 item or irrelevant tooltip - nothing to do here, abort! @@ -184,9 +262,44 @@ public class SkyBlockListener { } } + private boolean openLink(String itemName, ItemLookupType itemLookupType) { + String baseUrl = itemLookupType.getBaseUrl(); + try { + String url = baseUrl + URLEncoder.encode(itemName, "UTF-8"); + Desktop.getDesktop().browse(new URI(url)); + main.getLogger().info("Opening url: " + url); + return true; + } catch (Throwable throwable) { + main.getLogger().error("Couldn't open link: " + baseUrl + itemName, throwable); + return false; + } + } + private boolean isSubmitBidItem(ItemStack itemStack) { return ((itemStack.getItem().equals(Items.gold_nugget) || itemStack.getItem().equals(Item.getItemFromBlock(Blocks.gold_block))) && (itemStack.hasDisplayName() && (itemStack.getDisplayName().endsWith("Submit Bid") || itemStack.getDisplayName().endsWith("Collect Auction")))) || (/* green hardened clay + */ itemStack.hasDisplayName() && (itemStack.getDisplayName().endsWith("Create BIN Auction") || itemStack.getDisplayName().endsWith("Create Auction"))); } + + private enum ItemLookupType { + WIKI("wiki", "https://hypixel-skyblock.fandom.com/wiki/Special:Search?search="), + PRICE("price info", "https://stonks.gg/search?input="), + INVALID("nothing", "https://google.com/search?q="); + + private final String description; + private final String baseUrl; + + ItemLookupType(String description, String baseUrl) { + this.description = description; + this.baseUrl = baseUrl; + } + + public String getDescription() { + return description; + } + + public String getBaseUrl() { + return baseUrl; + } + } } diff --git a/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java b/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java index 44bfe13..8ce23e5 100644 --- a/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java +++ b/src/main/java/de/cowtipper/cowlection/util/GuiHelper.java @@ -49,9 +49,9 @@ public final class GuiHelper extends GuiScreen { return instance; } - public static Slot getSlotUnderMouse(GuiChest guiChest) { + public static Slot getSlotUnderMouse(GuiContainer guiContainer) { try { - return ReflectionHelper.getPrivateValue(GuiContainer.class, guiChest, "theSlot", "field_147006_u"); + return ReflectionHelper.getPrivateValue(GuiContainer.class, guiContainer, "theSlot", "field_147006_u"); } catch (ReflectionHelper.UnableToAccessFieldException e) { e.printStackTrace(); return null; @@ -94,6 +94,17 @@ public final class GuiHelper extends GuiScreen { tessellator.draw(); } + public static void drawHoveringTextWithGraph(List toolTip) { + int mouseX = Mouse.getX() * getInstance().width / getInstance().mc.displayWidth; + int mouseY = getInstance().height - Mouse.getY() * getInstance().height / getInstance().mc.displayHeight - 1; + ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); + + getInstance().width = scaledResolution.getScaledWidth(); + getInstance().height = scaledResolution.getScaledHeight(); + + getInstance().drawHoveringText(toolTip, mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, true); + } + public static void drawHoveringText(List textLines, int mouseX, int mouseY, int screenWidth, int screenHeight, int maxTextWidth) { if (ForgeVersion.getBuildVersion() < 1808) { // we're running a forge version from before 24 March 2016 (http://files.minecraftforge.net/maven/net/minecraftforge/forge/index_1.8.9.html for reference) @@ -107,17 +118,6 @@ public final class GuiHelper extends GuiScreen { } } - public static void drawHoveringTextWithGraph(List toolTip) { - int mouseX = Mouse.getX() * getInstance().width / getInstance().mc.displayWidth; - int mouseY = getInstance().height - Mouse.getY() * getInstance().height / getInstance().mc.displayHeight - 1; - ScaledResolution scaledResolution = new ScaledResolution(Minecraft.getMinecraft()); - - getInstance().width = scaledResolution.getScaledWidth(); - getInstance().height = scaledResolution.getScaledHeight(); - - getInstance().drawHoveringText(toolTip, mouseX, mouseY, scaledResolution.getScaledWidth(), scaledResolution.getScaledHeight(), -1, true); - } - /** * Fixed method for forge versions older than 1.8.9-11.15.1.1808 * diff --git a/src/main/java/de/cowtipper/cowlection/util/Utils.java b/src/main/java/de/cowtipper/cowlection/util/Utils.java index 8e8723c..8f4989c 100644 --- a/src/main/java/de/cowtipper/cowlection/util/Utils.java +++ b/src/main/java/de/cowtipper/cowlection/util/Utils.java @@ -1,7 +1,9 @@ package de.cowtipper.cowlection.util; import com.mojang.realmsclient.util.Pair; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumChatFormatting; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.text.WordUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.commons.lang3.time.DurationFormatUtils; @@ -273,4 +275,68 @@ public final class Utils { .sorted(Map.Entry.comparingByKey()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new)); } + + public static Pair extractSbItemBaseName(String originalItemName, NBTTagCompound extraAttributes, boolean strikethrough) { + String reforge = ""; + StringBuilder modifiedItemName = new StringBuilder(originalItemName); + String grayedOutFormatting = "" + EnumChatFormatting.GRAY + EnumChatFormatting.STRIKETHROUGH; + + if (extraAttributes.hasKey("modifier")) { + // item has been reforged; re-format item name to exclude reforges + reforge = StringUtils.capitalize(extraAttributes.getString("modifier")); + int modifierSuffix = Math.max(reforge.indexOf("_sword"), reforge.indexOf("_bow")); + if (modifierSuffix != -1) { + reforge = reforge.substring(0, modifierSuffix); + } + int reforgeInItemName = originalItemName.indexOf(reforge); + if (reforgeInItemName == -1 && reforge.equals("Light") && extraAttributes.getString("id").startsWith("HEAVY_")) { + // special case: heavy armor with light reforge + reforgeInItemName = originalItemName.indexOf("Heavy"); + } + + if (reforgeInItemName > 0 && !originalItemName.contains(EnumChatFormatting.STRIKETHROUGH.toString())) { + // we have a reforged item! remove reforge in item name and remove any essence upgrades (✪) + + int reforgeLength = reforge.length(); + String reforgePrefix = null; + // special cases for reforge + item name + if (reforge.equals("Heavy") && extraAttributes.getString("id").startsWith("HEAVY_")) { + reforgePrefix = "Extremely "; + } else if (reforge.equals("Light") && extraAttributes.getString("id").startsWith("HEAVY_")) { + reforgePrefix = "Not So "; + } else if ((reforge.equals("Wise") && extraAttributes.getString("id").startsWith("WISE_DRAGON_")) + || (reforge.equals("Strong") && extraAttributes.getString("id").startsWith("STRONG_DRAGON_"))) { + reforgePrefix = "Very "; + } else if (reforge.equals("Superior") && extraAttributes.getString("id").startsWith("SUPERIOR_DRAGON_")) { + reforgePrefix = "Highly "; + } else if (reforge.equals("Perfect") && extraAttributes.getString("id").startsWith("PERFECT_")) { + reforgePrefix = "Absolutely "; + } + if (reforgePrefix != null) { + reforgeInItemName -= reforgePrefix.length(); + reforgeLength = reforgePrefix.length() - 1; + } + + if (strikethrough) { + modifiedItemName.insert(reforgeInItemName, grayedOutFormatting) + .insert(reforgeInItemName + reforgeLength + grayedOutFormatting.length(), originalItemName.substring(0, reforgeInItemName)); + } else { + modifiedItemName.delete(reforgeInItemName, reforgeInItemName + reforgeLength); + } + } + } + // remove essence upgrade indicators (✪) + String essenceUpgradeIndicator = EnumChatFormatting.GOLD + "✪"; + int essenceModifier = modifiedItemName.indexOf(essenceUpgradeIndicator); + while (essenceModifier > 0) { + if (strikethrough) { + modifiedItemName.replace(essenceModifier, essenceModifier + essenceUpgradeIndicator.length(), grayedOutFormatting + "✪"); + } else { + modifiedItemName.delete(essenceModifier, essenceModifier + essenceUpgradeIndicator.length()); + } + essenceModifier = modifiedItemName.indexOf(essenceUpgradeIndicator); + } + + return Pair.of(modifiedItemName.toString().trim(), reforge); + } } diff --git a/src/main/resources/assets/cowlection/lang/en_US.lang b/src/main/resources/assets/cowlection/lang/en_US.lang index f4f189a..0972533 100644 --- a/src/main/resources/assets/cowlection/lang/en_US.lang +++ b/src/main/resources/assets/cowlection/lang/en_US.lang @@ -37,7 +37,7 @@ cowlection.config.notifyFreshServer.tooltip=Notify when entering a world that ha cowlection.config.notifyOldServer=Notify when server restarted ≥X days ago cowlection.config.notifyOldServer.tooltip=Notify when joining a server that hasn't restarted for X ingame days.\n§eSet to 0 to disable notifications! cowlection.config.tooltipToggleKeyBinding=Key binding: toggle tooltip -cowlection.config.tooltipToggleKeyBinding.tooltip=Hold down this key to toggle tooltip if one of the following settings is set to 'key press' +cowlection.config.tooltipToggleKeyBinding.tooltip=Hold down this key to toggle tooltip if one of the following settings is set to 'key press'\n\n§7§odisable key binding: §e§oset key binding to §lESC cowlection.config.tooltipAuctionHousePriceEach=§7Auction house: §rprice per item cowlection.config.tooltipAuctionHousePriceEach.tooltip=Add price per item if multiple items are bought or sold? cowlection.config.bazaarConnectGraphsNodes=§7Bazaar: §rconnect the graph nodes @@ -50,12 +50,16 @@ cowlection.config.tooltipItemTimestamp=Show item creation date cowlection.config.tooltipItemTimestamp.tooltip=Show item creation date? Only works for non-stackable items cowlection.config.numeralSystem=Numeral system cowlection.config.numeralSystem.tooltip=Use Roman or Arabic numeral system?\nThis is currently used to display numbers in the commands /moo stalkSkyBlock and /moo analyzeIsland +cowlection.config.lookupWikiKeyBinding=Key binding: lookup item wiki +cowlection.config.lookupWikiKeyBinding.tooltip=Hover over an item in any inventory and press keybinding to open the item's wiki article.\n§7§oAccesses §e§ohypixel-skyblock.fandom.com\n§7§odefault key: §e§oI = info\n\n§7§odisable key binding: §e§oset key binding to §lESC +cowlection.config.lookupPriceKeyBinding=Key binding: lookup item price +cowlection.config.lookupPriceKeyBinding.tooltip=Hover over an item in any inventory and press keybinding to open the item's price details.\n§7§oAccesses §e§ostonks.gg\n§7§odefault key: §e§oP = price\n\n§7§odisable key binding: §e§oset key binding to §lESC cowlection.config.showItemQualityAndFloor=Show item quality + obtained floor cowlection.config.showItemQualityAndFloor.tooltip=Should the item quality (in %%) and the obtained floor be added to the dungeon items' tooltips?\n§e'top' replaces the default 'gear score' entry §rwhich normally includes reforges and essence upgrades. cowlection.config.dungItemQualityPos=Item quality + obtained floor position cowlection.config.dungItemQualityPos.tooltip=Position of item quality and otained floor in dungeon item tooltips cowlection.config.dungItemToolTipToggleKeyBinding=Key binding: Show dungeon item base stats -cowlection.config.dungItemToolTipToggleKeyBinding.tooltip=Hold down this key to toggle dungeon item tooltip.\nDisplays the base stats of an item without reforges and without essence upgrades. +cowlection.config.dungItemToolTipToggleKeyBinding.tooltip=Hold down this key to toggle dungeon item tooltip.\nDisplays the base stats of an item without reforges and without essence upgrades.\n\n§7§odisable key binding: §e§oset key binding to §lESC cowlection.config.dungOverlayEnabled=Show overlay inside dungeons? cowlection.config.dungOverlayEnabled.tooltip=Show the performance overlay while inside a dungeon? cowlection.config.dungOverlayPositionX=Overlay x position (⇦/⇨ keys to fine-tune) -- cgit