diff --git a/gradle.properties b/gradle.properties index 6510f6b..f407125 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ mod_name = Rat-ons mod_id = ratons mod_version = 0.1 -skyhanni_version = 0.27.Beta.12 +skyhanni_version = 0.27.Beta.15 loom.platform=forge org.gradle.jvmargs=-Xmx4g diff --git a/src/main/kotlin/com/ratons/Ratons.kt b/src/main/kotlin/com/ratons/Ratons.kt index 68d2253..bfac45b 100644 --- a/src/main/kotlin/com/ratons/Ratons.kt +++ b/src/main/kotlin/com/ratons/Ratons.kt @@ -8,6 +8,7 @@ import com.ratons.data.KuudraAPI import com.ratons.data.PacketData import com.ratons.features.instances.AutoRefill import com.ratons.features.instances.dungeons.RelicSpawnTimer +import com.ratons.features.misc.ItemDataDisplay import com.ratons.features.misc.update.UpdateManager import net.minecraft.client.Minecraft import net.minecraftforge.common.MinecraftForge @@ -37,6 +38,7 @@ class Ratons { AutoRefill, RelicSpawnTimer, UpdateManager, + ItemDataDisplay, // data KuudraAPI, diff --git a/src/main/kotlin/com/ratons/config/features/Features.java b/src/main/kotlin/com/ratons/config/features/Features.java index 9a09388..5bc9d1b 100644 --- a/src/main/kotlin/com/ratons/config/features/Features.java +++ b/src/main/kotlin/com/ratons/config/features/Features.java @@ -2,9 +2,10 @@ import at.hannibal2.skyhanni.deps.moulconfig.Config; import at.hannibal2.skyhanni.deps.moulconfig.annotations.Category; -import com.ratons.Ratons; import com.google.gson.annotations.Expose; +import com.ratons.Ratons; import com.ratons.config.features.instances.InstancesConfig; +import com.ratons.config.features.misc.MiscConfig; public class Features extends Config { @@ -31,4 +32,8 @@ public void saveNow() { @Category(name = "Instances", desc = "Features for instanced content.") public InstancesConfig instancesConfig = new InstancesConfig(); + @Expose + @Category(name = "Misc", desc = "Miscellaneous features.") + public MiscConfig misc = new MiscConfig(); + } diff --git a/src/main/kotlin/com/ratons/config/features/misc/MiscConfig.java b/src/main/kotlin/com/ratons/config/features/misc/MiscConfig.java new file mode 100644 index 0000000..af57c80 --- /dev/null +++ b/src/main/kotlin/com/ratons/config/features/misc/MiscConfig.java @@ -0,0 +1,19 @@ +package com.ratons.config.features.misc; + +import at.hannibal2.skyhanni.deps.moulconfig.annotations.ConfigEditorBoolean; +import at.hannibal2.skyhanni.deps.moulconfig.annotations.ConfigOption; +import com.google.gson.annotations.Expose; + +public class MiscConfig { + + @Expose + @ConfigOption(name = "Dungeon Item Data", desc = "Displays data about dungeon items drops in its lore.") + @ConfigEditorBoolean + public boolean dungeonItemData = false; + + @Expose + @ConfigOption(name = "Item Age Data", desc = "Displays an item's age in its lore.") + @ConfigEditorBoolean + public boolean itemAgeData = false; + +} diff --git a/src/main/kotlin/com/ratons/features/misc/ItemDataDisplay.kt b/src/main/kotlin/com/ratons/features/misc/ItemDataDisplay.kt new file mode 100644 index 0000000..4f80040 --- /dev/null +++ b/src/main/kotlin/com/ratons/features/misc/ItemDataDisplay.kt @@ -0,0 +1,53 @@ +package com.ratons.features.misc + +import at.hannibal2.skyhanni.events.LorenzToolTipEvent +import at.hannibal2.skyhanni.utils.LorenzUtils +import com.ratons.Ratons +import com.ratons.utils.ItemUtils.getDungeonStatBoost +import com.ratons.utils.ItemUtils.getDungeonTier +import com.ratons.utils.ItemUtils.getItemTimestamp +import com.ratons.utils.ItemUtils.getRarityLoreIndex +import com.ratons.utils.ItemUtils.isDungeonItem +import com.ratons.utils.TimeUtils.shortFormat +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +@Suppress("SkyHanniModuleInspection") +object ItemDataDisplay { + + private val config get() = Ratons.feature.misc + + @SubscribeEvent(priority = EventPriority.HIGH) + fun onTooltip(event: LorenzToolTipEvent) { + if (!isEnabled()) return + val item = event.itemStack + + var index = item.getRarityLoreIndex(event.toolTip) + 1 + if (index == 0) return + if (event.toolTip.addDungeonQuality(index, item)) index++ + if (event.toolTip.addItemAge(index, item)) index++ + } + + private fun MutableList.addDungeonQuality(index: Int, item: ItemStack): Boolean { + if (!config.dungeonItemData) return false + if (!item.isDungeonItem()) return false + val itemTier = item.getDungeonTier() ?: return false + val itemQuality = item.getDungeonStatBoost() ?: return false + val qualityColor = if (itemQuality == 50) "§d" else "§6" + val tierColor = if (itemTier == 10) "§d" else "§6" + add(index, "§7Item Quality: $qualityColor$itemQuality% §7(Tier $tierColor$itemTier§7)") + return true + } + + private fun MutableList.addItemAge(index: Int, item: ItemStack): Boolean { + if (!config.itemAgeData) return false + val timestamp = item.getItemTimestamp() ?: return false + add(index, "§7Item Age: §8${timestamp.passedSince().shortFormat()}") + return true + } + + private fun isEnabled() = LorenzUtils.inSkyBlock && (config.dungeonItemData || config.itemAgeData) + + +} diff --git a/src/main/kotlin/com/ratons/utils/ItemUtils.kt b/src/main/kotlin/com/ratons/utils/ItemUtils.kt new file mode 100644 index 0000000..5b6d52c --- /dev/null +++ b/src/main/kotlin/com/ratons/utils/ItemUtils.kt @@ -0,0 +1,35 @@ +package com.ratons.utils + +import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull +import at.hannibal2.skyhanni.utils.ItemUtils.getLore +import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getExtraAttributes +import com.ratons.utils.RatUtils.cleanName +import net.minecraft.item.ItemStack + +object ItemUtils { + + fun ItemStack.getDungeonTier() = getAttributeInt("item_tier") + + fun ItemStack.getDungeonStatBoost() = getAttributeInt("baseStatBoostPercentage") + + fun ItemStack.getItemTimestamp(): SimpleTimeMark? { + val timestamp = getAttributeLong("timestamp") ?: return null + return SimpleTimeMark(timestamp) + } + + private fun ItemStack.getAttributeInt(label: String) = getExtraAttributes()?.getInteger(label)?.takeUnless { it == 0 } + + private fun ItemStack.getAttributeLong(label: String) = getExtraAttributes()?.getLong(label)?.takeUnless { it == 0L } + + private fun ItemStack.getAttributeBoolean(label: String) = getExtraAttributes()?.getBoolean(label) ?: false + + private fun ItemStack.getAttributeByte(label: String) = getExtraAttributes()?.getByte(label) ?: 0 + + fun ItemStack.isDungeonItem(): Boolean = getLore().indexOfLast { it.contains("DUNGEON ") } != -1 + + fun ItemStack.getRarityLoreIndex(lore: List): Int { + val rarity = getItemRarityOrNull()?.cleanName() ?: return -1 + return lore.indexOfLast { it.contains(rarity) } + } +} diff --git a/src/main/kotlin/com/ratons/utils/RatUtils.kt b/src/main/kotlin/com/ratons/utils/RatUtils.kt index 6a2fb4b..7a8feb9 100644 --- a/src/main/kotlin/com/ratons/utils/RatUtils.kt +++ b/src/main/kotlin/com/ratons/utils/RatUtils.kt @@ -9,4 +9,6 @@ object RatUtils { fun Duration.tick(): Duration = (this - 1.ticks).coerceAtLeast(0.seconds) fun Duration.isZero(): Boolean = this == 0.seconds + + fun > Enum.cleanName(): String = name.replace('_', ' ') } diff --git a/src/main/kotlin/com/ratons/utils/TimeUtils.kt b/src/main/kotlin/com/ratons/utils/TimeUtils.kt new file mode 100644 index 0000000..197f243 --- /dev/null +++ b/src/main/kotlin/com/ratons/utils/TimeUtils.kt @@ -0,0 +1,33 @@ +package com.ratons.utils + +import kotlin.time.Duration + +object TimeUtils { + + fun Duration.shortFormat(): String { + val millis = inWholeMilliseconds + val unit = TimeUnit.entries.find { millis >= it.factor } ?: TimeUnit.SECOND + val amount = millis / unit.factor + val remainder = millis % unit.factor + val decimal = (remainder * 10 / unit.factor).toInt() + return "$amount.$decimal ${unit.longName.lowercase()}" + if (amount != 1L) "s" else "" + } +} + +private const val FACTOR_SECONDS = 1000L +private const val FACTOR_MINUTES = FACTOR_SECONDS * 60 +private const val FACTOR_HOURS = FACTOR_MINUTES * 60 +private const val FACTOR_DAYS = FACTOR_HOURS * 24 +private const val FACTOR_WEEKS = FACTOR_DAYS * 7 +private const val FACTOR_MONTH = FACTOR_DAYS * 31 +private const val FACTOR_YEARS = (FACTOR_DAYS * 365.25).toLong() + +enum class TimeUnit(val factor: Long, val shortName: String, val longName: String) { + YEAR(FACTOR_YEARS, "y", "Year"), + MONTH(FACTOR_MONTH, "mo", "Month"), + WEEK(FACTOR_WEEKS, "w", "Week"), + DAY(FACTOR_DAYS, "d", "Day"), + HOUR(FACTOR_HOURS, "h", "Hour"), + MINUTE(FACTOR_MINUTES, "m", "Minute"), + SECOND(FACTOR_SECONDS, "s", "Second"), +}