aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/AttributeOverlayConfig.java58
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/AttributeGoodRollsJson.kt13
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/attribute/AttributeAPI.kt100
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/inventory/attribute/AttributeOverlay.kt60
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt7
6 files changed, 243 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/AttributeOverlayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/AttributeOverlayConfig.java
new file mode 100644
index 000000000..2761f7461
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/AttributeOverlayConfig.java
@@ -0,0 +1,58 @@
+package at.hannibal2.skyhanni.config.features.inventory;
+
+import at.hannibal2.skyhanni.config.FeatureToggle;
+import at.hannibal2.skyhanni.features.inventory.attribute.AttributeAPI;
+import com.google.gson.annotations.Expose;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider;
+import io.github.notenoughupdates.moulconfig.annotations.ConfigOption;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AttributeOverlayConfig {
+
+ @Expose
+ @ConfigOption(name = "Enabled", desc = "Show the attribute name and level on the item.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean enabled = false;
+
+ // TODO: add way of making config options with data classes from repo
+ @Expose
+ @ConfigOption(name = "Attributes Shown", desc = "List of attributes shown.")
+ @ConfigEditorDraggableList
+ public List<AttributeAPI.AttributeType> attributesList = new ArrayList<>(AttributeAPI.AttributeType.getEntries());
+
+ @Expose
+ @ConfigOption(
+ name = "Min Level",
+ desc = "Minimum level to show the attributes of."
+ )
+ @ConfigEditorSlider(minValue = 1, maxValue = 10, minStep = 1)
+ public int minimumLevel = 1;
+
+ @Expose
+ @ConfigOption(
+ name = "Highlight Good Rolls",
+ desc = "Highlights Good attribute combinations.\n" +
+ "§cNote: These are subjective and ever changing. If you\n" +
+ "§c want to suggest changes, please do so in the discord."
+ )
+ @ConfigEditorBoolean
+ public boolean highlightGoodRolls = true;
+
+ @Expose
+ @ConfigOption(
+ name = "Good Rolls Override Level",
+ desc = "Makes it so that Good Rolls are always shown no matter the attribute level."
+ )
+ @ConfigEditorBoolean
+ public boolean goodRollsOverrideLevel = true;
+
+ @Expose
+ @ConfigOption(name = "Hide non Good Rolls", desc = "Hides attributes that are not considered good rolls.")
+ @ConfigEditorBoolean
+ public boolean hideNonGoodRolls = false;
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
index c0a51a979..608fac71c 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
@@ -140,6 +140,11 @@ public class InventoryConfig {
public MagicalPowerConfig magicalPower = new MagicalPowerConfig();
@Expose
+ @ConfigOption(name = "Attribute Overlay", desc = "")
+ @Accordion
+ public AttributeOverlayConfig attributeOverlay = new AttributeOverlayConfig();
+
+ @Expose
@ConfigOption(name = "Item Number", desc = "Showing the item number as a stack size for these items.")
@ConfigEditorDraggableList
public List<ItemNumberEntry> itemNumberAsStackSize = new ArrayList<>(Arrays.asList(
diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/AttributeGoodRollsJson.kt b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/AttributeGoodRollsJson.kt
new file mode 100644
index 000000000..0e16db883
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/AttributeGoodRollsJson.kt
@@ -0,0 +1,13 @@
+package at.hannibal2.skyhanni.data.jsonobjects.repo
+
+import com.google.gson.annotations.Expose
+import com.google.gson.annotations.SerializedName
+
+data class AttributeGoodRollsJson(
+ @Expose @SerializedName("good_rolls") val goodRolls: Map<String, ItemRoll>,
+)
+
+data class ItemRoll(
+ @Expose val regex: String,
+ @Expose val list: List<List<String>>,
+)
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/attribute/AttributeAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/attribute/AttributeAPI.kt
new file mode 100644
index 000000000..f1711f256
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/attribute/AttributeAPI.kt
@@ -0,0 +1,100 @@
+package at.hannibal2.skyhanni.features.inventory.attribute
+
+import at.hannibal2.skyhanni.data.jsonobjects.repo.AttributeGoodRollsJson
+import at.hannibal2.skyhanni.events.RepositoryReloadEvent
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.CollectionUtils.equalsIgnoreOrder
+import at.hannibal2.skyhanni.utils.CollectionUtils.toPair
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.RegexUtils.matches
+import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getAttributes
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.util.regex.Pattern
+
+@SkyHanniModule
+object AttributeAPI {
+
+ private var goodRolls = listOf<GoodRollItem>()
+
+ enum class AttributeType(val displayName: String, val internalName: String, val shortName: String) {
+ ARACHNO("Arachno", "arachno", "AR"),
+ ATTACK_SPEED("Attack Speed", "attack_speed", "AS"),
+ BLAZING("Blazing", "blazing", "BL"),
+ COMBO("Combo", "combo", "CO"),
+ ELITE("Elite", "elite", "EL"),
+ ENDER("Ender", "ender", "EN"),
+ IGNITION("Ignition", "ignition", "IG"),
+ LIFE_RECOVERY("Life Recovery", "life_recovery", "LR"),
+ MANA_STEAL("Mana Steal", "mana_steal", "MS"),
+ MIDAS_TOUCH("Midas Touch", "midas_touch", "MT"),
+ UNDEAD("Undead", "undead", "UN"),
+ WARRIOR("Warrior", "warrior", "WA"),
+ DEADEYE("Deadeye", "deadeye", "DE"),
+ ARACHNO_RESISTANCE("Arachno Resistance", "arachno_resistance", "AR"),
+ BLAZING_RESISTANCE("Blazing Resistance", "blazing_resistance", "BR"),
+ BREEZE("Breeze", "breeze", "BZ"),
+ DOMINANCE("Dominance", "dominance", "DO"),
+ ENDER_RESISTANCE("Ender Resistance", "ender_resistance", "ER"),
+ EXPERIENCE("Experience", "experience", "EX"),
+ FORTITUDE("Fortitude", "fortitude", "FO"),
+ LIFE_REGENERATION("Life Regeneration", "life_regeneration", "LR"),
+ LIFELINE("Lifeline", "lifeline", "LL"),
+ MAGIC_FIND("Magic Find", "magic_find", "MF"),
+ MANA_POOL("Mana Pool", "mana_pool", "MP"),
+ MANA_REGENERATION("Mana Regeneration", "mana_regeneration", "MR"),
+ VITALITY("Vitality", "mending", "VI"),
+ SPEED("Speed", "speed", "SP"),
+ UNDEAD_RESISTANCE("Undead Resistance", "undead_resistance", "UR"),
+ VETERAN("Veteran", "veteran", "VE"),
+ BLAZING_FORTUNE("Blazing Fortune", "blazing_fortune", "BF"),
+ FISHING_EXPERIENCE("Fishing Experience", "fishing_experience", "FE"),
+ INFECTION("Infection", "infection", "IN"),
+ DOUBLE_HOOK("Double Hook", "double_hook", "DH"),
+ FISHERMAN("Fisherman", "fisherman", "FH"),
+ FISHING_SPEED("Fishing Speed", "fishing_speed", "FS"),
+ HUNTER("Hunter", "hunter", "HU"),
+ TROPHY_HUNTER("Trophy Hunter", "trophy_hunter", "TH"),
+ UNKNOWN("Unknown", "unknown", "??"),
+ ;
+
+ override fun toString() = "§b$displayName"
+
+ companion object {
+
+ fun getByInternalNameOrNull(internalName: String) = entries.find { it.internalName == internalName }
+
+ fun getByInternalName(internalName: String) = getByInternalNameOrNull(internalName) ?: UNKNOWN
+ }
+ }
+
+ data class Attribute(val type: AttributeType, val level: Int)
+
+ private data class GoodRollItem(val regex: Pattern, val attributes: List<Pair<AttributeType, AttributeType>>)
+
+ @SubscribeEvent
+ fun onRepoReload(event: RepositoryReloadEvent) {
+ val data = event.getConstant<AttributeGoodRollsJson>("AttributeGoodRolls")
+ goodRolls = data.goodRolls.values.map {
+ val regex = it.regex.toPattern()
+ val list = it.list.map { combo ->
+ val first = AttributeType.getByInternalName(combo[0])
+ val second = AttributeType.getByInternalName(combo[1])
+ first to second
+ }
+ GoodRollItem(regex, list)
+ }
+ }
+
+ fun ItemStack.getAttributesLevels(): Pair<Attribute, Attribute>? =
+ getAttributes()?.takeIf { it.isNotEmpty() }?.mapNotNull { (name, level) ->
+ AttributeType.getByInternalNameOrNull(name.lowercase())?.let { Attribute(it, level) }
+ }?.toPair()
+
+ fun Pair<Attribute, Attribute>.isGoodRoll(internalName: NEUInternalName): Boolean =
+ goodRolls.firstOrNull { it.regex.matches(internalName.asString()) }?.let { goodRoll ->
+ val attributes = first.type to second.type
+ goodRoll.attributes.any { it.equalsIgnoreOrder(attributes) }
+ } ?: false
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/attribute/AttributeOverlay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/attribute/AttributeOverlay.kt
new file mode 100644
index 000000000..2787c98d1
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/attribute/AttributeOverlay.kt
@@ -0,0 +1,60 @@
+package at.hannibal2.skyhanni.features.inventory.attribute
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.GuiRenderItemEvent
+import at.hannibal2.skyhanni.features.inventory.attribute.AttributeAPI.getAttributesLevels
+import at.hannibal2.skyhanni.features.inventory.attribute.AttributeAPI.isGoodRoll
+import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.RenderUtils.drawSlotText
+import at.hannibal2.skyhanni.utils.StringUtils.width
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+@SkyHanniModule
+object AttributeOverlay {
+
+ private const val SCALE = 0.5714286f
+
+ private val config get() = SkyHanniMod.feature.inventory.attributeOverlay
+
+ @SubscribeEvent
+ fun onRenderItemOverlayPost(event: GuiRenderItemEvent.RenderOverlayEvent.GuiRenderItemPost) {
+ if (!isEnabled()) return
+
+ val stack = event.stack ?: return
+ val attributes = stack.getAttributesLevels() ?: return
+ val internalName = stack.getInternalNameOrNull() ?: return
+
+ val isGoodRoll = attributes.isGoodRoll(internalName)
+ attributes.toList().filter { (attr, level) ->
+ val inConfig = attr in config.attributesList
+ val isLevel = level >= config.minimumLevel
+ val goodRoll = !config.hideNonGoodRolls || isGoodRoll
+ inConfig && goodRoll && (!config.goodRollsOverrideLevel || isLevel)
+ }.forEachIndexed { index, attribute ->
+ event.drawAttribute(attribute, isGoodRoll && config.highlightGoodRolls, index)
+ }
+ }
+
+ private fun GuiRenderItemEvent.RenderOverlayEvent.GuiRenderItemPost.drawAttribute(
+ attribute: AttributeAPI.Attribute,
+ goodRoll: Boolean,
+ index: Int,
+ ) {
+ val color = if (goodRoll) "§e" else "§b"
+ val attributeString = color + attribute.type.shortName
+ val attributeWidth = attributeString.width()
+ val attributeX = x + attributeWidth + (if (index == 1) 16 - attributeWidth * SCALE else 0).toInt()
+ val attributeY = y
+ drawSlotText(attributeX, attributeY, attributeString, SCALE)
+
+ val levelString = "§a${attribute.level}"
+ val levelWidth = levelString.width()
+ val levelX = x + levelWidth + (if (index == 1) 16 - levelWidth * SCALE else 0).toInt()
+ val levelY = y + (10 * SCALE).toInt()
+ drawSlotText(levelX, levelY, levelString, SCALE)
+ }
+
+ private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt
index 860a6a3d6..fd3cadd4b 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt
@@ -273,6 +273,13 @@ object CollectionUtils {
fun <T> Collection<T>.takeIfNotEmpty(): Collection<T>? = takeIf { it.isNotEmpty() }
+
+ fun <T> List<T>.toPair(): Pair<T, T>? = if (size == 2) this[0] to this[1] else null
+
+ fun <T> Pair<T, T>.equalsIgnoreOrder(other: Pair<T, T>): Boolean = toSet() == other.toSet()
+
+ fun <T> Pair<T, T>.toSet(): Set<T> = setOf(first, second)
+
// TODO add cache
fun MutableList<Renderable>.addString(
text: String,