aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/features/misc
diff options
context:
space:
mode:
authorHiZe_ <superhize@hotmail.com>2023-08-10 12:23:02 +0200
committerGitHub <noreply@github.com>2023-08-10 12:23:02 +0200
commit1efe50bff3fbb0e6a782aaf5284fab3fd60ec637 (patch)
tree8ba814aee575609da3461d2be0107b8fc46f2f8b /src/main/java/at/hannibal2/skyhanni/features/misc
parentd0bbd687ca9d33cc7bd8f53e3103ecc92905f8dc (diff)
downloadskyhanni-1efe50bff3fbb0e6a782aaf5284fab3fd60ec637.tar.gz
skyhanni-1efe50bff3fbb0e6a782aaf5284fab3fd60ec637.tar.bz2
skyhanni-1efe50bff3fbb0e6a782aaf5284fab3fd60ec637.zip
Merge pull request #348
* Chest Value
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/features/misc')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt32
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/ChestValue.kt261
2 files changed, 265 insertions, 28 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt
index 87ab04dca..626d24f03 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/BestiaryData.kt
@@ -8,6 +8,9 @@ import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
import at.hannibal2.skyhanni.utils.*
import at.hannibal2.skyhanni.utils.ItemUtils.getLore
import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
+import at.hannibal2.skyhanni.utils.LorenzUtils.addButton
+import at.hannibal2.skyhanni.utils.LorenzUtils.toBoolean
+import at.hannibal2.skyhanni.utils.LorenzUtils.toInt
import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
import at.hannibal2.skyhanni.utils.NumberUtil.formatNumber
import at.hannibal2.skyhanni.utils.NumberUtil.romanToDecimalIfNeeded
@@ -230,7 +233,7 @@ object BestiaryData {
if (isMaxed && config.hideMaxed) continue
val text = getMobLine(mob, isMaxed)
val tips = getMobHover(mob)
- newDisplay.addAsSingletonList(Renderable.hoverTips(text, tips, false) { true })
+ newDisplay.addAsSingletonList(Renderable.hoverTips(text, tips) { true })
}
}
@@ -413,9 +416,6 @@ object BestiaryData {
else -> "0"
}
- private fun Int.toBoolean() = this != 0
- private fun Boolean.toInt() = if (!this) 0 else 1
-
data class Category(
val name: String,
val familiesFound: Long,
@@ -452,30 +452,6 @@ object BestiaryData {
fun getNextLevel() = level.getNextLevel()
}
- private fun MutableList<List<Any>>.addButton(
- prefix: String,
- getName: String,
- onChange: () -> Unit,
- tips: List<String> = emptyList(),
- ) {
- val onClick = {
- if ((System.currentTimeMillis() - lastclicked) > 100) { // funny thing happen if I don't do that
- onChange()
- SoundUtils.playClickSound()
- lastclicked = System.currentTimeMillis()
- }
- }
- add(buildList {
- add(prefix)
- add("§a[")
- if (tips.isEmpty()) {
- add(Renderable.link("§e$getName", false, onClick))
- } else {
- add(Renderable.clickAndHover("§e$getName", tips, false, onClick))
- }
- add("§a]")
- })
- }
private fun String.romanOrInt() = romanToDecimalIfNeeded().let {
if (config.replaceRoman || it == 0) it.toString() else it.toRoman()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/ChestValue.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/ChestValue.kt
new file mode 100644
index 000000000..e0f2e860e
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/ChestValue.kt
@@ -0,0 +1,261 @@
+package at.hannibal2.skyhanni.features.misc
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.data.IslandType
+import at.hannibal2.skyhanni.events.*
+import at.hannibal2.skyhanni.features.misc.items.EstimatedItemValue
+import at.hannibal2.skyhanni.utils.*
+import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
+import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
+import at.hannibal2.skyhanni.utils.LorenzUtils.addButton
+import at.hannibal2.skyhanni.utils.LorenzUtils.toBoolean
+import at.hannibal2.skyhanni.utils.LorenzUtils.toInt
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.RenderUtils.highlight
+import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
+import at.hannibal2.skyhanni.utils.renderables.Renderable
+import net.minecraft.client.Minecraft
+import net.minecraft.client.gui.inventory.GuiChest
+import net.minecraft.init.Items
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.EventPriority
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.awt.Color
+
+class ChestValue {
+
+ private val config get() = SkyHanniMod.feature.inventory.chestValueConfig
+ private var display = emptyList<List<Any>>()
+ private val chestItems = mutableMapOf<String, Item>()
+ private val inInventory get() = InventoryUtils.openInventoryName().isValidStorage()
+
+ @SubscribeEvent
+ fun onBackgroundDraw(event: GuiRenderEvent.ChestBackgroundRenderEvent) {
+ if (!isEnabled()) return
+ if (InventoryUtils.openInventoryName() == "") return
+ if (inInventory) {
+ config.position.renderStringsAndItems(
+ display,
+ extraSpace = -1,
+ itemScale = 1.3,
+ posLabel = "Estimated Chest Value"
+ )
+ }
+ }
+
+ @SubscribeEvent
+ fun onTick(event: LorenzTickEvent) {
+ if (!isEnabled()) return
+ if (event.isMod(5)) {
+ update()
+ }
+ }
+
+ @SubscribeEvent
+ fun onInventoryOpen(event: InventoryOpenEvent) {
+ if (!isEnabled()) return
+ if (inInventory) {
+ update()
+ }
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ chestItems.clear()
+ Renderable.list.clear()
+ }
+
+ @SubscribeEvent(priority = EventPriority.LOW)
+ fun onDrawBackground(event: GuiContainerEvent.BackgroundDrawnEvent) {
+ if (!isEnabled()) return
+ if (!config.enableHighlight) return
+ if (inInventory) {
+ for ((_, indexes) in Renderable.list) {
+ for (slot in InventoryUtils.getItemsInOpenChest()) {
+ if (indexes.contains(slot.slotIndex)) {
+ slot highlight Color(SpecialColour.specialToChromaRGB(config.highlightColor), true)
+ }
+ }
+ }
+ }
+ }
+
+ private fun update() {
+ display = drawDisplay()
+ }
+
+ private fun drawDisplay(): List<List<Any>> {
+ val newDisplay = mutableListOf<List<Any>>()
+
+ init()
+
+ if (chestItems.isEmpty()) return newDisplay
+
+ addList(newDisplay)
+ addButton(newDisplay)
+
+ return newDisplay
+ }
+
+ private fun addList(newDisplay: MutableList<List<Any>>) {
+ val sortedList = sortedList()
+ var totalPrice = 0.0
+ var rendered = 0
+ val amountShowing = if (config.itemToShow > sortedList.size) sortedList.size else config.itemToShow
+ newDisplay.addAsSingletonList("§7Estimated Chest Value: §o(Showing $amountShowing of ${sortedList.size} items)")
+ for ((index, amount, stack, total, tips) in sortedList) {
+ totalPrice += total
+ if (rendered >= config.itemToShow) continue
+ if (total < config.hideBelow) continue
+ val textAmount = " §7x$amount:"
+ val width = Minecraft.getMinecraft().fontRendererObj.getStringWidth(textAmount)
+ val name = "${stack.displayName.reduceStringLength((config.nameLength - width), ' ')} $textAmount"
+ val price = "§b${(total).formatPrice()}"
+ val text = if (config.alignedDisplay)
+ "$name $price"
+ else
+ "${stack.displayName} §7x$amount: §b${total.formatPrice()}"
+ newDisplay.add(buildList {
+ val renderable = Renderable.hoverTips(
+ text,
+ tips,
+ stack = stack,
+ indexes = index)
+ add(" §7- ")
+ if (config.showStacks) add(stack)
+ add(renderable)
+ })
+ rendered++
+ }
+ newDisplay.addAsSingletonList("§6Total value : §b${totalPrice.formatPrice()}")
+ }
+
+ private fun sortedList(): MutableList<Item> {
+ return when (config.sortingType) {
+ 0 -> chestItems.values.sortedByDescending { it.total }
+ 1 -> chestItems.values.sortedBy { it.total }
+ else -> chestItems.values.sortedByDescending { it.total }
+ }.toMutableList()
+ }
+
+ private fun addButton(newDisplay: MutableList<List<Any>>) {
+ newDisplay.addButton("§7Sorted By: ",
+ getName = SortType.entries[config.sortingType].longName,
+ onChange = {
+ config.sortingType = (config.sortingType + 1) % 2
+ update()
+ })
+
+ newDisplay.addButton("§7Value format: ",
+ getName = FormatType.entries[config.formatType].type,
+ onChange = {
+ config.formatType = (config.formatType + 1) % 2
+ update()
+ })
+
+ newDisplay.addButton("§7Display Type: ",
+ getName = DisplayType.entries[config.alignedDisplay.toInt()].type,
+ onChange = {
+ config.alignedDisplay = ((config.alignedDisplay.toInt() + 1) % 2).toBoolean()
+ update()
+ })
+ }
+
+ private fun init() {
+ if (inInventory) {
+ val isMinion = InventoryUtils.openInventoryName().contains(" Minion ")
+ val slots = InventoryUtils.getItemsInOpenChest().filter {
+ it.hasStack && it.inventory != Minecraft.getMinecraft().thePlayer.inventory && (!isMinion || it.slotNumber % 9 != 1)
+ }
+ val stacks = buildMap {
+ slots.forEach {
+ put(it.slotIndex, it.stack)
+ }
+ }
+ chestItems.clear()
+ for ((i, stack) in stacks) {
+ val internalName = stack.getInternalName()
+ if (internalName == "") continue
+ if (NEUItems.getItemStackOrNull(internalName) == null) continue
+ val list = mutableListOf<String>()
+ val pair = EstimatedItemValue.getEstimatedItemPrice(stack, list)
+ var (total, _) = pair
+ if (stack.item == Items.enchanted_book)
+ total /= 2
+ list.add("§aTotal: §6§l${total.formatPrice()}")
+ if (total == 0.0) continue
+ val item = chestItems.getOrPut(internalName) {
+ Item(mutableListOf(), 0, stack, 0.0, list)
+ }
+ item.index.add(i)
+ item.amount += stack.stackSize
+ item.total += total * stack.stackSize
+ }
+ }
+ }
+
+ private fun Double.formatPrice(): String {
+ return when (config.formatType) {
+ 0 -> if (this > 1_000_000_000) NumberUtil.format(this, true) else NumberUtil.format(this)
+ 1 -> this.addSeparators()
+ else -> "0"
+ }
+ }
+
+ enum class SortType(val shortName: String, val longName: String) {
+ PRICE_DESC("Price D", "Price Descending"),
+ PRICE_ASC("Price A", "Price Ascending")
+ ;
+ }
+
+ enum class FormatType(val type: String) {
+ SHORT("Formatted"),
+ LONG("Unformatted")
+ ;
+ }
+
+ enum class DisplayType(val type: String) {
+ NORMAL("Normal"),
+ COMPACT("Aligned")
+ }
+
+ private fun String.isValidStorage() = Minecraft.getMinecraft().currentScreen is GuiChest && ((this == "Chest" ||
+ this == "Large Chest") ||
+ (contains("Minion") && !contains("Recipe") && LorenzUtils.skyBlockIsland == IslandType.PRIVATE_ISLAND) ||
+ this == "Personal Vault")
+
+
+ private fun String.reduceStringLength(targetLength: Int, char: Char): String {
+ val mc = Minecraft.getMinecraft()
+ val spaceWidth = mc.fontRendererObj.getCharWidth(char)
+
+ var currentString = this
+ var currentLength = mc.fontRendererObj.getStringWidth(currentString)
+
+ while (currentLength > targetLength) {
+ currentString = currentString.dropLast(1)
+ currentLength = mc.fontRendererObj.getStringWidth(currentString)
+ }
+
+ val difference = targetLength - currentLength
+
+ if (difference > 0) {
+ val numSpacesToAdd = difference / spaceWidth
+ val spaces = " ".repeat(numSpacesToAdd)
+ return currentString + spaces
+ }
+
+ return currentString
+ }
+
+
+ data class Item(
+ val index: MutableList<Int>,
+ var amount: Int,
+ val stack: ItemStack,
+ var total: Double,
+ val tips: MutableList<String>
+ )
+
+ private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled
+} \ No newline at end of file