aboutsummaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal002@users.noreply.github.com>2024-09-12 02:33:44 +0200
committerGitHub <noreply@github.com>2024-09-12 02:33:44 +0200
commite350ade0d86955ce1a865f4286cd208d54693777 (patch)
tree9fcfaaf1a15a55b85a55df58d83b1c0c9e66b885 /src/main
parentb2d1c22d4baebc6eaf9eef823b11fa9d1801ced1 (diff)
downloadskyhanni-e350ade0d86955ce1a865f4286cd208d54693777.tar.gz
skyhanni-e350ade0d86955ce1a865f4286cd208d54693777.tar.bz2
skyhanni-e350ade0d86955ce1a865f4286cd208d54693777.zip
Improvement: Stars in Estimated Item Value (#2492)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java9
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuEssenceCostJson.kt40
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt193
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/EssenceItemUtils.kt136
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt4
7 files changed, 378 insertions, 26 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java
index 096370308..3f5874ac0 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/EstimatedItemValueConfig.java
@@ -40,6 +40,15 @@ public class EstimatedItemValueConfig {
public Property<Integer> enchantmentsCap = Property.of(7);
@Expose
+ @ConfigOption(name = "Star Material Cap", desc = "Only show the top # most expensive parts of star prices.")
+ @ConfigEditorSlider(
+ minValue = 1,
+ maxValue = 15,
+ minStep = 1
+ )
+ public Property<Integer> starMaterialCap = Property.of(3);
+
+ @Expose
@ConfigOption(name = "Show Exact Price", desc = "Show the exact total price instead of the compact number.")
@ConfigEditorBoolean
public Property<Boolean> exactPrice = Property.of(false);
diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuEssenceCostJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuEssenceCostJson.kt
new file mode 100644
index 000000000..12aa600ee
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuEssenceCostJson.kt
@@ -0,0 +1,40 @@
+package at.hannibal2.skyhanni.data.jsonobjects.repo.neu
+
+import com.google.gson.annotations.Expose
+import com.google.gson.annotations.SerializedName
+import com.google.gson.reflect.TypeToken
+import java.lang.reflect.Type
+
+data class NeuEssenceCostJson(
+ @Expose @SerializedName("type") val essenceType: String,
+ @Expose @SerializedName("dungeonize") val essenceForDungeonize: Int?,
+ @Expose @SerializedName("1") val essenceFor1: Int?,
+ @Expose @SerializedName("2") val essenceFor2: Int?,
+ @Expose @SerializedName("3") val essenceFor3: Int?,
+ @Expose @SerializedName("4") val essenceFor4: Int?,
+ @Expose @SerializedName("5") val essenceFor5: Int?,
+ @Expose @SerializedName("6") val essenceFor6: Int?,
+ @Expose @SerializedName("7") val essenceFor7: Int?,
+ @Expose @SerializedName("8") val essenceFor8: Int?,
+ @Expose @SerializedName("9") val essenceFor9: Int?,
+ @Expose @SerializedName("10") val essenceFor10: Int?,
+ @Expose @SerializedName("11") val essenceFor11: Int?,
+ @Expose @SerializedName("12") val essenceFor12: Int?,
+ @Expose @SerializedName("13") val essenceFor13: Int?,
+ @Expose @SerializedName("14") val essenceFor14: Int?,
+ @Expose @SerializedName("15") val essenceFor15: Int?,
+ @Expose @SerializedName("items") val extraItems: Map<String, List<String>>?,
+
+ @Expose @SerializedName("catacombs_requirements") val catacombsRequirements: List<NeuCatacombsRequirements>,
+) {
+
+ companion object {
+ val TYPE: Type = object : TypeToken<Map<String?, NeuEssenceCostJson>>() {}.type
+ }
+}
+
+data class NeuCatacombsRequirements(
+ @Expose @SerializedName("type") val type: String,
+ @Expose @SerializedName("dungeon_type") val dungeonType: String?,
+ @Expose @SerializedName("level") val level: Int,
+)
diff --git a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
index 6f7df5964..c2bd261ca 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
@@ -1,6 +1,9 @@
+
package at.hannibal2.skyhanni.events
import at.hannibal2.skyhanni.config.ConfigManager
+import at.hannibal2.skyhanni.data.repo.RepoError
+import at.hannibal2.skyhanni.data.repo.RepoUtils
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.NEUItems.manager
import at.hannibal2.skyhanni.utils.json.fromJson
@@ -8,6 +11,7 @@ import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.JsonSyntaxException
import java.io.File
+import java.lang.reflect.Type
class NeuRepositoryReloadEvent : LorenzEvent() {
fun getConstant(file: String): JsonObject? {
@@ -26,4 +30,11 @@ class NeuRepositoryReloadEvent : LorenzEvent() {
throw e
}
}
+
+ inline fun <reified T : Any> getConstant(constant: String, type: Type? = null, gson: Gson = ConfigManager.gson): T = try {
+ if (!manager.repoLocation.exists()) throw RepoError("NEU-Repo folder does not exist!")
+ RepoUtils.getConstant(manager.repoLocation, constant, gson, T::class.java, type)
+ } catch (e: Exception) {
+ throw RepoError("Repo parsing error while trying to read constant '$constant'", e)
+ }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt
index a587443e5..046325749 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt
@@ -21,6 +21,7 @@ import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.ItemUtils.isRune
import at.hannibal2.skyhanni.utils.ItemUtils.itemName
import at.hannibal2.skyhanni.utils.ItemUtils.name
+import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyClicked
import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.NEUInternalName
@@ -32,6 +33,7 @@ import net.minecraft.client.Minecraft
import net.minecraft.init.Items
import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import org.lwjgl.input.Keyboard
import kotlin.math.roundToLong
@SkyHanniModule
@@ -88,6 +90,15 @@ object EstimatedItemValue {
currentlyShowing = checkCurrentlyVisible()
if (!currentlyShowing) return
+ // TODO add "is debug enabled" check once users notice this easteregg
+ if (Keyboard.KEY_RIGHT.isKeyClicked()) {
+ EstimatedItemValueCalculator.starChange += 1
+ cache.clear()
+ } else if (Keyboard.KEY_LEFT.isKeyClicked()) {
+ EstimatedItemValueCalculator.starChange -= 1
+ cache.clear()
+ }
+
config.itemPriceDataPos.renderStringsAndItems(display, posLabel = "Estimated Item Value")
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt
index ffa92489c..6842ccc77 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt
@@ -3,9 +3,14 @@ package at.hannibal2.skyhanni.features.misc.items
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.api.ReforgeAPI
import at.hannibal2.skyhanni.test.command.ErrorManager
+import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut
+import at.hannibal2.skyhanni.utils.CollectionUtils.sorted
import at.hannibal2.skyhanni.utils.CollectionUtils.sortedDesc
+import at.hannibal2.skyhanni.utils.EssenceItemUtils
+import at.hannibal2.skyhanni.utils.EssenceItemUtils.getEssencePrices
import at.hannibal2.skyhanni.utils.ItemUtils.getAttributeFromShard
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.ItemUtils.isRune
@@ -20,6 +25,7 @@ import at.hannibal2.skyhanni.utils.NEUItems.getItemStackOrNull
import at.hannibal2.skyhanni.utils.NEUItems.getNpcPriceOrNull
import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull
import at.hannibal2.skyhanni.utils.NEUItems.getRawCraftCostOrNull
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAbilityScrolls
@@ -41,6 +47,7 @@ import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getPowerScroll
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getReforgeName
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getRune
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getSilexCount
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getStarCount
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getTransmissionTunerCount
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasArtOfPeace
import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.hasArtOfWar
@@ -62,6 +69,8 @@ object EstimatedItemValueCalculator {
private val kuudraSets = listOf("AURORA", "CRIMSON", "TERROR", "HOLLOW", "FERVOR")
+ var starChange = 0
+
private val additionalCostFunctions = listOf(
::addAttributeCost,
::addReforgeStone,
@@ -79,6 +88,7 @@ object EstimatedItemValueCalculator {
::addDivanPowderCoating,
// counted
+ ::addStars, // crimson, dungeon
::addMasterStars,
::addHotPotatoBooks,
::addFarmingForDummies,
@@ -110,6 +120,8 @@ object EstimatedItemValueCalculator {
val transmissionTuner = "TRANSMISSION_TUNER".asInternalName()
val manaDisintegrator = "MANA_DISINTEGRATOR".asInternalName()
+ val kuudraUpgradeTiers = listOf("HOT_", "BURNING_", "FIERY_", "INFERNAL_")
+
fun getTotalPrice(stack: ItemStack): Double = EstimatedItemValueCalculator.calculate(stack, mutableListOf()).first
fun calculate(stack: ItemStack, list: MutableList<String>): Pair<Double, Double> {
@@ -118,9 +130,12 @@ object EstimatedItemValueCalculator {
return Pair(totalPrice, basePrice)
}
- private fun isKuudraSet(internalName: String) =
- (kuudraSets.any { internalName.contains(it) } &&
- listOf("CHESTPLATE", "LEGGINGS", "HELMET", "BOOTS").any { internalName.endsWith(it) })
+ private fun isKuudraSet(internalName: String) = (kuudraSets.any { internalName.contains(it) } && listOf(
+ "CHESTPLATE",
+ "LEGGINGS",
+ "HELMET",
+ "BOOTS",
+ ).any { internalName.endsWith(it) })
private fun addAttributeCost(stack: ItemStack, list: MutableList<String>): Double {
val attributes = stack.getAttributes() ?: return 0.0
@@ -150,8 +165,7 @@ object EstimatedItemValueCalculator {
}
for (attr in attributes) {
val attributeName = "$genericName+ATTRIBUTE_${attr.first}"
- val price =
- getPriceOrCompositePriceForAttribute(attributeName, attr.second)
+ val price = getPriceOrCompositePriceForAttribute(attributeName, attr.second)
var priceColor = "§7"
val useless = isUselessAttribute(attributeName)
var nameColor = if (!useless) "§9" else "§7"
@@ -177,21 +191,21 @@ object EstimatedItemValueCalculator {
if (!isKuudraSet(original)) return original
var internalName = original
- for (prefix in listOf("HOT_", "BURNING_", "FIERY_", "INFERNAL_")) {
+ for (prefix in kuudraUpgradeTiers) {
internalName = internalName.removePrefix(prefix)
}
return internalName
}
- private fun addAttributePrice(attributePrice: Double, basePrice: Double): Double =
- if (attributePrice > basePrice) {
- attributePrice - basePrice
- } else {
- 0.0
- }
+ private fun addAttributePrice(attributePrice: Double, basePrice: Double): Double = if (attributePrice > basePrice) {
+ attributePrice - basePrice
+ } else {
+ 0.0
+ }
private fun isUselessAttribute(internalName: String): Boolean {
if (internalName.contains("RESISTANCE")) return true
+ if (internalName.contains("FISHING_SPEED")) return false
if (internalName.contains("SPEED")) return true
if (internalName.contains("EXPERIENCE")) return true
if (internalName.contains("FORTITUDE")) return true
@@ -205,8 +219,7 @@ object EstimatedItemValueCalculator {
private fun getPriceOrCompositePriceForAttribute(attributeName: String, level: Int): Double? {
val intRange = if (config.useAttributeComposite.get()) 1..10 else level..level
return intRange.mapNotNull { lowerLevel ->
- "$attributeName;$lowerLevel".asInternalName().getPriceOrNull()
- ?.let { it / (1 shl lowerLevel) * (1 shl level).toDouble() }
+ "$attributeName;$lowerLevel".asInternalName().getPriceOrNull()?.let { it / (1 shl lowerLevel) * (1 shl level).toDouble() }
}.minOrNull()
}
@@ -414,10 +427,143 @@ object EstimatedItemValueCalculator {
return price
}
+ private fun addStars(stack: ItemStack, list: MutableList<String>): Double {
+ val internalName = stack.getInternalNameOrNull() ?: return 0.0
+ var totalStars = stack.getDungeonStarCount() ?: stack.getStarCount() ?: 0
+
+ starChange.takeIf { it != 0 }?.let {
+ list.add("change: $it")
+ totalStars += it
+ }
+
+ val (price, stars) = calculateStarPrice(internalName, totalStars) ?: return 0.0
+ val (havingStars, maxStars) = stars
+
+ var totalPrice = 0.0
+ val map = mutableMapOf<String, Double>()
+ price.essencePrice.let {
+ val essenceName = "ESSENCE_${it.essenceType}".asInternalName()
+ val amount = it.essenceAmount
+ val essencePrice = essenceName.getPrice() * amount
+ map[" §8${amount.addSeparators()}x ${essenceName.itemName} §7(§6${essencePrice.shortFormat()}§7)"] = essencePrice
+ totalPrice += essencePrice
+ }
+
+ price.coinPrice.takeIf { it != 0L }?.let {
+ map[" §6${it.shortFormat()} coins"] = it.toDouble()
+ totalPrice += it
+ }
+
+ for ((materialInternalName, amount) in price.itemPrice) {
+ val itemPrice = materialInternalName.getPriceOrNull()?.let { it * amount }
+ if (itemPrice != null) {
+ map[" §8${amount.addSeparators()}x ${materialInternalName.itemName} §7(§6${itemPrice.shortFormat()}§7)"] = itemPrice
+ } else {
+ map[" §8${amount.addSeparators()}x ${materialInternalName.itemName}"] = 0.0
+ }
+ totalPrice += itemPrice ?: 0.0
+ }
+
+ list.add("§7Stars: §e$havingStars§7/§e$maxStars §7(§6" + totalPrice.shortFormat() + "§7)")
+ val starMaterialCap: Int = config.starMaterialCap.get()
+ list.addAll(map.sortedDesc().keys.take(starMaterialCap))
+ return totalPrice
+ }
+
+ private fun calculateStarPrice(
+ internalName: NEUInternalName,
+ inputStars: Int,
+ ): Pair<EssenceItemUtils.EssenceUpgradePrice, Pair<Int, Int>>? {
+ var totalStars = inputStars
+ val rawInternalName = internalName.asString()
+ val (price, maxStars) = if (isKuudraSet(rawInternalName)) {
+ val tier = getKuudraTier(internalName)
+ totalStars += (tier + 1) * 10
+
+ var remainingStars = totalStars
+
+ val removed = removeKuudraArmorPrefix(rawInternalName)
+ var maxStars = 0
+ var finalPrice: EssenceItemUtils.EssenceUpgradePrice? = null
+
+ val tiers = mutableMapOf<NEUInternalName, Int>()
+
+ for ((id, prices) in EssenceItemUtils.itemPrices) {
+ if (!id.contains(removed)) continue
+ tiers[id] = getKuudraTier(id)
+
+ }
+ for ((id, tier) in tiers.sorted()) {
+ val prices = EssenceItemUtils.itemPrices[id]!!
+ maxStars += prices.size
+ if (remainingStars <= 0) continue
+
+ val price = getPriceFor(prices, remainingStars) ?: return null
+ println(" ")
+ println("price for $id ($remainingStars)")
+ println("price.itemPrice: ${price.itemPrice}")
+ println("essencePrice: ${price.essencePrice}")
+ println("itemPrice: ${price.itemPrice}")
+ finalPrice = finalPrice?.let { it + price } ?: price
+ remainingStars -= prices.size
+ }
+ if (finalPrice == null) return null
+
+ finalPrice to maxStars
+ } else {
+ if (totalStars == 0) return null
+
+ val prices = internalName.getEssencePrices() ?: return null
+
+ (getPriceFor(prices, totalStars) ?: return null) to prices.size
+ }
+ val havingStars = totalStars.coerceAtMost(maxStars)
+
+ return price to (havingStars to maxStars)
+ }
+
+ private fun getKuudraTier(internalName: NEUInternalName): Int {
+ for (tier in kuudraUpgradeTiers) {
+ if (internalName.asString().contains(tier)) {
+ return kuudraUpgradeTiers.indexOf(tier)
+ }
+ }
+ return 0
+ }
+// private fun getKuudraTier(internalName: NEUInternalName): Int? =
+// kuudraUpgradeTiers.firstOrNull { it in internalName.toString() }?.let { kuudraUpgradeTiers.indexOf(it) }
+
+ private fun getPriceFor(
+ prices: Map<Int, EssenceItemUtils.EssenceUpgradePrice>,
+ totalStars: Int,
+ ): EssenceItemUtils.EssenceUpgradePrice? {
+ var totalEssencePrice: EssenceItemUtils.EssencePrice? = null
+ var totalCoinPrice = 0L
+ val totalItemPrice = mutableMapOf<NEUInternalName, Int>()
+
+ for ((tier, price) in prices) {
+ if (tier > totalStars) break
+ val essencePrice = price.essencePrice
+ totalEssencePrice = totalEssencePrice?.let { it + essencePrice } ?: essencePrice
+
+ price.coinPrice?.let {
+ totalCoinPrice += it
+ }
+ for (entry in price.itemPrice) {
+ totalItemPrice.addOrPut(entry.key, entry.value)
+ }
+ }
+ totalEssencePrice ?: return null
+ return EssenceItemUtils.EssenceUpgradePrice(totalEssencePrice, totalCoinPrice, totalItemPrice)
+ }
+
private fun addMasterStars(stack: ItemStack, list: MutableList<String>): Double {
- val totalStars = stack.getDungeonStarCount() ?: return 0.0
+ var totalStars = stack.getDungeonStarCount() ?: return 0.0
+ starChange.takeIf { it != 0 }?.let {
+ totalStars += it
+ }
- val masterStars = totalStars - 5
+ val masterStars = (totalStars - 5).coerceAtMost(5)
if (masterStars < 1) return 0.0
var price = 0.0
@@ -600,8 +746,7 @@ object EstimatedItemValueCalculator {
//todo use repo
val tieredEnchants = listOf("compact", "cultivating", "champion", "expertise", "hecatomb", "toxophilite")
- val onlyTierOnePrices =
- listOf("ultimate_chimera", "ultimate_fatal_tempo", "smoldering", "ultimate_flash", "divine_gift")
+ val onlyTierOnePrices = listOf("ultimate_chimera", "ultimate_fatal_tempo", "smoldering", "ultimate_flash", "divine_gift")
val onlyTierFivePrices = listOf("ferocious_mana", "hardened_mana", "mana_vampire", "strong_mana")
val internalName = stack.getInternalName()
@@ -718,8 +863,7 @@ object EstimatedItemValueCalculator {
val internalName = stack.getInternalName()
// item have to contains gems.unlocked_slots NBT array for unlocked slot detection
- val unlockedSlots =
- stack.getExtraAttributes()?.getCompoundTag("gems")?.getTag("unlocked_slots")?.toString() ?: return 0.0
+ val unlockedSlots = stack.getExtraAttributes()?.getCompoundTag("gems")?.getTag("unlocked_slots")?.toString() ?: return 0.0
// TODO detection for old items which doesn't have gems.unlocked_slots NBT array
// if (unlockedSlots == "null") return 0.0
@@ -782,9 +926,8 @@ object EstimatedItemValueCalculator {
return "§b$name ${second} Shard"
}
- fun Pair<String, Int>.getAttributePrice(): Double? =
- EstimatedItemValueCalculator.getPriceOrCompositePriceForAttribute(
- "ATTRIBUTE_SHARD+ATTRIBUTE_" + first,
- second,
- )
+ fun Pair<String, Int>.getAttributePrice(): Double? = EstimatedItemValueCalculator.getPriceOrCompositePriceForAttribute(
+ "ATTRIBUTE_SHARD+ATTRIBUTE_" + first,
+ second,
+ )
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/EssenceItemUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/EssenceItemUtils.kt
new file mode 100644
index 000000000..fbb106d08
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/utils/EssenceItemUtils.kt
@@ -0,0 +1,136 @@
+package at.hannibal2.skyhanni.utils
+
+import at.hannibal2.skyhanni.config.ConfigManager
+import at.hannibal2.skyhanni.data.jsonobjects.repo.neu.NeuEssenceCostJson
+import at.hannibal2.skyhanni.events.NeuRepositoryReloadEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.test.command.ErrorManager
+import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+@SkyHanniModule
+object EssenceItemUtils {
+ var itemPrices = mapOf<NEUInternalName, Map<Int, EssenceUpgradePrice>>()
+
+ @SubscribeEvent
+ fun onNeuRepoReload(event: NeuRepositoryReloadEvent) {
+ val unformattedData = event.getConstant<Map<String, NeuEssenceCostJson>>("essencecosts", NeuEssenceCostJson.TYPE)
+
+ ConfigManager.gson.toJson(unformattedData).let {
+ ChatUtils.debug("saved to clipboard!")
+ OSUtils.copyToClipboard(it)
+ }
+ this.itemPrices = reformatData(unformattedData)
+
+ println("result: ${itemPrices.size}")
+ }
+
+ fun NEUInternalName.getEssencePrices(): Map<Int, EssenceUpgradePrice>? = itemPrices[this]
+
+ private fun reformatData(unformattedData: Map<String, NeuEssenceCostJson>): MutableMap<NEUInternalName, Map<Int, EssenceUpgradePrice>> {
+ val itemPrices = mutableMapOf<NEUInternalName, Map<Int, EssenceUpgradePrice>>()
+ for ((name, data) in unformattedData) {
+
+ val essencePrices = loadEssencePrices(data)
+ val extraItems = data.extraItems ?: emptyMap()
+ val (coinPrices, iemPrices) = loadCoinAndItemPrices(extraItems)
+
+ val upgradePrices = mutableMapOf<Int, EssenceUpgradePrice>()
+ for ((tier, essencePrice) in essencePrices) {
+ val coinPrice = coinPrices[tier]
+ val itemPrice = iemPrices[tier] ?: emptyMap()
+ upgradePrices[tier] = EssenceUpgradePrice(essencePrice, coinPrice, itemPrice)
+ }
+
+ val internalName = name.asInternalName()
+ itemPrices[internalName] = upgradePrices
+ }
+ return itemPrices
+ }
+
+ private fun loadCoinAndItemPrices(
+ extraItems: Map<String, List<String>>,
+ ): Pair<MutableMap<Int, Long>, MutableMap<Int, Map<NEUInternalName, Int>>> {
+
+ val collectCoinPrices = mutableMapOf<Int, Long>()
+ val collectItemPrices = mutableMapOf<Int, Map<NEUInternalName, Int>>()
+
+ for ((tier, rawItems) in extraItems.mapKeys { it.key.toInt() }) {
+ val itemPrices = mutableMapOf<NEUInternalName, Int>()
+
+ for ((itemName, amount) in rawItems.map { split(it) }) {
+ if (itemName == NEUInternalName.SKYBLOCK_COIN) {
+ collectCoinPrices[tier] = amount
+ } else {
+ itemPrices[itemName] = amount.toInt()
+ }
+ }
+
+ collectItemPrices[tier] = itemPrices
+ }
+ return Pair(collectCoinPrices, collectItemPrices)
+ }
+
+ private fun split(string: String): Pair<NEUInternalName, Long> = string.split(":").let { it[0].asInternalName() to it[1].toLong() }
+
+ private fun loadEssencePrices(data: NeuEssenceCostJson): MutableMap<Int, EssencePrice> {
+ val map = mutableMapOf<Int, EssencePrice>()
+ val essenceType = data.essenceType
+ data.essenceFor1?.let { map[1] = EssencePrice(it, essenceType) }
+ data.essenceFor2?.let { map[2] = EssencePrice(it, essenceType) }
+ data.essenceFor3?.let { map[3] = EssencePrice(it, essenceType) }
+ data.essenceFor4?.let { map[4] = EssencePrice(it, essenceType) }
+ data.essenceFor5?.let { map[5] = EssencePrice(it, essenceType) }
+ data.essenceFor6?.let { map[6] = EssencePrice(it, essenceType) }
+ data.essenceFor7?.let { map[7] = EssencePrice(it, essenceType) }
+ data.essenceFor8?.let { map[8] = EssencePrice(it, essenceType) }
+ data.essenceFor9?.let { map[9] = EssencePrice(it, essenceType) }
+ data.essenceFor10?.let { map[10] = EssencePrice(it, essenceType) }
+ data.essenceFor11?.let { map[11] = EssencePrice(it, essenceType) }
+ data.essenceFor12?.let { map[12] = EssencePrice(it, essenceType) }
+ data.essenceFor13?.let { map[13] = EssencePrice(it, essenceType) }
+ data.essenceFor14?.let { map[14] = EssencePrice(it, essenceType) }
+ data.essenceFor15?.let { map[15] = EssencePrice(it, essenceType) }
+ return map
+ }
+
+ data class EssenceUpgradePrice(
+ val essencePrice: EssencePrice,
+ val coinPrice: Long?,
+ val itemPrice: Map<NEUInternalName, Int>,
+ ) {
+
+ operator fun plus(other: EssenceUpgradePrice): EssenceUpgradePrice {
+ if (other.essencePrice.essenceType != essencePrice.essenceType) ErrorManager.skyHanniError(
+ "Trying to add non compatible EssenceUpgradePrices!",
+ "essencePrice.essenceType" to essencePrice.essenceType,
+ "other.essencePrice.essenceType" to other.essencePrice.essenceType,
+ )
+
+ val coinPrice = coinPrice ?: 0L
+ val otherCoinPrice = other.coinPrice ?: 0L
+
+ val map = itemPrice.toMutableMap()
+ for (entry in other.itemPrice) {
+ map.addOrPut(entry.key, entry.value)
+ }
+
+ return EssenceUpgradePrice(essencePrice + other.essencePrice, coinPrice + otherCoinPrice, map)
+ }
+ }
+
+ data class EssencePrice(val essenceAmount: Int, val essenceType: String) {
+
+ operator fun plus(other: EssencePrice): EssencePrice {
+ if (other.essenceType != essenceType) ErrorManager.skyHanniError(
+ "Trying to add non compatible essence prices!",
+ "essenceType" to essenceType,
+ "other.essenceType" to other.essenceType,
+ )
+
+ return EssencePrice(essenceAmount + other.essenceAmount, essenceType)
+ }
+ }
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt
index c9e193329..4d0cf4468 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/SkyBlockItemModifierUtils.kt
@@ -46,9 +46,11 @@ object SkyBlockItemModifierUtils {
fun ItemStack.getManaDisintegrators() = getAttributeInt("mana_disintegrator_count")
fun ItemStack.getDungeonStarCount() = if (isDungeonItem()) {
- getAttributeInt("upgrade_level") ?: getAttributeInt("dungeon_item_level")
+ getStarCount() ?: getAttributeInt("dungeon_item_level")
} else null
+ fun ItemStack.getStarCount() = getAttributeInt("upgrade_level")
+
private fun ItemStack.isDungeonItem() = getLore().any { it.contains("DUNGEON ") }
fun ItemStack.getPetExp() = getPetInfo()?.get("exp")?.asDouble