aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Misc.java32
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/EstimatedItemValue.kt527
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt283
6 files changed, 851 insertions, 5 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
index 9a4990595..5a1a92a4b 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
@@ -241,6 +241,7 @@ public class SkyHanniMod {
loadModule(new GardenComposterInventoryFeatures());
loadModule(new MinionCollectLogic());
loadModule(new PasteIntoSigns());
+ loadModule(new EstimatedItemValue());
Commands.INSTANCE.init();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
index 609f72e43..8b9ea625a 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Misc.java
@@ -2,11 +2,9 @@ package at.hannibal2.skyhanni.config.features;
import at.hannibal2.skyhanni.config.core.config.Position;
import com.google.gson.annotations.Expose;
-import io.github.moulberry.moulconfig.annotations.ConfigAccordionId;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorAccordion;
-import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
-import io.github.moulberry.moulconfig.annotations.ConfigOption;
+import io.github.moulberry.moulconfig.annotations.*;
import io.github.moulberry.moulconfig.observer.Property;
+import org.lwjgl.input.Keyboard;
public class Misc {
@@ -211,6 +209,32 @@ public class Misc {
public Position chickenHeadTimerPosition = new Position(-372, 73, false, true);
@Expose
+ @ConfigOption(name = "Estimated Item Value", desc = "(Enchantments, reforging stone prices, gemstones, gemstones, drill parts and more)")
+ @ConfigEditorAccordion(id = 11)
+ public boolean estimatedItemValue = false;
+
+ @Expose
+ @ConfigOption(name = "Enable Estimated Price", desc = "Displays an estimated item value for the item you hover over.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 11)
+ public boolean estimatedIemValueEnabled = false;
+
+ @Expose
+ @ConfigOption(name = "Hotkey", desc = "Press this key to show the estimated item value.")
+ @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE)
+ @ConfigAccordionId(id = 11)
+ public int estimatedItemValueHotkey = Keyboard.KEY_NONE;
+
+ @Expose
+ @ConfigOption(name = "Show always", desc = "Ignore the hotkey and always display the item value.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 11)
+ public boolean estimatedIemValueAlwaysEnabled = true;
+
+ @Expose
+ public Position itemPriceDataPos = new Position(140, 90, false, true);
+
+ @Expose
@ConfigOption(name = "Exp Bottles", desc = "Hides all the experience orbs lying on the ground.")
@ConfigEditorBoolean
public boolean hideExpBottles = false;
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/EstimatedItemValue.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/EstimatedItemValue.kt
new file mode 100644
index 000000000..a92dcf231
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/EstimatedItemValue.kt
@@ -0,0 +1,527 @@
+package at.hannibal2.skyhanni.features.misc
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.ItemUtils.name
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
+import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc
+import at.hannibal2.skyhanni.utils.NEUItems
+import at.hannibal2.skyhanni.utils.NumberUtil
+import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAbilityScrolls
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getDrillUpgrades
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getEnchantments
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getFarmingForDummiesCount
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getGemstones
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getHotPotatoCount
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getManaDisintegrators
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getMasterStars
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPowerScroll
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getReforgeName
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getSilexCount
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getTransmissionTunerCount
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasArtOfPiece
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasArtOfWar
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasBookOfStats
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasEtherwarp
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasJalapenoBook
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasWoodSingularity
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.isRecombobulated
+import at.hannibal2.skyhanni.utils.StringUtils.removeColor
+import io.github.moulberry.moulconfig.internal.KeybindHelper
+import io.github.moulberry.notenoughupdates.util.Constants
+import net.minecraft.init.Items
+import net.minecraft.item.ItemStack
+import net.minecraftforge.event.entity.player.ItemTooltipEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class EstimatedItemValue {
+ private val config get() = SkyHanniMod.feature.misc
+ private var display = listOf<List<Any>>()
+ private val cache = mutableMapOf<ItemStack, List<List<Any>>>()
+ private var lastToolTipTime = 0L
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.ChestBackgroundRenderEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.estimatedIemValueEnabled) return
+ if (!KeybindHelper.isKeyDown(config.estimatedItemValueHotkey) && !config.estimatedIemValueAlwaysEnabled) return
+ if (System.currentTimeMillis() > lastToolTipTime + 200) return
+
+ config.itemPriceDataPos.renderStringsAndItems(display, posLabel = "Estimated Item Value")
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ cache.clear()
+ }
+
+ @SubscribeEvent
+ fun onItemTooltipLow(event: ItemTooltipEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ if (!config.estimatedIemValueEnabled) return
+
+ val item = event.itemStack
+ val oldData = cache[item]
+ if (oldData != null) {
+ display = oldData
+ lastToolTipTime = System.currentTimeMillis()
+ return
+ }
+
+ val newDisplay = try {
+ draw(item)
+ } catch (e: Exception) {
+ LorenzUtils.debug("Estimated Item Value error: ${e.message}")
+ e.printStackTrace()
+ listOf()
+ }
+
+ cache[item] = newDisplay
+ display = newDisplay
+ lastToolTipTime = System.currentTimeMillis()
+ }
+
+ private fun draw(stack: ItemStack): MutableList<List<Any>> {
+ val list = mutableListOf<String>()
+ list.add("§aEstimated Item Value:")
+
+ val internalName = stack.getInternalName()
+ if (internalName == "") return mutableListOf()
+
+ //FIX neu item list
+ if (internalName.startsWith("ULTIMATE_ULTIMATE_")) return mutableListOf()
+ if (stack.item == Items.enchanted_book) return mutableListOf()
+
+ var totalPrice = 0.0
+ val basePrice = addBaseItem(stack, list)
+ totalPrice += basePrice
+ totalPrice += addReforgeStone(stack, list)
+
+ // once
+ totalPrice += addRecomb(stack, list)
+ totalPrice += addArtOfWar(stack, list)
+ totalPrice += addArtOfPiece(stack, list)
+ totalPrice += addEtherwarp(stack, list)
+ totalPrice += addPowerScrolls(stack, list)
+ totalPrice += addWoodSingularity(stack, list)
+ totalPrice += addJalapenoBook(stack, list)
+
+ // counted
+ totalPrice += addMasterStars(stack, list)
+ totalPrice += addHotPotatoBooks(stack, list)
+ totalPrice += addFarmingForDummies(stack, list)
+ totalPrice += addSilex(stack, list)
+ totalPrice += addStatsBook(stack, list)
+ totalPrice += addTransmissionTuners(stack, list)
+ totalPrice += addManaDisintegrators(stack, list)
+
+ // dynamic
+ totalPrice += addAbilityScrolls(stack, list)
+ totalPrice += addDrillUpgrades(stack, list)
+ totalPrice += addGemstones(stack, list)
+ totalPrice += addEnchantments(stack, list)
+
+ if (basePrice == totalPrice) return mutableListOf()
+
+ list.add("§aTotal: §6§l" + NumberUtil.format(totalPrice))
+
+ val newDisplay = mutableListOf<List<Any>>()
+ for (line in list) {
+ newDisplay.addAsSingletonList(line)
+ }
+ return newDisplay
+ }
+
+ private fun addReforgeStone(stack: ItemStack, list: MutableList<String>): Double {
+ val rawReforgeName = stack.getReforgeName() ?: return 0.0
+
+ for ((internalName, values) in Constants.REFORGESTONES.entrySet()) {
+ val stone = values.asJsonObject
+ val reforgeName = stone.get("reforgeName").asString
+ if (rawReforgeName == reforgeName.lowercase()) {
+ val price = NEUItems.getPrice(internalName)
+ val name = NEUItems.getItemStack(internalName).name
+ list.add("§7Reforge: §9$reforgeName")
+ list.add(" §7($name §6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+ }
+
+ return 0.0
+ }
+
+ private fun addRecomb(stack: ItemStack, list: MutableList<String>): Double {
+ if (stack.isRecombobulated()) {
+ val wtfHardcodedRecomb = "RECOMBOBULATOR_3000"
+ val price = NEUItems.getPrice(wtfHardcodedRecomb)
+ list.add("§7Recombobulated: §a§l✔ §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ return 0.0
+ }
+
+ private fun addJalapenoBook(stack: ItemStack, list: MutableList<String>): Double {
+ if (stack.hasJalapenoBook()) {
+ val wtfHardcodedJalapeno = "JALAPENO_BOOK"
+
+ val price = NEUItems.getPrice(wtfHardcodedJalapeno)
+ list.add("§7Jalapeno Book: §a§l✔ §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ return 0.0
+ }
+
+ private fun addEtherwarp(stack: ItemStack, list: MutableList<String>): Double {
+ if (stack.hasEtherwarp()) {
+ val wtfHardcodedConduit = "ETHERWARP_CONDUIT"
+ val wtfHardcodedMerger = "ETHERWARP_MERGER"
+ val price = NEUItems.getPrice(wtfHardcodedConduit) + NEUItems.getPrice(wtfHardcodedMerger)
+ list.add("§7Etherwarp: §a§l✔ §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ return 0.0
+ }
+
+ private fun addWoodSingularity(stack: ItemStack, list: MutableList<String>): Double {
+ if (stack.hasWoodSingularity()) {
+ val wtfHardcodedSingularity = "WOOD_SINGULARITY"
+ val price = NEUItems.getPrice(wtfHardcodedSingularity)
+ list.add("§7Wood Singularity: §a§l✔ §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ return 0.0
+ }
+
+ private fun addArtOfWar(stack: ItemStack, list: MutableList<String>): Double {
+ if (stack.hasArtOfWar()) {
+ val ripTechno = "THE_ART_OF_WAR"
+ val price = NEUItems.getPrice(ripTechno)
+ list.add("§7The Art of War: §a§l✔ §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ return 0.0
+ }
+
+ private fun addStatsBook(stack: ItemStack, list: MutableList<String>): Double {
+ if (stack.hasBookOfStats()) {
+ val ripTechno = "BOOK_OF_STATS"
+ val price = NEUItems.getPrice(ripTechno)
+ list.add("§7Book of Stats: §a§l✔ §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ return 0.0
+ }
+
+ // TODO untested
+ private fun addArtOfPiece(stack: ItemStack, list: MutableList<String>): Double {
+ if (stack.hasArtOfPiece()) {
+ val ripTechno = "THE_ART_OF_PEACE"
+ val price = NEUItems.getPrice(ripTechno)
+ list.add("§7The Art Of Piece: §a§l✔ §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ return 0.0
+ }
+
+ private fun addHotPotatoBooks(stack: ItemStack, list: MutableList<String>): Double {
+ val count = stack.getHotPotatoCount()
+ if (count == 0) return 0.0
+
+ val hpb: Int
+ val fuming: Int
+ if (count <= 10) {
+ hpb = count
+ fuming = 0
+ } else {
+ hpb = 10
+ fuming = count - 10
+ }
+
+ var totalPrice = 0.0
+
+ val wtfHardcodedHpb = "HOT_POTATO_BOOK"
+ val hpbPrice = NEUItems.getPrice(wtfHardcodedHpb) * hpb
+ list.add("§7HPB's: §e$hpb§7/§e10 §7(§6" + NumberUtil.format(hpbPrice) + "§7)")
+ totalPrice += hpbPrice
+
+ if (fuming > 0) {
+ val wtfHardcodedFuming = "FUMING_POTATO_BOOK"
+ val fumingPrice = NEUItems.getPrice(wtfHardcodedFuming) * fuming
+ list.add("§7Fuming: §e$fuming§7/§e5 §7(§6" + NumberUtil.format(fumingPrice) + "§7)")
+ totalPrice += fumingPrice
+ }
+
+ return totalPrice
+ }
+
+ private fun addFarmingForDummies(stack: ItemStack, list: MutableList<String>): Double {
+ val count = stack.getFarmingForDummiesCount()
+ if (count == 0) return 0.0
+
+ val wtfHardcodedDumbFarmers = "FARMING_FOR_DUMMIES"
+ val price = NEUItems.getPrice(wtfHardcodedDumbFarmers) * count
+ list.add("§7Farming for Dummies: §e$count§7/§e5 §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ private fun addSilex(stack: ItemStack, list: MutableList<String>): Double {
+ val tier = stack.getSilexCount()
+ if (tier == 0) return 0.0
+
+ val internalName = stack.getInternalName()
+ val maxTier = if (internalName == "STONK_PICKAXE") 4 else 5
+
+ val wtfHardcodedSilex = "SIL_EX"
+ val price = NEUItems.getPrice(wtfHardcodedSilex) * tier
+ list.add("§7Silex: §e$tier§7/§e$maxTier §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ private fun addTransmissionTuners(stack: ItemStack, list: MutableList<String>): Double {
+ val count = stack.getTransmissionTunerCount()
+ if (count == 0) return 0.0
+
+ val wtfHardcodedTuner = "TRANSMISSION_TUNER"
+ val price = NEUItems.getPrice(wtfHardcodedTuner) * count
+ list.add("§7Transmission Tuners: §e$count§7/§e4 §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ private fun addManaDisintegrators(stack: ItemStack, list: MutableList<String>): Double {
+ val count = stack.getManaDisintegrators()
+ if (count == 0) return 0.0
+
+ val wtfHardcodedTuner = "MANA_DISINTEGRATOR"
+ val price = NEUItems.getPrice(wtfHardcodedTuner) * count
+ list.add("§7Mana Disintegrators: §e$count§7/§e10 §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ private fun addMasterStars(stack: ItemStack, list: MutableList<String>): Double {
+ val masterStars = stack.getMasterStars()
+ if (masterStars == 0) return 0.0
+
+ var price = 0.0
+
+ val stars = mapOf(
+ "FIRST" to 1,
+ "SECOND" to 2,
+ "THIRD" to 3,
+ "FOURTH" to 4,
+ "FIFTH" to 5,
+ )
+
+ for ((prefix, number) in stars) {
+ if (masterStars >= number) {
+ val internalName = "${prefix}_MASTER_STAR"
+ price += NEUItems.getPrice(internalName)
+ }
+ }
+
+ list.add("§7Master Stars: §e$masterStars§7/§e5 §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ private fun addDrillUpgrades(stack: ItemStack, list: MutableList<String>): Double {
+ var totalPrice = 0.0
+ val map = mutableMapOf<String, Double>()
+ for (internalName in stack.getDrillUpgrades()) {
+ val name = NEUItems.getItemStackOrNull(internalName)!!.name
+ val price = NEUItems.getPriceOrNull(internalName) ?: continue
+
+ totalPrice += price
+ val format = NumberUtil.format(price)
+ map[" $name §7(§6$format§7)"] = price
+ }
+ if (map.isNotEmpty()) {
+ list.add("§7Drill upgrades: §6" + NumberUtil.format(totalPrice))
+ list += map.sortedDesc().keys
+ }
+ return totalPrice
+ }
+
+ private fun addPowerScrolls(stack: ItemStack, list: MutableList<String>): Double {
+ val internalName = stack.getPowerScroll() ?: return 0.0
+
+ val price = NEUItems.getPrice(internalName)
+ val name = NEUItems.getItemStack(internalName).name!!.removeColor()
+ list.add("§7$name: §a§l✔ §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ private fun addAbilityScrolls(stack: ItemStack, list: MutableList<String>): Double {
+ var totalPrice = 0.0
+ val map = mutableMapOf<String, Double>()
+ for (internalName in stack.getAbilityScrolls()) {
+ val name = NEUItems.getItemStackOrNull(internalName)!!.name
+ val price = NEUItems.getPriceOrNull(internalName) ?: continue
+
+ totalPrice += price
+ val format = NumberUtil.format(price)
+ map[" $name §7(§6$format§7)"] = price
+ }
+ if (map.isNotEmpty()) {
+ list.add("§7Ability Scrolls: §6" + NumberUtil.format(totalPrice))
+ list += map.sortedDesc().keys
+ }
+ return totalPrice
+ }
+
+ private fun addBaseItem(stack: ItemStack, list: MutableList<String>): Double {
+ val internalName = stack.getInternalName()
+ var price = NEUItems.getPrice(internalName)
+ if (price == -1.0) {
+ price = 0.0
+ }
+
+ val name = NEUItems.getItemStack(internalName).name
+ if (internalName.startsWith("ENCHANTED_BOOK_BUNDLE_")) {
+ list.add("§7Base item: $name")
+ return 0.0
+ }
+
+ list.add("§7Base item: $name §7(§6" + NumberUtil.format(price) + "§7)")
+ return price
+ }
+
+ private fun addEnchantments(stack: ItemStack, list: MutableList<String>): Double {
+ var totalPrice = 0.0
+ val map = mutableMapOf<String, Double>()
+
+ val tieredEnchants = listOf("compact", "cultivating", "champion", "expertise", "hecatomb")
+ val hasAlwaysScavenger = listOf(
+ "CRYPT_DREADLORD_SWORD",
+ "ZOMBIE_SOLDIER_CUTLASS",
+ "CONJURING_SWORD",
+ "EARTH_SHARD",
+ "ZOMBIE_KNIGHT_SWORD",
+ "SILENT_DEATH",
+ "ZOMBIE_COMMANDER_WHIP",
+ )
+
+ val internalName = stack.getInternalName()
+ for ((rawName, rawLevel) in stack.getEnchantments()) {
+ // efficiency 1-5 is cheap, 6-10 is handled by silex
+ if (rawName == "efficiency") continue
+
+ if (rawName == "scavenger" && rawLevel == 5) {
+ if (internalName in hasAlwaysScavenger) continue
+ }
+
+ var level = rawLevel
+ if (rawName in tieredEnchants) level = 1
+
+ val enchantmentName = "$rawName;$level".uppercase()
+ val itemStack = NEUItems.getItemStackOrNull(enchantmentName) ?: continue
+ var name = itemStack.getLore()[0]
+ val singlePrice = NEUItems.getPriceOrNull(enchantmentName) ?: continue
+ val multiplier = if (internalName.startsWith("ENCHANTED_BOOK_BUNDLE_")) {
+ name = "§85x $name"
+ 5
+ } else 1
+ val price = singlePrice * multiplier
+
+ totalPrice += price
+ val format = NumberUtil.format(price)
+
+
+ map[" $name §7(§6$format§7)"] = price
+ }
+ if (map.isNotEmpty()) {
+ list.add("§7Enchantments: §6" + NumberUtil.format(totalPrice))
+ var i = 0
+ val size = map.size
+ for (entry in map.sortedDesc().keys) {
+ if (i == 7) {
+ val missing = size - i
+ list.add(" §7§o$missing more enchantments..")
+ break
+ }
+ list.add(entry)
+ i++
+ }
+ }
+ return totalPrice
+ }
+
+ private fun addGemstones(stack: ItemStack, list: MutableList<String>): Double {
+ val gemstones = stack.getGemstones()
+ if (gemstones.isEmpty()) return 0.0
+
+ var totalPrice = 0.0
+ val counterMap = mutableMapOf<String, Int>()
+ for (gemstone in gemstones) {
+ val internalName = gemstone.getInternalName()
+ val old = counterMap[internalName] ?: 0
+ counterMap[internalName] = old + 1
+ }
+
+ val priceMap = mutableMapOf<String, Double>()
+ for ((internalName, amount) in counterMap) {
+
+ val name = NEUItems.getItemStack(internalName).name
+ val price = NEUItems.getPrice(internalName) * amount
+
+ totalPrice += price
+ val format = NumberUtil.format(price)
+
+ val text = if (amount == 1) {
+ " $name §7(§6$format§7)"
+ } else {
+ " §8${amount}x $name §7(§6$format§7)"
+ }
+ priceMap[text] = price
+ }
+
+ if (priceMap.isNotEmpty()) {
+ list.add("§7Gemstones: §6" + NumberUtil.format(totalPrice))
+ list += priceMap.sortedDesc().keys
+ }
+ return totalPrice
+ }
+
+ class GemstoneSlot(val type: GemstoneType, val tier: GemstoneTier) {
+ fun getInternalName() = "${tier}_${type}_GEM"
+ }
+
+ enum class GemstoneTier(val displayName: String) {
+ ROUGH("Rough"),
+ FLAWED("Flawed"),
+ FINE("Fine"),
+ FLAWLESS("Flawless"),
+ PERFECT("Perfect"),
+ ;
+
+ companion object {
+ fun getByName(name: String) = GemstoneTier.values().firstOrNull { it.name == name }
+ }
+ }
+
+ enum class GemstoneType(val displayName: String) {
+ JADE("Jade"),
+ AMBER("Amber"),
+ TOPAZ("Topaz"),
+ SAPPHIRE("Sapphire"),
+ AMETHYST("Amethyst"),
+ JASPER("Jasper"),
+ RUBY("Ruby"),
+ OPAL("Opal"),
+ ;
+
+ companion object {
+ fun getByName(name: String) = values().firstOrNull { it.name == name }
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt
index 557950fbe..049caf3d1 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/ItemUtils.kt
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.utils
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.isRecombobulated
import at.hannibal2.skyhanni.utils.StringUtils.matchRegex
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import com.google.gson.GsonBuilder
@@ -28,15 +29,17 @@ object ItemUtils {
return list
}
+ // TODO change else janni is sad
fun isCoopSoulBound(stack: ItemStack): Boolean =
stack.getLore().any {
it == "§8§l* §8Co-op Soulbound §8§l*" || it == "§8§l* §8Soulbound §8§l*"
}
+ // TODO change else janni is sad
fun isSoulBound(stack: ItemStack): Boolean =
stack.getLore().any { it == "§8§l* §8Soulbound §8§l*" }
- fun isRecombobulated(stack: ItemStack): Boolean = stack.getLore().any { it.contains("§k") }//TODO use item api
+ fun isRecombobulated(stack: ItemStack) = stack.isRecombobulated()
fun isPet(name: String): Boolean = name.matchRegex("\\[Lvl (.*)] (.*)") && !listOf(
"Archer",
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
index 23ed9be71..25d67bb07 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
@@ -47,6 +47,14 @@ object NEUItems {
.resolveInternalName() ?: ""
}
+ fun getPriceOrNull(internalName: String, useSellingPrice: Boolean = false): Double? {
+ val price = getPrice(internalName, useSellingPrice)
+ if (price == -1.0) {
+ return null
+ }
+ return price
+ }
+
fun getPrice(internalName: String, useSellingPrice: Boolean = false): Double {
val bazaarData = BazaarApi.getBazaarDataForInternalName(internalName)
bazaarData?.let {
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt
new file mode 100644
index 000000000..4229a80df
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt
@@ -0,0 +1,283 @@
+package at.hannibal2.skyhanni.utils
+
+import at.hannibal2.skyhanni.features.misc.EstimatedItemValue
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.ItemUtils.name
+import net.minecraft.item.ItemStack
+
+object SkyBlockItemModifierUtils {
+ private val drillPartTypes = listOf("drill_part_upgrade_module", "drill_part_engine", "drill_part_fuel_tank")
+
+ fun ItemStack.getHotPotatoCount(): Int {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes != "hot_potato_count") continue
+ return extraAttributes.getInteger(attributes)
+ }
+ }
+ return 0
+ }
+
+ fun ItemStack.getFarmingForDummiesCount(): Int {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes != "farming_for_dummies_count") continue
+ return extraAttributes.getInteger(attributes)
+ }
+ }
+ return 0
+ }
+
+ fun ItemStack.getSilexCount(): Int {
+ var silexTier = 0
+ for ((name, amount) in getEnchantments()) {
+ if (name == "efficiency") {
+ if (amount > 5) {
+ silexTier = amount - 5
+ }
+ }
+ }
+
+ if (getInternalName() == "STONK_PICKAXE") {
+ silexTier--
+ }
+
+ return silexTier
+ }
+
+ fun ItemStack.getTransmissionTunerCount(): Int {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes != "tuned_transmission") continue
+ return extraAttributes.getInteger(attributes)
+ }
+ }
+ return 0
+ }
+
+ fun ItemStack.getManaDisintegrators(): Int {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes != "mana_disintegrator_count") continue
+ return extraAttributes.getInteger(attributes)
+ }
+ }
+ return 0
+ }
+
+ fun ItemStack.getMasterStars(): Int {
+ val stars = mapOf(
+ "➊" to 1,
+ "➋" to 2,
+ "➌" to 3,
+ "➍" to 4,
+ "➎" to 5,
+ )
+ val itemName = name!!
+ for ((icon, number) in stars) {
+ if (itemName.endsWith(icon)) {
+ return number
+ }
+ }
+
+ return 0
+ }
+
+ fun ItemStack.getDrillUpgrades(): List<String> {
+ val list = mutableListOf<String>()
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes in drillPartTypes) {
+ val upgradeItem = extraAttributes.getString(attributes)
+ list.add(upgradeItem.uppercase())
+ }
+ }
+ }
+
+ return list
+ }
+
+ fun ItemStack.getPowerScroll(): String? {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes == "power_ability_scroll") {
+ return extraAttributes.getString(attributes)
+ }
+ }
+ }
+
+ return null
+ }
+
+ fun ItemStack.getAbilityScrolls(): List<String> {
+ val list = mutableListOf<String>()
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes == "ability_scroll") {
+
+ val tagList = extraAttributes.getTagList(attributes, 8)
+ for (i in 0..3) {
+ val text = tagList.get(i).toString()
+ if (text == "END") break
+ var internalName = text.replace("\"", "")
+ list.add(internalName)
+ }
+ }
+ }
+ }
+
+ return list
+ }
+
+ fun ItemStack.getReforgeName(): String? {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes != "modifier") continue
+ return extraAttributes.getString(attributes)
+ }
+ }
+ return null
+ }
+
+ fun ItemStack.isRecombobulated(): Boolean {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ return extraAttributes.hasKey("rarity_upgrades")
+ }
+
+ return false
+ }
+
+ fun ItemStack.hasJalapenoBook(): Boolean {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ return extraAttributes.hasKey("jalapeno_count")
+ }
+
+ return false
+ }
+
+ fun ItemStack.hasEtherwarp(): Boolean {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ return extraAttributes.hasKey("ethermerge")
+ }
+
+ return false
+ }
+
+ fun ItemStack.hasWoodSingularity(): Boolean {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ return extraAttributes.hasKey("wood_singularity_count")
+ }
+
+ return false
+ }
+
+ fun ItemStack.hasArtOfWar(): Boolean {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ return extraAttributes.hasKey("art_of_war_count")
+ }
+
+ return false
+ }
+
+ // TODO untested
+ fun ItemStack.hasBookOfStats(): Boolean {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ return extraAttributes.hasKey("stats_book")
+ }
+
+ return false
+ }
+
+ fun ItemStack.hasArtOfPiece(): Boolean {
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ return extraAttributes.hasKey("artOfPeaceApplied")
+ }
+
+ return false
+ }
+
+ fun ItemStack.getEnchantments(): Map<String, Int> {
+ val map = mutableMapOf<String, Int>()
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes != "enchantments") continue
+ val enchantments = extraAttributes.getCompoundTag(attributes)
+ for (key in enchantments.keySet) {
+ map[key] = enchantments.getInteger(key)
+ }
+ }
+ }
+ return map
+ }
+
+ fun ItemStack.getGemstones(): List<EstimatedItemValue.GemstoneSlot> {
+ val list = mutableListOf<EstimatedItemValue.GemstoneSlot>()
+ for (tags in tagCompound.keySet) {
+ if (tags != "ExtraAttributes") continue
+ val extraAttributes = tagCompound.getCompoundTag(tags)
+ for (attributes in extraAttributes.keySet) {
+ if (attributes != "gems") continue
+ val gemstones = extraAttributes.getCompoundTag(attributes)
+ for (key in gemstones.keySet) {
+ if (key.endsWith("_gem")) continue
+ if (key == "unlocked_slots") continue
+ val value = gemstones.getString(key)
+ if (value == "") continue
+
+ val rawType = key.split("_")[0]
+ val type = EstimatedItemValue.GemstoneType.getByName(rawType)
+
+ val tier = EstimatedItemValue.GemstoneTier.getByName(value)
+ if (tier == null) {
+ LorenzUtils.debug("Gemstone tier is null for item $name: ('$key' = '$value')")
+ continue
+ }
+ if (type != null) {
+ list.add(EstimatedItemValue.GemstoneSlot(type, tier))
+ } else {
+ val newKey = gemstones.getString(key + "_gem")
+ val newType = EstimatedItemValue.GemstoneType.getByName(newKey)
+ if (newType == null) {
+ LorenzUtils.debug("Gemstone type is null for item $name: ('$newKey' with '$key' = '$value')")
+ continue
+ }
+ list.add(EstimatedItemValue.GemstoneSlot(newType, tier))
+ }
+ }
+ }
+ }
+ return list
+ }
+} \ No newline at end of file