aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal002@users.noreply.github.com>2024-05-29 07:43:22 +0200
committerGitHub <noreply@github.com>2024-05-29 07:43:22 +0200
commit2250aa8b2a64ea1f1850b74c5f4f34ffa617609e (patch)
tree1c01b2fd03da182f851bf176ec4c6b050c42d1b0 /src/main/java
parenta1801699f7191de07523c8d54359234645c20520 (diff)
downloadskyhanni-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/java')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishDisplayConfig.java202
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/fishing/trophyfishing/TrophyFishingConfig.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/data/GuiEditManager.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/events/fishing/TrophyFishCaughtEvent.kt7
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/FishingAPI.kt19
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/ShowFishingItemName.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/tracker/SeaCreatureTracker.kt25
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishAPI.kt31
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishDisplay.kt272
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishManager.kt25
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/fishing/trophy/TrophyFishMessages.kt6
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/HideMobNames.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerItemsOnGround.kt2
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/summonings/SummoningSoulsName.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/CollectionUtils.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedCache.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/TimeLimitedSet.kt6
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)