diff options
author | Lorenz <lo.scherf@gmail.com> | 2022-09-07 12:51:29 +0200 |
---|---|---|
committer | Lorenz <lo.scherf@gmail.com> | 2022-09-07 12:51:29 +0200 |
commit | e1c1b44f1ab432827233ba44b0f03d67340f994a (patch) | |
tree | ce3c564cdfcf48e161a6b9f54bd3bc61319db95c | |
parent | 163cc857b0b1e6f52d56e663b8cb1c55f5e1bff2 (diff) | |
download | skyhanni-e1c1b44f1ab432827233ba44b0f03d67340f994a.tar.gz skyhanni-e1c1b44f1ab432827233ba44b0f03d67340f994a.tar.bz2 skyhanni-e1c1b44f1ab432827233ba44b0f03d67340f994a.zip |
Fixed enchanted books in bazaar.
6 files changed, 226 insertions, 53 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index c51a2d55d..4022db3b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ ### Misc - Added hiding the flame particles when using the Fire Veil Wand ability +### Fixes +- Fixed enchanted books in bazaar + ## Version 0.7 - Dungeon and Colored Highlight diff --git a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt index 5ae100ac2..c2c8bcb18 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt @@ -1,7 +1,9 @@ package at.hannibal2.skyhanni.features.bazaar +import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import net.minecraft.item.ItemStack class BazaarApi { @@ -44,9 +46,10 @@ class BazaarApi { return null } - fun isBazaarItem(name: String): Boolean { - val bazaarName = getCleanBazaarName(name) - return bazaarMap.containsKey(bazaarName) + fun isBazaarItem(stack: ItemStack): Boolean { + val internalName = stack.getInternalName() + return bazaarMap.any { it.value.apiName == internalName } + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataGrabber.kt b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataGrabber.kt index 01f01015c..642298ba5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataGrabber.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataGrabber.kt @@ -85,7 +85,7 @@ internal class BazaarDataGrabber(private var bazaarMap: MutableMap<String, Bazaa val products = bazaarData["products"].asJsonObject for (entry in products.entrySet()) { - val apiName = entry.key + var apiName = entry.key //TODO use repo if (apiName == "ENCHANTED_CARROT_ON_A_STICK") continue @@ -108,6 +108,16 @@ internal class BazaarDataGrabber(private var bazaarMap: MutableMap<String, Bazaa LorenzUtils.warning("§c[SkyHanni] bazaar item '$apiName' not found! Try restarting your minecraft to fix this.") continue } + + //parse bazaar api format into internal name format + if (apiName.startsWith("ENCHANTMENT_")) { + val split = apiName.split("_") + val last = split.last() + val dropLast = split.drop(1).dropLast(1) + val text = dropLast.joinToString("_") + ";" + last + apiName = text + } + val data = BazaarData(apiName, itemName, sellPrice, buyPrice) bazaarMap[itemName] = data } diff --git a/src/main/java/at/hannibal2/skyhanni/features/items/HideNotClickableItems.kt b/src/main/java/at/hannibal2/skyhanni/features/items/HideNotClickableItems.kt index 549d347eb..2829742dc 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/items/HideNotClickableItems.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/items/HideNotClickableItems.kt @@ -384,8 +384,7 @@ class HideNotClickableItems { return true } - val displayName = stack.displayName - if (bazaarInventory != BazaarApi.isBazaarItem(displayName)) { + if (bazaarInventory != BazaarApi.isBazaarItem(stack)) { if (bazaarInventory) hideReason = "This item is not a Bazaar Product!" if (auctionHouseInventory) hideReason = "Bazaar Products cannot be auctioned!" diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ItemResolutionQuery.java b/src/main/java/at/hannibal2/skyhanni/utils/ItemResolutionQuery.java new file mode 100644 index 000000000..1f8988613 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/ItemResolutionQuery.java @@ -0,0 +1,201 @@ +package at.hannibal2.skyhanni.utils; + +import at.hannibal2.skyhanni.config.ConfigManager; +import com.google.common.collect.Iterables; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.init.Items; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.List; +import java.util.Locale; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class ItemResolutionQuery { + + private static final Pattern ENCHANTED_BOOK_NAME_PATTERN = Pattern.compile("^((?:§.)+)([^§]+) ([IVXL]+)$"); + private static final String EXTRA_ATTRIBUTES = "ExtraAttributes"; + private static final List<String> PET_RARITIES = Arrays.asList( + "COMMON", + "UNCOMMON", + "RARE", + "EPIC", + "LEGENDARY", + "MYTHIC" + ); + private ItemStack stack; + private Item itemType; + private int stackSize = -1; + private Gui guiContext; + private String knownInternalName; + + public ItemResolutionQuery withItemStack(ItemStack stack) { + if (stack == null) return this; + this.itemType = stack.getItem(); + this.stack = stack; + this.stackSize = stack.stackSize; + return this; + } + + public ItemResolutionQuery withGuiContext(Gui gui) { + this.guiContext = gui; + return this; + } + + public ItemResolutionQuery withCurrentGuiContext() { + this.guiContext = Minecraft.getMinecraft().currentScreen; + return this; + } + + public ItemResolutionQuery withKnownInternalName(String knownInternalName) { + this.knownInternalName = knownInternalName; + return this; + } + + @Nullable + public String resolveInternalName() { + if (knownInternalName != null) { + return knownInternalName; + } + String resolvedName = resolveFromSkyblock(); + if (resolvedName == null) { + resolvedName = resolveContextualName(); + } else { + switch (resolvedName.intern()) { + case "PET": + resolvedName = resolvePetName(); + break; + case "RUNE": + resolvedName = resolveRuneName(); + break; + case "ENCHANTED_BOOK": + resolvedName = resolveEnchantedBookNameFromNBT(); + break; + case "PARTY_HAT_CRAB": + resolvedName = resolveCrabHatName(); + break; + } + } + + return resolvedName; + } + + // <editor-fold desc="Resolution Helpers"> + private boolean isBazaar(IInventory chest) { + if (chest.getDisplayName().getFormattedText().startsWith("Bazaar ➜ ")) { + return true; + } + int bazaarSlot = chest.getSizeInventory() - 5; + if (bazaarSlot < 0) return false; + ItemStack stackInSlot = chest.getStackInSlot(bazaarSlot); + if (stackInSlot == null || stackInSlot.stackSize == 0) return false; + // NBT lore, we do not care about rendered lore + List<String> lore = ItemUtils.INSTANCE.getLore(stackInSlot); + return lore.contains("§7To Bazaar"); + } + + private String resolveContextualName() { + if (!(guiContext instanceof GuiChest)) { + return null; + } + GuiChest chest = (GuiChest) guiContext; + ContainerChest inventorySlots = (ContainerChest) chest.inventorySlots; + String guiName = inventorySlots.getLowerChestInventory().getDisplayName().getUnformattedText(); + boolean isOnBazaar = isBazaar(inventorySlots.getLowerChestInventory()); + String displayName = ItemUtils.INSTANCE.getName(stack); + if (displayName == null) return null; + if (itemType == Items.enchanted_book && isOnBazaar) { + return resolveEnchantmentByName(displayName); + } + if (displayName.endsWith("Enchanted Book") && guiName.startsWith("Superpairs")) { + for (String loreLine : ItemUtils.INSTANCE.getLore(stack)) { + String enchantmentIdCandidate = resolveEnchantmentByName(loreLine); + if (enchantmentIdCandidate != null) return enchantmentIdCandidate; + } + return null; + } + return null; + } + + private String getDisplayName(NBTTagCompound compound) { + if (compound == null) return null; + String string = compound.getCompoundTag("display").getString("Name"); + if (string == null || string.isEmpty()) + return null; + return string; + } + + private String resolveEnchantmentByName(String name) { + Matcher matcher = ENCHANTED_BOOK_NAME_PATTERN.matcher(name); + if (!matcher.matches()) return null; + String format = matcher.group(1).toLowerCase(Locale.ROOT); + String enchantmentName = matcher.group(2).trim(); + String romanLevel = matcher.group(3); + boolean ultimate = (format.contains("§l")); + + return (ultimate ? "ULTIMATE_" : "") + + enchantmentName.replace(" ", "_").toUpperCase(Locale.ROOT) + + ";" + NumberUtil.INSTANCE.romanToDecimal(romanLevel); + } + + private String resolveCrabHatName() { + String color = getExtraAttributes().getString("party_hat_color"); + return "PARTY_HAT_CRAB_" + color.toUpperCase(Locale.ROOT); + } + + private String resolveEnchantedBookNameFromNBT() { + NBTTagCompound enchantments = getExtraAttributes().getCompoundTag("enchantments"); + String enchantName = Iterables.getOnlyElement(enchantments.getKeySet(), null); + if (enchantName == null || enchantName.isEmpty()) return null; + return enchantName.toUpperCase(Locale.ROOT) + ";" + enchantments.getInteger(enchantName); + } + + private String resolveRuneName() { + NBTTagCompound runes = getExtraAttributes().getCompoundTag("runes"); + String runeName = Iterables.getOnlyElement(runes.getKeySet(), null); + if (runeName == null || runeName.isEmpty()) return null; + return runeName.toUpperCase(Locale.ROOT) + "_RUNE;" + runes.getInteger(runeName); + } + + private String resolvePetName() { + String petInfo = getExtraAttributes().getString("petInfo"); + if (petInfo == null || petInfo.isEmpty()) return null; + try { + JsonObject petInfoObject = ConfigManager.Companion.getGson().fromJson(petInfo, JsonObject.class); + String petId = petInfoObject.get("type").getAsString(); + String petTier = petInfoObject.get("tier").getAsString(); + int rarityIndex = PET_RARITIES.indexOf(petTier); + return petId.toUpperCase(Locale.ROOT) + ";" + rarityIndex; + } catch (JsonParseException | ClassCastException ex) { + /* This happens if Hypixel changed the pet json format; + I still log this exception, since this case *is* exceptional and cannot easily be recovered from */ + ex.printStackTrace(); + return null; + } + } + + private NBTTagCompound getExtraAttributes() { + NBTTagCompound compound = stack.getTagCompound(); + if (compound == null) return new NBTTagCompound(); + return compound.getCompoundTag(EXTRA_ATTRIBUTES); + } + + private String resolveFromSkyblock() { + String internalName = getExtraAttributes().getString("id"); + if (internalName == null || internalName.isEmpty()) return null; + return internalName.toUpperCase(Locale.ROOT); + } + + // </editor-fold> + +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt index 3b38bd84a..ca0e6728c 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt @@ -113,53 +113,10 @@ object ItemUtils { } fun ItemStack.getInternalName(): String { - val tag = tagCompound - if (tag == null || !tag.hasKey("ExtraAttributes", 10)) return "" - - val extraAttributes = tag.getCompoundTag("ExtraAttributes") - var internalName = if (extraAttributes.hasKey("id", 8)) { - extraAttributes.getString("id").replace(":".toRegex(), "-") - } else { - return "" - } - - if (internalName == "PET") { - val petInfo = extraAttributes.getString("petInfo") - if (petInfo.isNotEmpty()) { - val petInfoObject: JsonObject = gson.fromJson(petInfo, JsonObject::class.java) - internalName = petInfoObject["type"].asString - return when (petInfoObject["tier"].asString) { - "COMMON" -> "$internalName;0" - "UNCOMMON" -> "$internalName;1" - "RARE" -> "$internalName;2" - "EPIC" -> "$internalName;3" - "LEGENDARY" -> "$internalName;4" - "MYTHIC" -> "$internalName;5" - else -> internalName - } - } - } - - if (internalName == "ENCHANTED_BOOK" && extraAttributes.hasKey("enchantments", 10)) { - val enchants = extraAttributes.getCompoundTag("enchantments") - for (enchantment in enchants.keySet) { - return enchantment.uppercase(Locale.getDefault()) + ";" + enchants.getInteger(enchantment) - } - } - - if (internalName == "RUNE" && extraAttributes.hasKey("runes", 10)) { - val rune = extraAttributes.getCompoundTag("runes") - for (enchantment in rune.keySet) { - return enchantment.uppercase(Locale.getDefault()) + "_RUNE" + ";" + rune.getInteger(enchantment) - } - } - - if (internalName == "PARTY_HAT_CRAB" && extraAttributes.getString("party_hat_color") != null) { - val crabHat = extraAttributes.getString("party_hat_color") - return "PARTY_HAT_CRAB" + "_" + crabHat.uppercase(Locale.getDefault()) - } - - return internalName + return ItemResolutionQuery() + .withCurrentGuiContext() + .withItemStack(this) + .resolveInternalName() ?: "" } fun ItemStack.getSkullTexture(): String? { |