aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt198
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/ReforgeHelperConfig.java36
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeJson.kt (renamed from src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeStoneJson.kt)28
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt80
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/ReforgeHelper.kt432
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValue.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/items/EstimatedItemValueCalculator.kt13
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt70
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt29
12 files changed, 843 insertions, 63 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt b/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt
new file mode 100644
index 000000000..70f6910c9
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/api/ReforgeAPI.kt
@@ -0,0 +1,198 @@
+package at.hannibal2.skyhanni.api
+
+import at.hannibal2.skyhanni.data.jsonobjects.repo.neu.NeuReforgeJson
+import at.hannibal2.skyhanni.data.model.SkyblockStat
+import at.hannibal2.skyhanni.data.model.SkyblockStatList
+import at.hannibal2.skyhanni.events.NeuRepositoryReloadEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.ItemCategory
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull
+import at.hannibal2.skyhanni.utils.ItemUtils.itemNameWithoutColor
+import at.hannibal2.skyhanni.utils.LorenzRarity
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.json.BaseGsonBuilder
+import at.hannibal2.skyhanni.utils.json.SkyHanniTypeAdapters
+import com.google.gson.Gson
+import com.google.gson.TypeAdapter
+import com.google.gson.stream.JsonReader
+import com.google.gson.stream.JsonWriter
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+@SkyHanniModule
+object ReforgeAPI {
+ var reforgeList: List<Reforge> = emptyList()
+ private set(value) {
+ field = value
+ nonePowerStoneReforge = value.filterNot { it.isReforgeStone }
+ onlyPowerStoneReforge = value.filter { it.isReforgeStone }
+ }
+
+ var nonePowerStoneReforge: List<Reforge> = emptyList()
+ private set
+
+ var onlyPowerStoneReforge: List<Reforge> = emptyList()
+ private set
+
+ enum class ReforgeType {
+ SWORD,
+ BOW,
+ ARMOR,
+ CHESTPLATE,
+ HELMET,
+ CLOAK,
+ AXE,
+ HOE,
+ AXE_AND_HOE,
+ PICKAXE,
+ EQUIPMENT,
+ ROD,
+ SWORD_AND_ROD,
+ SPECIAL_ITEMS,
+ VACUUM
+ }
+
+ class Reforge(
+ val name: String,
+ val type: ReforgeType,
+ val stats: Map<LorenzRarity, SkyblockStatList>,
+ val reforgeStone: NEUInternalName? = null,
+ val specialItems: List<NEUInternalName>? = null,
+ val extraProperty: Map<LorenzRarity, String> = emptyMap(),
+ val costs: Map<LorenzRarity, Long>? = null,
+ ) {
+
+ val isReforgeStone = reforgeStone != null
+
+ val rawReforgeStoneName = reforgeStone?.itemNameWithoutColor
+
+ val lowercaseName = name.lowercase()
+
+ fun isValid(itemStack: ItemStack) = isValid(itemStack.getItemCategoryOrNull(), itemStack.getInternalName())
+
+ fun isValid(itemCategory: ItemCategory?, internalName: NEUInternalName) = when (type) {
+ ReforgeType.SWORD -> setOf(
+ ItemCategory.SWORD,
+ ItemCategory.GAUNTLET,
+ ItemCategory.LONGSWORD,
+ ItemCategory.FISHING_WEAPON,
+ ).contains(itemCategory)
+
+ ReforgeType.BOW -> itemCategory == ItemCategory.BOW || itemCategory == ItemCategory.SHORT_BOW
+ ReforgeType.ARMOR -> setOf(
+ ItemCategory.HELMET,
+ ItemCategory.CHESTPLATE,
+ ItemCategory.LEGGINGS,
+ ItemCategory.BOOTS,
+ ).contains(itemCategory)
+
+ ReforgeType.CHESTPLATE -> itemCategory == ItemCategory.CHESTPLATE
+ ReforgeType.HELMET -> itemCategory == ItemCategory.HELMET
+ ReforgeType.CLOAK -> itemCategory == ItemCategory.CLOAK
+ ReforgeType.AXE -> itemCategory == ItemCategory.AXE
+ ReforgeType.HOE -> itemCategory == ItemCategory.HOE
+ ReforgeType.AXE_AND_HOE -> itemCategory == ItemCategory.HOE || itemCategory == ItemCategory.AXE
+ ReforgeType.PICKAXE ->
+ itemCategory == ItemCategory.PICKAXE ||
+ itemCategory == ItemCategory.DRILL ||
+ itemCategory == ItemCategory.GAUNTLET
+
+ ReforgeType.EQUIPMENT -> setOf(
+ ItemCategory.CLOAK,
+ ItemCategory.BELT,
+ ItemCategory.NECKLACE,
+ ItemCategory.BRACELET,
+ ItemCategory.GLOVES,
+ ).contains(itemCategory)
+
+ ReforgeType.ROD -> itemCategory == ItemCategory.FISHING_ROD || itemCategory == ItemCategory.FISHING_WEAPON
+ ReforgeType.SWORD_AND_ROD -> setOf(
+ ItemCategory.SWORD,
+ ItemCategory.GAUNTLET,
+ ItemCategory.LONGSWORD,
+ ItemCategory.FISHING_ROD,
+ ItemCategory.FISHING_WEAPON,
+ ).contains(itemCategory)
+
+ ReforgeType.VACUUM -> itemCategory == ItemCategory.VACUUM
+ ReforgeType.SPECIAL_ITEMS -> specialItems?.contains(internalName) ?: false
+ }
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as Reforge
+
+ if (name != other.name) return false
+ if (type != other.type) return false
+ if (stats != other.stats) return false
+ if (reforgeStone != other.reforgeStone) return false
+ if (specialItems != other.specialItems) return false
+ if (extraProperty != other.extraProperty) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = name.hashCode()
+ result = 31 * result + type.hashCode()
+ result = 31 * result + stats.hashCode()
+ result = 31 * result + (reforgeStone?.hashCode() ?: 0)
+ result = 31 * result + (specialItems?.hashCode() ?: 0)
+ result = 31 * result + extraProperty.hashCode()
+ return result
+ }
+
+ override fun toString(): String = "Reforge $name"
+ }
+
+ @SubscribeEvent
+ fun onNeuRepoReload(event: NeuRepositoryReloadEvent) {
+ val reforgeStoneData = event.readConstant<Map<String, NeuReforgeJson>>("reforgestones", reforgeGson).values
+ val reforgeData = event.readConstant<Map<String, NeuReforgeJson>>("reforges", reforgeGson).values
+ reforgeList = (reforgeStoneData + reforgeData).map(::mapReforge)
+ }
+
+ private val reforgeGson: Gson = BaseGsonBuilder.gson()
+ .registerTypeAdapter(SkyblockStat::class.java, SkyHanniTypeAdapters.SKYBLOCK_STAT.nullSafe())
+ .registerTypeAdapter(
+ SkyblockStatList::class.java,
+ object : TypeAdapter<SkyblockStatList>() {
+ override fun write(out: JsonWriter, value: SkyblockStatList) {
+ out.beginObject()
+ value.entries.forEach {
+ out.name(it.key.name.lowercase()).value(it.value)
+ }
+ out.endObject()
+ }
+
+ override fun read(reader: JsonReader): SkyblockStatList {
+ reader.beginObject()
+ val list = SkyblockStatList()
+ while (reader.hasNext()) {
+ val name = reader.nextName()
+ val value = reader.nextDouble()
+ list[SkyblockStat.valueOf(name.uppercase())] = value
+ }
+ reader.endObject()
+ return list
+ }
+ },
+ ).create()
+
+ private fun mapReforge(it: NeuReforgeJson): Reforge {
+ val type = it.itemType
+ return Reforge(
+ name = it.reforgeName,
+ type = LorenzUtils.enumValueOf<ReforgeType>(type.first),
+ stats = it.reforgeStats ?: emptyMap(),
+ reforgeStone = it.internalName,
+ specialItems = type.second.takeIf { it.isNotEmpty() },
+ extraProperty = it.reforgeAbility,
+ costs = it.reforgeCosts,
+ )
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java
index 990399d62..f6818d2c8 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/HelperConfig.java
@@ -53,6 +53,11 @@ public class HelperConfig {
public TiaRelayConfig tiaRelay = new TiaRelayConfig();
@Expose
+ @ConfigOption(name = "Reforge Helper", desc = "")
+ @Accordion
+ public ReforgeHelperConfig reforge = new ReforgeHelperConfig();
+
+ @Expose
@ConfigOption(name = "Enchanting", desc = "")
@Accordion
public EnchantingConfig enchanting = new EnchantingConfig();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/ReforgeHelperConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/ReforgeHelperConfig.java
new file mode 100644
index 000000000..43bba7f8c
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/helper/ReforgeHelperConfig.java
@@ -0,0 +1,36 @@
+package at.hannibal2.skyhanni.config.features.inventory.helper;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import at.hannibal2.skyhanni.config.core.config.Position;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigLink;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+public class ReforgeHelperConfig {
+
+ @Expose
+ @ConfigLink(owner = ReforgeHelperConfig.class, field = "enabled")
+ public Position position = new Position(80, 85, true, true);
+
+ @Expose
+ @ConfigOption(name = "Enable", desc = "Enables the reforge helper.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean enabled = true;
+
+ @Expose
+ @ConfigOption(name = "Stones Hex Only", desc = "Displays reforge stones only when in Hex.")
+ @ConfigEditorBoolean
+ public boolean reforgeStonesOnlyHex = true;
+
+ @Expose
+ @ConfigOption(name = "Show Diff", desc = "Shows the difference of the new reforge to the current one in the slecetion list.")
+ @ConfigEditorBoolean
+ public boolean showDiff = false;
+
+ @Expose
+ @ConfigOption(name = "Hide chat", desc = "Hides the vanilla chat messages from reforging.")
+ @ConfigEditorBoolean
+ public boolean hideChat = false;
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeStoneJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeJson.kt
index 8ebe2dea6..a8c8f3fe4 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeStoneJson.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/neu/NeuReforgeJson.kt
@@ -1,21 +1,26 @@
package at.hannibal2.skyhanni.data.jsonobjects.repo.neu
+import at.hannibal2.skyhanni.data.model.SkyblockStatList
import at.hannibal2.skyhanni.utils.LorenzRarity
import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName
+import at.hannibal2.skyhanni.utils.NEUItems
import com.google.gson.annotations.Expose
import com.google.gson.annotations.SerializedName
+import net.minecraft.item.Item
-data class NeuReforgeStoneJson(
- @Expose val internalName: NEUInternalName,
+data class NeuReforgeJson(
+ @Expose val internalName: NEUInternalName?,
@Expose val reforgeName: String,
@Expose @SerializedName("itemTypes") val rawItemTypes: Any,
@Expose val requiredRarities: List<LorenzRarity>,
- @Expose val reforgeCosts: Map<LorenzRarity, Long>,
- @Expose val reforgeStats: Map<LorenzRarity, Map<String, Double>>,
+ @Expose val reforgeCosts: Map<LorenzRarity, Long>?,
+ @Expose val reforgeStats: Map<LorenzRarity, SkyblockStatList>?,
@Expose @SerializedName("reforgeAbility") val rawReforgeAbility: Any?,
) {
private lateinit var reforgeAbilityField: Map<LorenzRarity, String>
+ private lateinit var itemTypeField: Pair<String, List<NEUInternalName>>
val reforgeAbility
get() = if (this::reforgeAbilityField.isInitialized) reforgeAbilityField
@@ -27,7 +32,7 @@ data class NeuReforgeStoneJson(
is Map<*, *> -> (this.rawReforgeAbility as? Map<String, String>)?.mapKeys {
LorenzRarity.valueOf(
- it.key.uppercase().replace(" ", "_")
+ it.key.uppercase().replace(" ", "_"),
)
} ?: emptyMap()
@@ -36,28 +41,27 @@ data class NeuReforgeStoneJson(
reforgeAbilityField
}
- /* used in ReforgeAPI which isn't in beta yet
- val itemType: Pair<String, List<NEUInternalName>> by lazy {
+ val itemType: Pair<String, List<NEUInternalName>>
+ get() = if (this::itemTypeField.isInitialized) itemTypeField
+ else run {
val any = this.rawItemTypes
- return@lazy when (any) {
+ return when (any) {
is String -> {
any.replace("/", "_AND_").uppercase() to emptyList()
}
is Map<*, *> -> {
val type = "SPECIAL_ITEMS"
- val map = any as? Map<String, List<String>> ?: return@lazy type to emptyList()
+ val map = any as? Map<String, List<String>> ?: return type to emptyList()
val internalNames = map["internalName"]?.map { it.asInternalName() } ?: emptyList()
val itemType = map["itemid"]?.map {
NEUItems.getInternalNamesForItemId(Item.getByNameOrId(it))
- }?.flatten()
- ?: emptyList()
+ }?.flatten() ?: emptyList()
type to (internalNames + itemType)
}
else -> throw IllegalStateException()
}
}
-*/
}
diff --git a/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt b/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt
new file mode 100644
index 000000000..161ec76f5
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/model/SkyblockStat.kt
@@ -0,0 +1,80 @@
+package at.hannibal2.skyhanni.data.model
+
+import at.hannibal2.skyhanni.utils.StringUtils.allLettersFirstUppercase
+import net.minecraft.client.Minecraft
+import java.util.EnumMap
+
+enum class SkyblockStat(val icon: String) {
+ DAMAGE("§c❁"),
+ HEALTH("§c❤"),
+ DEFENSE("§a❈"),
+ STRENGTH("§c❁"),
+ INTELLIGENCE("§b✎"),
+ CRIT_DAMAGE("§9☠"),
+ CRIT_CHANCE("§9☣"),
+ FEROCITY("§c⫽"),
+ BONUS_ATTACK_SPEED("§e⚔"),
+ ABILITY_DAMAGE("§c๑"),
+ HEALTH_REGEN("§c❣"),
+ VITALITY("§4♨"),
+ MENDING("§a☄"),
+ TRUE_DEFENCE("§7❂"),
+ SWING_RANGE("§eⓈ"),
+ SPEED("§f✦"),
+ SEA_CREATURE_CHANCE("§3α"),
+ MAGIC_FIND("§b✯"),
+ PET_LUCK("§d♣"),
+ FISHING_SPEED("§b☂"),
+ BONUS_PEST_CHANCE("§2ൠ"),
+ COMBAT_WISDOM("§3☯"),
+ MINING_WISDOM("§3☯"),
+ FARMING_WISDOM("§3☯"),
+ FORAGING_WISDOM("§3☯"),
+ FISHING_WISDOM("§3☯"),
+ ENCHANTING_WISDOM("§3☯"),
+ ALCHEMY_WISDOM("§3☯"),
+ CARPENTRY_WISDOM("§3☯"),
+ RUNECRAFTING_WISDOM("§3☯"),
+ SOCIAL_WISDOM("§3☯"),
+ TAMING_WISDOM("§3☯"),
+ MINING_SPEED("§6⸕"),
+ BREAKING_POWER("§2Ⓟ"),
+ PRISTINE("§5✧"),
+ FORAGING_FORTUNE("§☘"),
+ FARMING_FORTUNE("§6☘"),
+ MINING_FORTUNE("§6☘"),
+ FEAR("§a☠")
+ ;
+
+ val capitalizedName = name.lowercase().allLettersFirstUppercase()
+
+ val iconWithName = "$icon $capitalizedName"
+
+ fun asString(value: Int) = (if (value > 0) "+" else "") + value.toString() + " " + this.icon
+
+ companion object {
+ val fontSizeOfLargestIcon by lazy {
+ entries.maxOf { Minecraft.getMinecraft().fontRendererObj.getStringWidth(it.icon) } + 1
+ }
+ }
+}
+
+class SkyblockStatList : EnumMap<SkyblockStat, Double>(SkyblockStat::class.java), Map<SkyblockStat, Double> {
+ operator fun minus(other: SkyblockStatList): SkyblockStatList {
+ return SkyblockStatList().apply {
+ val keys = this.keys + other.keys
+ for (key in keys) {
+ this[key] = (this@SkyblockStatList[key] ?: 0.0) - (other[key] ?: 0.0)
+ }
+ }
+ }
+
+ companion object {
+ fun mapOf(vararg list: Pair<SkyblockStat, Double>) = SkyblockStatList().apply {
+ for ((key, value) in list) {
+ this[key] = value
+ }
+ }
+ }
+}
+
diff --git a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
index a02cb308f..6f7df5964 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/NeuRepositoryReloadEvent.kt
@@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.config.ConfigManager
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.NEUItems.manager
import at.hannibal2.skyhanni.utils.json.fromJson
+import com.google.gson.Gson
import com.google.gson.JsonObject
import com.google.gson.JsonSyntaxException
import java.io.File
@@ -13,14 +14,14 @@ class NeuRepositoryReloadEvent : LorenzEvent() {
return manager.getJsonFromFile(File(manager.repoLocation, "constants/$file.json"))
}
- inline fun <reified T : Any> readConstant(file: String): T {
+ inline fun <reified T : Any> readConstant(file: String, gson: Gson = ConfigManager.gson): T {
val data = getConstant(file) ?: ErrorManager.skyHanniError("$file failed to load from neu repo!")
return try {
- ConfigManager.gson.fromJson<T>(data)
+ gson.fromJson<T>(data)
} catch (e: JsonSyntaxException) {
ErrorManager.logErrorWithData(
e, "$file failed to read from neu repo!",
- "data" to data
+ "data" to data,
)
throw e
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ReforgeHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ReforgeHelper.kt
new file mode 100644
index 000000000..d1826b481
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ReforgeHelper.kt
@@ -0,0 +1,432 @@
+package at.hannibal2.skyhanni.features.inventory
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.api.ReforgeAPI
+import at.hannibal2.skyhanni.data.model.SkyblockStat
+import at.hannibal2.skyhanni.data.model.SkyblockStatList
+import at.hannibal2.skyhanni.events.GuiContainerEvent
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
+import at.hannibal2.skyhanni.events.LorenzChatEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.DelayedRun
+import at.hannibal2.skyhanni.utils.ItemUtils.cleanName
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull
+import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull
+import at.hannibal2.skyhanni.utils.ItemUtils.name
+import at.hannibal2.skyhanni.utils.LorenzColor
+import at.hannibal2.skyhanni.utils.LorenzRarity
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.NumberUtil.toStringWithPlus
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.RenderUtils
+import at.hannibal2.skyhanni.utils.RenderUtils.drawSlotText
+import at.hannibal2.skyhanni.utils.RenderUtils.highlight
+import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getReforgeName
+import at.hannibal2.skyhanni.utils.SoundUtils
+import at.hannibal2.skyhanni.utils.TimeUtils.ticks
+import at.hannibal2.skyhanni.utils.renderables.Renderable
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.client.Minecraft
+import net.minecraft.init.Items
+import net.minecraft.inventory.Container
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.awt.Color
+import java.util.concurrent.atomic.AtomicBoolean
+import at.hannibal2.skyhanni.utils.renderables.Renderable.Companion.string as renderableString
+
+@SkyHanniModule
+object ReforgeHelper {
+
+ private val config get() = SkyHanniMod.feature.inventory.helper.reforge
+
+ private val repoGroup = RepoPattern.group("reforge")
+
+ private val reforgeMenu by repoGroup.pattern(
+ "menu.blacksmith",
+ "Reforge Item",
+ )
+ private val reforgeHexMenu by repoGroup.pattern(
+ "menu.hex",
+ "The Hex ➜ Reforges",
+ )
+ private val reforgeChatMessage by repoGroup.pattern(
+ "chat.success",
+ "§aYou reforged your .* §r§ainto a .*!|§aYou applied a .* §r§ato your .*!",
+ )
+ private val reforgeChatFail by repoGroup.pattern(
+ "chat.fail",
+ "§cWait a moment before reforging again!|§cWhoa! Slow down there!",
+ )
+
+ private var isInReforgeMenu = false
+ private var isInHexReforgeMenu = false
+
+ private fun isReforgeMenu(chestName: String) = reforgeMenu.matches(chestName)
+ private fun isHexReforgeMenu(chestName: String) = reforgeHexMenu.matches(chestName)
+
+ private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled && isInReforgeMenu
+
+ private var itemToReforge: ItemStack? = null
+ private var inventoryContainer: Container? = null
+
+ private var currentReforge: ReforgeAPI.Reforge? = null
+ private var reforgeToSearch: ReforgeAPI.Reforge? = null
+
+ private var hoveredReforge: ReforgeAPI.Reforge? = null
+
+ private val reforgeItem get() = if (isInHexReforgeMenu) 19 else 13
+ private val reforgeButton get() = if (isInHexReforgeMenu) 48 else 22
+
+ private const val HEX_REFORGE_NEXT_DOWN_BUTTON = 35
+ private const val HEX_REFORGE_NEXT_UP_BUTTON = 17
+
+ private const val EXIT_BUTTON = 40
+
+ private var waitForChat = AtomicBoolean(false)
+
+ /** Gatekeeps instant double switches of the state */
+ private var waitDelay = false
+
+ private var sortAfter: SkyblockStat? = null
+
+ private var display: List<Renderable> = generateDisplay()
+
+ private val hoverColor = LorenzColor.GOLD.addOpacity(50)
+ private val selectedColor = LorenzColor.BLUE.addOpacity(100)
+ private val finishedColor = LorenzColor.GREEN.addOpacity(75)
+
+ private fun itemUpdate() {
+ val newItem = inventoryContainer?.getSlot(reforgeItem)?.stack
+ if (newItem?.getInternalName() != itemToReforge?.getInternalName()) {
+ reforgeToSearch = null
+ }
+ itemToReforge = newItem
+ val newReforgeName = itemToReforge?.getReforgeName() ?: ""
+ if (newReforgeName == currentReforge?.lowercaseName) return
+ currentReforge = ReforgeAPI.reforgeList.firstOrNull { it.lowercaseName == newReforgeName }
+ updateDisplay()
+ }
+
+ @SubscribeEvent
+ fun onClick(event: GuiContainerEvent.SlotClickEvent) {
+ if (!isEnabled()) return
+ if (event.slot?.slotNumber == reforgeButton) {
+ if (event.slot.stack?.name == "§eReforge Item" || event.slot.stack?.name == "§cError!") return
+ if (handleReforgeButtonClick(event)) return
+ }
+
+ DelayedRun.runNextTick {
+ itemUpdate()
+ }
+ }
+
+ private fun handleReforgeButtonClick(event: GuiContainerEvent.SlotClickEvent): Boolean {
+ if (currentReforge == reforgeToSearch) {
+ event.cancel()
+ waitForChat.set(false)
+ SoundUtils.playBeepSound()
+ } else if (waitForChat.get()) {
+ waitDelay = true
+ event.cancel()
+ } else {
+ if (event.clickedButton == 2) return true
+ if (waitDelay) {
+ waitDelay = false
+ } else {
+ waitForChat.set(true)
+ }
+ }
+ return false
+ }
+
+ @SubscribeEvent
+ fun onChat(event: LorenzChatEvent) {
+ if (!isEnabled()) return
+ when {
+ reforgeChatMessage.matches(event.message) -> {
+ DelayedRun.runDelayed(2.ticks) {
+ itemUpdate()
+ waitForChat.set(false)
+ }
+ if (config?.hideChat == true) {
+ event.blockedReason = "reforge_hide"
+ }
+ }
+
+ reforgeChatFail.matches(event.message) -> {
+ DelayedRun.runDelayed(2.ticks) {
+ waitForChat.set(false)
+ }
+ if (config?.hideChat == true) {
+ event.blockedReason = "reforge_hide"
+ }
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onOpen(event: InventoryFullyOpenedEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ when {
+ isHexReforgeMenu(event.inventoryName) -> {
+ isInHexReforgeMenu = true
+ DelayedRun.runDelayed(2.ticks) {
+ itemUpdate() // update since an item must already be in place
+ }
+ }
+
+ isReforgeMenu(event.inventoryName) -> {
+ itemToReforge = null
+ currentReforge = null
+ }
+
+ else -> return
+ }
+ isInReforgeMenu = true
+ waitForChat.set(false)
+ DelayedRun.runNextTick {
+ inventoryContainer = Minecraft.getMinecraft().thePlayer.openContainer
+ }
+ }
+
+ @SubscribeEvent
+ fun onClose(event: InventoryCloseEvent) {
+ if (!isInReforgeMenu) return
+ isInReforgeMenu = false
+ isInHexReforgeMenu = false
+ reforgeToSearch = null
+ currentReforge = null
+ hoveredReforge = null
+ sortAfter = null
+ itemToReforge = null
+ display = emptyList()
+ }
+
+ private fun updateDisplay() {
+ display = generateDisplay()
+ }
+
+ private fun generateDisplay() = buildList<Renderable> {
+ this.add(renderableString("§6Reforge Overlay"))
+
+ val item = itemToReforge ?: run {
+ reforgeToSearch = null
+ return@buildList
+ }
+
+ val internalName = item.getInternalName()
+ val itemType = item.getItemCategoryOrNull()
+ val itemRarity = item.getItemRarityOrNull() ?: return@buildList
+
+ val rawReforgeList =
+ if (!isInHexReforgeMenu && config.reforgeStonesOnlyHex) ReforgeAPI.nonePowerStoneReforge else ReforgeAPI.reforgeList
+ val reforgeList = rawReforgeList.filter { it.isValid(itemType, internalName) }
+
+ val statTypes = reforgeList.mapNotNull { it.stats[itemRarity]?.keys }.flatten().toSet()
+
+ val statTypeButtons = (listOf(getStatButton(null)) + statTypes.map { getStatButton(it) }).chunked(9)
+ this.add(Renderable.table(statTypeButtons, xPadding = 3, yPadding = 2))
+
+ val list = reforgeList.sortedWith(getSortSelector(itemRarity, sortAfter)).map(getReforgeView(itemRarity))
+ this.addAll(list)
+ }
+
+ private fun getReforgeColour(reforge: ReforgeAPI.Reforge) = when {
+ currentReforge == reforge -> "§6"
+ reforgeToSearch == reforge -> "§3"
+ reforge.isReforgeStone -> "§9"
+ else -> "§7"
+ }
+
+ private fun getReforgeView(itemRarity: LorenzRarity): (ReforgeAPI.Reforge) -> Renderable = { reforge ->
+ val text = getReforgeColour(reforge) + reforge.name
+ val tips = getReforgeTips(reforge, itemRarity)
+ val onHover = if (!isInHexReforgeMenu) {
+ {}
+ } else {
+ { hoveredReforge = reforge }
+ }
+
+ Renderable.clickAndHover(
+ text, tips,
+ onClick = {
+ SoundUtils.playClickSound()
+ reforgeToSearch = reforge
+ updateDisplay()
+ },
+ onHover = onHover,
+ )
+ }
+
+ private fun getReforgeTips(
+ reforge: ReforgeAPI.Reforge,
+ itemRarity: LorenzRarity,
+ ): List<Renderable> {
+ val stats: List<Renderable>
+ val removedEffect: List<Renderable>
+ val addEffectText: String
+ val click: List<Renderable>
+ if (currentReforge == reforge) {
+ stats = currentReforge?.stats?.get(itemRarity)?.print() ?: emptyList()
+ removedEffect = emptyList()
+ addEffectText = "§aEffect:"
+ click = listOf(renderableString(""), renderableString("§3Reforge is currently applied!"))
+ } else {
+ stats = reforge.stats[itemRarity]?.print(currentReforge?.stats?.get(itemRarity)) ?: emptyList()
+ removedEffect = getReforgeEffect(
+ currentReforge,
+ itemRarity,
+ )?.let { listOf(renderableString("§cRemoves Effect:")) + it }?.takeIf { config.showDiff } ?: emptyList()
+ addEffectText = "§aAdds Effect:"
+ click = if (reforgeToSearch != reforge) {
+ listOf(renderableString(""), renderableString("§eClick to select!"))
+ } else emptyList()
+ }
+
+ val addedEffect = getReforgeEffect(reforge, itemRarity)?.let { listOf(renderableString(addEffectText)) + it } ?: emptyList()
+
+ return listOf(renderableString("§6Reforge Stats")) + stats + removedEffect + addedEffect + click
+ }
+
+ private fun getReforgeEffect(reforge: ReforgeAPI.Reforge?, rarity: LorenzRarity) =
+ reforge?.extraProperty?.get(rarity)?.let {
+ Renderable.wrappedString(
+ it,
+ 190,
+ color = LorenzColor.GRAY.toColor(),
+ )
+ }
+
+ private fun getSortSelector(
+ itemRarity: LorenzRarity,
+ sorting: SkyblockStat?,
+ ): Comparator<ReforgeAPI.Reforge> =
+ if (sorting != null) {
+ Comparator.comparing<ReforgeAPI.Reforge, Double> { it.stats[itemRarity]?.get(sorting) ?: 0.0 }.reversed()
+ } else {
+ Comparator.comparing { it.isReforgeStone }
+ }
+
+ private fun getStatButton(stat: SkyblockStat?): Renderable {
+ val icon: String
+ val tip: String
+ if (stat == null) {
+ icon = "§7D"
+ tip = "§7Default"
+ } else {
+ icon = stat.icon
+ tip = stat.iconWithName
+ }
+
+ val alreadySelected = sortAfter == stat
+ val fieldColor = if (alreadySelected) LorenzColor.GRAY else LorenzColor.DARK_GRAY
+
+
+ val tips = if (alreadySelected) {
+ listOf("§6Sort by", tip)
+ } else {
+ listOf("§6Sort by", tip, "", "§eClick to apply sorting!")
+ }
+ val sortField =
+ Renderable.drawInsideRoundedRect(
+ Renderable.hoverTips(
+ Renderable.fixedSizeLine(
+ renderableString(icon, horizontalAlign = RenderUtils.HorizontalAlignment.CENTER),
+ SkyblockStat.fontSizeOfLargestIcon,
+ ),
+ tips,
+ ),
+ fieldColor.toColor(), radius = 15, padding = 1,
+ )
+ return if (alreadySelected) {
+ sortField
+ } else {
+ Renderable.clickable(
+ sortField,
+ {
+ sortAfter = stat
+ updateDisplay()
+ },
+ )
+ }
+ }
+
+ @SubscribeEvent
+ fun onRender(event: GuiRenderEvent.ChestGuiOverlayRenderEvent) {
+ if (!isEnabled()) return
+ config.position.renderRenderables(display, posLabel = "Reforge Overlay")
+ }
+
+ @SubscribeEvent
+ fun onForegroundDrawn(event: GuiContainerEvent.ForegroundDrawnEvent) {
+ if (!isEnabled()) return
+ if (currentReforge == null) return
+
+ inventoryContainer?.getSlot(reforgeItem)?.let {
+ event.drawSlotText(it.xDisplayPosition - 5, it.yDisplayPosition, "§e${currentReforge?.name}", 1f)
+ }
+ }
+
+ @SubscribeEvent
+ fun onGuiContainerBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) {
+ if (hoveredReforge != null && isInHexReforgeMenu) {
+ if (hoveredReforge != currentReforge) {
+ colorReforgeStone(hoverColor, hoveredReforge?.rawReforgeStoneName ?: "Random Basic Reforge")
+ } else {
+ inventoryContainer?.getSlot(reforgeItem)?.highlight(hoverColor)
+
+ //?.get(reforgeItem)?. = hoverColor
+ }
+ hoveredReforge = null
+ }
+
+ if (reforgeToSearch == null) return
+ if (reforgeToSearch != currentReforge) {
+ colorSelected()
+ } else {
+ inventoryContainer?.getSlot(reforgeItem)?.highlight(finishedColor)
+ }
+ }
+
+ private fun colorSelected() = if (reforgeToSearch?.isReforgeStone == true) {
+ if (isInHexReforgeMenu) {
+ colorReforgeStone(selectedColor, reforgeToSearch?.rawReforgeStoneName)
+ } else {
+ inventoryContainer?.getSlot(EXIT_BUTTON)?.highlight(selectedColor)
+ }
+ } else {
+ inventoryContainer?.getSlot(reforgeButton)?.highlight(selectedColor)
+ }
+
+ private fun colorReforgeStone(color: Color, reforgeStone: String?) {
+ val inventory = inventoryContainer?.inventorySlots ?: return
+ val slot = inventory.firstOrNull { it?.stack?.cleanName() == reforgeStone }
+ if (slot != null) {
+ slot highlight color
+ } else {
+ inventory[HEX_REFORGE_NEXT_DOWN_BUTTON]?.takeIf { it.stack.item == Items.skull }?.highlight(color)
+ inventory[HEX_REFORGE_NEXT_UP_BUTTON]?.takeIf { it.stack.item == Items.skull }?.highlight(color)
+ }
+ }
+
+ private fun SkyblockStatList.print(appliedReforge: SkyblockStatList? = null): List<Renderable> {
+ val diff = appliedReforge?.takeIf { config.showDiff }?.let { this - it }
+ val main = ((diff ?: this).mapNotNull {
+ val key = it.key
+ val value = this[key] ?: 0.0
+ buildList<Renderable> {
+ add(renderableString("§9${value.toStringWithPlus().removeSuffix(".0")}"))
+ diff?.get(key)?.let { add(renderableString((if (it < 0) "§c" else "§a") + it.toStringWithPlus().removeSuffix(".0"))) }
+ add(renderableString(key.iconWithName))
+ }
+ })
+ val table = Renderable.table(main, 5)
+ return listOf(table)
+ }
+}
+
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 724583e20..dee0a6749 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
@@ -4,7 +4,6 @@ import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.api.event.HandleEvent
import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.data.jsonobjects.repo.ItemsJson
-import at.hannibal2.skyhanni.data.jsonobjects.repo.neu.NeuReforgeStoneJson
import at.hannibal2.skyhanni.events.ConfigLoadEvent
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.InventoryCloseEvent
@@ -45,7 +44,6 @@ object EstimatedItemValue {
private val cache = mutableMapOf<ItemStack, List<List<Any>>>()
private var lastToolTipTime = 0L
var gemstoneUnlockCosts = HashMap<NEUInternalName, HashMap<String, List<String>>>()
- var reforges = mapOf<NEUInternalName, NeuReforgeStoneJson>()
var bookBundleAmount = mapOf<String, Int>()
private var currentlyShowing = false
@@ -55,8 +53,6 @@ object EstimatedItemValue {
fun onNeuRepoReload(event: NeuRepositoryReloadEvent) {
gemstoneUnlockCosts =
event.readConstant<HashMap<NEUInternalName, HashMap<String, List<String>>>>("gemstonecosts")
- reforges =
- event.readConstant<Map<NEUInternalName, NeuReforgeStoneJson>>("reforgestones")
}
@SubscribeEvent
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 e1619ad92..05d53fa65 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
@@ -1,6 +1,7 @@
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.sortedDesc
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
@@ -130,7 +131,7 @@ object EstimatedItemValueCalculator {
)
if (price != null) {
val name = attributes[0].first.fixMending().allLettersFirstUppercase()
- list.add("§7Attribute §9$name ${attributes[0].second}§7: (§6${price.shortFormat()}§7)",)
+ list.add("§7Attribute §9$name ${attributes[0].second}§7: (§6${price.shortFormat()}§7)")
return price
}
}
@@ -214,15 +215,15 @@ object EstimatedItemValueCalculator {
private fun addReforgeStone(stack: ItemStack, list: MutableList<String>): Double {
val rawReforgeName = stack.getReforgeName() ?: return 0.0
- val reforge = EstimatedItemValue.reforges.values.firstOrNull {
- rawReforgeName == it.reforgeName.lowercase() || rawReforgeName == it.internalName.asString().lowercase()
+ val reforge = ReforgeAPI.onlyPowerStoneReforge.firstOrNull {
+ rawReforgeName == it.lowercaseName || rawReforgeName == it.reforgeStone?.asString()?.lowercase()
} ?: return 0.0
- val internalName = reforge.internalName.asString().asInternalName()
+ val internalName = reforge.reforgeStone ?: return 0.0
val reforgeStonePrice = internalName.getPrice()
val reforgeStoneName = internalName.itemName
- val applyCost = getReforgeStoneApplyCost(stack, reforge.reforgeCosts, internalName) ?: return 0.0
+ val applyCost = reforge.costs?.let { getReforgeStoneApplyCost(stack, it, internalName) } ?: return 0.0
- list.add("§7Reforge: §9${reforge.reforgeName}")
+ list.add("§7Reforge: §9${reforge.name}")
list.add(" §7Stone $reforgeStoneName §7(§6" + reforgeStonePrice.shortFormat() + "§7)")
list.add(" §7Apply cost: (§6" + applyCost.shortFormat() + "§7)")
return reforgeStonePrice + applyCost
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
index bb2d3fd3e..4b334d027 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
@@ -42,6 +42,7 @@ import net.minecraft.client.renderer.GlStateManager
import net.minecraft.client.renderer.RenderHelper
import net.minecraft.init.Blocks
import net.minecraft.init.Items
+import net.minecraft.item.Item
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@@ -54,35 +55,39 @@ object NEUItems {
private val multiplierCache = mutableMapOf<NEUInternalName, PrimitiveItemStack>()
private val recipesCache = mutableMapOf<NEUInternalName, Set<NeuRecipe>>()
private val ingredientsCache = mutableMapOf<NeuRecipe, Set<Ingredient>>()
+ private val itemIdCache = mutableMapOf<Item, List<NEUInternalName>>()
private val hypixelApiGson by lazy {
BaseGsonBuilder.gson()
- .registerTypeAdapter(HypixelApiTrophyFish::class.java, object : TypeAdapter<HypixelApiTrophyFish>() {
- override fun write(out: JsonWriter, value: HypixelApiTrophyFish) {}
-
- override fun read(reader: JsonReader): HypixelApiTrophyFish {
- val trophyFish = mutableMapOf<String, Int>()
- var totalCaught = 0
- reader.beginObject()
- while (reader.hasNext()) {
- val key = reader.nextName()
- if (key == "total_caught") {
- totalCaught = reader.nextInt()
- continue
- }
- if (reader.peek() == JsonToken.NUMBER) {
- val valueAsString = reader.nextString()
- if (valueAsString.isInt()) {
- trophyFish[key] = valueAsString.toInt()
+ .registerTypeAdapter(
+ HypixelApiTrophyFish::class.java,
+ object : TypeAdapter<HypixelApiTrophyFish>() {
+ override fun write(out: JsonWriter, value: HypixelApiTrophyFish) {}
+
+ override fun read(reader: JsonReader): HypixelApiTrophyFish {
+ val trophyFish = mutableMapOf<String, Int>()
+ var totalCaught = 0
+ reader.beginObject()
+ while (reader.hasNext()) {
+ val key = reader.nextName()
+ if (key == "total_caught") {
+ totalCaught = reader.nextInt()
continue
}
+ if (reader.peek() == JsonToken.NUMBER) {
+ val valueAsString = reader.nextString()
+ if (valueAsString.isInt()) {
+ trophyFish[key] = valueAsString.toInt()
+ continue
+ }
+ }
+ reader.skipValue()
}
- reader.skipValue()
+ reader.endObject()
+ return HypixelApiTrophyFish(totalCaught, trophyFish)
}
- reader.endObject()
- return HypixelApiTrophyFish(totalCaught, trophyFish)
- }
- }.nullSafe())
+ }.nullSafe(),
+ )
.create()
}
@@ -94,7 +99,7 @@ object NEUItems {
Utils.createItemStack(
ItemStack(Blocks.barrier).item,
"§cMissing Repo Item",
- "§cYour NEU repo seems to be out of date"
+ "§cYour NEU repo seems to be out of date",
)
}
@@ -119,7 +124,7 @@ object NEUItems {
} catch (e: Exception) {
ErrorManager.logErrorWithData(
e, "Error reading hypixel player api data",
- "data" to apiData
+ "data" to apiData,
)
}
}
@@ -210,7 +215,7 @@ object NEUItems {
"This may be because your NEU repo is outdated. Please ask in the SkyHanni " +
"Discord if this is the case.",
"Item name" to this.asString(),
- "repo commit" to manager.latestRepoCommit
+ "repo commit" to manager.latestRepoCommit,
)
fallbackItem
}
@@ -225,7 +230,7 @@ object NEUItems {
x: Float,
y: Float,
scaleMultiplier: Double = itemFontSize,
- rescaleSkulls: Boolean = true
+ rescaleSkulls: Boolean = true,
) {
val item = checkBlinkItem()
val isSkull = rescaleSkulls && item.item === Items.skull
@@ -281,13 +286,24 @@ object NEUItems {
fun allNeuRepoItems(): Map<String, JsonObject> = NotEnoughUpdates.INSTANCE.manager.itemInformation
+ fun getInternalNamesForItemId(item: Item): List<NEUInternalName> {
+ itemIdCache[item]?.let {
+ return it
+ }
+ val result = allNeuRepoItems()
+ .filter { Item.getByNameOrId(it.value.get("itemid").asString) == item }
+ .keys.map { it.asInternalName() }
+ itemIdCache[item] = result
+ return result
+ }
+
fun getPrimitiveMultiplier(internalName: NEUInternalName, tryCount: Int = 0): PrimitiveItemStack {
multiplierCache[internalName]?.let { return it }
if (tryCount == 10) {
ErrorManager.logErrorStateWithData(
"Could not load recipe data.",
"Failed to find item multiplier",
- "internalName" to internalName
+ "internalName" to internalName,
)
return internalName.makePrimitiveStack()
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt b/src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt
index 1ee34699c..b97298ce4 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/NumberUtil.kt
@@ -33,7 +33,7 @@ object NumberUtil {
5 to "V",
4 to "IV",
1 to "I",
- )
+ ),
)
@Deprecated("outdated", ReplaceWith("value.shortFormat(preciseBillions)"))
@@ -170,6 +170,8 @@ object NumberUtil {
} else romanSymbols[l] + (this - l).toRoman()
}
+ fun Number.toStringWithPlus() = (if (this.toDouble() >= 0.0) "+" else "") + this.toString()
+
private fun processDecimal(decimal: Int, lastNumber: Int, lastDecimal: Int) = if (lastNumber > decimal) {
lastDecimal - decimal
} else {
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt b/src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt
index dc50eef74..7859853ca 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/json/SkyHanniTypeAdapters.kt
@@ -1,6 +1,7 @@
package at.hannibal2.skyhanni.utils.json
import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.data.model.SkyblockStat
import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity
import at.hannibal2.skyhanni.features.garden.CropType
import at.hannibal2.skyhanni.features.garden.pests.PestType
@@ -24,22 +25,22 @@ object SkyHanniTypeAdapters {
val UUID: TypeAdapter<UUID> = SimpleStringTypeAdapter(
{ this.toString() },
- { java.util.UUID.fromString(this) }
+ { java.util.UUID.fromString(this) },
)
val INTERNAL_NAME: TypeAdapter<NEUInternalName> = SimpleStringTypeAdapter(
{ this.asString() },
- { this.asInternalName() }
+ { this.asInternalName() },
)
val VEC_STRING: TypeAdapter<LorenzVec> = SimpleStringTypeAdapter(
{ "$x:$y:$z" },
- { LorenzVec.decodeFromString(this) }
+ { LorenzVec.decodeFromString(this) },
)
val TROPHY_RARITY: TypeAdapter<TrophyRarity> = SimpleStringTypeAdapter(
{ name },
- { TrophyRarity.getByName(this) ?: error("Could not parse TrophyRarity from '$this'") }
+ { TrophyRarity.getByName(this) ?: error("Could not parse TrophyRarity from '$this'") },
)
val TIME_MARK: TypeAdapter<SimpleTimeMark> = object : TypeAdapter<SimpleTimeMark>() {
@@ -54,12 +55,17 @@ object SkyHanniTypeAdapters {
val CROP_TYPE: TypeAdapter<CropType> = SimpleStringTypeAdapter(
{ name },
- { CropType.getByName(this) }
+ { CropType.getByName(this) },
)
val PEST_TYPE: TypeAdapter<PestType> = SimpleStringTypeAdapter(
{ name },
- { PestType.getByName(this) }
+ { PestType.getByName(this) },
+ )
+
+ val SKYBLOCK_STAT: TypeAdapter<SkyblockStat> = SimpleStringTypeAdapter(
+ { name.lowercase() },
+ { SkyblockStat.valueOf(this.uppercase()) },
)
val TRACKER_DISPLAY_MODE = SimpleStringTypeAdapter.forEnum<SkyHanniTracker.DefaultDisplayMode>()
@@ -70,10 +76,13 @@ object SkyHanniTypeAdapters {
crossinline write: (JsonWriter, T) -> Unit,
crossinline read: (JsonReader) -> T,
): GsonBuilder {
- this.registerTypeAdapter(T::class.java, object : TypeAdapter<T>() {
- override fun write(out: JsonWriter, value: T) = write(out, value)
- override fun read(reader: JsonReader) = read(reader)
- }.nullSafe())
+ this.registerTypeAdapter(
+ T::class.java,
+ object : TypeAdapter<T>() {
+ override fun write(out: JsonWriter, value: T) = write(out, value)
+ override fun read(reader: JsonReader) = read(reader)
+ }.nullSafe(),
+ )
return this
}
}