aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLorenz <lo.scherf@gmail.com>2022-09-07 12:51:29 +0200
committerLorenz <lo.scherf@gmail.com>2022-09-07 12:51:29 +0200
commite1c1b44f1ab432827233ba44b0f03d67340f994a (patch)
treece3c564cdfcf48e161a6b9f54bd3bc61319db95c
parent163cc857b0b1e6f52d56e663b8cb1c55f5e1bff2 (diff)
downloadskyhanni-e1c1b44f1ab432827233ba44b0f03d67340f994a.tar.gz
skyhanni-e1c1b44f1ab432827233ba44b0f03d67340f994a.tar.bz2
skyhanni-e1c1b44f1ab432827233ba44b0f03d67340f994a.zip
Fixed enchanted books in bazaar.
-rw-r--r--CHANGELOG.md3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarDataGrabber.kt12
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/items/HideNotClickableItems.kt3
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ItemResolutionQuery.java201
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt51
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? {