diff options
author | hannibal2 <24389977+hannibal002@users.noreply.github.com> | 2024-05-29 07:43:22 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-05-29 07:43:22 +0200 |
commit | 2250aa8b2a64ea1f1850b74c5f4f34ffa617609e (patch) | |
tree | 1c01b2fd03da182f851bf176ec4c6b050c42d1b0 /src/main | |
parent | a1801699f7191de07523c8d54359234645c20520 (diff) | |
download | skyhanni-2250aa8b2a64ea1f1850b74c5f4f34ffa617609e.tar.gz skyhanni-2250aa8b2a64ea1f1850b74c5f4f34ffa617609e.tar.bz2 skyhanni-2250aa8b2a64ea1f1850b74c5f4f34ffa617609e.zip |
Feature: Trophy Fish Display (#1754)
Co-authored-by: hannibal2 <24389977+hannibal00212@users.noreply.github.com>
Diffstat (limited to 'src/main')
18 files changed, 570 insertions, 57 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 8258a58dd..4cb09bfe9 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -177,6 +177,7 @@ import at.hannibal2.skyhanni.features.fishing.tracker.FishingProfitTracker import at.hannibal2.skyhanni.features.fishing.tracker.SeaCreatureTracker import at.hannibal2.skyhanni.features.fishing.trophy.GeyserFishing import at.hannibal2.skyhanni.features.fishing.trophy.OdgerWaypoint +import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishDisplay import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishFillet import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishMessages @@ -734,6 +735,7 @@ class SkyHanniMod { loadModule(SharkFishCounter()) loadModule(PowerStoneGuideFeatures()) loadModule(OdgerWaypoint()) + loadModule(TrophyFishDisplay()) loadModule(TiaRelayHelper()) loadModule(TiaRelayWaypoints()) loadModule(BasketWaypoints()) diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishDisplayConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishDisplayConfig.java new file mode 100644 index 000000000..a4fa9940f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishDisplayConfig.java @@ -0,0 +1,202 @@ +package at.hannibal2.skyhanni.config.features.fishing.trophyfishing; + +import at.hannibal2.skyhanni.config.FeatureToggle; +import at.hannibal2.skyhanni.config.core.config.Position; +import com.google.gson.annotations.Expose; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorBoolean; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDraggableList; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorDropdown; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorKeybind; +import io.github.notenoughupdates.moulconfig.annotations.ConfigEditorSlider; +import io.github.notenoughupdates.moulconfig.annotations.ConfigLink; +import io.github.notenoughupdates.moulconfig.annotations.ConfigOption; +import io.github.notenoughupdates.moulconfig.observer.Property; +import org.lwjgl.input.Keyboard; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class TrophyFishDisplayConfig { + + @Expose + @ConfigOption( + name = "Enabled", + desc = "Show a display of all trophy fishes ever caught." + ) + @ConfigEditorBoolean + @FeatureToggle + public Property<Boolean> enabled = Property.of(false); + + @Expose + @ConfigOption(name = "When Show", desc = "Change when the trophy fish display should be visible in Crimson Isle.") + @ConfigEditorDropdown + public Property<WhenToShow> whenToShow = Property.of(WhenToShow.ALWAYS); + + public enum WhenToShow { + ALWAYS("Always"), + ONLY_IN_INVENTORY("In inventory"), + ONLY_WITH_ROD_IN_HAND("Rod in hand"), + ONLY_WITH_KEYBIND("On keybind"), + ; + + private final String str; + + WhenToShow(String str) { + this.str = str; + } + + @Override + public String toString() { + return str; + } + } + + @Expose + @ConfigOption(name = "Keybind", desc = "") + @ConfigEditorKeybind(defaultKey = Keyboard.KEY_NONE) + public int keybind = Keyboard.KEY_NONE; + + @Expose + @ConfigOption( + name = "Hunter Armor", + desc = "Only show when wearing a full Hunter Armor." + ) + @ConfigEditorBoolean + public Property<Boolean> requireHunterArmor = Property.of(false); + + @Expose + @ConfigOption( + name = "Highlight New", + desc = "Highlight new trophies green for couple seconds." + ) + @ConfigEditorBoolean + public Property<Boolean> highlightNew = Property.of(true); + + @Expose + @ConfigOption(name = "Extra space", desc = "Space between each line of text.") + @ConfigEditorSlider( + minValue = 0, + maxValue = 10, + minStep = 1) + public Property<Integer> extraSpace = Property.of(1); + + @Expose + @ConfigOption(name = "Sorted By", desc = "Sorting type of items in sack.") + @ConfigEditorDropdown + public Property<TrophySorting> sortingType = Property.of(TrophySorting.ITEM_RARITY); + + public enum TrophySorting { + ITEM_RARITY("Item Rarity"), + TOTAL_AMOUNT("Total Amount"), + BRONZE_AMOUNT("Bronze Amount"), + SILVER_AMOUNT("Silver Amount"), + GOLD_AMOUNT("Gold Amount"), + DIAMOND_AMOUNT("Diamond Amount"), + HIGHEST_RARITY("Highest Rariy"), + NAME("Name Alphabetical"), + ; + + private final String str; + + TrophySorting(String str) { + this.str = str; + } + + @Override + public String toString() { + return str; + } + } + + @Expose + @ConfigOption( + name = "Reverse Order", + desc = "Reverse the sorting order." + ) + @ConfigEditorBoolean + public Property<Boolean> reverseOrder = Property.of(false); + + @Expose + @ConfigOption( + name = "Text Order", + desc = "Drag text to change the line format." + ) + @ConfigEditorDraggableList + public Property<List<TextPart>> textOrder = Property.of(new ArrayList<>(Arrays.asList( + TextPart.NAME, + TextPart.ICON, + TextPart.TOTAL, + TextPart.BRONZE, + TextPart.SILVER, + TextPart.GOLD, + TextPart.DIAMOND + ))); + + public enum TextPart { + ICON("Item Icon"), + NAME("Item Name"), + BRONZE("Amount Bronze"), + SILVER("Amount Silver"), + GOLD("Amount Gold"), + DIAMOND("Amount Diamond"), + TOTAL("Amount Total"), + ; + + private final String str; + + TextPart(String str) { + this.str = str; + } + + @Override + public String toString() { + return str; + } + } + + @Expose + @ConfigOption( + name = "Show ✖", + desc = "instead of the number 0, show §c✖ §7 if not found." + ) + @ConfigEditorBoolean + public Property<Boolean> showCross = Property.of(false); + + @Expose + @ConfigOption( + name = "Show ✔", + desc = "instead of the exact numbers, show §e§l✔ §7 if found." + ) + @ConfigEditorBoolean + public Property<Boolean> showCheckmark = Property.of(false); + + @Expose + @ConfigOption(name = "Only Show Missing", desc = "Only show Trophy Fishes that are still missing at this rarity.") + @ConfigEditorDropdown + public Property<HideCaught> onlyShowMissing = Property.of(HideCaught.NONE); + + public enum HideCaught { + NONE("Show All"), + BRONZE("Bronze"), + SILVER("Silver"), + GOLD("Gold"), + DIAMOND("Diamond"), + ; + + private final String str; + + HideCaught(String str) { + this.str = str; + } + + @Override + public String toString() { + return str; + } + } + + @Expose + @ConfigLink(owner = TrophyFishDisplayConfig.class, field = "enabled") + public Position position = new Position(144, 139, false, true); +} diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishingConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishingConfig.java index 25f542863..3449c7b5a 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishingConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishingConfig.java @@ -15,6 +15,11 @@ public class TrophyFishingConfig { public ChatMessagesConfig chatMessages = new ChatMessagesConfig(); @Expose + @ConfigOption(name = "Trophy Fishing Display", desc = "") + @Accordion + public TrophyFishDisplayConfig display = new TrophyFishDisplayConfig(); + + @Expose @ConfigOption(name = "Geyser Fishing", desc = "") @Accordion public GeyserFishingConfig geyserOptions = new GeyserFishingConfig(); diff --git a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt index af68cd847..f10565776 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt @@ -79,7 +79,7 @@ class GuiEditManager { name = if (posLabel == "none") "none " + UUID.randomUUID() else posLabel position.internalName = name } - currentPositions.put(name, position) + currentPositions[name] = position currentBorderSize[posLabel] = Pair(x, y) } diff --git a/src/main/java/at/hannibal2/skyhanni/events/fishing/TrophyFishCaughtEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/fishing/TrophyFishCaughtEvent.kt new file mode 100644 index 000000000..358b057bc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/fishing/TrophyFishCaughtEvent.kt @@ -0,0 +1,7 @@ +package at.hannibal2.skyhanni.events.fishing + +import at.hannibal2.skyhanni.events.LorenzEvent +import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity + +// trophyFishName is NO Neu Internal Name +class TrophyFishCaughtEvent(val trophyFishName: String, val rarity: TrophyRarity) : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt index 3be2e00b8..72a7cb131 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt @@ -11,6 +11,7 @@ import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager.getFilletValue import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity import at.hannibal2.skyhanni.utils.BlockUtils.getBlockAt +import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemCategory import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.ItemUtils.getItemCategoryOrNull @@ -18,7 +19,9 @@ import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzVec import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.StringUtils.matches import at.hannibal2.skyhanni.utils.getLorenzVec +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraft.client.Minecraft import net.minecraft.entity.item.EntityArmorStand import net.minecraft.entity.projectile.EntityFishHook @@ -29,6 +32,11 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent object FishingAPI { + private val trophyArmorNames by RepoPattern.pattern( + "fishing.trophyfishing.armor", + "(BRONZE|SILVER|GOLD|DIAMOND)_HUNTER_(HELMET|CHESTPLATE|LEGGINGS|BOOTS)" + ) + val lavaBlocks = listOf(Blocks.lava, Blocks.flowing_lava) private val waterBlocks = listOf(Blocks.water, Blocks.flowing_water) @@ -43,6 +51,8 @@ object FishingAPI { var bobber: EntityFishHook? = null var bobberHasTouchedWater = false + var wearingTrophyArmor = false + @SubscribeEvent fun onJoinWorld(event: EntityJoinWorldEvent) { if (!LorenzUtils.inSkyBlock || !holdingRod) return @@ -69,6 +79,11 @@ object FishingAPI { @SubscribeEvent fun onTick(event: LorenzTickEvent) { if (!LorenzUtils.inSkyBlock) return + + if (event.isMod(5)) { + wearingTrophyArmor = isWearingTrophyArmor() + } + val bobber = bobber ?: return if (bobber.isDead) { resetBobber() @@ -145,4 +160,8 @@ object FishingAPI { } return 1 } + + private fun isWearingTrophyArmor(): Boolean = InventoryUtils.getArmor().all { + trophyArmorNames.matches(it?.getInternalName()?.asString()) + } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt index 13bd451f7..7587e5536 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt @@ -51,7 +51,7 @@ class ShowFishingItemName { text += name } - itemsOnGround.put(entityItem, text) + itemsOnGround[entityItem] = text } } 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 3f86b5a42..ab9498b8c 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 @@ -4,7 +4,6 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.ConfigLoadEvent import at.hannibal2.skyhanni.events.FishingBobberCastEvent import at.hannibal2.skyhanni.events.GuiRenderEvent -import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.SeaCreatureFishEvent import at.hannibal2.skyhanni.features.fishing.FishingAPI import at.hannibal2.skyhanni.features.fishing.SeaCreatureManager @@ -13,8 +12,6 @@ import at.hannibal2.skyhanni.utils.CollectionUtils.addAsSingletonList import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.CollectionUtils.sumAllValues import at.hannibal2.skyhanni.utils.ConditionalUtils -import at.hannibal2.skyhanni.utils.InventoryUtils -import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.addButton import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators @@ -26,21 +23,13 @@ import at.hannibal2.skyhanni.utils.tracker.SkyHanniTracker import at.hannibal2.skyhanni.utils.tracker.TrackerData import com.google.gson.annotations.Expose import net.minecraftforge.fml.common.eventhandler.SubscribeEvent -import kotlin.time.Duration.Companion.seconds object SeaCreatureTracker { private val config get() = SkyHanniMod.feature.fishing.seaCreatureTracker - private val trophyArmorNames by RepoPattern.pattern( - "fishing.trophyfishing.armor", - "(BRONZE|SILVER|GOLD|DIAMOND)_HUNTER_(HELMET|CHESTPLATE|LEGGINGS|BOOTS)" - ) - private val tracker = SkyHanniTracker("Sea Creature Tracker", { Data() }, { it.fishing.seaCreatureTracker }) { drawDisplay(it) } - private var lastArmorCheck = SimpleTimeMark.farPast() - private var isTrophyFishing = false class Data : TrackerData() { @@ -171,16 +160,6 @@ object SeaCreatureTracker { tracker.resetCommand() } - private fun isEnabled() = LorenzUtils.inSkyBlock && config.enabled && !isTrophyFishing && !LorenzUtils.inKuudraFight - - private fun isWearingTrophyArmor(): Boolean = InventoryUtils.getArmor().all { - trophyArmorNames.matches(it?.getInternalName()?.asString()) - } - - @SubscribeEvent - fun onTick(event: LorenzTickEvent) { - if (lastArmorCheck.passedSince() < 3.seconds) return - lastArmorCheck = SimpleTimeMark.now() - isTrophyFishing = isWearingTrophyArmor() - } + private fun isEnabled() = + LorenzUtils.inSkyBlock && config.enabled && !FishingAPI.wearingTrophyArmor && !LorenzUtils.inKuudraFight } diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishAPI.kt new file mode 100644 index 000000000..fec662f39 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishAPI.kt @@ -0,0 +1,31 @@ +package at.hannibal2.skyhanni.features.fishing.trophy + +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.StringUtils.splitLines + +object TrophyFishAPI { + + fun hoverInfo(internalName: String): String? { + val trophyFishes = TrophyFishManager.fish ?: return null + val info = TrophyFishManager.getInfo(internalName) ?: return null + val counts = trophyFishes[internalName] ?: emptyMap() + val bestFishObtained = counts.keys.maxOrNull() ?: TrophyRarity.BRONZE + val rateString = if (info.rate != null) "§8[§7${info.rate}%§8]" else "" + return """ + |${info.displayName} $rateString + |${info.description.splitLines(150)} + | + |${TrophyRarity.DIAMOND.formattedString}: ${formatCount(counts, TrophyRarity.DIAMOND)} + |${TrophyRarity.GOLD.formattedString}: ${formatCount(counts, TrophyRarity.GOLD)} + |${TrophyRarity.SILVER.formattedString}: ${formatCount(counts, TrophyRarity.SILVER)} + |${TrophyRarity.BRONZE.formattedString}: ${formatCount(counts, TrophyRarity.BRONZE)} + | + |§7Total: ${bestFishObtained.formatCode}${counts.values.sum().addSeparators()} + """.trimMargin() + } + + private fun formatCount(counts: Map<TrophyRarity, Int>, rarity: TrophyRarity): String { + val count = counts.getOrDefault(rarity, 0) + return if (count > 0) "§6${count.addSeparators()}" else "§c✖" + } +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishDisplay.kt new file mode 100644 index 000000000..a25f2d9c2 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishDisplay.kt @@ -0,0 +1,272 @@ +package at.hannibal2.skyhanni.features.fishing.trophy + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.config.features.fishing.trophyfishing.TrophyFishDisplayConfig.HideCaught +import at.hannibal2.skyhanni.config.features.fishing.trophyfishing.TrophyFishDisplayConfig.TextPart +import at.hannibal2.skyhanni.config.features.fishing.trophyfishing.TrophyFishDisplayConfig.TrophySorting +import at.hannibal2.skyhanni.config.features.fishing.trophyfishing.TrophyFishDisplayConfig.WhenToShow +import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.events.ConfigLoadEvent +import at.hannibal2.skyhanni.events.GuiRenderEvent +import at.hannibal2.skyhanni.events.IslandChangeEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.events.fishing.TrophyFishCaughtEvent +import at.hannibal2.skyhanni.features.fishing.FishingAPI +import at.hannibal2.skyhanni.features.misc.items.EstimatedItemValue +import at.hannibal2.skyhanni.test.command.ErrorManager +import at.hannibal2.skyhanni.utils.CollectionUtils.addSingleString +import at.hannibal2.skyhanni.utils.CollectionUtils.addString +import at.hannibal2.skyhanni.utils.CollectionUtils.sumAllValues +import at.hannibal2.skyhanni.utils.ConditionalUtils +import at.hannibal2.skyhanni.utils.DelayedRun +import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull +import at.hannibal2.skyhanni.utils.ItemUtils.itemName +import at.hannibal2.skyhanni.utils.KeyboardManager.isKeyHeld +import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland +import at.hannibal2.skyhanni.utils.NEUInternalName +import at.hannibal2.skyhanni.utils.NEUInternalName.Companion.asInternalName +import at.hannibal2.skyhanni.utils.NEUItems +import at.hannibal2.skyhanni.utils.NEUItems.getItemStack +import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators +import at.hannibal2.skyhanni.utils.RenderUtils.renderRenderables +import at.hannibal2.skyhanni.utils.StringUtils.removeColor +import at.hannibal2.skyhanni.utils.TimeLimitedCache +import at.hannibal2.skyhanni.utils.renderables.Renderable +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.inventory.GuiInventory +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.seconds + +class TrophyFishDisplay { + private val config get() = SkyHanniMod.feature.fishing.trophyFishing.display + + private var recentlyDroppedTrophies = TimeLimitedCache<NEUInternalName, TrophyRarity>(5.seconds) + private val itemNameCache = mutableMapOf<String, NEUInternalName>() + + private var display = emptyList<Renderable>() + + @SubscribeEvent + fun onIslandChange(event: IslandChangeEvent) { + if (event.newIsland == IslandType.CRIMSON_ISLE) { + DelayedRun.runDelayed(200.milliseconds) { + update() + } + } + } + + @SubscribeEvent + fun onTrophyFishCaught(event: TrophyFishCaughtEvent) { + recentlyDroppedTrophies[getInternalName(event.trophyFishName)] = event.rarity + update() + DelayedRun.runDelayed(5.1.seconds) { + update() + } + } + + @SubscribeEvent + fun onProfileJoin(event: ProfileJoinEvent) { + display = emptyList() + update() + } + + @SubscribeEvent + fun onConfigReload(event: ConfigLoadEvent) { + with(config) { + ConditionalUtils.onToggle( + enabled, + highlightNew, + extraSpace, + sortingType, + reverseOrder, + textOrder, + showCross, + showCheckmark, + onlyShowMissing, + ) { + update() + } + } + } + + fun update() { + if (!isEnabled()) return + val list = mutableListOf<Renderable>() + list.addString("§e§lTrophy Fish Display") + list.add(Renderable.table(createTable(), yPadding = config.extraSpace.get())) + + display = list + } + + private fun createTable(): List<List<Renderable>> { + val trophyFishes = TrophyFishManager.fish ?: return emptyList() + val table = mutableListOf<List<Renderable>>() + for ((rawName, data) in getOrder(trophyFishes)) { + addRow(rawName, data, table) + } + if (table.isEmpty()) { + get(config.onlyShowMissing.get())?.let { rarity -> + val name = rarity.formattedString + table.addSingleString("§eYou caught all $name Trophy Fishes") + if (rarity != TrophyRarity.DIAMOND) { + table.addSingleString("§cChange §eOnly Show Missing §cin the config to show more.") + } + } + } + return table + } + + private fun addRow( + rawName: String, + data: MutableMap<TrophyRarity, Int>, + table: MutableList<List<Renderable>>, + ) { + get(config.onlyShowMissing.get())?.let { atLeast -> + val list = TrophyRarity.entries.filter { it <= atLeast } + if (list.all { (data[it] ?: 0) > 0 }) { + return + } + } + val hover = TrophyFishAPI.hoverInfo(rawName) + fun string(string: String): Renderable = hover?.let { + Renderable.hoverTips(Renderable.string(string), tips = it.split("\n")) + } ?: Renderable.string(string) + + val row = mutableMapOf<TextPart, Renderable>() + row[TextPart.NAME] = string(getItemName(rawName)) + + val internalName = getInternalName(rawName) + row[TextPart.ICON] = Renderable.itemStack(internalName.getItemStack()) + + val recentlyDroppedRarity = recentlyDroppedTrophies.getOrNull(internalName).takeIf { config.highlightNew.get() } + + for (rarity in TrophyRarity.entries) { + val amount = data[rarity] ?: 0 + val recentlyDropped = rarity == recentlyDroppedRarity + val format = if (config.showCross.get() && amount == 0) "§c✖" else { + val color = if (recentlyDropped) "§a" else rarity.formatCode + val numberformat = if (config.showCheckmark.get()) "§l✔" else amount.addSeparators() + "$color$numberformat" + } + row[get(rarity)] = string(format) + } + val total = data.sumAllValues() + val color = if (recentlyDroppedRarity != null) "§a" else "§5" + row[TextPart.TOTAL] = string("$color${total.addSeparators()}") + + table.add(config.textOrder.get().mapNotNull { row[it] }) + } + + private fun get(value: TrophyRarity) = when (value) { + TrophyRarity.BRONZE -> TextPart.BRONZE + TrophyRarity.SILVER -> TextPart.SILVER + TrophyRarity.GOLD -> TextPart.GOLD + TrophyRarity.DIAMOND -> TextPart.DIAMOND + } + + private fun get(value: HideCaught) = when (value) { + HideCaught.NONE -> null + HideCaught.BRONZE -> TrophyRarity.BRONZE + HideCaught.SILVER -> TrophyRarity.SILVER + HideCaught.GOLD -> TrophyRarity.GOLD + HideCaught.DIAMOND -> TrophyRarity.DIAMOND + } + + private fun getOrder(trophyFishes: MutableMap<String, MutableMap<TrophyRarity, Int>>) = sort(trophyFishes).let { + if (config.reverseOrder.get()) it.reversed() else it + } + + private fun sort(trophyFishes: Map<String, MutableMap<TrophyRarity, Int>>): List<Map.Entry<String, MutableMap<TrophyRarity, Int>>> = + when (config.sortingType.get()!!) { + TrophySorting.TOTAL_AMOUNT -> trophyFishes.entries.sortedBy { it.value.sumAllValues() } + + TrophySorting.BRONZE_AMOUNT -> count(trophyFishes, TrophyRarity.BRONZE) + TrophySorting.SILVER_AMOUNT -> count(trophyFishes, TrophyRarity.SILVER) + TrophySorting.GOLD_AMOUNT -> count(trophyFishes, TrophyRarity.GOLD) + TrophySorting.DIAMOND_AMOUNT -> count(trophyFishes, TrophyRarity.DIAMOND) + + TrophySorting.ITEM_RARITY -> { + trophyFishes.entries.sortedBy { data -> + val name = getInternalName(data.key) + name.getItemStack().getItemRarityOrNull() + } + } + + TrophySorting.HIGHEST_RARITY -> { + trophyFishes.entries.sortedBy { data -> + TrophyRarity.entries.filter { + data.value.contains(it) + }.maxByOrNull { it.ordinal } + } + } + + TrophySorting.NAME -> { + trophyFishes.entries.sortedBy { data -> + getItemName(data.key).removeColor() + } + } + } + + private fun count( + trophyFishes: Map<String, MutableMap<TrophyRarity, Int>>, rarity: TrophyRarity, + ) = trophyFishes.entries.sortedBy { it.value[rarity] ?: 0 } + + private fun getItemName(rawName: String): String { + val name = getInternalName(rawName).itemName + return name.split(" ").dropLast(1).joinToString(" ").replace("§k", "") + } + + private fun getInternalName(name: String): NEUInternalName { + itemNameCache[name]?.let { + return it + } + // getOrPut does not support our null check + readInternalName(name)?.let { + itemNameCache[name] = it + return it + } + + ErrorManager.skyHanniError( + "No Trophy Fishing name found", + "name" to name + ) + } + + private fun readInternalName(rawName: String): NEUInternalName? { + for ((name, internalName) in NEUItems.allItemsCache) { + val test = name.removeColor().replace(" ", "").replace("-", "") + if (test.startsWith(rawName)) { + return internalName + } + } + if (rawName.endsWith("1")) return "OBFUSCATED_FISH_1_BRONZE".asInternalName() + if (rawName.endsWith("2")) return "OBFUSCATED_FISH_2_BRONZE".asInternalName() + if (rawName.endsWith("3")) return "OBFUSCATED_FISH_3_BRONZE".asInternalName() + + return null + } + + @SubscribeEvent + fun onGuiRender(event: GuiRenderEvent) { + if (!isEnabled()) return + if (!canRender()) return + if (EstimatedItemValue.isCurrentlyShowing()) return + + if (config.requireHunterArmor.get() && !FishingAPI.wearingTrophyArmor) return + + config.position.renderRenderables( + display, + extraSpace = config.extraSpace.get(), + posLabel = "Trophy Fishing Display" + ) + } + + fun canRender(): Boolean = when (config.whenToShow.get()!!) { + WhenToShow.ALWAYS -> true + WhenToShow.ONLY_IN_INVENTORY -> Minecraft.getMinecraft().currentScreen is GuiInventory + WhenToShow.ONLY_WITH_ROD_IN_HAND -> FishingAPI.holdingLavaRod + WhenToShow.ONLY_WITH_KEYBIND -> config.keybind.isKeyHeld() + } + + fun isEnabled() = IslandType.CRIMSON_ISLE.isInIsland() && config.enabled.get() +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishManager.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishManager.kt index 564e56edf..77701c1b0 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishManager.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishManager.kt @@ -8,8 +8,6 @@ import at.hannibal2.skyhanni.events.NeuProfileDataLoadedEvent import at.hannibal2.skyhanni.events.RepositoryReloadEvent import at.hannibal2.skyhanni.test.command.ErrorManager import at.hannibal2.skyhanni.utils.ChatUtils -import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators -import at.hannibal2.skyhanni.utils.StringUtils.splitLines import net.minecraft.event.HoverEvent import net.minecraft.util.ChatComponentText import net.minecraft.util.ChatStyle @@ -81,15 +79,10 @@ object TrophyFishManager { private var trophyFishInfo = mapOf<String, TrophyFishInfo>() - fun getInfo(internalName: String) = trophyFishInfo[internalName] + fun getInfo(internalName: String): TrophyFishInfo? = trophyFishInfo[internalName] fun getInfoByName(name: String) = trophyFishInfo.values.find { it.displayName == name } - private fun formatCount(counts: Map<TrophyRarity, Int>, rarity: TrophyRarity): String { - val count = counts.getOrDefault(rarity, 0) - return if (count > 0) "§6${count.addSeparators()}" else "§c✖" - } - fun TrophyFishInfo.getFilletValue(rarity: TrophyRarity): Int { if (fillet == null) { ErrorManager.logErrorStateWithData( @@ -103,20 +96,8 @@ object TrophyFishManager { return fillet.getOrDefault(rarity, -1) } - fun TrophyFishInfo.getTooltip(counts: Map<TrophyRarity, Int>): ChatStyle { - val bestFishObtained = counts.keys.maxOrNull() ?: TrophyRarity.BRONZE - val rateString = if (rate != null) "§8[§7$rate%§8]" else "" - val display = """ - |$displayName $rateString - |${description.splitLines(150)} - | - |${TrophyRarity.DIAMOND.formattedString}: ${formatCount(counts, TrophyRarity.DIAMOND)} - |${TrophyRarity.GOLD.formattedString}: ${formatCount(counts, TrophyRarity.GOLD)} - |${TrophyRarity.SILVER.formattedString}: ${formatCount(counts, TrophyRarity.SILVER)} - |${TrophyRarity.BRONZE.formattedString}: ${formatCount(counts, TrophyRarity.BRONZE)} - | - |§7Total: ${bestFishObtained.formatCode}${counts.values.sum().addSeparators()} - """.trimMargin() + fun getTooltip(internalName: String): ChatStyle? { + val display = TrophyFishAPI.hoverInfo(internalName) ?: return null return ChatStyle().setChatHoverEvent( HoverEvent(HoverEvent.Action.SHOW_TEXT, ChatComponentText(display)) ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt index 601bfc89e..d6cff8d69 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt @@ -4,6 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.fishing.trophyfishing.ChatMessagesConfig.DesignFormat import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.fishing.TrophyFishCaughtEvent import at.hannibal2.skyhanni.features.fishing.trophy.TrophyFishManager.getTooltip import at.hannibal2.skyhanni.utils.CollectionUtils.addOrPut import at.hannibal2.skyhanni.utils.CollectionUtils.sumAllValues @@ -44,6 +45,7 @@ class TrophyFishMessages { val trophyFishes = TrophyFishManager.fish ?: return val trophyFishCounts = trophyFishes.getOrPut(internalName) { mutableMapOf() } val amount = trophyFishCounts.addOrPut(rarity, 1) + TrophyFishCaughtEvent(internalName, rarity).postAndCatch() if (shouldBlockTrophyFish(rarity, amount)) { event.blockedReason = "low_trophy_fish" @@ -72,8 +74,8 @@ class TrophyFishMessages { } if (config.tooltip) { - TrophyFishManager.getInfo(internalName)?.let { - edited.chatStyle = it.getTooltip(trophyFishCounts) + getTooltip(internalName)?.let { + edited.chatStyle = it } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/HideMobNames.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/HideMobNames.kt index 75fe4b0ee..e6d0fe0f6 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/slayer/HideMobNames.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/HideMobNames.kt @@ -66,7 +66,7 @@ class HideMobNames { return } - lastMobName.put(id, name) + lastMobName[id] = name mobNamesHidden.remove(id) if (shouldNameBeHidden(name)) { diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemsOnGround.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemsOnGround.kt index 7474b1088..bfb21cea5 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemsOnGround.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemsOnGround.kt @@ -31,7 +31,7 @@ class SlayerItemsOnGround { if (itemStack.getInternalName() == NEUInternalName.NONE) continue val (name, price) = SlayerAPI.getItemNameAndPrice(itemStack.getInternalName(), itemStack.stackSize) if (config.minimumPrice > price) continue - itemsOnGround.put(entityItem, name) + itemsOnGround[entityItem] = name } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/summonings/SummoningSoulsName.kt b/src/main/java/at/hannibal2/skyhanni/features/summonings/SummoningSoulsName.kt index cabd8dd4e..e04890620 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/summonings/SummoningSoulsName.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/summonings/SummoningSoulsName.kt @@ -64,8 +64,8 @@ class SummoningSoulsName { val id = entity.entityId val consumer = entity.getNameTagWith(2, "§c❤") if (consumer != null && !consumer.name.contains("§e0")) { - mobsLastLocation.put(id, entity.getLorenzVec()) - mobsName.put(id, consumer.name) + mobsLastLocation[id] = entity.getLorenzVec() + mobsName[id] = consumer.name } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt index 915677bb6..2e1237fe8 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt @@ -156,6 +156,10 @@ object CollectionUtils { add(Collections.singletonList(text)) } + fun MutableList<List<Renderable>>.addSingleString(text: String) { + add(Collections.singletonList(Renderable.string(text))) + } + fun <K, V : Comparable<V>> List<Pair<K, V>>.sorted(): List<Pair<K, V>> { return sortedBy { (_, value) -> value } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt index 182b1381b..caf5b7734 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt @@ -14,11 +14,14 @@ class TimeLimitedCache<K: Any, V: Any>( .removalListener { removalListener(it.key, it.value) } .build<K, V>() - fun put(key: K, value: V) = cache.put(key, value) + // TODO IntelliJ cant replace this, find another way? +// @Deprecated("outdated", ReplaceWith("[key] = value")) + @Deprecated("outdated", ReplaceWith("set(key, value)")) + fun put(key: K, value: V) = set(key, value) fun getOrNull(key: K): V? = cache.getIfPresent(key) - fun getOrPut(key: K, defaultValue: () -> V) = getOrNull(key) ?: defaultValue().also { put(key, it) } + fun getOrPut(key: K, defaultValue: () -> V) = getOrNull(key) ?: defaultValue().also { set(key, it) } fun clear() = cache.invalidateAll() @@ -31,4 +34,8 @@ class TimeLimitedCache<K: Any, V: Any>( fun containsKey(key: K): Boolean = cache.getIfPresent(key) != null override fun iterator(): Iterator<Map.Entry<K, V>> = entries().iterator() + + operator fun set(key: K, value: V) { + cache.put(key, value) + } } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt index fae86fac5..aab5595da 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt @@ -2,14 +2,16 @@ package at.hannibal2.skyhanni.utils import kotlin.time.Duration -class TimeLimitedSet<T: Any>( +class TimeLimitedSet<T : Any>( expireAfterWrite: Duration, private val removalListener: (T) -> Unit = {}, ) { private val cache = TimeLimitedCache<T, Unit>(expireAfterWrite) { key, _ -> key?.let { removalListener(it) } } - fun add(element: T) = cache.put(element, Unit) + fun add(element: T) { + cache[element] = Unit + } operator fun contains(element: T): Boolean = cache.containsKey(element) |