diff options
author | hannibal2 <24389977+hannibal002@users.noreply.github.com> | 2024-09-09 15:26:16 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-09-09 15:26:16 +0200 |
commit | 18da4a7c13d215fb6cd7969654986d9072dd24fa (patch) | |
tree | 493b5f4aed0e6511cac67cfdd7815d4eb7852b31 /src/main/java/at | |
parent | e17e70b6933982ca417577f441928f77cbbf9ef1 (diff) | |
download | skyhanni-18da4a7c13d215fb6cd7969654986d9072dd24fa.tar.gz skyhanni-18da4a7c13d215fb6cd7969654986d9072dd24fa.tar.bz2 skyhanni-18da4a7c13d215fb6cd7969654986d9072dd24fa.zip |
Improvement: SH Tracker Search (#2477)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main/java/at')
22 files changed, 513 insertions, 261 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/combat/endernodetracker/EnderNodeTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/combat/endernodetracker/EnderNodeTracker.kt index 931f3b622..51deea2b8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/combat/endernodetracker/EnderNodeTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/combat/endernodetracker/EnderNodeTracker.kt @@ -13,7 +13,7 @@ import at.hannibal2.skyhanni.events.OwnInventoryItemUpdateEvent import at.hannibal2.skyhanni.events.SackChangeEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.ConditionalUtils.afterChange import at.hannibal2.skyhanni.utils.ConfigUtils import at.hannibal2.skyhanni.utils.InventoryUtils @@ -26,7 +26,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.NEUItems.getPriceOrNull import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat -import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData import com.google.gson.annotations.Expose @@ -212,36 +212,35 @@ object EnderNodeTracker { else -> null } - private fun drawDisplay(data: Data) = buildList<Renderable> { + private fun drawDisplay(data: Data) = buildList<Searchable> { val lootProfit = getLootProfit(data) - addString("§5§lEnder Node Tracker") - addString("§d${data.totalNodesMined.addSeparators()} Ender Nodes mined") - addString("§6${lootProfit.values.sum().shortFormat()} Coins made") - addString(" ") - addString("§b${data.totalEndermiteNests.addSeparators()} §cEndermite Nest") + addSearchString("§5§lEnder Node Tracker") + addSearchString("§d${data.totalNodesMined.addSeparators()} Ender Nodes mined") + addSearchString("§6${lootProfit.values.sum().shortFormat()} Coins made") + addSearchString(" ") + addSearchString("§b${data.totalEndermiteNests.addSeparators()} §cEndermite Nest", "Endermite Nest") for (item in EnderNode.entries.subList(0, 11)) { val count = (data.lootCount[item] ?: 0).addSeparators() val profit = (lootProfit[item] ?: 0.0).shortFormat() - addString("§b$count ${item.displayName} §7(§6$profit§7)") + addSearchString("§b$count ${item.displayName} §7(§6$profit§7)", item.displayName) } - addString(" ") + addSearchString(" ") val totalEnderArmor = calculateEnderArmor(data) - addString( - "§b${totalEnderArmor.addSeparators()} §5Ender Armor " + - "§7(§6${(totalEnderArmor * 10_000).shortFormat()}§7)" + addSearchString( + "§b${totalEnderArmor.addSeparators()} §5Ender Armor " + "§7(§6${(totalEnderArmor * 10_000).shortFormat()}§7)" ) for (item in EnderNode.entries.subList(11, 16)) { val count = (data.lootCount[item] ?: 0).addSeparators() val profit = (lootProfit[item] ?: 0.0).shortFormat() - addString("§b$count ${item.displayName} §7(§6$profit§7)") + addSearchString("§b$count ${item.displayName} §7(§6$profit§7)") } // enderman pet rarities val (c, u, r, e, l) = EnderNode.entries.subList(16, 21).map { (data.lootCount[it] ?: 0).addSeparators() } val profit = EnderNode.entries.subList(16, 21).sumOf { lootProfit[it] ?: 0.0 }.shortFormat() - addString("§f$c§7-§a$u§7-§9$r§7-§5$e§7-§6$l §fEnderman Pet §7(§6$profit§7)") + addSearchString("§f$c§7-§a$u§7-§9$r§7-§5$e§7-§6$l §fEnderman Pet §7(§6$profit§7)") } private fun calculateEnderArmor(storage: Data) = @@ -249,10 +248,10 @@ object EnderNodeTracker { .map { it.value } .sum() - private fun formatDisplay(map: List<Renderable>): List<Renderable> { + private fun formatDisplay(map: List<Searchable>): List<Searchable> { if (!ProfileStorageData.loaded) return emptyList() - val newList = mutableListOf<Renderable>() + val newList = mutableListOf<Searchable>() for (index in config.textFormat.get()) { // TODO, change functionality to use enum rather than ordinals newList.add(map[index.ordinal]) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaProfitTracker.kt index f8ae6165b..ade5966ea 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/DianaProfitTracker.kt @@ -9,7 +9,7 @@ import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators @@ -19,6 +19,8 @@ import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.ItemTrackerData import at.hannibal2.skyhanni.utils.tracker.SkyHanniItemTracker @@ -77,8 +79,8 @@ object DianaProfitTracker { } } - private fun drawDisplay(data: Data): List<Renderable> = buildList { - addString("§e§lDiana Profit Tracker") + private fun drawDisplay(data: Data): List<Searchable> = buildList { + addSearchString("§e§lDiana Profit Tracker") val profit = tracker.drawItems(data, { true }, this) @@ -87,7 +89,7 @@ object DianaProfitTracker { Renderable.hoverTips( "§7Burrows dug: §e${treasureCoins.addSeparators()}", listOf("§7You dug out griffin burrows §e${treasureCoins.addSeparators()} §7times."), - ), + ).toSearchable(), ) add(tracker.addTotalProfit(profit, data.burrowsDug, "burrow")) diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/MythologicalCreatureTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/MythologicalCreatureTracker.kt index fc7442faf..ec882d6ec 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/MythologicalCreatureTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/MythologicalCreatureTracker.kt @@ -6,14 +6,14 @@ import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.sumAllValues import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData @@ -30,32 +30,31 @@ object MythologicalCreatureTracker { private val patternGroup = RepoPattern.group("event.diana.mythological.tracker") private val minotaurPattern by patternGroup.pattern( "minotaur", - ".* §r§eYou dug out a §r§2Minotaur§r§e!" + ".* §r§eYou dug out a §r§2Minotaur§r§e!", ) private val gaiaConstructPattern by patternGroup.pattern( "gaiaconstruct", - ".* §r§eYou dug out a §r§2Gaia Construct§r§e!" + ".* §r§eYou dug out a §r§2Gaia Construct§r§e!", ) private val minosChampionPattern by patternGroup.pattern( "minoschampion", - ".* §r§eYou dug out a §r§2Minos Champion§r§e!" + ".* §r§eYou dug out a §r§2Minos Champion§r§e!", ) private val siameseLynxesPattern by patternGroup.pattern( "siameselynxes", - ".* §r§eYou dug out §r§2Siamese Lynxes§r§e!" + ".* §r§eYou dug out §r§2Siamese Lynxes§r§e!", ) private val minosHunterPattern by patternGroup.pattern( "minoshunter", - ".* §r§eYou dug out a §r§2Minos Hunter§r§e!" + ".* §r§eYou dug out a §r§2Minos Hunter§r§e!", ) private val minosInquisitorPattern by patternGroup.pattern( "minosinquisitor", - ".* §r§eYou dug out a §r§2Minos Inquisitor§r§e!" + ".* §r§eYou dug out a §r§2Minos Inquisitor§r§e!", ) private val tracker = - SkyHanniTracker("Mythological Creature Tracker", { Data() }, { it.diana.mythologicalMobTracker }) - { drawDisplay(it) } + SkyHanniTracker("Mythological Creature Tracker", { Data() }, { it.diana.mythologicalMobTracker }) { drawDisplay(it) } class Data : TrackerData() { @@ -90,8 +89,7 @@ object MythologicalCreatureTracker { // TODO migrate to abstract feature in the future if (creatureType == MythologicalCreatureType.MINOS_INQUISITOR) { - event.chatComponent = - ChatComponentText(event.message + " §e(${it.creaturesSinceLastInquisitor})") + event.chatComponent = ChatComponentText(event.message + " §e(${it.creaturesSinceLastInquisitor})") it.creaturesSinceLastInquisitor = 0 } else it.creaturesSinceLastInquisitor++ } @@ -100,8 +98,8 @@ object MythologicalCreatureTracker { } } - private fun drawDisplay(data: Data): List<Renderable> = buildList { - addString("§7Mythological Creature Tracker:") + private fun drawDisplay(data: Data): List<Searchable> = buildList { + addSearchString("§7Mythological Creature Tracker:") val total = data.count.sumAllValues() for ((creatureType, amount) in data.count.entries.sortedByDescending { it.value }) { val percentageSuffix = if (config.showPercentage.get()) { @@ -109,10 +107,13 @@ object MythologicalCreatureTracker { " §7$percentage" } else "" - addString(" §7- §e${amount.addSeparators()} ${creatureType.displayName}$percentageSuffix") + addSearchString( + " §7- §e${amount.addSeparators()} ${creatureType.displayName}$percentageSuffix", + searchText = creatureType.displayName, + ) } - addString(" §7- §e${total.addSeparators()} §7Total Mythological Creatures") - addString(" §7- §e${data.creaturesSinceLastInquisitor.addSeparators()} §7Creatures since last Minos Inquisitor") + addSearchString(" §7- §e${total.addSeparators()} §7Total Mythological Creatures") + addSearchString(" §7- §e${data.creaturesSinceLastInquisitor.addSeparators()} §7Creatures since last Minos Inquisitor") } @SubscribeEvent diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/jerry/frozentreasure/FrozenTreasureTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/event/jerry/frozentreasure/FrozenTreasureTracker.kt index 4fc5b824b..80812c4c5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/jerry/frozentreasure/FrozenTreasureTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/jerry/frozentreasure/FrozenTreasureTracker.kt @@ -12,7 +12,7 @@ import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.ConfigUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators @@ -20,7 +20,7 @@ import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.StringUtils.removeColor -import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData @@ -105,8 +105,8 @@ object FrozenTreasureTracker { icePerHour = (icePerSecond.average() * 3600).toInt() } - private fun formatDisplay(map: List<Renderable>): List<Renderable> { - val newList = mutableListOf<Renderable>() + private fun formatDisplay(map: List<Searchable>): List<Searchable> { + val newList = mutableListOf<Searchable>() for (index in config.textFormat) { // TODO, change functionality to use enum rather than ordinals newList.add(map[index.ordinal]) @@ -137,20 +137,20 @@ object FrozenTreasureTracker { } } - private fun drawDisplay(data: Data) = buildList { + private fun drawDisplay(data: Data) = buildList<Searchable> { calculateIce(data) - addString("§e§lFrozen Treasure Tracker") - addString("§6${formatNumber(data.treasuresMined)} Treasures Mined") - addString("§3${formatNumber(estimatedIce)} Total Ice") - addString("§3${formatNumber(icePerHour)} Ice/hr") - addString("§8${formatNumber(data.compactProcs)} Compact Procs") - addString("") + addSearchString("§e§lFrozen Treasure Tracker") + addSearchString("§6${formatNumber(data.treasuresMined)} Treasures Mined") + addSearchString("§3${formatNumber(estimatedIce)} Total Ice") + addSearchString("§3${formatNumber(icePerHour)} Ice/hr") + addSearchString("§8${formatNumber(data.compactProcs)} Compact Procs") + addSearchString("") for (treasure in FrozenTreasure.entries) { val count = (data.treasureCount[treasure] ?: 0) * if (config.showAsDrops) treasure.defaultAmount else 1 - addString("§b${formatNumber(count)} ${treasure.displayName}") + addSearchString("§b${formatNumber(count)} ${treasure.displayName}", treasure.displayName) } - addString("") + addSearchString("") } fun formatNumber(amount: Number): String { diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/FishingProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/FishingProfitTracker.kt index 619334a98..12f3accd1 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/FishingProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/FishingProfitTracker.kt @@ -13,8 +13,7 @@ import at.hannibal2.skyhanni.features.fishing.FishingAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.CollectionUtils.addButton -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUInternalName @@ -26,6 +25,9 @@ import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.addButton +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.ItemTrackerData import at.hannibal2.skyhanni.utils.tracker.SkyHanniItemTracker @@ -119,8 +121,8 @@ object FishingProfitTracker { return map } - private fun drawDisplay(data: Data): List<Renderable> = buildList { - addString("§e§lFishing Profit Tracker") + private fun drawDisplay(data: Data): List<Searchable> = buildList { + addSearchString("§e§lFishing Profit Tracker") val filter: (NEUInternalName) -> Boolean = addCategories(data) val profit = tracker.drawItems(data, filter, this) @@ -130,7 +132,7 @@ object FishingProfitTracker { Renderable.hoverTips( "§7Times fished: §e${fishedCount.addSeparators()}", listOf("§7You've reeled in §e${fishedCount.addSeparators()} §7catches."), - ), + ).toSearchable(), ) add(tracker.addTotalProfit(profit, data.totalCatchAmount, "catch")) @@ -138,7 +140,7 @@ object FishingProfitTracker { tracker.addPriceFromButton(this) } - private fun MutableList<Renderable>.addCategories(data: Data): (NEUInternalName) -> Boolean { + private fun MutableList<Searchable>.addCategories(data: Data): (NEUInternalName) -> Boolean { val amounts = getCurrentCategories(data) checkMissingItems(data) val list = amounts.keys.toList() diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt index fd41883ef..b293c2736 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt @@ -9,15 +9,15 @@ import at.hannibal2.skyhanni.features.fishing.FishingAPI import at.hannibal2.skyhanni.features.fishing.SeaCreatureManager import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager -import at.hannibal2.skyhanni.utils.CollectionUtils.addButton import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.sumAllValues import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.StringUtils.allLettersFirstUppercase -import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.addButton +import at.hannibal2.skyhanni.utils.renderables.Searchable import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData import com.google.gson.annotations.Expose @@ -71,8 +71,8 @@ object SeaCreatureTracker { return map } - private fun drawDisplay(data: Data): List<Renderable> = buildList { - addString("§7Sea Creature Tracker:") + private fun drawDisplay(data: Data): List<Searchable> = buildList { + addSearchString("§7Sea Creature Tracker:") val filter: (String) -> Boolean = addCategories(data) val realAmount = data.amount.filter { filter(it.key) } @@ -94,12 +94,12 @@ object SeaCreatureTracker { " §7$percentage" } else "" - addString(" §7- §e${amount.addSeparators()} $displayName$percentageSuffix") + addSearchString(" §7- §e${amount.addSeparators()} $displayName$percentageSuffix", displayName) } - addString(" §7- §e${total.addSeparators()} §7Total Sea Creatures") + addSearchString(" §7- §e${total.addSeparators()} §7Total Sea Creatures") } - private fun MutableList<Renderable>.addCategories(data: Data): (String) -> Boolean { + private fun MutableList<Searchable>.addCategories(data: Data): (String) -> Boolean { val amounts = getCurrentCategories(data) val list = amounts.keys.toList() if (currentCategory !in list) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/ArmorDropTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/ArmorDropTracker.kt index 1e9397d5f..90c68a046 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/ArmorDropTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/ArmorDropTracker.kt @@ -14,13 +14,13 @@ import at.hannibal2.skyhanni.features.garden.CropType import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.sortedDesc import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.SimpleTimeMark -import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData @@ -84,11 +84,11 @@ object ArmorDropTracker { } } - private fun drawDisplay(data: Data): List<Renderable> = buildList { - addString("§7Armor Drop Tracker:") + private fun drawDisplay(data: Data): List<Searchable> = buildList { + addSearchString("§7Armor Drop Tracker:") for ((drop, amount) in data.drops.sortedDesc()) { val dropName = drop.dropName - addString(" §7- §e${amount.addSeparators()}x $dropName") + addSearchString(" §7- §e${amount.addSeparators()}x $dropName", dropName) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/DicerRngDropTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/DicerRngDropTracker.kt index 34d3fe53d..8cc8c55cb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/DicerRngDropTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/DicerRngDropTracker.kt @@ -10,12 +10,15 @@ import at.hannibal2.skyhanni.features.garden.CropType import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.sortedDesc import at.hannibal2.skyhanni.utils.ConditionalUtils import at.hannibal2.skyhanni.utils.ItemUtils.name import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData @@ -120,30 +123,28 @@ object DicerRngDropTracker { } } - private fun drawDisplay(data: Data) = buildList<Renderable> { + private fun drawDisplay(data: Data) = buildList<Searchable> { val cropInHand = cropInHand ?: return@buildList val topLine = mutableListOf<Renderable>() topLine.add(Renderable.itemStack(cropInHand.icon)) topLine.add(Renderable.string("§7Dicer Tracker:")) - add(Renderable.horizontalContainer(topLine)) + add(Renderable.horizontalContainer(topLine).toSearchable()) val items = data.drops[cropInHand] ?: return@buildList - val list = mutableListOf<Renderable>() if (config.compact.get()) { val compactLine = items.sortedDesc().map { (rarity, amount) -> "§${rarity.colorCode}${amount.addSeparators()}" }.joinToString("§7/") - list.add(Renderable.string(compactLine)) + addSearchString(compactLine) } else { for ((rarity, amount) in items.sortedDesc()) { val colorCode = rarity.colorCode val displayName = rarity.displayName - list.add(Renderable.string(" §7- §e${amount.addSeparators()}x §$colorCode$displayName")) + addSearchString(" §7- §e${amount.addSeparators()}x §$colorCode$displayName", displayName) } } - add(Renderable.verticalContainer(list)) } private var cropInHand: CropType? = null diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestProfitTracker.kt index 7dcd07861..19506109e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/pests/PestProfitTracker.kt @@ -11,7 +11,7 @@ import at.hannibal2.skyhanni.events.PurseChangeCause import at.hannibal2.skyhanni.events.PurseChangeEvent import at.hannibal2.skyhanni.features.garden.GardenAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators @@ -19,6 +19,8 @@ import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.ItemTrackerData import at.hannibal2.skyhanni.utils.tracker.SkyHanniItemTracker @@ -117,8 +119,8 @@ object PestProfitTracker { lastPestKillTime = SimpleTimeMark.now() } - private fun drawDisplay(data: Data): List<Renderable> = buildList { - addString("§e§lPest Profit Tracker") + private fun drawDisplay(data: Data): List<Searchable> = buildList { + addSearchString("§e§lPest Profit Tracker") val profit = tracker.drawItems(data, { true }, this) val pestsKilled = data.totalPestsKills @@ -126,7 +128,7 @@ object PestProfitTracker { Renderable.hoverTips( "§7Pests killed: §e${pestsKilled.addSeparators()}", listOf("§7You killed pests §e${pestsKilled.addSeparators()} §7times."), - ), + ).toSearchable(), ) add(tracker.addTotalProfit(profit, data.totalPestsKills, "kill")) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt index 697947e3f..eb15f6165 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt @@ -27,6 +27,7 @@ import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RenderUtils.highlight import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.buildSearchableTable import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @SkyHanniModule @@ -82,7 +83,7 @@ object SackDisplay { val sortedPairs = sort(sackItems) val amountShowing = if (config.itemToShow > sortedPairs.size) sortedPairs.size else config.itemToShow list.addString("§7Items in Sacks: §o(Rendering $amountShowing of ${sortedPairs.size} items)") - val table = mutableListOf<List<Renderable>>() + val table = mutableMapOf<List<Renderable>, String?>() for ((itemName, item) in sortedPairs) { val (internalName, colorCode, total, magmaFish) = item val stored = item.stored @@ -92,7 +93,7 @@ object SackDisplay { totalPrice += price if (rendered >= config.itemToShow) continue if (stored == 0 && !config.showEmpty) continue - table.add(buildList { + table[buildList { addString(" §7- ") addItemStack(internalName) // TODO move replace into itemName @@ -156,10 +157,10 @@ object SackDisplay { addItemStack("MAGMA_FISH".asInternalName()) } if (config.showPrice && price != 0L) addAlignedNumber("§6${format(price)}") - }) + }] = itemName rendered++ } - list.add(Renderable.table(table)) + list.add(table.buildSearchableTable()) if (SackAPI.isTrophySack) list.addString("§cTotal Magmafish: §6${totalMagmaFish.addSeparators()}") return totalPrice @@ -230,10 +231,10 @@ object SackDisplay { private fun drawRunesDisplay(list: MutableList<Renderable>) { if (SackAPI.runeItem.isEmpty()) return list.addString("§7Runes:") - val table = mutableListOf<List<Renderable>>() + val table = mutableMapOf<List<Renderable>, String?>() for ((name, rune) in sort(SackAPI.runeItem.toList())) { val (stack, lv1, lv2, lv3) = rune - table.add(buildList { + table[buildList { addString(" §7- ") stack?.let { addItemStack(it) } add( @@ -246,19 +247,19 @@ object SackDisplay { addAlignedNumber("§e$lv1") addAlignedNumber("§e$lv2") addAlignedNumber("§e$lv3") - }) + }] = name } - list.add(Renderable.table(table)) + list.add(table.buildSearchableTable()) } private fun drawGemstoneDisplay(list: MutableList<Renderable>): Long { if (SackAPI.gemstoneItem.isEmpty()) return 0L list.addString("§7Gemstones:") var totalPrice = 0L - val table = mutableListOf<List<Renderable>>() + val table = mutableMapOf<List<Renderable>, String?>() for ((name, gem) in sort(SackAPI.gemstoneItem.toList())) { val (internalName, rough, flawed, fine, roughprice, flawedprice, fineprice) = gem - table.add(buildList { + table[buildList { addString(" §7- ") addItemStack(internalName) add(Renderable.optionalLink( @@ -274,9 +275,10 @@ object SackDisplay { val price = roughprice + flawedprice + fineprice totalPrice += price if (config.showPrice && price != 0L) addAlignedNumber("§7(§6${format(price)}§7)") - }) + }] = name } - list.add(Renderable.table(table)) + + list.add(table.buildSearchableTable()) return totalPrice } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt index abab20400..5c964c639 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/chocolatefactory/ChocolateFactoryStrayTracker.kt @@ -7,9 +7,7 @@ import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.features.event.hoppity.HoppityAPI import at.hannibal2.skyhanni.features.event.hoppity.HoppityEventSummary import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.CollectionUtils.addAsSingletonList import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut -import at.hannibal2.skyhanni.utils.CollectionUtils.addString import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getLore @@ -24,6 +22,8 @@ import at.hannibal2.skyhanni.utils.RegexUtils.matches import at.hannibal2.skyhanni.utils.StringUtils.removeResets import at.hannibal2.skyhanni.utils.TimeUtils.format import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData import com.google.gson.annotations.Expose @@ -149,7 +149,7 @@ object ChocolateFactoryStrayTracker { tracker.modify { it.goldenTypesCaught.addOrPut(typeCaught, amount) } } - private fun drawDisplay(data: Data): List<Renderable> = buildList { + private fun drawDisplay(data: Data): List<Searchable> = buildList { val extraChocMs = data.straysExtraChocMs.values.sum().milliseconds val formattedExtraTime = extraChocMs.let { if (it == 0.milliseconds) "0s" else it.format() } @@ -157,14 +157,14 @@ object ChocolateFactoryStrayTracker { Renderable.hoverTips( "§6§lStray Tracker", tips = listOf("§a+§b${formattedExtraTime} §afrom strays§7"), - ), + ).toSearchable(), ) rarityFormatMap.keys.forEach { rarity -> extractHoverableOfRarity(rarity, data)?.let { add(it) } } } - private fun extractHoverableOfRarity(rarity: String, data: Data): Renderable? { + private fun extractHoverableOfRarity(rarity: String, data: Data): Searchable? { val caughtOfRarity = data.straysCaught[rarity] val caughtString = caughtOfRarity?.toString() ?: return null @@ -175,11 +175,12 @@ object ChocolateFactoryStrayTracker { val lineHeader = "$colorCode${rarity.substring(0, 1).uppercase()}${rarity.substring(1)}§7: §r$colorCode" val lineFormat = "${lineHeader}${caughtString}" - return rarityExtraChocMs?.let { + val renderable = rarityExtraChocMs?.let { val tip = "§a+§b$extraChocFormat §afrom $colorCode$rarity strays§7${if (rarity == "legendary") extractGoldenTypesCaught(data) else ""}" Renderable.hoverTips(Renderable.string(lineFormat), tips = tip.split("\n")) } ?: Renderable.string(lineFormat) + return renderable.toSearchable(rarity) } private fun extractGoldenTypesCaught(data: Data): String { diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/fossilexcavator/ExcavatorProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/fossilexcavator/ExcavatorProfitTracker.kt index 655b885e0..ef3f922fb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/fossilexcavator/ExcavatorProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/fossilexcavator/ExcavatorProfitTracker.kt @@ -9,7 +9,7 @@ import at.hannibal2.skyhanni.events.ItemAddEvent import at.hannibal2.skyhanni.events.mining.FossilExcavationEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.ItemUtils.itemName import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland @@ -19,6 +19,8 @@ import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.StringUtils import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import at.hannibal2.skyhanni.utils.tracker.ItemTrackerData import at.hannibal2.skyhanni.utils.tracker.SkyHanniItemTracker import com.google.gson.annotations.Expose @@ -73,8 +75,8 @@ object ExcavatorProfitTracker { private val scrapItem get() = FossilExcavatorAPI.scrapItem - private fun drawDisplay(data: Data): List<Renderable> = buildList { - addString("§e§lFossil Excavation Profit Tracker") + private fun drawDisplay(data: Data): List<Searchable> = buildList { + addSearchString("§e§lFossil Excavation Profit Tracker") var profit = tracker.drawItems(data, { true }, this) val timesExcavated = data.timesExcavated @@ -82,7 +84,7 @@ object ExcavatorProfitTracker { Renderable.hoverTips( "§7Times excavated: §e${timesExcavated.addSeparators()}", listOf("§7You excavated §e${timesExcavated.addSeparators()} §7times."), - ), + ).toSearchable(), ) profit = addScrap(timesExcavated, profit) @@ -98,7 +100,7 @@ object ExcavatorProfitTracker { tracker.addPriceFromButton(this) } - private fun MutableList<Renderable>.addFossilDust( + private fun MutableList<Searchable>.addFossilDust( fossilDustGained: Long, profit: Double, ): Double { @@ -116,12 +118,12 @@ object ExcavatorProfitTracker { "", "§7Price Per Fossil Dust: §6${pricePer.shortFormat()}", ), - ), + ).toSearchable("Fossil Dust"), ) return profit + fossilDustPrice } - private fun MutableList<Renderable>.addGlacitePowder(data: Data) { + private fun MutableList<Searchable>.addGlacitePowder(data: Data) { val glacitePowderGained = data.glacitePowderGained if (glacitePowderGained <= 0) return add( @@ -131,11 +133,11 @@ object ExcavatorProfitTracker { "§7No real profit,", "§7but still nice to see! Right?", ), - ), + ).toSearchable("Glacite Powder"), ) } - private fun MutableList<Renderable>.addScrap( + private fun MutableList<Searchable>.addScrap( timesExcavated: Long, profit: Double, ): Double { @@ -151,7 +153,7 @@ object ExcavatorProfitTracker { "§7for all §e$timesExcavated $name", "§7you have used.", ), - ), + ).toSearchable("Scrap"), ) return profit - scrapPrice } diff --git a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt index a8c81edab..a90b980d9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/mining/powdertracker/PowderTracker.kt @@ -1,8 +1,6 @@ package at.hannibal2.skyhanni.features.mining.powdertracker import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.api.HotmAPI -import at.hannibal2.skyhanni.api.event.HandleEvent import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.mining.PowderTrackerConfig.PowderDisplayEntry import at.hannibal2.skyhanni.data.BossbarData @@ -14,10 +12,8 @@ import at.hannibal2.skyhanni.events.IslandChangeEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzWorldChangeEvent import at.hannibal2.skyhanni.events.SecondPassedEvent -import at.hannibal2.skyhanni.events.mining.PowderGainEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule -import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.ConditionalUtils.afterChange import at.hannibal2.skyhanni.utils.ConfigUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland @@ -27,7 +23,7 @@ import at.hannibal2.skyhanni.utils.RegexUtils.groupOrNull import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.TimeUtils -import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData @@ -37,7 +33,6 @@ import com.google.gson.annotations.Expose import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import kotlin.time.Duration import kotlin.time.Duration.Companion.minutes -import kotlin.time.Duration.Companion.seconds @SkyHanniModule object PowderTracker { @@ -198,11 +193,13 @@ object PowderTracker { } for (reward in PowderChestReward.entries) { - if (reward == PowderChestReward.MITHRIL_POWDER || reward == PowderChestReward.GEMSTONE_POWDER) return reward.chatPattern.matchMatcher(msg) { tracker.modify { val count = it.rewards[reward] ?: 0 - val amount = groupOrNull("amount")?.formatLong() ?: 1 + var amount = groupOrNull("amount")?.formatLong() ?: 1 + if ((reward == PowderChestReward.MITHRIL_POWDER || reward == PowderChestReward.GEMSTONE_POWDER) && doublePowder) { + amount *= 2 + } it.rewards[reward] = count + amount } } @@ -210,20 +207,6 @@ object PowderTracker { tracker.update() } - @HandleEvent(onlyOnIsland = IslandType.CRYSTAL_HOLLOWS) - fun onPowderGain(event: PowderGainEvent) { - if (lastChestPicked.passedSince() > 5.seconds) return - tracker.modify { - val reward = when (event.powder) { - HotmAPI.PowderType.GEMSTONE -> PowderChestReward.GEMSTONE_POWDER - HotmAPI.PowderType.MITHRIL -> PowderChestReward.MITHRIL_POWDER - else -> return@modify - } - it.rewards.addOrPut(reward, event.amount) - } - tracker.update() - } - @SubscribeEvent fun onConfigLoad(event: ConfigLoadEvent) { config.textFormat.afterChange { @@ -284,10 +267,10 @@ object PowderTracker { } } - private fun formatDisplay(map: List<Renderable>) = buildList<Renderable> { + private fun formatDisplay(map: List<Searchable>) = buildList<Searchable> { if (map.isEmpty()) return@buildList - addString("§b§lPowder Tracker") + addSearchString("§b§lPowder Tracker") for (index in config.textFormat.get()) { // TODO, change functionality to use enum rather than ordinals @@ -295,7 +278,7 @@ object PowderTracker { } } - private fun drawDisplay(data: Data): List<Renderable> = buildList { + private fun drawDisplay(data: Data): List<Searchable> = buildList { calculate(data, gemstoneInfo, PowderChestReward.GEMSTONE_POWDER) calculate(data, mithrilInfo, PowderChestReward.MITHRIL_POWDER) calculate(data, diamondEssenceInfo, PowderChestReward.DIAMOND_ESSENCE) @@ -304,20 +287,20 @@ object PowderTracker { calculateHardStone(data) val chestPerHour = format(chestInfo.perHour) - addString("§d${data.totalChestPicked.addSeparators()} Total Chests Picked §7($chestPerHour/h)") - addString("§bDouble Powder: ${if (doublePowder) "§aActive! §7($powderTimer)" else "§cInactive!"}") + addSearchString("§d${data.totalChestPicked.addSeparators()} Total Chests Picked §7($chestPerHour/h)") + addSearchString("§bDouble Powder: ${if (doublePowder) "§aActive! §7($powderTimer)" else "§cInactive!"}") val entries = PowderChestReward.entries val rewards = data.rewards addPerHour(rewards, entries[0], mithrilInfo) addPerHour(rewards, entries[1], gemstoneInfo) - addString("") + addSearchString("") addPerHour(rewards, entries[46], diamondEssenceInfo) addPerHour(rewards, entries[47], goldEssenceInfo) - addString("") + addSearchString("") val hardStonePerHour = format(hardStoneInfo.perHour) - addString("§b${data.totalHardStoneCompacted.addSeparators()} §fHard Stone §bCompacted §7($hardStonePerHour/h)") - addString("") + addSearchString("§b${data.totalHardStoneCompacted.addSeparators()} §fHard Stone §bCompacted §7($hardStonePerHour/h)", "Hard Stone") + addSearchString("") for ((gem, color) in gemstones) { var totalGemstone = 0L @@ -334,38 +317,40 @@ object PowderTracker { } val (flawless, fine, flawed, rough) = convert(totalGemstone) - addString("§5${flawless}§7-§9${fine}§7-§a${flawed}§f-${rough} $color$gem Gemstone") + addSearchString("§5${flawless}§7-§9${fine}§7-§a${flawed}§f-${rough} $color$gem Gemstone", "Gemstone") } var totalParts = 0L for (reward in entries.subList(26, 32)) { // robots part val count = rewards.getOrDefault(reward, 0) totalParts += count - addString("§b${count.addSeparators()} ${reward.displayName}") + val name = reward.displayName + addSearchString("§b${count.addSeparators()} $name", name) } - addString("§b${totalParts.addSeparators()} §9Total Robot Parts") + addSearchString("§b${totalParts.addSeparators()} §9Total Robot Parts") val goblinEgg = rewards.getOrDefault(PowderChestReward.GOBLIN_EGG, 0) val greenEgg = rewards.getOrDefault(PowderChestReward.GREEN_GOBLIN_EGG, 0) val redEgg = rewards.getOrDefault(PowderChestReward.RED_GOBLIN_EGG, 0) val yellowEgg = rewards.getOrDefault(PowderChestReward.YELLOW_GOBLIN_EGG, 0) val blueEgg = rewards.getOrDefault(PowderChestReward.BLUE_GOBLIN_EGG, 0) - addString("§3$blueEgg§7-§c$redEgg§7-§e$yellowEgg§f-§a$greenEgg§f-§9$goblinEgg §fGoblin Egg") + addSearchString("§3$blueEgg§7-§c$redEgg§7-§e$yellowEgg§f-§a$greenEgg§f-§9$goblinEgg §fGoblin Egg") for (reward in entries.subList(37, 46)) { val count = rewards.getOrDefault(reward, 0).addSeparators() - addString("§b$count ${reward.displayName}") + val name = reward.displayName + addSearchString("§b$count $name", name) } } - private fun MutableList<Renderable>.addPerHour( + private fun MutableList<Searchable>.addPerHour( map: Map<PowderChestReward, Long>, reward: PowderChestReward, info: ResourceInfo, ) { val mithrilCount = map.getOrDefault(reward, 0).addSeparators() val mithrilPerHour = format(info.perHour) - addString("§b$mithrilCount ${reward.displayName} §7($mithrilPerHour/h)") + addSearchString("§b$mithrilCount ${reward.displayName} §7($mithrilPerHour/h)") } private fun format(e: Double): String = if (e < 0) "0" else e.toInt().addSeparators() diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminTracker.kt index c8fabc226..e47fe8002 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/westvillage/VerminTracker.kt @@ -9,7 +9,7 @@ import at.hannibal2.skyhanni.events.SecondPassedEvent import at.hannibal2.skyhanni.features.rift.RiftAPI import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.ItemUtils.getLore @@ -18,7 +18,7 @@ import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.RegexUtils.matches -import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData @@ -151,11 +151,11 @@ object VerminTracker { tracker.modify(SkyHanniTracker.DisplayMode.TOTAL) { it.count[vermin] = count } } - private fun drawDisplay(data: Data): List<Renderable> = buildList { - addString("§7Vermin Tracker:") + private fun drawDisplay(data: Data): List<Searchable> = buildList { + addSearchString("§7Vermin Tracker:") for ((vermin, amount) in data.count.entries.sortedBy { it.key.order }) { val verminName = vermin.vermin - addString(" §7- §e${amount.addSeparators()} $verminName") + addSearchString(" §7- §e${amount.addSeparators()} $verminName", verminName) } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt index ee4192b03..acd37e9d5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt @@ -16,7 +16,7 @@ import at.hannibal2.skyhanni.events.SlayerChangeEvent import at.hannibal2.skyhanni.events.SlayerQuestCompleteEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators @@ -25,6 +25,8 @@ import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.RegexUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import at.hannibal2.skyhanni.utils.tracker.ItemTrackerData import at.hannibal2.skyhanni.utils.tracker.SkyHanniItemTracker @@ -171,9 +173,9 @@ object SlayerProfitTracker { return internalName in allowedList } - private fun drawDisplay(data: Data) = buildList { + private fun drawDisplay(data: Data) = buildList<Searchable> { val tracker = getTracker() ?: return@buildList - addString("§e§l$itemLogCategory Profit Tracker") + addSearchString("§e§l$itemLogCategory Profit Tracker") var profit = tracker.drawItems(data, { true }, this) val slayerSpawnCost = data.slayerSpawnCost @@ -183,7 +185,7 @@ object SlayerProfitTracker { Renderable.hoverTips( " §7Slayer Spawn Costs: §c$slayerSpawnCostFormat", listOf("§7You paid §c$slayerSpawnCostFormat §7in total", "§7for starting the slayer quests."), - ), + ).toSearchable(), ) profit += slayerSpawnCost } @@ -193,7 +195,7 @@ object SlayerProfitTracker { Renderable.hoverTips( "§7Bosses killed: §e${slayerCompletedCount.addSeparators()}", listOf("§7You killed the $itemLogCategory boss", "§e${slayerCompletedCount.addSeparators()} §7times."), - ), + ).toSearchable(), ) add(tracker.addTotalProfit(profit, data.slayerCompletedCount, "boss")) diff --git a/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt b/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt index 4564b9b72..e720b57ca 100644 --- a/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt +++ b/src/main/java/at/hannibal2/skyhanni/test/GraphEditor.kt @@ -13,6 +13,7 @@ import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.skyhannimodule.SkyHanniModule import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchString import at.hannibal2.skyhanni.utils.CollectionUtils.addString import at.hannibal2.skyhanni.utils.ColorUtils import at.hannibal2.skyhanni.utils.KeyboardManager @@ -33,6 +34,9 @@ import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.renderables.Renderable import at.hannibal2.skyhanni.utils.renderables.ScrollValue +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.buildSearchableScrollable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import kotlinx.coroutines.runBlocking import net.minecraft.client.settings.KeyBinding import net.minecraftforge.fml.common.eventhandler.SubscribeEvent @@ -89,7 +93,6 @@ object GraphEditor { private var inTutorialMode = false - private val textBox = TextInput() private val nodeColor = LorenzColor.BLUE.addOpacity(200) @@ -102,7 +105,8 @@ object GraphEditor { private val edgeSelectedColor = LorenzColor.DARK_RED.addOpacity(150) val scrollValue = ScrollValue() - var nodesDisplay = emptyList<Renderable>() + val textInput = TextInput() + var nodesDisplay = emptyList<Searchable>() var lastUpdate = SimpleTimeMark.farPast() @SubscribeEvent @@ -185,6 +189,8 @@ object GraphEditor { @SubscribeEvent fun onGuiRender(event: GuiRenderEvent) { if (!isEnabled()) return + + config.namedNodesList.renderRenderables( buildList { val list = getNodeNames() @@ -192,14 +198,14 @@ object GraphEditor { addString("§eGraph Nodes: $size") val height = (size * 10).coerceAtMost(150) if (list.isNotEmpty()) { - add(Renderable.scrollList(list, height, scrollValue = scrollValue, velocity = 10.0)) + add(list.buildSearchableScrollable(height, textInput, scrollValue, velocity = 10.0)) } }, posLabel = "Graph Nodes List", ) } - private fun getNodeNames(): List<Renderable> { + private fun getNodeNames(): List<Searchable> { if (lastUpdate.passedSince() > 250.milliseconds) { updateNodeNames() } @@ -216,16 +222,16 @@ object GraphEditor { nodesDisplay = drawTagNames(node) } - private fun drawTagNames(node: GraphingNode): List<Renderable> = buildList { - addString("§eChange tag for node '${node.name}§e'") - addString("") + private fun drawTagNames(node: GraphingNode): List<Searchable> = buildList { + addSearchString("§eChange tag for node '${node.name}§e'") + addSearchString("") for (tag in GraphNodeTag.entries) { val state = if (tag in node.tags) "§aYES" else "§cNO" val name = state + " §r" + tag.displayName add(createTagName(name, tag, node)) } - addString("") + addSearchString("") add( Renderable.clickAndHover( "§cGo Back!", @@ -233,11 +239,11 @@ object GraphEditor { onClick = { updateNodeNames() }, - ), + ).toSearchable(), ) } -private fun createTagName( + private fun createTagName( name: String, tag: GraphNodeTag, node: GraphingNode, @@ -257,9 +263,9 @@ private fun createTagName( } updateTagView(node) }, - ) + ).toSearchable(name) - private fun drawNodeNames(): List<Renderable> = buildList { + private fun drawNodeNames(): List<Searchable> = buildList { for ((node, distance: Double) in nodes.map { it to it.position.distanceSqToPlayer() }.sortedBy { it.second }) { val name = node.name?.takeIf { !it.isBlank() } ?: continue val color = if (node == activeNode) "§a" else "§7" @@ -278,11 +284,11 @@ private fun createTagName( } } - private fun MutableList<Renderable>.createNodeTextLine( + private fun MutableList<Searchable>.createNodeTextLine( text: String, name: String, node: GraphingNode, - ): Renderable = Renderable.clickAndHover( + ): Searchable = Renderable.clickAndHover( text, tips = buildList { add("Node '$name'") @@ -308,7 +314,7 @@ private fun createTagName( updateNodeNames() } }, - ) + ).toSearchable(name) private fun feedBackInTutorial(text: String) { if (inTutorialMode) { @@ -388,8 +394,7 @@ private fun createTagName( } } - private fun chatAtDisable() = - ChatUtils.clickableChat("Graph Editor is now inactive. §lClick to activate.", ::commandIn) + private fun chatAtDisable() = ChatUtils.clickableChat("Graph Editor is now inactive. §lClick to activate.", ::commandIn) private fun input() { if (LorenzUtils.isAnyGuiActive()) return @@ -538,11 +543,9 @@ private fun createTagName( if (config.showsStats) { val length = edges.sumOf { it.node1.position.distance(it.node2.position) }.toInt().addSeparators() ChatUtils.chat( - "§lStats\n" + - "§eNamed Nodes: ${nodes.count { it.name != null }.addSeparators()}\n" + - "§eNodes: ${nodes.size.addSeparators()}\n" + - "§eEdges: ${edges.size.addSeparators()}\n" + - "§eLength: $length", + "§lStats\n" + "§eNamed Nodes: ${ + nodes.count { it.name != null }.addSeparators() + }\n" + "§eNodes: ${nodes.size.addSeparators()}\n" + "§eEdges: ${edges.size.addSeparators()}\n" + "§eLength: $length", ) } } @@ -619,15 +622,14 @@ private fun createTagName( ).let { e -> edges.indexOfFirst { it == e }.takeIf { it != -1 } } else null - private fun addEdge(node1: GraphingNode?, node2: GraphingNode?) = - if (node1 != null && node2 != null && node1 != node2) { - val edge = GraphingEdge(node1, node2) - if (edge.isInEdge(activeNode)) { - checkDissolve() - selectedEdge = findEdgeBetweenActiveAndClosed() - } - edges.add(edge) - } else false + private fun addEdge(node1: GraphingNode?, node2: GraphingNode?) = if (node1 != null && node2 != null && node1 != node2) { + val edge = GraphingEdge(node1, node2) + if (edge.isInEdge(activeNode)) { + checkDissolve() + selectedEdge = findEdgeBetweenActiveAndClosed() + } + edges.add(edge) + } else false /** Has a side effect on the graphing graph, since it runs [prune] on the graphing graph*/ private fun compileGraph(): Graph { @@ -748,8 +750,7 @@ private class GraphingEdge(val node1: GraphingNode, val node2: GraphingNode) { other as GraphingEdge - return (this.node1 == other.node1 && this.node2 == other.node2) || - (this.node1 == other.node2 && this.node2 == other.node1) + return (this.node1 == other.node1 && this.node2 == other.node2) || (this.node1 == other.node2 && this.node2 == other.node1) } override fun hashCode(): Int { diff --git a/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt index d91078d71..41560553e 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt @@ -3,6 +3,8 @@ package at.hannibal2.skyhanni.utils import at.hannibal2.skyhanni.utils.NEUItems.getItemStack import at.hannibal2.skyhanni.utils.renderables.Renderable import at.hannibal2.skyhanni.utils.renderables.RenderableUtils +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import net.minecraft.enchantment.Enchantment import net.minecraft.item.ItemStack import java.util.Collections @@ -276,6 +278,16 @@ object CollectionUtils { add(Renderable.string(text, horizontalAlign = horizontalAlign, verticalAlign = verticalAlign)) } + // TODO add cache + fun MutableList<Searchable>.addSearchString( + text: String, + searchText: String? = null, + horizontalAlign: RenderUtils.HorizontalAlignment = RenderUtils.HorizontalAlignment.LEFT, + verticalAlign: RenderUtils.VerticalAlignment = RenderUtils.VerticalAlignment.CENTER, + ) { + add(Renderable.string(text, horizontalAlign = horizontalAlign, verticalAlign = verticalAlign).toSearchable(searchText)) + } + // TODO add internal name support, and caching fun MutableList<Renderable>.addItemStack( itemStack: ItemStack, @@ -307,13 +319,22 @@ object CollectionUtils { add(Renderable.horizontalContainer(buildSelector<T>(prefix, getName, isCurrent, onChange))) } + inline fun <reified T : Enum<T>> MutableList<Searchable>.addSearchableSelector( + prefix: String, + getName: (T) -> String, + isCurrent: (T) -> Boolean, + crossinline onChange: (T) -> Unit, + ) { + add(Renderable.horizontalContainer(buildSelector<T>(prefix, getName, isCurrent, onChange)).toSearchable()) + } + // TODO move to RenderableUtils inline fun <reified T : Enum<T>> buildSelector( prefix: String, getName: (T) -> String, isCurrent: (T) -> Boolean, crossinline onChange: (T) -> Unit, - ) = buildList { + ) = buildList<Renderable> { addString(prefix) for (entry in enumValues<T>()) { val display = getName(entry) diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt index 48d5caafb..e916d01e1 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt @@ -99,8 +99,7 @@ interface Renderable { bypassChecks: Boolean = false, highlightsOnHoverSlots: List<Int> = emptyList(), condition: () -> Boolean = { true }, - ): Renderable = - link(string(text), onClick, bypassChecks, highlightsOnHoverSlots = highlightsOnHoverSlots, condition) + ): Renderable = link(string(text), onClick, bypassChecks, highlightsOnHoverSlots = highlightsOnHoverSlots, condition) fun link( renderable: Renderable, @@ -164,9 +163,7 @@ interface Renderable { override val verticalAlign = render.verticalAlign override fun render(posX: Int, posY: Int) { - if (isHovered(posX, posY) && condition() && - shouldAllowLink(true, bypassChecks) && (button - 100).isKeyClicked() - ) { + if (isHovered(posX, posY) && condition() && shouldAllowLink(true, bypassChecks) && (button - 100).isKeyClicked()) { onClick() } render.render(posX, posY) @@ -185,11 +182,8 @@ interface Renderable { override val verticalAlign = render.verticalAlign override fun render(posX: Int, posY: Int) { - if (isHovered(posX, posY) && condition() && - shouldAllowLink(true, bypassChecks) - ) for ((button, onClick) in click) { - if ((button - 100).isKeyClicked()) - onClick() + if (isHovered(posX, posY) && condition() && shouldAllowLink(true, bypassChecks)) for ((button, onClick) in click) { + if ((button - 100).isKeyClicked()) onClick() } render.render(posX, posY) } @@ -265,16 +259,8 @@ interface Renderable { openGui.let { it.startsWith("gg.skytils.vigilance.gui.") || it.startsWith("gg.skytils.skytilsmod.gui.") } val isInNeuSettings = openGui.startsWith("io.github.moulberry.notenoughupdates.") - val result = isGuiScreen && - isGuiPositionEditor && - inMenu && - isNotInSignAndOnSlot && - isConfigScreen && - !isInNeuPv && - !isInSkytilsPv && - !neuFocus && - !isInSkytilsSettings && - !isInNeuSettings + val result = + isGuiScreen && isGuiPositionEditor && inMenu && isNotInSignAndOnSlot && isConfigScreen && !isInNeuPv && !isInSkytilsPv && !neuFocus && !isInSkytilsSettings && !isInNeuSettings if (debug) { if (!result) { @@ -374,20 +360,19 @@ interface Renderable { rescaleSkulls: Boolean = true, horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, verticalAlign: VerticalAlignment = VerticalAlignment.TOP, - ) = - hoverTips( - itemStack( - item, - scale, - xSpacing, - ySpacing, - rescaleSkulls, - horizontalAlign = horizontalAlign, - verticalAlign = verticalAlign, - ), - item.getTooltip(Minecraft.getMinecraft().thePlayer, false), - stack = item, - ) + ) = hoverTips( + itemStack( + item, + scale, + xSpacing, + ySpacing, + rescaleSkulls, + horizontalAlign = horizontalAlign, + verticalAlign = verticalAlign, + ), + item.getTooltip(Minecraft.getMinecraft().thePlayer, false), + stack = item, + ) fun itemStack( item: ItemStack, @@ -497,11 +482,57 @@ interface Renderable { } } + fun searchableTable( + map: Map<List<Renderable?>, String?>, + textInput: TextInput, + key: Int, + xPadding: Int = 1, + yPadding: Int = 0, + useEmptySpace: Boolean = false, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + ) = object : Renderable { + var content = map.keys.toList() + val xOffsets: List<Int> = calculateTableXOffsets(content, xPadding) + val yOffsets: List<Int> = calculateTableYOffsets(content, yPadding) + override val horizontalAlign = horizontalAlign + override val verticalAlign = verticalAlign + + override val width = xOffsets.last() - xPadding + override val height = yOffsets.last() - yPadding + + val emptySpaceX = if (useEmptySpace) 0 else xPadding + val emptySpaceY = if (useEmptySpace) 0 else yPadding + + init { + textInput.registerToEvent(key) { + // null = ignored, never filtered + content = map.filter { it.value?.contains(textInput.textBox, ignoreCase = true) ?: true }.keys.toList() + } + } + + override fun render(posX: Int, posY: Int) { + for ((rowIndex, row) in content.withIndex()) { + for ((index, renderable) in row.withIndex()) { + GlStateManager.pushMatrix() + GlStateManager.translate(xOffsets[index].toFloat(), yOffsets[rowIndex].toFloat(), 0F) + renderable?.renderXYAligned( + posX + xOffsets[index], + posY + yOffsets[rowIndex], + xOffsets[index + 1] - xOffsets[index] - emptySpaceX, + yOffsets[rowIndex + 1] - yOffsets[rowIndex] - emptySpaceY, + ) + GlStateManager.popMatrix() + } + } + } + } + /** * @param content the list of rows the table should render */ fun table( - content: List<List<Renderable?>>, + content: List<List<Renderable>>, xPadding: Int = 1, yPadding: Int = 0, useEmptySpace: Boolean = false, @@ -565,7 +596,6 @@ interface Renderable { color: Color = Color.WHITE, key: Int = 0, ) = object : Renderable { - val textBoxHeight = (9 * scale).toInt() + 1 val isTextBoxEmpty get() = textInput.textBox.isEmpty() @@ -879,6 +909,39 @@ interface Renderable { } } + fun verticalSearchableContainer( + content: Map<Renderable, String?>, + spacing: Int = 0, + textInput: TextInput, + key: Int, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + ) = object : Renderable { + var renderables = filterList(content, textInput.textBox) + + override val width = renderables.maxOfOrNull { it.width } ?: 0 + override val height = renderables.sumOf { it.height } + spacing * (renderables.size - 1) + override val horizontalAlign = horizontalAlign + override val verticalAlign = verticalAlign + + init { + textInput.registerToEvent(key) { + // null = ignored, never filtered + renderables = filterList(content, textInput.textBox) + } + } + + override fun render(posX: Int, posY: Int) { + var yOffset = posY + renderables.forEach { + it.renderXAligned(posX, yOffset, width) + yOffset += it.height + spacing + GlStateManager.translate(0f, (it.height + spacing).toFloat(), 0f) + } + GlStateManager.translate(0f, -height.toFloat() - spacing.toFloat(), 0f) + } + } + fun scrollList( list: List<Renderable>, height: Int, @@ -933,6 +996,83 @@ interface Renderable { } } + fun searchableScrollList( + content: Map<Renderable, String?>, + height: Int, + scrollValue: ScrollValue = ScrollValue(), + velocity: Double = 2.0, + button: Int? = null, + textInput: TextInput, + key: Int, + bypassChecks: Boolean = false, + horizontalAlign: HorizontalAlignment = HorizontalAlignment.LEFT, + verticalAlign: VerticalAlignment = VerticalAlignment.TOP, + ) = object : Renderable { + private var list = filterList(content, textInput.textBox) + override val width = list.maxOf { it.width } + override val height = height + override val horizontalAlign = horizontalAlign + override val verticalAlign = verticalAlign + + init { + textInput.registerToEvent(key) { + // null = ignored, never filtered + list = filterList(content, textInput.textBox) + scroll = createScroll() + } + } + + // correct + private val virtualHeight get() = list.sumOf { it.height } + + private var scroll = createScroll() + + private fun createScroll() = ScrollInput.Companion.Vertical( + scrollValue, + 0, + virtualHeight - height, + velocity, + button, + ) + + private val end get() = scroll.asInt() + height + + override fun render(posX: Int, posY: Int) { + scroll.update( + isHovered(posX, posY) && shouldAllowLink(true, bypassChecks), + ) + + var renderY = 0 + var virtualY = 0 + var found = false + for (renderable in list) { + if ((virtualY..virtualY + renderable.height) in scroll.asInt()..end) { + renderable.renderXAligned(posX, posY + renderY, width) + GlStateManager.translate(0f, renderable.height.toFloat(), 0f) + renderY += renderable.height + found = true + } else if (found) { + found = false + if (renderY + renderable.height <= height) { + renderable.renderXAligned(posX, posY + renderY, width) + } + continue + } + virtualY += renderable.height + } + GlStateManager.translate(0f, -renderY.toFloat(), 0f) + } + } + + private fun filterList(content: Map<Renderable, String?>, textBox: String): Set<Renderable> { + val map = content.filter { it.value?.contains(textBox, ignoreCase = true) ?: true } + val set = map.keys.toMutableSet() + if (map.filter { it.value != null }.isEmpty()) { + set.add(string("§cNo search results!")) + } + return set + } + fun scrollTable( content: List<List<Renderable?>>, height: Int, @@ -988,17 +1128,14 @@ interface Renderable { GlStateManager.translate(0f, yShift.toFloat(), 0f) renderY += yShift } - val range = - yOffsets.indexOfFirst { it >= scroll.asInt() }..<(yOffsets.indexOfFirst { it >= end } - .takeIf { it > 0 } - ?: yOffsets.size) - 1 - - val range2 = - if (range.last + 3 <= yOffsets.size && yOffsets[range.last + 2] - yOffsets[range.first] <= height - renderY) { - range.first..range.last() + 1 - } else { - range - } + val range = yOffsets.indexOfFirst { it >= scroll.asInt() }..<(yOffsets.indexOfFirst { it >= end }.takeIf { it > 0 } + ?: yOffsets.size) - 1 + + val range2 = if (range.last + 3 <= yOffsets.size && yOffsets[range.last + 2] - yOffsets[range.first] <= height - renderY) { + range.first..range.last() + 1 + } else { + range + } for (rowIndex in range2) { for ((index, renderable) in content[rowIndex].withIndex()) { @@ -1242,10 +1379,8 @@ interface Renderable { GlStateManager.color(1f, 1f, 1f, 1f) if (color != null) RenderLivingEntityHelper.setEntityColor(player, color, colorCondition) val mouse = currentRenderPassMousePosition ?: return - val mouseXRelativeToPlayer = - if (followMouse) (posX + playerX - mouse.first).toFloat() else eyesX - val mouseYRelativeToPlayer = - if (followMouse) (posY + playerY - mouse.second - 1.62 * entityScale).toFloat() else eyesY + val mouseXRelativeToPlayer = if (followMouse) (posX + playerX - mouse.first).toFloat() else eyesX + val mouseYRelativeToPlayer = if (followMouse) (posY + playerY - mouse.second - 1.62 * entityScale).toFloat() else eyesY GlStateManager.translate(0f, 0f, 100f) drawEntityOnScreen( playerX, diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt index 4a8f28c8e..9200b467a 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/RenderableUtils.kt @@ -1,7 +1,10 @@ package at.hannibal2.skyhanni.utils.renderables +import at.hannibal2.skyhanni.utils.ChatUtils +import at.hannibal2.skyhanni.utils.CollectionUtils.addString import at.hannibal2.skyhanni.utils.RenderUtils.HorizontalAlignment import at.hannibal2.skyhanni.utils.RenderUtils.VerticalAlignment +import at.hannibal2.skyhanni.utils.SoundUtils import net.minecraft.client.Minecraft import net.minecraft.client.renderer.GlStateManager import java.awt.Color @@ -84,6 +87,36 @@ internal object RenderableUtils { GlStateManager.scale(inverseScale, inverseScale, 1.0) GlStateManager.translate(-1.0, -1.0, 0.0) } + + // TODO move to RenderableUtils + inline fun MutableList<Searchable>.addButton( + prefix: String, + getName: String, + crossinline onChange: () -> Unit, + tips: List<String> = emptyList(), + ) { + val onClick = { + if ((System.currentTimeMillis() - ChatUtils.lastButtonClicked) > 150) { // funny thing happen if I don't do that + onChange() + SoundUtils.playClickSound() + ChatUtils.lastButtonClicked = System.currentTimeMillis() + } + } + add( + Renderable.horizontalContainer( + buildList { + addString(prefix) + addString("§a[") + if (tips.isEmpty()) { + add(Renderable.link("§e$getName", false, onClick)) + } else { + add(Renderable.clickAndHover("§e$getName", tips, false, onClick)) + } + addString("§a]") + }, + ).toSearchable(), + ) + } } internal abstract class RenderableWrapper internal constructor(protected val content: Renderable) : Renderable { diff --git a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Searchable.kt b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Searchable.kt new file mode 100644 index 000000000..8ce7c5ec2 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Searchable.kt @@ -0,0 +1,58 @@ +package at.hannibal2.skyhanni.utils.renderables + +import at.hannibal2.skyhanni.data.model.TextInput +import at.hannibal2.skyhanni.utils.StringUtils.removeColor + +class Searchable(val renderable: Renderable, val string: String?) + +fun Renderable.toSearchable(searchText: String? = null) = Searchable(this, searchText?.removeColor()) +fun Searchable.toRenderable() = renderable +fun List<Searchable>.toRenderable() = map { it.toRenderable() } +fun List<Searchable>.toMap() = associate { it.renderable to it.string } +val searchPrefix = "§eSearch: §7" +fun List<Searchable>.buildSearchBox(): Renderable { + val textInput = TextInput() + val key = 0 + return Renderable.searchBox( + Renderable.verticalSearchableContainer(toMap(), textInput = textInput, key = key + 1), + searchPrefix, + onUpdateSize = { println("onUpdateSize") }, + textInput = textInput, + key = key, + ) +} + +fun List<Searchable>.buildSearchableScrollable( + height: Int, + textInput: TextInput, + scrollValue: ScrollValue = ScrollValue(), + velocity: Double = 2.0, +): Renderable { + val key = 0 + return Renderable.searchBox( + Renderable.searchableScrollList( + toMap(), + textInput = textInput, + key = key + 1, + height = height, + scrollValue = scrollValue, + velocity = velocity, + ), + searchPrefix, + onUpdateSize = { println("onUpdateSize") }, + textInput = textInput, + key = key, + ) +} + +fun Map<List<Renderable>, String?>.buildSearchableTable(): Renderable { + val textInput = TextInput() + val key = 0 + return Renderable.searchBox( + Renderable.searchableTable(toMap(), textInput = textInput, key = key + 1), + searchPrefix, + onUpdateSize = { println("onUpdateSize") }, + textInput = textInput, + key = key, + ) +} diff --git a/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniItemTracker.kt b/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniItemTracker.kt index 8806f3bdb..8d6f98d69 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniItemTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniItemTracker.kt @@ -5,7 +5,7 @@ import at.hannibal2.skyhanni.config.storage.ProfileSpecificStorage import at.hannibal2.skyhanni.data.SlayerAPI import at.hannibal2.skyhanni.data.TrackerManager import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.CollectionUtils.addSelector +import at.hannibal2.skyhanni.utils.CollectionUtils.addSearchableSelector import at.hannibal2.skyhanni.utils.CollectionUtils.sortedDesc import at.hannibal2.skyhanni.utils.ItemPriceSource import at.hannibal2.skyhanni.utils.ItemUtils.itemName @@ -17,13 +17,15 @@ import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators import at.hannibal2.skyhanni.utils.NumberUtil.shortFormat import at.hannibal2.skyhanni.utils.StringUtils.removeColor import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.toSearchable import kotlin.time.Duration.Companion.seconds class SkyHanniItemTracker<Data : ItemTrackerData>( name: String, createNewSession: () -> Data, getStorage: (ProfileSpecificStorage) -> Data, - drawDisplay: (Data) -> List<Renderable>, + drawDisplay: (Data) -> List<Searchable>, ) : SkyHanniTracker<Data>(name, createNewSession, getStorage, drawDisplay) { companion object { @@ -60,9 +62,9 @@ class SkyHanniItemTracker<Data : ItemTrackerData>( } } - fun addPriceFromButton(lists: MutableList<Renderable>) { + fun addPriceFromButton(lists: MutableList<Searchable>) { if (isInventoryOpen()) { - lists.addSelector<ItemPriceSource>( + lists.addSearchableSelector<ItemPriceSource>( "", getName = { type -> type.sellName }, isCurrent = { it.ordinal == config.priceSource.ordinal }, // todo avoid ordinal @@ -77,7 +79,7 @@ class SkyHanniItemTracker<Data : ItemTrackerData>( fun drawItems( data: Data, filter: (NEUInternalName) -> Boolean, - lists: MutableList<Renderable>, + lists: MutableList<Searchable>, ): Double { var profit = 0.0 val items = mutableMapOf<NEUInternalName, Long>() @@ -117,8 +119,9 @@ class SkyHanniItemTracker<Data : ItemTrackerData>( val newDrop = itemProfit.lastTimeUpdated.passedSince() < 10.seconds && config.showRecentDrops val numberColor = if (newDrop) "§a§l" else "§7" + val name = cleanName.removeColor(keepFormatting = true).replace("§r", "") var displayName = if (hidden) { - "§8§m" + cleanName.removeColor(keepFormatting = true).replace("§r", "") + "§8§m$name" } else cleanName displayName = " $numberColor${displayAmount.addSeparators()}x $displayName§7: §6$priceFormat" @@ -149,10 +152,10 @@ class SkyHanniItemTracker<Data : ItemTrackerData>( }, ) else Renderable.string(displayName) - lists.add(renderable) + lists.add(renderable.toSearchable(name)) } if (hiddenItemTexts.size > 0) { - val text = Renderable.hoverTips(" §7${hiddenItemTexts.size} cheap items are hidden.", hiddenItemTexts) + val text = Renderable.hoverTips(" §7${hiddenItemTexts.size} cheap items are hidden.", hiddenItemTexts).toSearchable() lists.add(text) } @@ -190,7 +193,7 @@ class SkyHanniItemTracker<Data : ItemTrackerData>( } } - fun addTotalProfit(profit: Double, totalAmount: Long, action: String): Renderable { + fun addTotalProfit(profit: Double, totalAmount: Long, action: String): Searchable { val profitFormat = profit.toLong().addSeparators() val profitPrefix = if (profit < 0) "§c" else "§6" @@ -201,6 +204,6 @@ class SkyHanniItemTracker<Data : ItemTrackerData>( } else emptyList() val text = "§eTotal Profit: $profitPrefix$profitFormat coins" - return Renderable.hoverTips(text, tips) + return Renderable.hoverTips(text, tips).toSearchable() } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniTracker.kt b/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniTracker.kt index 9d77d4668..5b07c9906 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniTracker.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniTracker.kt @@ -13,6 +13,8 @@ import at.hannibal2.skyhanni.utils.NEUItems.getPrice import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables import at.hannibal2.skyhanni.utils.SimpleTimeMark import at.hannibal2.skyhanni.utils.renderables.Renderable +import at.hannibal2.skyhanni.utils.renderables.Searchable +import at.hannibal2.skyhanni.utils.renderables.buildSearchBox import net.minecraft.client.Minecraft import net.minecraft.client.gui.inventory.GuiChest import net.minecraft.client.gui.inventory.GuiInventory @@ -22,8 +24,7 @@ open class SkyHanniTracker<Data : TrackerData>( val name: String, private val createNewSession: () -> Data, private val getStorage: (ProfileSpecificStorage) -> Data, - // TODO change to renderable - private val drawDisplay: (Data) -> List<Renderable>, + private val drawDisplay: (Data) -> List<Searchable>, ) { private var inventoryOpen = false @@ -83,9 +84,9 @@ open class SkyHanniTracker<Data : TrackerData>( if (dirty || TrackerManager.dirty) { display = getSharedTracker()?.let { - val get = it.get(getDisplayMode()) - val rawList = drawDisplay(get) - buildFinalDisplay(rawList) + val data = it.get(getDisplayMode()) + val searchables = drawDisplay(data) + buildFinalDisplay(searchables.buildSearchBox()) } ?: emptyList() dirty = false } @@ -97,13 +98,14 @@ open class SkyHanniTracker<Data : TrackerData>( dirty = true } - private fun buildFinalDisplay(rawList: List<Renderable>) = rawList.toMutableList().also { - if (it.isEmpty()) return@also + private fun buildFinalDisplay(searchBox: Renderable) = buildList { + add(searchBox) + if (isEmpty()) return@buildList if (inventoryOpen) { - it.add(1, buildDisplayModeView()) + add(buildDisplayModeView()) } if (inventoryOpen && getDisplayMode() == DisplayMode.SESSION) { - it.add(buildSessionResetButton()) + add(buildSessionResetButton()) } } |