diff --git a/CHANGELOG.md b/CHANGELOG.md
index cfe6bc44e54e..a773164acb58 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,21 @@
+ Added Sea Creature Tracker. - hannibal2
+ Allows to only show single variants, e.g. water or lava or winter.
+#### Inventory Features
+
++ Added Power Stone Guide features. - hannibal2
+ + Highlight missing power stones, show their total bazaar price, and allows to open the bazaar when clicking on the
+ items in the Power Stone Guide.
++ Option to make normal clicks to shift clicks in equipment inventory. - Thunderblade73
+
+#### Item Features
+
++ Lesser Orb of Healing Hider. - jani
+
+#### Chat Features
+
++ Add tab list fire sale advertisement hider. - nea
+
### Changes
#### Garden Changes
@@ -29,6 +44,9 @@
+ Don't count Bountiful as a max reforge fortune on tools. - alexia
+ /shcroptime now supports k, m and b numbers. - DylanBruner
+ Only show the Garden Vacuum Bag on your own vacuums. - alexia
++ Jacob Contest feature now has clickable calendar open command when Elite API is not ready yet. - alexia
++ Mark carrot/pumpkin fortune as completed when giving to Carrolyn after already done. - alexia
++ Added ability to get unique visitors served without Green Thumb. - alexia
#### Rift Changes
@@ -41,6 +59,7 @@
#### Fishing Changes
+ Odger highlight feature tells in description that it is only useful for users without abiphone. - hannibal2
++ Added toggle to count double hook catches as two catches in Sea Creature Tracker. - hannibal2
#### Mining Changes
@@ -60,6 +79,7 @@
#### Dungeon Changes
+ Changed the description of the Dungeon Chat Filter feature to be more descriptive. - Wambo
++ Added options to change exactly what part of the Dungeon Chat Filter should be used. - Wambo
#### Chat Changes
@@ -81,15 +101,21 @@
hannibal2
+ Auto-fixing plots marked as pests when killing all pests without SkyHanni earlier. - hannibal2
+ Fixed error message that nearest pests cannot get removed properly. - hannibal2
++ Fixed grammar in Jacob Contest chat messages. - alexia
++ Fixed rarity error for items thrown around when using Sprayanator. - hannibal2
#### Combat Fixes
+ Fixed corrupted Kada Knight getting detected as Revenant Slayer mini boss. - hannibal2
++ Fixed Daily Kuudra part of Crimson Isle Reputation Helper not detecting completed runs. - hannibal2
++ Fixed wrong calculation when zero bosses killed in slayer profit trackers. - hannibal2
++ Hide No Fishing Bait warning during Kuudra fight. - hannibal2
#### Mining Fixes
+ Fixed an error when showing all elements in Powder Tracker. - hannibal2
+ Fixed powder tracker detecting gemstone chat messages. - CalMWolfs
++ Fixed Mining Chat Filter not hiding gemstone messages. - CalMWolfs
#### Rift Fixes
@@ -117,6 +143,10 @@
+ Fixed poisoned candy potion chat message not getting compacted. - alexia
+#### GUI Fixes
+
++ Fixed items in SkyHanni GUI elements rendering over minecraft menus. - Thunderblade73
+
#### Misc Fixes
+ Maybe fixed Tia Relay Helper. - Thunderblade73
@@ -138,6 +168,12 @@
+ Moving minion craft helper fully over to neu internal names. - hannibal2
+ Added information about trackers to the Discord FAQ. - j10a1n15
+ Defined the way how dependent PRs should be written in contributing.md. - Thunderblade73
++ Added debug command /shtestburrow. - hannibal2
++ Using SkyHanniMod.coroutineScope instead of CoroutineScope(Dispatchers.Default). - CalMWolfs
++ Creating function addTotalProfit for item trackers. - hannibal2
++ Tell people how to name a pattern variable. - CalMWolfs
++ Typo fixes in contributing md. - CalMWolfs
++ Make Repo Pattern keys more consistent for Farming Gear. - CalMWolfs
## Version 0.22
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 67d8e3c0b4c0..8df368ead409 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -71,14 +71,15 @@ format like "- #821" to illustrate the dependency.
- See [this commit](https://github.com/hannibal002/SkyHanni/commit/3d748cb79f3a1afa7f1a9b7d0561e5d7bb284a9b)
as an example.
- Try to avoid using kotlin's `!!` (catch if not null) feature.
- - Replace it with `?:` (ff null return this).
- - This will most likely not be possible to avoid when working with obects from java.
+ - Replace it with `?:` (if null return this).
+ - This will most likely not be possible to avoid when working with objects from java.
- Don't forget to add `@FeatureToggle` to new standalone features (not options to that feature) in the config.
- Do not use `e.printStackTrace()`, use `CopyErrorCommand.logError(e, "explanation for users")` instead.
- Do not use `MinecraftForge.EVENT_BUS.post(event)`, use `event.postAndCatch()` instead.
- Do not use `toRegex()` or `toPattern()`, use `RepoPattern` instead.
- See [RepoPattern.kt](https://github.com/walkerselby/SkyHanni/blob/beta/src/main/java/at/hannibal2/skyhanni/utils/repopatterns/RepoPattern.kt)
- for more information and usages.
+for more information and usages.
+ - The pattern variables are named in the scheme `variableNamePattern`
- Please use Regex instead of String comparison when it is likely Hypixel will change the message in the future.
## Software Used in SkyHanni
@@ -116,8 +117,8 @@ For more information, see https://github.com/NotEnoughUpdates/MoulConfig
SkyHanni utilizes the [Elite API](https://api.elitebot.dev/) (view the [public site here](https://elitebot.dev)) for
some farming features.
-This includes features relating to Farming Weight, as well as syncing jacob contests amongst players for conviencience.
-All data sent is anonymonized and opt-in.
+This includes features relating to Farming Weight, as well as syncing jacob contests amongst players for convenience.
+All data sent is anonymized and opt-in.
### Mixin
@@ -128,7 +129,7 @@ It allows to easily modify methods in Minecraft itself, without conflicting with
For more information, see https://github.com/SpongePowered/Mixin or [our existing mixins](https://github.com/hannibal002/SkyHanni/tree/beta/src/main/java/at/hannibal2/skyhanni/mixins/transformers).
-When creating new Mixins, try to keep the code inside of the mixin as small as possible, and calling a hook as soon as
+When creating new Mixins, try to keep the code inside the mixin as small as possible, and calling a hook as soon as
possible.
### Repo
diff --git a/FEATURES.md b/FEATURES.md
index 836aecfedff3..76a8ee2e16a7 100644
--- a/FEATURES.md
+++ b/FEATURES.md
@@ -30,6 +30,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game.
+ Optional if left or right side of name.
+ Should not break with other mods.
+ Hide the repeating fire sale reminder chat messages. - hannibal2
++ Add tab list fire sale advertisement hider. - nea
#### Chat Filter
@@ -132,6 +133,10 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game.
+ This removes the need to shift-click to swap the equipment items, without the annoying "pick up animation".
+ Added Copy Underbid Price. - hannibal2
+ Copies the price of an item in the "Create BIN Auction" minus 1 coin into the clipboard for faster under-bidding.
++ Added Power Stone Guide features. - hannibal2
+ + Highlight missing power stones, show their total bazaar price, and allows to open the bazaar when clicking on the
+ items in the Power Stone Guide.
++ Option to make normal clicks to shift clicks in equipment inventory. - Thunderblade73
@@ -145,6 +150,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game.
+ Supports dungeon mage cooldown reduction. - Cad
+ Hiding the flame particles when using the Fire Veil Wand ability.
+ Circle around the player when having the Fire Veil Wand ability active.
++ Lesser Orb of Healing Hider. - jani
diff --git a/build.gradle.kts b/build.gradle.kts
index 23773b307343..e7f55fadd021 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -13,7 +13,7 @@ plugins {
}
group = "at.hannibal2.skyhanni"
-version = "0.23.Beta.6"
+version = "0.23.Beta.7"
val gitHash by lazy {
val baos = ByteArrayOutputStream()
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
index 218b2f88fd3d..a7d46b4ab740 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt
@@ -205,10 +205,12 @@ import at.hannibal2.skyhanni.features.inventory.HideNotClickableItems
import at.hannibal2.skyhanni.features.inventory.HighlightBonzoMasks
import at.hannibal2.skyhanni.features.inventory.ItemDisplayOverlayFeatures
import at.hannibal2.skyhanni.features.inventory.ItemStars
+import at.hannibal2.skyhanni.features.inventory.PowerStoneGuideFeatures
import at.hannibal2.skyhanni.features.inventory.QuickCraftFeatures
import at.hannibal2.skyhanni.features.inventory.RngMeterInventory
import at.hannibal2.skyhanni.features.inventory.SackDisplay
import at.hannibal2.skyhanni.features.inventory.ShiftClickEquipment
+import at.hannibal2.skyhanni.features.inventory.ShiftClickNPCSell
import at.hannibal2.skyhanni.features.inventory.SkyBlockLevelGuideHelper
import at.hannibal2.skyhanni.features.inventory.StatsTuning
import at.hannibal2.skyhanni.features.inventory.tiarelay.TiaRelayHelper
@@ -235,6 +237,7 @@ import at.hannibal2.skyhanni.features.misc.FixNEUHeavyPearls
import at.hannibal2.skyhanni.features.misc.HideArmor
import at.hannibal2.skyhanni.features.misc.InGameDateDisplay
import at.hannibal2.skyhanni.features.misc.JoinCrystalHollows
+import at.hannibal2.skyhanni.features.misc.LesserOrbHider
import at.hannibal2.skyhanni.features.misc.LimboTimeTracker
import at.hannibal2.skyhanni.features.misc.LockMouseLook
import at.hannibal2.skyhanni.features.misc.MarkedPlayerManager
@@ -365,7 +368,7 @@ import org.apache.logging.log4j.Logger
clientSideOnly = true,
useMetadata = true,
guiFactory = "at.hannibal2.skyhanni.config.ConfigGuiForgeInterop",
- version = "0.23.Beta.6",
+ version = "0.23.Beta.7",
)
class SkyHanniMod {
@Mod.EventHandler
@@ -516,6 +519,7 @@ class SkyHanniMod {
loadModule(SoopyGuessBurrow())
loadModule(DianaProfitTracker)
loadModule(MythologicalCreatureTracker)
+ loadModule(ShiftClickNPCSell)
loadModule(HighlightJerries())
loadModule(TheGreatSpook())
loadModule(GriffinBurrowHelper)
@@ -529,10 +533,12 @@ class SkyHanniMod {
loadModule(CompactBingoChat())
loadModule(BrewingStandOverlay())
loadModule(FishingTimer())
+ loadModule(LesserOrbHider())
loadModule(FishingHookDisplay())
loadModule(CrimsonIsleReputationHelper(this))
loadModule(SharkFishCounter())
loadModule(SkyBlockLevelGuideHelper())
+ loadModule(PowerStoneGuideFeatures())
loadModule(OdgerWaypoint())
loadModule(TiaRelayHelper())
loadModule(TiaRelayWaypoints())
diff --git a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
index 3c7aaaa12114..f3fce19846d9 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
+++ b/src/main/java/at/hannibal2/skyhanni/config/commands/Commands.kt
@@ -16,6 +16,7 @@ import at.hannibal2.skyhanni.features.combat.ghostcounter.GhostUtil
import at.hannibal2.skyhanni.features.commands.PartyCommands
import at.hannibal2.skyhanni.features.event.diana.BurrowWarpHelper
import at.hannibal2.skyhanni.features.event.diana.DianaProfitTracker
+import at.hannibal2.skyhanni.features.event.diana.GriffinBurrowHelper
import at.hannibal2.skyhanni.features.event.diana.InquisitorWaypointShare
import at.hannibal2.skyhanni.features.event.diana.MythologicalCreatureTracker
import at.hannibal2.skyhanni.features.event.jerry.frozentreasure.FrozenTreasureTracker
@@ -317,6 +318,10 @@ object Commands {
"shconfigsave",
"Manually saving the config"
) { SkyHanniMod.configManager.saveConfig(ConfigFileType.FEATURES, "manual-command") }
+ registerCommand(
+ "shtestburrow",
+ "Sets a test burrow waypoint at your location"
+ ) { GriffinBurrowHelper.setTestBurrow(it) }
}
private fun developersCodingHelp() {
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java
index 52ecc0aa3bc8..1784d916dcf9 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/chat/ChatConfig.java
@@ -4,10 +4,14 @@
import com.google.gson.annotations.Expose;
import io.github.moulberry.moulconfig.annotations.Accordion;
import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
+import io.github.moulberry.moulconfig.annotations.ConfigEditorDraggableList;
import io.github.moulberry.moulconfig.annotations.ConfigEditorKeybind;
import io.github.moulberry.moulconfig.annotations.ConfigOption;
import org.lwjgl.input.Keyboard;
+import java.util.ArrayList;
+import java.util.List;
+
public class ChatConfig {
@Expose
@@ -32,10 +36,36 @@ public class ChatConfig {
public ChatSymbols chatSymbols = new ChatSymbols();
@Expose
- @ConfigOption(name = "Dungeon Filter", desc = "Hides pickup, reminder, buff, damage, ability, puzzle and end messages in Dungeons.")
- @ConfigEditorBoolean
- @FeatureToggle
- public boolean dungeonMessages = true;
+ @ConfigOption(name = "Dungeon Filter", desc = "Hide specific message types in Dungeons.")
+ @ConfigEditorDraggableList
+ public List dungeonFilteredMessageTypes = new ArrayList<>();
+
+
+ public enum DungeonMessageTypes {
+ PREPARE("§bPreparation"),
+ START("§aClass Buffs §r/ §cMort Dialogue"),
+ AMBIENCE("§bAmbience"),
+ PICKUP("§ePickup"),
+ REMINDER("§cReminder"),
+ BUFF("§dBlessings"),
+ NOT_POSSIBLE("§cNot possible"),
+ DAMAGE("§cDamage"),
+ ABILITY("§dAbilities"),
+ PUZZLE("§dPuzzle §r/ §cQuiz"),
+ END("§cEnd §a(End of run spam)"),
+ ;
+
+ private final String name;
+
+ DungeonMessageTypes(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+ }
@Expose
@ConfigOption(name = "Dungeon Boss Messages", desc = "Hide messages from the Watcher and bosses in the Dungeon.")
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/SeaCreatureTrackerConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/SeaCreatureTrackerConfig.java
index 91c26aa21108..4558e1413e35 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/fishing/SeaCreatureTrackerConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/fishing/SeaCreatureTrackerConfig.java
@@ -27,4 +27,9 @@ public class SeaCreatureTrackerConfig {
@ConfigOption(name = "Hide Chat", desc = "Hide the chat messages when catching a sea creature.")
@ConfigEditorBoolean
public boolean hideChat = false;
+
+ @Expose
+ @ConfigOption(name = "Count Double", desc = "Count double hook catches as two catches.")
+ @ConfigEditorBoolean
+ public boolean countDouble = true;
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
index 80ee5023312a..0aed8ec3f7c3 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/inventory/InventoryConfig.java
@@ -9,7 +9,6 @@
import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean;
import io.github.moulberry.moulconfig.annotations.ConfigEditorDraggableList;
import io.github.moulberry.moulconfig.annotations.ConfigOption;
-
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -155,6 +154,13 @@ public String toString() {
@FeatureToggle
public boolean highlightMissingSkyBlockLevelGuide = true;
+ @Expose
+ @ConfigOption(name = "Power Stone Guide",
+ desc = "Highlight missing power stones, show their total bazaar price, and allows to open the bazaar when clicking on the items in the Power Stone Guide.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean powerStoneGuide = true;
+
@Expose
@ConfigOption(name = "Highlight Auctions",
desc = "Highlight own items that are sold in green and that are expired in red.")
@@ -177,9 +183,15 @@ public String toString() {
public boolean copyUnderbidPrice = false;
@Expose
- @ConfigOption(name = "Shift Click Equipment", desc = "Makes normal clicks to shift clicks in equipment inventory")
+ @ConfigOption(name = "Shift Click Equipment", desc = "Makes normal clicks to shift clicks in equipment inventory.")
@ConfigEditorBoolean
@FeatureToggle
public boolean shiftClickForEquipment = false;
+ @Expose
+ @ConfigOption(name = "Shift Click NPC sell", desc = "Makes normal clicks to shift clicks in npc inventory for selling.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean shiftClickNPCSell = false;
+
}
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java
index 350f321f27c3..69db7f53d1b0 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/MiscConfig.java
@@ -203,6 +203,14 @@ public class MiscConfig {
@FeatureToggle
public boolean showTimeInLimbo = true;
+ @Expose
+ @ConfigOption(
+ name = "Lesser Orb of Healing Hider",
+ desc = "Hides the Lesser Orb of Healing.")
+ @ConfigEditorBoolean
+ @FeatureToggle
+ public boolean lesserOrbHider = false;
+
@Expose
@ConfigOption(
name = "Lock Mouse Message",
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/misc/compacttablist/CompactTabListConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/misc/compacttablist/CompactTabListConfig.java
index 2236d886b6cf..4d5530ea39fc 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/misc/compacttablist/CompactTabListConfig.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/misc/compacttablist/CompactTabListConfig.java
@@ -20,6 +20,11 @@ public class CompactTabListConfig {
@ConfigEditorBoolean
public boolean hideAdverts = false;
+ @Expose
+ @ConfigOption(name = "Hide Fire Sale Adverts", desc = "Hides fire sales from the tablist")
+ @ConfigEditorBoolean
+ public boolean hideFiresales = false;
+
@Expose
@ConfigOption(name = "Advanced Player List", desc = "")
@Accordion
diff --git a/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt b/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt
index aa942f5bc651..a3eef5dd9df5 100644
--- a/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt
+++ b/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt
@@ -5,7 +5,7 @@ enum class IslandType(val displayName: String, val modeName: String = "null") {
PRIVATE_ISLAND("Private Island"),
PRIVATE_ISLAND_GUEST("Private Island Guest"),
THE_END("The End"),
- KUUDRA_ARENA("Instanced"),
+ KUUDRA_ARENA("Kuudra"),
CRIMSON_ISLE("Crimson Isle"),
DWARVEN_MINES("Dwarven Mines"),
DUNGEON_HUB("Dungeon Hub", "dungeon_hub"),
diff --git a/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt
index 767643755893..90d68ed35a15 100644
--- a/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt
+++ b/src/main/java/at/hannibal2/skyhanni/events/LorenzEvent.kt
@@ -66,4 +66,9 @@ abstract class LorenzEvent : Event() {
}
fun postWithoutCatch() = MinecraftForge.EVENT_BUS.post(this)
+
+ // TODO let walker use this function for all 101 other uses
+ fun cancel() {
+ isCanceled = true
+ }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/events/SkipTabListLineEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SkipTabListLineEvent.kt
new file mode 100644
index 000000000000..0250b821f1f5
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/events/SkipTabListLineEvent.kt
@@ -0,0 +1,11 @@
+package at.hannibal2.skyhanni.events
+
+import at.hannibal2.skyhanni.features.misc.compacttablist.TabLine
+import net.minecraftforge.fml.common.eventhandler.Cancelable
+
+@Cancelable
+data class SkipTabListLineEvent(
+ val line: TabLine,
+ val lastSubTitle: TabLine?,
+ val lastTitle: TabLine?,
+) : LorenzEvent()
diff --git a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
index a0037812c39a..48e1b0175732 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/chat/ChatFilter.kt
@@ -281,8 +281,8 @@ class ChatFilter {
// Powder Mining
private val powderMiningPatterns = listOf(
"§cYou need a stronger tool to mine (Amethyst|Ruby|Jade|Amber|Sapphire|Topaz) Gemstone Block§r§c.".toPattern(),
- "§aYou received §r§f\\d* §r§f[❤❈☘⸕✎✧] §r§fRough (Ruby|Amethyst|Jade|Amber|Sapphire|Topaz) Gemstone§r§a\\.".toPattern(),
- "§aYou received §r§f\\d §r§a[❤❈☘⸕✎✧] §r§aFlawed (Ruby|Amethyst|Jade|Amber|Sapphire|Topaz) Gemstone§r§a\\.".toPattern(),
+ "§aYou received §r§f\\d* §r§f[❤❈☘⸕✎✧] Rough (Ruby|Amethyst|Jade|Amber|Sapphire|Topaz) Gemstone§r§a\\.".toPattern(),
+ "§aYou received §r§f\\d §r§a[❤❈☘⸕✎✧] Flawed (Ruby|Amethyst|Jade|Amber|Sapphire|Topaz) Gemstone§r§a\\.".toPattern(),
// Jungle
"§aYou received §r§f\\d* §r§aSludge Juice§r§a\\.".toPattern(),
diff --git a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt
index 4bc4b3c46d39..3a29ac603288 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/dungeon/DungeonChatFilter.kt
@@ -1,12 +1,15 @@
package at.hannibal2.skyhanni.features.dungeon
import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.config.features.chat.ChatConfig
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.StringUtils.matches
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import java.util.regex.Pattern
+private typealias MessageTypes = ChatConfig.DungeonMessageTypes
+
class DungeonChatFilter {
private val config get() = SkyHanniMod.feature.chat
@@ -110,10 +113,7 @@ class DungeonChatFilter {
"§4[STATUE] Oruo the Omniscient§r§f: §r§fI've had enough of you and your party fiddling with my buttons. Scram!",
"§4[STATUE] Oruo the Omniscient§r§f: §r§fEnough! My buttons are not to be pressed with such lack of grace!"
)
- private val unsortedBlockedPatterns = listOf( // TODO sort out and filter separately
- "(.*) §r§ehas obtained §r§a§r§9Beating Heart§r§e!".toPattern()
- )
- private val unsortedBlockedMessages = listOf(
+ private val ambienceMessages = listOf(
"§5A shiver runs down your spine..."
)
private val reminderMessages = listOf(
@@ -133,7 +133,8 @@ class DungeonChatFilter {
"§c(.*) §r§eYou picked up a Ability Damage Orb from (.*) §r§ehealing you for §r§c(.*) §r§eand granting you +§r§c(.*)% §r§eAbility Damage for §r§b10 §r§eseconds.".toPattern(),
"§c(.*) §r§eYou picked up a Damage Orb from (.*) §r§ehealing you for §r§c(.*) §r§eand granting you +§r§c(.*)% §r§eDamage for §r§b10 §r§eseconds.".toPattern(),
"(.*) §r§ehas obtained §r§a§r§9Premium Flesh§r§e!".toPattern(),
- "§6§lRARE DROP! §r§9Beating Heart §r§b(.*)".toPattern()
+ "§6§lRARE DROP! §r§9Beating Heart §r§b(.*)".toPattern(),
+ "(.*) §r§ehas obtained §r§a§r§9Beating Heart§r§e!".toPattern()
)
private val pickupMessages = listOf(
"§fYou found a §r§dWither Essence§r§f! Everyone gains an extra essence!"
@@ -161,37 +162,36 @@ class DungeonChatFilter {
"§aYou can no longer consume or splash any potions during the remainder of this Dungeon run!",
)
- private val messagesMap: Map> = mapOf(
- "prepare" to prepareMessages,
- "start" to startMessages,
- "unsorted" to unsortedBlockedMessages,
- "pickup" to pickupMessages,
- "reminder" to reminderMessages,
- "buff" to buffMessages,
- "not_possible" to notPossibleMessages,
- "damage" to damageMessages,
- "ability" to abilityMessages,
- "puzzle" to puzzleMessages,
- )
- private val patternsMap: Map> = mapOf(
- "prepare" to preparePatterns,
- "start" to startPatterns,
- "unsorted" to unsortedBlockedPatterns,
- "pickup" to pickupPatterns,
- "buff" to buffPatterns,
- "damage" to damagePatterns,
- "ability" to abilityPatterns,
- "puzzle" to puzzlePatterns,
- "end" to endPatterns,
- )
- private val messagesEndsWithMap: Map> = mapOf(
- "end" to endMessagesEndWith,
+ private val messagesMap: Map> = mapOf(
+ MessageTypes.PREPARE to prepareMessages,
+ MessageTypes.START to startMessages,
+ MessageTypes.AMBIENCE to ambienceMessages,
+ MessageTypes.PICKUP to pickupMessages,
+ MessageTypes.REMINDER to reminderMessages,
+ MessageTypes.BUFF to buffMessages,
+ MessageTypes.NOT_POSSIBLE to notPossibleMessages,
+ MessageTypes.DAMAGE to damageMessages,
+ MessageTypes.ABILITY to abilityMessages,
+ MessageTypes.PUZZLE to puzzleMessages,
+ )
+ private val patternsMap: Map> = mapOf(
+ MessageTypes.PREPARE to preparePatterns,
+ MessageTypes.START to startPatterns,
+ MessageTypes.PICKUP to pickupPatterns,
+ MessageTypes.BUFF to buffPatterns,
+ MessageTypes.DAMAGE to damagePatterns,
+ MessageTypes.ABILITY to abilityPatterns,
+ MessageTypes.PUZZLE to puzzlePatterns,
+ MessageTypes.END to endPatterns,
+ )
+ private val messagesEndsWithMap: Map> = mapOf(
+ MessageTypes.END to endMessagesEndWith,
)
///
@SubscribeEvent
fun onChatMessage(event: LorenzChatEvent) {
- if (!LorenzUtils.onHypixel || !config.dungeonMessages) return
+ if (!LorenzUtils.onHypixel || config.dungeonFilteredMessageTypes.isEmpty()) return
// Workaround since the potion message gets always sent at that moment when SkyBlock is set as false
if (!LorenzUtils.inSkyBlock && !event.message.startsWith("§aYour active Potion Effects")) return
@@ -204,26 +204,30 @@ class DungeonChatFilter {
private fun block(message: String): String {
when {
- message.isPresent("prepare") -> return "prepare"
- message.isPresent("start") -> return "start"
+ message.isFiltered(MessageTypes.PREPARE) -> return "prepare"
+ message.isFiltered(MessageTypes.START) -> return "start"
}
if (!LorenzUtils.inDungeons) return ""
return when {
- message.isPresent("unsorted") -> "unsorted"
- message.isPresent("pickup") -> "pickup"
- message.isPresent("reminder") -> "reminder"
- message.isPresent("buff") -> "buff"
- message.isPresent("not_possible") -> "not_possible"
- message.isPresent("damage") -> "damage"
- message.isPresent("ability") -> "ability"
- message.isPresent("puzzle") -> "puzzle"
- message.isPresent("end") -> "end"
+ message.isFiltered(MessageTypes.AMBIENCE) -> "ambience"
+ message.isFiltered(MessageTypes.PICKUP) -> "pickup"
+ message.isFiltered(MessageTypes.REMINDER) -> "reminder"
+ message.isFiltered(MessageTypes.BUFF) -> "buff"
+ message.isFiltered(MessageTypes.NOT_POSSIBLE) -> "not_possible"
+ message.isFiltered(MessageTypes.DAMAGE) -> "damage"
+ message.isFiltered(MessageTypes.ABILITY) -> "ability"
+ message.isFiltered(MessageTypes.PUZZLE) -> "puzzle"
+ message.isFiltered(MessageTypes.END) -> "end"
else -> ""
}
}
+ private fun String.isFiltered(key: MessageTypes) : Boolean {
+ return config.dungeonFilteredMessageTypes.contains(key) && this.isPresent(key)
+ }
+
/**
* Checks if the message is present in the list of messages or patterns
* Checks against three maps that compare in different ways.
@@ -234,7 +238,7 @@ class DungeonChatFilter {
* @see patternsMap
* @see messagesEndsWithMap
*/
- private fun String.isPresent(key: String): Boolean {
+ private fun String.isPresent(key: MessageTypes): Boolean {
return this in (messagesMap[key] ?: emptyList()) ||
(patternsMap[key] ?: emptyList()).any { it.matches(this) } ||
(messagesEndsWithMap[key] ?: emptyList()).any { this.endsWith(it) }
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 67468351f943..5b8776bec779 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
@@ -81,19 +81,7 @@ object DianaProfitTracker {
)
)
- val profitFormat = profit.addSeparators()
- val profitPrefix = if (profit < 0) "§c" else "§6"
-
- val profitPerBurrow = profit / data.burrowsDug
- val profitPerBurrowFormat = NumberUtil.format(profitPerBurrow)
-
- val text = "§eTotal Profit: $profitPrefix$profitFormat coins"
- addAsSingletonList(
- Renderable.hoverTips(
- text,
- listOf("§7Profit per burrow: $profitPrefix$profitPerBurrowFormat")
- )
- )
+ addAsSingletonList(tracker.addTotalProfit(profit, data.burrowsDug, "burrow"))
tracker.addPriceFromButton(this)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt
index b611f77eef6d..da26ce43f9b9 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/event/diana/GriffinBurrowHelper.kt
@@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.event.diana
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
import at.hannibal2.skyhanni.data.EntityMovementData
+import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.events.BurrowDetectEvent
import at.hannibal2.skyhanni.events.BurrowDugEvent
import at.hannibal2.skyhanni.events.BurrowGuessEvent
@@ -18,6 +19,7 @@ import at.hannibal2.skyhanni.utils.LocationUtils.distanceToPlayer
import at.hannibal2.skyhanni.utils.LorenzColor
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.LorenzUtils.editCopy
+import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland
import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.RenderUtils.draw3DLine
import at.hannibal2.skyhanni.utils.RenderUtils.drawColor
@@ -246,4 +248,46 @@ object GriffinBurrowHelper {
}
private fun isEnabled() = DianaAPI.isDoingDiana()
+
+ fun setTestBurrow(strings: Array) {
+ if (!IslandType.HUB.isInIsland()) {
+ LorenzUtils.userError("You can only create test burrows on the hub island!")
+ return
+ }
+
+ if (!isEnabled()) {
+ if (!config.alwaysDiana) {
+ LorenzUtils.clickableChat("§cEnable Always Diana in the config!", "sh always diana")
+ } else {
+ LorenzUtils.userError("Have an Ancestral Spade in the inventory!")
+ }
+ return
+ }
+
+ if (strings.size != 1) {
+ LorenzUtils.userError("/shtestburrow ")
+ return
+ }
+
+ val type: BurrowType = when (strings[0].lowercase()) {
+ "reset" -> {
+ particleBurrows = emptyMap()
+ update()
+ LorenzUtils.chat("Manually reset all burrow waypoints.")
+ return
+ }
+ "1", "start" -> BurrowType.START
+ "2", "mob" -> BurrowType.MOB
+ "3", "treasure" -> BurrowType.TREASURE
+ else -> {
+ LorenzUtils.userError("Unknown burrow type! Try 1-3 instead.")
+ return
+ }
+ }
+
+ EntityMovementData.addToTrack(Minecraft.getMinecraft().thePlayer)
+ val location = LocationUtils.playerLocation().roundLocation()
+ particleBurrows = particleBurrows.editCopy { this[location] = type }
+ update()
+ }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingBaitWarnings.kt b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingBaitWarnings.kt
index 7688a7f9841b..7785da35649f 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingBaitWarnings.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/fishing/FishingBaitWarnings.kt
@@ -85,5 +85,5 @@ class FishingBaitWarnings {
LorenzUtils.chat("You do not use any fishing baits!")
}
- private fun isEnabled() = LorenzUtils.inSkyBlock && FishingAPI.hasFishingRodInHand()
+ private fun isEnabled() = LorenzUtils.inSkyBlock && FishingAPI.hasFishingRodInHand() && !LorenzUtils.inKuudraFight
}
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 979fa845febf..1ccac83de993 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
@@ -112,14 +112,7 @@ object FishingProfitTracker {
)
)
- val profitFormat = profit.addSeparators()
- val profitPrefix = if (profit < 0) "§c" else "§6"
-
- val profitPerCatch = profit / data.totalCatchAmount
- val profitPerCatchFormat = NumberUtil.format(profitPerCatch)
-
- val text = "§eTotal Profit: $profitPrefix$profitFormat coins"
- addAsSingletonList(Renderable.hoverTips(text, listOf("§7Profit per catch: $profitPrefix$profitPerCatchFormat")))
+ addAsSingletonList(tracker.addTotalProfit(profit, data.totalCatchAmount, "catch"))
tracker.addPriceFromButton(this)
}
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 6a1e1a382732..c9168c306dd5 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
@@ -42,7 +42,7 @@ object SeaCreatureTracker {
if (!isEnabled()) return
tracker.modify {
- val amount = if (event.doubleHook) 2 else 1
+ val amount = if (event.doubleHook && config.countDouble) 2 else 1
it.amount.addOrPut(event.seaCreature.name, amount)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt
index d40d02718b16..c7f05d807789 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/FarmingFortuneDisplay.kt
@@ -139,6 +139,12 @@ class FarmingFortuneDisplay {
if (upgradeFortune == null) {
updatedDisplay.addAsSingletonList("§cOpen §e/cropupgrades§c for more exact data!")
}
+
+ val uniqueVisitors = GardenAPI.storage?.uniqueVisitors?.toDouble() ?: 0.0
+ if (uniqueVisitors == 0.0) {
+ updatedDisplay.addAsSingletonList("§cOpen §e/visitormilestones§c for more exact data!")
+ }
+
if (accessoryFortune == null) {
updatedDisplay.addAsSingletonList("§cOpen Accessory Bag for more exact data!")
if (CropAccessoryData.isLoadingAccessories) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt
index f6ece600ba5d..e2fa5b63f382 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt
@@ -194,7 +194,7 @@ object GardenNextJacobContest {
sendContests()
} else {
LorenzUtils.clickableChat(
- "§2Click here to submit this years farming contests, thank you for helping everyone out!",
+ "§2Click here to submit this year's farming contests. Thank you for helping everyone out!",
"shsendcontests"
)
}
@@ -294,7 +294,7 @@ object GardenNextJacobContest {
if (isCloseToNewYear()) {
list.add(closeToNewYear)
} else {
- list.add("§cOpen calendar to read jacob contest times!")
+ list.add("§cOpen calendar to read Jacob contest times!")
}
return list
}
@@ -308,7 +308,7 @@ object GardenNextJacobContest {
if (isCloseToNewYear()) {
list.add(closeToNewYear)
} else {
- list.add("§cOpen calendar to read jacob contest times!")
+ list.add("§cOpen calendar to read Jacob contest times!")
}
fetchedFromElite = false
@@ -503,7 +503,8 @@ object GardenNextJacobContest {
newContests[timeMark + contestDuration] = FarmingContest(timeMark + contestDuration, crops)
}
} else {
- LorenzUtils.chat("This years contests aren't available to fetch automatically yet, please load them from your calender or wait 10 minutes!")
+ LorenzUtils.chat("This year's contests aren't available to fetch automatically yet, please load them from your calendar or wait 10 minutes.")
+ LorenzUtils.clickableChat("Click here to open your calendar!", "calendar")
}
if (newContests.count() == maxContestsPerYear) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt
index f9cafd982ca5..dd457688ad74 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/CaptureFarmingGear.kt
@@ -1,5 +1,6 @@
package at.hannibal2.skyhanni.features.garden.fortuneguide
+import at.hannibal2.skyhanni.config.Storage
import at.hannibal2.skyhanni.data.ProfileStorageData
import at.hannibal2.skyhanni.events.GardenToolChangeEvent
import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
@@ -18,6 +19,8 @@ import at.hannibal2.skyhanni.utils.SkyBlockItemModifierUtils.getEnchantments
import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
import at.hannibal2.skyhanni.utils.StringUtils.removeColor
import at.hannibal2.skyhanni.utils.TabListData
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.item.ItemStack
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import kotlin.math.round
import kotlin.time.Duration.Companion.days
@@ -37,6 +40,16 @@ class CaptureFarmingGear {
private val cakePattern = "(?:Big )?Yum! You (?:gain|refresh) [+]5☘ Farming Fortune for 48 hours!".toPattern()
+ private val patternGroup = RepoPattern.group("garden.fortuneguide.capture")
+ private val tierPattern by patternGroup.pattern(
+ "uniquevisitors.tier",
+ "§7Progress to Tier (?\\d+):.*"
+ )
+ private val tierProgressPattern by patternGroup.pattern(
+ "uniquevisitors.tierprogress",
+ ".* §e(?.*)§6/(?.*)"
+ )
+
companion object {
private val strengthPattern = " Strength: §r§c❁(?.*)".toPattern()
private val farmingSets = arrayListOf(
@@ -90,6 +103,16 @@ class CaptureFarmingGear {
storage.pumpkinFortune = !storage.pumpkinFortune
LorenzUtils.chat("Toggled expired pumpkin fortune to: ${storage.pumpkinFortune}")
}
+
+ private fun getUniqueVisitorsForTier(tier: Int): Int {
+ return when {
+ tier == 0 -> 0
+ tier == 1 -> 1
+ tier == 2 -> 5
+ tier >= 3 -> 10 * (tier - 2)
+ else -> throw IllegalStateException("Unexpected unique visitors tier: $tier")
+ }
+ }
}
@SubscribeEvent
@@ -103,115 +126,167 @@ class CaptureFarmingGear {
val storage = GardenAPI.storage?.fortune ?: return
val farmingItems = farmingItems ?: return
val outdatedItems = outdatedItems ?: return
- if (event.inventoryName == "Your Equipment and Stats") {
- for ((_, slot) in event.inventoryItems) {
- val split = slot.getInternalName().asString().split("_")
- if (split.first() == "LOTUS") {
- for (item in FarmingItems.entries) {
- if (item.name == split.last()) {
- farmingItems[item] = slot
- outdatedItems[item] = false
- }
- }
- FarmingFortuneDisplay.loadFortuneLineData(slot, 0.0)
- val enchantments = slot.getEnchantments() ?: emptyMap()
- val greenThumbLvl = (enchantments["green_thumb"] ?: continue)
- val visitors = FarmingFortuneDisplay.greenThumbFortune / (greenThumbLvl * 0.05)
- GardenAPI.storage?.uniqueVisitors = round(visitors).toInt()
+ val items = event.inventoryItems
+ when (event.inventoryName) {
+ "Your Equipment and Stats" -> equipmentAndStats(items, farmingItems, outdatedItems)
+ "Pets" -> pets(farmingItems, items, outdatedItems)
+ "Your Skills" -> skills(items, storage)
+ "Community Shop" -> communityShop(items)
+ "Configure Plots" -> configurePlots(items, storage)
+ "Anita" -> anita(items, storage)
+ "Visitor Milestones" -> visitorMilestones(items)
+ }
+ }
+
+ private fun visitorMilestones(items: Map) {
+ for ((_, item) in items) {
+ if (item.displayName != "§aUnique Visitors Served") continue
+
+ var tier = -1
+ var tierProgress = -1
+ for (line in item.getLore()) {
+ tierPattern.matchMatcher(line) {
+ tier = group("nextTier").toInt() - 1
}
+ tierProgressPattern.matchMatcher(line) {
+ tierProgress = group("having").toInt()
+ }
+ }
+ if (tier > -1 && tierProgress > -1) {
+ GardenAPI.storage?.uniqueVisitors = getUniqueVisitorsForTier(tier) + tierProgress
}
}
- if (event.inventoryName.contains("Pets")) {
- // If they've 2 of same pet, one will be overwritten
- // optimize
+ }
- for (pet in listOf(
- FarmingItems.ELEPHANT,
- FarmingItems.MOOSHROOM_COW,
- FarmingItems.RABBIT,
- FarmingItems.BEE
- )) {
- if (farmingItems[pet] == null) {
- farmingItems[pet] = FFGuideGUI.getFallbackItem(pet)
+ private fun anita(
+ items: Map,
+ storage: Storage.ProfileSpecific.GardenStorage.Fortune
+ ) {
+ var level = -1
+ for ((_, item) in items) {
+ if (item.displayName.contains("Extra Farming Fortune")) {
+ level = 0
+ for (line in item.getLore()) {
+ anitaMenuPattern.matchMatcher(line) {
+ level = group("level").toInt() / 4
+ }
}
}
+ }
+ if (level == -1) {
+ storage.anitaUpgrade = 15
+ } else {
+ storage.anitaUpgrade = level
+ }
+ }
- // setting to current saved level -1 to stop later pages saving low rarity pets
- var highestElephantRarity = (farmingItems[FarmingItems.ELEPHANT]?.getItemRarityOrNull()?.id ?: -1) - 1
- var highestMooshroomRarity = (farmingItems[FarmingItems.MOOSHROOM_COW]?.getItemRarityOrNull()?.id ?: -1) - 1
- var highestRabbitRarity = (farmingItems[FarmingItems.RABBIT]?.getItemRarityOrNull()?.id ?: -1) - 1
- var highestBeeRarity = (farmingItems[FarmingItems.BEE]?.getItemRarityOrNull()?.id ?: -1) - 1
+ private fun configurePlots(
+ items: Map,
+ storage: Storage.ProfileSpecific.GardenStorage.Fortune
+ ) {
+ var plotsUnlocked = 24
+ for (slot in items) {
+ if (slot.value.getLore().contains("§7Cost:")) {
+ plotsUnlocked -= 1
+ }
+ }
+ storage.plotsUnlocked = plotsUnlocked
+ }
- for ((_, item) in event.inventoryItems) {
- val split = item.getInternalName().asString().split(";")
- if (split.first() == "ELEPHANT" && split.last().toInt() > highestElephantRarity) {
- farmingItems[FarmingItems.ELEPHANT] = item
- outdatedItems[FarmingItems.ELEPHANT] = false
- highestElephantRarity = split.last().toInt()
- }
- if (split.first() == "MOOSHROOM_COW" && split.last().toInt() > highestMooshroomRarity) {
- farmingItems[FarmingItems.MOOSHROOM_COW] = item
- outdatedItems[FarmingItems.MOOSHROOM_COW] = false
- highestMooshroomRarity = split.last().toInt()
- }
- if (split.first() == "RABBIT" && split.last().toInt() > highestRabbitRarity) {
- farmingItems[FarmingItems.RABBIT] = item
- outdatedItems[FarmingItems.RABBIT] = false
- highestRabbitRarity = split.last().toInt()
- }
- if (split.first() == "BEE" && split.last().toInt() > highestBeeRarity) {
- farmingItems[FarmingItems.BEE] = item
- outdatedItems[FarmingItems.BEE] = false
- highestBeeRarity = split.last().toInt()
+ private fun communityShop(items: Map) {
+ for ((_, item) in items) {
+ if (item.displayName.contains("Garden Farming Fortune")) {
+ if (item.getLore().contains("§aMaxed out!")) {
+ ProfileStorageData.playerSpecific?.gardenCommunityUpgrade =
+ item.displayName.split(" ").last().romanToDecimal()
+ } else {
+ ProfileStorageData.playerSpecific?.gardenCommunityUpgrade =
+ item.displayName.split(" ").last().romanToDecimal() - 1
}
}
}
+ }
- if (event.inventoryName.contains("Your Skills")) {
- for ((_, item) in event.inventoryItems) {
- if (item.displayName.contains("Farming ")) {
- storage.farmingLevel = item.displayName.split(" ").last().romanToDecimalIfNecessary()
- }
+ private fun skills(
+ items: Map,
+ storage: Storage.ProfileSpecific.GardenStorage.Fortune
+ ) {
+ for ((_, item) in items) {
+ if (item.displayName.contains("Farming ")) {
+ storage.farmingLevel = item.displayName.split(" ").last().romanToDecimalIfNecessary()
}
}
- if (event.inventoryName.contains("Community Shop")) {
- for ((_, item) in event.inventoryItems) {
- if (item.displayName.contains("Garden Farming Fortune")) {
- if (item.getLore().contains("§aMaxed out!")) {
- ProfileStorageData.playerSpecific?.gardenCommunityUpgrade =
- item.displayName.split(" ").last().romanToDecimal()
- } else {
- ProfileStorageData.playerSpecific?.gardenCommunityUpgrade =
- item.displayName.split(" ").last().romanToDecimal() - 1
- }
- }
+ }
+
+ private fun pets(
+ farmingItems: MutableMap,
+ items: Map,
+ outdatedItems: MutableMap
+ ) {
+ // If they've 2 of same pet, one will be overwritten
+ // optimize
+
+ for (pet in listOf(
+ FarmingItems.ELEPHANT,
+ FarmingItems.MOOSHROOM_COW,
+ FarmingItems.RABBIT,
+ FarmingItems.BEE
+ )) {
+ if (farmingItems[pet] == null) {
+ farmingItems[pet] = FFGuideGUI.getFallbackItem(pet)
}
}
- if (event.inventoryName.contains("Configure Plots")) {
- var plotsUnlocked = 24
- for (slot in event.inventoryItems) {
- if (slot.value.getLore().contains("§7Cost:")) {
- plotsUnlocked -= 1
- }
+
+ // setting to current saved level -1 to stop later pages saving low rarity pets
+ var highestElephantRarity = (farmingItems[FarmingItems.ELEPHANT]?.getItemRarityOrNull()?.id ?: -1) - 1
+ var highestMooshroomRarity = (farmingItems[FarmingItems.MOOSHROOM_COW]?.getItemRarityOrNull()?.id ?: -1) - 1
+ var highestRabbitRarity = (farmingItems[FarmingItems.RABBIT]?.getItemRarityOrNull()?.id ?: -1) - 1
+ var highestBeeRarity = (farmingItems[FarmingItems.BEE]?.getItemRarityOrNull()?.id ?: -1) - 1
+
+ for ((_, item) in items) {
+ val split = item.getInternalName().asString().split(";")
+ if (split.first() == "ELEPHANT" && split.last().toInt() > highestElephantRarity) {
+ farmingItems[FarmingItems.ELEPHANT] = item
+ outdatedItems[FarmingItems.ELEPHANT] = false
+ highestElephantRarity = split.last().toInt()
+ }
+ if (split.first() == "MOOSHROOM_COW" && split.last().toInt() > highestMooshroomRarity) {
+ farmingItems[FarmingItems.MOOSHROOM_COW] = item
+ outdatedItems[FarmingItems.MOOSHROOM_COW] = false
+ highestMooshroomRarity = split.last().toInt()
+ }
+ if (split.first() == "RABBIT" && split.last().toInt() > highestRabbitRarity) {
+ farmingItems[FarmingItems.RABBIT] = item
+ outdatedItems[FarmingItems.RABBIT] = false
+ highestRabbitRarity = split.last().toInt()
+ }
+ if (split.first() == "BEE" && split.last().toInt() > highestBeeRarity) {
+ farmingItems[FarmingItems.BEE] = item
+ outdatedItems[FarmingItems.BEE] = false
+ highestBeeRarity = split.last().toInt()
}
- storage.plotsUnlocked = plotsUnlocked
}
- if (event.inventoryName.contains("Anita")) {
- var level = -1
- for ((_, item) in event.inventoryItems) {
- if (item.displayName.contains("Extra Farming Fortune")) {
- level = 0
- for (line in item.getLore()) {
- anitaMenuPattern.matchMatcher(line) {
- level = group("level").toInt() / 4
- }
+ }
+
+ private fun equipmentAndStats(
+ items: Map,
+ farmingItems: MutableMap,
+ outdatedItems: MutableMap
+ ) {
+ for ((_, slot) in items) {
+ val split = slot.getInternalName().asString().split("_")
+ if (split.first() == "LOTUS") {
+ for (item in FarmingItems.entries) {
+ if (item.name == split.last()) {
+ farmingItems[item] = slot
+ outdatedItems[item] = false
}
}
- }
- if (level == -1) {
- storage.anitaUpgrade = 15
- } else {
- storage.anitaUpgrade = level
+ FarmingFortuneDisplay.loadFortuneLineData(slot, 0.0)
+ val enchantments = slot.getEnchantments() ?: emptyMap()
+ val greenThumbLvl = (enchantments["green_thumb"] ?: continue)
+ val visitors = FarmingFortuneDisplay.greenThumbFortune / (greenThumbLvl * 0.05)
+ GardenAPI.storage?.uniqueVisitors = round(visitors).toInt()
}
}
}
@@ -256,5 +331,13 @@ class CaptureFarmingGear {
if (msg == "PUMPKINS EXPORTATION COMPLETE!") {
storage.pumpkinFortune = true
}
+ if (msg == "[NPC] Carrolyn: Thank you for the carrots.") {
+ storage.carrotFortune = true
+ LorenzUtils.chat("§aYou have already given Carrolyn enough Exportable Carrots.")
+ }
+ if (msg == "[NPC] Carrolyn: Thank you for the pumpkins.") {
+ storage.pumpkinFortune = true
+ LorenzUtils.chat("§aYou have already given Carrolyn enough Expired Pumpkins.")
+ }
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt
index 8f0c6be6aaad..f9962b5c80d8 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/HarpFeatures.kt
@@ -33,9 +33,9 @@ object HarpFeatures {
}
private val buttonColors = listOf('d', 'e', 'a', '2', '5', '9', 'b')
- private val inventoryTitleRegex by RepoPattern.pattern("harp.inventory", "^Harp.*")
+ private val inventoryTitlePattern by RepoPattern.pattern("harp.inventory", "^Harp.*")
- private fun isHarpGui() = inventoryTitleRegex.matches(openInventoryName())
+ private fun isHarpGui() = inventoryTitlePattern.matches(openInventoryName())
@SubscribeEvent
fun onGui(event: GuiScreenEvent) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt
index 5a563c254819..aa93dfd72aad 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/HideNotClickableItems.kt
@@ -6,7 +6,6 @@ import at.hannibal2.skyhanni.data.ItemRenderBackground.Companion.background
import at.hannibal2.skyhanni.data.ItemRenderBackground.Companion.borderLine
import at.hannibal2.skyhanni.data.jsonobjects.repo.HideNotClickableItemsJson
import at.hannibal2.skyhanni.data.jsonobjects.repo.HideNotClickableItemsJson.SalvageFilter
-import at.hannibal2.skyhanni.data.jsonobjects.repo.MultiFilterJson
import at.hannibal2.skyhanni.events.GuiContainerEvent
import at.hannibal2.skyhanni.events.RepositoryReloadEvent
import at.hannibal2.skyhanni.features.bazaar.BazaarApi
@@ -49,16 +48,12 @@ class HideNotClickableItems {
private val hideNpcSellFilter = MultiFilter()
private val hideInStorageFilter = MultiFilter()
- private val tradeNpcFilter = MultiFilter()
private val itemsToSalvage = mutableListOf()
private val hidePlayerTradeFilter = MultiFilter()
private val notAuctionableFilter = MultiFilter()
@SubscribeEvent
fun onRepoReload(event: RepositoryReloadEvent) {
- val data = event.getConstant("TradeNpcs")
- tradeNpcFilter.load(data)
-
val hideNotClickable = event.getConstant("HideNotClickableItems")
hideNpcSellFilter.load(hideNotClickable.hide_npc_sell)
hideInStorageFilter.load(hideNotClickable.hide_in_storage)
@@ -175,7 +170,7 @@ class HideNotClickableItems {
reverseColor = false
return when {
- hideNpcSell(chestName, stack) -> true
+ hideNpcSell(stack) -> true
hideInStorage(chestName, stack) -> true
hideSalvage(chestName, stack) -> true
hidePlayerTrade(chestName, stack) -> true
@@ -260,7 +255,7 @@ class HideNotClickableItems {
"BRACELET"
)
for (type in list) {
- if (stack.getLore().any { it.contains("§l") && it.contains(type) }) {//todo use item api
+ if (stack.getLore().any { it.contains("§l") && it.contains(type) }) {// todo use item api
reverseColor = true
return false
}
@@ -289,7 +284,7 @@ class HideNotClickableItems {
private fun hidePrivateIslandChest(chestName: String, stack: ItemStack): Boolean {
if (chestName != "Chest" && chestName != "Large Chest") return false
- //TODO make check if player is on private island
+ // TODO make check if player is on private island
if (!ItemUtils.isSoulBound(stack)) return false
@@ -378,8 +373,8 @@ class HideNotClickableItems {
return result
}
- private fun hideNpcSell(chestName: String, stack: ItemStack): Boolean {
- if (!tradeNpcFilter.match(chestName)) return false
+ private fun hideNpcSell(stack: ItemStack): Boolean {
+ if (!ShiftClickNPCSell.inInventory) return false
if (VisitorAPI.inInventory) return false
reverseColor = true
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/PowerStoneGuideFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/PowerStoneGuideFeatures.kt
new file mode 100644
index 000000000000..24972cde587a
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/PowerStoneGuideFeatures.kt
@@ -0,0 +1,78 @@
+package at.hannibal2.skyhanni.features.inventory
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.GuiContainerEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
+import at.hannibal2.skyhanni.events.LorenzToolTipEvent
+import at.hannibal2.skyhanni.features.bazaar.BazaarApi
+import at.hannibal2.skyhanni.utils.ItemUtils.getItemName
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.LorenzColor
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.nextAfter
+import at.hannibal2.skyhanni.utils.NEUInternalName
+import at.hannibal2.skyhanni.utils.NEUItems.getPrice
+import at.hannibal2.skyhanni.utils.NumberUtil
+import at.hannibal2.skyhanni.utils.RenderUtils.highlight
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class PowerStoneGuideFeatures {
+
+ private var missing = mutableMapOf()
+ private var inInventory = false
+
+ @SubscribeEvent
+ fun onInventoryOpen(event: InventoryFullyOpenedEvent) {
+ if (!isEnabled()) return
+ if (event.inventoryName != "Power Stones Guide") return
+
+ inInventory = true
+
+ for ((slot, item) in event.inventoryItems) {
+ val lore = item.getLore()
+ if (lore.contains("§7Learned: §cNot Yet ✖")) {
+ val rawName = lore.nextAfter("§7Power stone:") ?: continue
+ val name = NEUInternalName.fromItemName(rawName)
+ missing[slot] = name
+ }
+ }
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ inInventory = false
+ }
+
+ @SubscribeEvent
+ fun onBackgroundDrawn(event: GuiContainerEvent.BackgroundDrawnEvent) {
+ if (!isEnabled()) return
+ if (!inInventory) return
+
+ event.gui.inventorySlots.inventorySlots
+ .filter { missing.containsKey(it.slotNumber) }
+ .forEach { it highlight LorenzColor.RED }
+ }
+
+ @SubscribeEvent
+ fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) {
+ if (!isEnabled()) return
+ if (!inInventory) return
+ val internalName = missing[event.slotId] ?: return
+
+ BazaarApi.searchForBazaarItem(internalName.getItemName(), 9)
+ }
+
+ @SubscribeEvent
+ fun onTooltip(event: LorenzToolTipEvent) {
+ if (!isEnabled()) return
+ if (!inInventory) return
+
+ val internalName = missing[event.slot.slotNumber] ?: return
+ val totalPrice = internalName.getPrice() * 9
+ event.toolTip.add(5, "9x from Bazaar: §6${NumberUtil.format(totalPrice)}")
+ }
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && SkyHanniMod.feature.inventory.powerStoneGuide
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/ShiftClickNPCSell.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/ShiftClickNPCSell.kt
new file mode 100644
index 000000000000..db1375b75d1e
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/ShiftClickNPCSell.kt
@@ -0,0 +1,54 @@
+package at.hannibal2.skyhanni.features.inventory
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.GuiContainerEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.StringUtils.matches
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
+import net.minecraft.client.Minecraft
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+object ShiftClickNPCSell {
+
+ private val config get() = SkyHanniMod.feature.inventory.shiftClickNPCSell
+
+ private val sellSlot = 49
+ private val lastLoreLineOfSellPattern by RepoPattern.pattern(
+ "inventory.npc.sell.lore",
+ "§7them to this Shop!|§eClick to buyback!"
+ )
+
+ var inInventory = false
+ private set
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && config
+
+ @SubscribeEvent
+ fun onOpen(event: InventoryFullyOpenedEvent) {
+ if (!LorenzUtils.inSkyBlock) return
+ inInventory = lastLoreLineOfSellPattern.matches(event.inventoryItems[sellSlot]?.getLore()?.lastOrNull() ?: "")
+ }
+
+ @SubscribeEvent
+ fun onClose(event: InventoryCloseEvent) {
+ inInventory = false
+ }
+
+ @SubscribeEvent
+ fun onSlotClick(event: GuiContainerEvent.SlotClickEvent) {
+ if (!isEnabled()) return
+ if (!inInventory) return
+
+ val slot = event.slot ?: return
+
+ if (slot.slotNumber == slot.slotIndex) return
+
+ event.isCanceled = true
+ Minecraft.getMinecraft().playerController.windowClick(
+ event.container.windowId, event.slot.slotNumber, event.clickedButton, 1, Minecraft.getMinecraft().thePlayer
+ )
+ }
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/LesserOrbHider.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/LesserOrbHider.kt
new file mode 100644
index 000000000000..000587afdbb3
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/LesserOrbHider.kt
@@ -0,0 +1,54 @@
+package at.hannibal2.skyhanni.features.misc
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.CheckRenderEntityEvent
+import at.hannibal2.skyhanni.events.EntityEquipmentChangeEvent
+import at.hannibal2.skyhanni.events.ReceiveParticleEvent
+import at.hannibal2.skyhanni.utils.ItemUtils.getSkullTexture
+import at.hannibal2.skyhanni.utils.LocationUtils.distanceTo
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import net.minecraft.entity.item.EntityArmorStand
+import net.minecraft.util.EnumParticleTypes
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+class LesserOrbHider {
+ private val config get() = SkyHanniMod.feature.misc
+ private val hiddenEntities = LorenzUtils.weakReferenceList()
+
+ private val lesserTexture =
+ "eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjgzMjM2NjM5NjA3MDM2YzFiYTM5MWMyYjQ2YTljN2IwZWZkNzYwYzhiZmEyOTk2YTYwNTU1ODJiNGRhNSJ9fX0="
+
+ @SubscribeEvent
+ fun onArmorChange(event: EntityEquipmentChangeEvent) {
+ val entity = event.entity
+ val itemStack = event.newItemStack ?: return
+
+ if (entity is EntityArmorStand && event.isHand && itemStack.getSkullTexture() == lesserTexture) {
+ hiddenEntities.add(entity)
+ }
+ }
+
+ @SubscribeEvent
+ fun onCheckRender(event: CheckRenderEntityEvent<*>) {
+ if (!isEnabled()) return
+
+ if (event.entity in hiddenEntities) {
+ event.isCanceled = true
+ }
+ }
+
+ @SubscribeEvent
+ fun onReceiveParticle(event: ReceiveParticleEvent) {
+ if (!isEnabled()) return
+ if (event.type != EnumParticleTypes.REDSTONE) return
+
+ for (armorStand in hiddenEntities) {
+ val distance = armorStand.distanceTo(event.location)
+ if (distance < 4) {
+ event.isCanceled = true
+ }
+ }
+ }
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && config.lesserOrbHider
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/RenderColumn.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/RenderColumn.kt
index 2ee1e3442870..894dee93ba27 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/RenderColumn.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/RenderColumn.kt
@@ -1,8 +1,6 @@
package at.hannibal2.skyhanni.features.misc.compacttablist
-class RenderColumn {
-
- val lines = mutableListOf()
+class RenderColumn(val lines: MutableList = mutableListOf()) {
fun size(): Int {
return lines.size
@@ -15,4 +13,4 @@ class RenderColumn {
fun getMaxWidth(): Int {
return lines.maxOfOrNull { it.getWidth() } ?: 0
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListRenderer.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListRenderer.kt
index d5cc7f8756bc..b42378e08717 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListRenderer.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/compacttablist/TabListRenderer.kt
@@ -1,8 +1,12 @@
package at.hannibal2.skyhanni.features.misc.compacttablist
import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.SkipTabListLineEvent
import at.hannibal2.skyhanni.mixins.transformers.AccessorGuiPlayerTabOverlay
import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.filterToMutable
+import at.hannibal2.skyhanni.utils.StringUtils.matches
+import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.Gui
import net.minecraft.client.gui.ScaledResolution
@@ -91,9 +95,22 @@ object TabListRenderer {
}
var middleX = x
- for (column in columns) {
+ var lastTitle: TabLine? = null
+ var lastSubTitle: TabLine? = null
+ for (originalColumn in columns) {
var middleY = if (config.hideAdverts) headerY else headerY + padding + 2
+ val column = originalColumn.lines.filterToMutable { tabLine ->
+ if (tabLine.type == TabStringType.TITLE) {
+ lastSubTitle = null
+ lastTitle = tabLine
+ }
+ if (tabLine.type == TabStringType.SUB_TITLE) {
+ lastSubTitle = tabLine
+ }
+ !SkipTabListLineEvent(tabLine, lastSubTitle, lastTitle).postAndCatch()
+ }.let(::RenderColumn)
+
Gui.drawRect(
middleX - padding + 1,
middleY - padding + 1,
@@ -156,4 +173,14 @@ object TabListRenderer {
}
}
}
-}
\ No newline at end of file
+
+ private val fireSalePattern by RepoPattern.pattern("tablist.firesaletitle", "§b§lFire Sales: §r§f\\([0-9]+\\)")
+
+ @SubscribeEvent
+ fun hideFireFromTheTabListBecauseWhoWantsThose(event: SkipTabListLineEvent) {
+ if (config.hideFiresales && event.lastSubTitle != null && fireSalePattern.matches(event.lastSubTitle.text)) {
+ event.cancel()
+ }
+ }
+
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/items/GlowingDroppedItems.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/items/GlowingDroppedItems.kt
index 11bf4655b7f3..3e5bf7989ec4 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/misc/items/GlowingDroppedItems.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/items/GlowingDroppedItems.kt
@@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.misc.items
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.events.RenderEntityOutlineEvent
+import at.hannibal2.skyhanni.features.garden.pests.SprayType
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalNameOrNull
import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull
import at.hannibal2.skyhanni.utils.ItemUtils.name
@@ -56,7 +57,9 @@ class GlowingDroppedItems {
return null
}
- entityItem.getInternalNameOrNull() ?: return null
+ val internalName = entityItem.getInternalNameOrNull() ?: return null
+ val isSprayItem = LorenzUtils.enumValueOfOrNull(internalName.asString()) != null
+ if (isSprayItem) return null
val rarity = entityItem.getItemRarityOrNull()
return rarity?.color?.toColor()?.rgb
}
@@ -79,4 +82,4 @@ class GlowingDroppedItems {
return false
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt
index bf88fb865008..d8f52a641f7c 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/nether/reputationhelper/dailykuudra/DailyKuudraBossHelper.kt
@@ -3,6 +3,7 @@ package at.hannibal2.skyhanni.features.nether.reputationhelper.dailykuudra
import at.hannibal2.skyhanni.config.Storage
import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.data.ScoreboardData
+import at.hannibal2.skyhanni.data.jsonobjects.repo.CrimsonIsleReputationJson.ReputationQuest
import at.hannibal2.skyhanni.events.LorenzChatEvent
import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent
import at.hannibal2.skyhanni.features.nether.reputationhelper.CrimsonIsleReputationHelper
@@ -13,7 +14,6 @@ import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
import at.hannibal2.skyhanni.utils.LorenzVec
import at.hannibal2.skyhanni.utils.NEUItems
import at.hannibal2.skyhanni.utils.RenderUtils.drawDynamicText
-import at.hannibal2.skyhanni.data.jsonobjects.repo.CrimsonIsleReputationJson.ReputationQuest
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
class DailyKuudraBossHelper(private val reputationHelper: CrimsonIsleReputationHelper) {
@@ -38,8 +38,7 @@ class DailyKuudraBossHelper(private val reputationHelper: CrimsonIsleReputationH
@SubscribeEvent
fun onChat(event: LorenzChatEvent) {
- if (!LorenzUtils.inSkyBlock) return
- if (LorenzUtils.skyBlockIsland != IslandType.KUUDRA_ARENA) return
+ if (!LorenzUtils.inKuudraFight) return
if (!reputationHelper.config.enabled) return
val message = event.message
diff --git a/src/main/java/at/hannibal2/skyhanni/features/rift/area/mirrorverse/DanceRoomHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/rift/area/mirrorverse/DanceRoomHelper.kt
index a2b337668734..5118bf25b528 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/rift/area/mirrorverse/DanceRoomHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/rift/area/mirrorverse/DanceRoomHelper.kt
@@ -1,6 +1,8 @@
package at.hannibal2.skyhanni.features.rift.area.mirrorverse
+import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator
+import at.hannibal2.skyhanni.data.jsonobjects.repo.DanceRoomInstructionsJson
import at.hannibal2.skyhanni.events.CheckRenderEntityEvent
import at.hannibal2.skyhanni.events.GuiRenderEvent
import at.hannibal2.skyhanni.events.LorenzTickEvent
@@ -12,10 +14,6 @@ import at.hannibal2.skyhanni.features.rift.RiftAPI
import at.hannibal2.skyhanni.utils.LocationUtils.isPlayerInside
import at.hannibal2.skyhanni.utils.RenderUtils.renderStrings
import at.hannibal2.skyhanni.utils.StringUtils.firstLetterUppercase
-import at.hannibal2.skyhanni.data.jsonobjects.repo.DanceRoomInstructionsJson
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
@@ -142,7 +140,7 @@ object DanceRoomHelper {
val countdownString = "%01d:%03d".format(seconds, milliseconds)
countdown = countdownString
- CoroutineScope(Dispatchers.Default).launch {
+ SkyHanniMod.coroutineScope.launch {
delay(1)
var updatedSeconds = seconds
var updatedMilliseconds = milliseconds - 1
@@ -169,8 +167,8 @@ object DanceRoomHelper {
instructions = event.getConstant("DanceRoomInstructions").instructions
}
- fun start(interval: Long): Job {
- return CoroutineScope(Dispatchers.Default).launch {
+ fun start(interval: Long) {
+ SkyHanniMod.coroutineScope.launch {
while (isActive && found) {
index++
startCountdown(0, 500)
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 6ff20129bdbb..d0c374a8bf9a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/SlayerProfitTracker.kt
@@ -43,7 +43,7 @@ object SlayerProfitTracker {
var slayerSpawnCost: Long = 0
@Expose
- var slayerCompletedCount = 0
+ var slayerCompletedCount = 0L
override fun getDescription(timesDropped: Long): List {
val percentage = timesDropped.toDouble() / slayerCompletedCount
@@ -168,14 +168,7 @@ object SlayerProfitTracker {
)
)
- val profitFormat = profit.addSeparators()
- val profitPrefix = if (profit < 0) "§c" else "§6"
-
- val profitPerBoss = profit / itemLog.slayerCompletedCount
- val profitPerBossFormat = NumberUtil.format(profitPerBoss)
-
- val text = "§eTotal Profit: $profitPrefix$profitFormat coins"
- addAsSingletonList(Renderable.hoverTips(text, listOf("§7Profit per boss: $profitPrefix$profitPerBossFormat")))
+ addAsSingletonList(tracker.addTotalProfit(profit, itemLog.slayerCompletedCount, "boss"))
tracker.addPriceFromButton(this)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt
index e1f837a7b500..baf43b001682 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/slayer/VampireSlayerFeatures.kt
@@ -32,8 +32,6 @@ import at.hannibal2.skyhanni.utils.RenderUtils.exactPlayerEyeLocation
import at.hannibal2.skyhanni.utils.SoundUtils
import at.hannibal2.skyhanni.utils.SoundUtils.playSound
import at.hannibal2.skyhanni.utils.toLorenzVec
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import net.minecraft.client.Minecraft
@@ -208,7 +206,7 @@ object VampireSlayerFeatures {
}
private fun playTwinclawsSound() {
- CoroutineScope(Dispatchers.Default).launch {
+ SkyHanniMod.coroutineScope.launch {
repeat(15) {
delay(50)
SoundUtils.createSound("random.orb", 0.5f).playSound()
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt
index ce3c07d907ff..bec3af2f1a01 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt
@@ -27,6 +27,7 @@ import net.minecraft.launchwrapper.Launch
import net.minecraft.util.ChatComponentText
import net.minecraftforge.fml.common.FMLCommonHandler
import java.awt.Color
+import java.lang.reflect.Constructor
import java.lang.reflect.Field
import java.lang.reflect.Modifier
import java.text.DecimalFormat
@@ -35,6 +36,7 @@ import java.text.SimpleDateFormat
import java.util.Collections
import java.util.Timer
import java.util.TimerTask
+import java.util.WeakHashMap
import java.util.regex.Matcher
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KMutableProperty1
@@ -62,7 +64,7 @@ object LorenzUtils {
val skyBlockArea get() = if (inSkyBlock) HypixelData.skyBlockArea else "?"
- val inKuudraFight get() = skyBlockIsland == IslandType.KUUDRA_ARENA
+ val inKuudraFight get() = IslandType.KUUDRA_ARENA.isInIsland()
val noTradeMode get() = HypixelData.noTrade
@@ -523,8 +525,8 @@ object LorenzUtils {
val tileSign = (this as AccessorGuiEditSign).tileSign
return (tileSign.signText[1].unformattedText.removeColor() == "^^^^^^"
- && tileSign.signText[2].unformattedText.removeColor() == "Set your"
- && tileSign.signText[3].unformattedText.removeColor() == "speed cap!")
+ && tileSign.signText[2].unformattedText.removeColor() == "Set your"
+ && tileSign.signText[3].unformattedText.removeColor() == "speed cap!")
}
fun IslandType.isInIsland() = inSkyBlock && skyBlockIsland == this
@@ -577,6 +579,8 @@ object LorenzUtils {
fun Field.makeAccessible() = also { isAccessible = true }
+ fun Constructor.makeAccessible() = also { isAccessible = true }
+
// Taken and modified from Skytils
@JvmStatic
fun T.equalsOneOf(vararg other: T): Boolean {
@@ -655,4 +659,10 @@ object LorenzUtils {
fun Matcher.groupOrNull(groupName: String): String? {
return runCatching { this.group(groupName) }.getOrNull()
}
+
+ // Let garbage collector handle the removal of entries in this list
+ fun weakReferenceList(): MutableSet = Collections.newSetFromMap(WeakHashMap())
+
+
+ fun MutableCollection.filterToMutable(predicate: (T) -> Boolean) = filterTo(mutableListOf(), predicate)
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
index ad2df542c1f0..8a909f15e7b7 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/NEUItems.kt
@@ -22,12 +22,14 @@ import io.github.moulberry.notenoughupdates.recipes.NeuRecipe
import io.github.moulberry.notenoughupdates.util.ItemResolutionQuery
import io.github.moulberry.notenoughupdates.util.Utils
import net.minecraft.client.Minecraft
+import net.minecraft.client.renderer.GLAllocation
import net.minecraft.client.renderer.GlStateManager
import net.minecraft.client.renderer.RenderHelper
import net.minecraft.init.Blocks
import net.minecraft.init.Items
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
+import org.lwjgl.opengl.GL11
import java.util.regex.Pattern
object NEUItems {
@@ -192,8 +194,8 @@ object NEUItems {
ErrorManager.logError(
IllegalStateException("Something went wrong!"),
"Encountered an error getting the item for §7$this§c. " +
- "This may be because your NEU repo is outdated. Please ask in the SkyHanni " +
- "Discord if this is the case"
+ "This may be because your NEU repo is outdated. Please ask in the SkyHanni " +
+ "Discord if this is the case"
)
fallbackItem
}
@@ -201,6 +203,7 @@ object NEUItems {
fun isVanillaItem(item: ItemStack): Boolean =
manager.auctionManager.isVanillaItem(item.getInternalName().asString())
+
fun ItemStack.renderOnScreen(x: Float, y: Float, scaleMultiplier: Double = 1.0) {
val item = checkBlinkItem()
val isSkull = item.item === Items.skull
@@ -221,16 +224,39 @@ object NEUItems {
GlStateManager.pushMatrix()
- GlStateManager.translate(translateX, translateY, 1F)
- GlStateManager.scale(finalScale, finalScale, 1.0)
+ GlStateManager.translate(translateX, translateY, -19f)
+ GlStateManager.scale(finalScale, finalScale, 0.2)
+ GL11.glNormal3f(0f, 0f, 1f / 0.2f) // Compensate for z scaling
RenderHelper.enableGUIStandardItemLighting()
+
+ AdjustStandardItemLighting.adjust() // Compensate for z scaling
+
Minecraft.getMinecraft().renderItem.renderItemIntoGUI(item, 0, 0)
RenderHelper.disableStandardItemLighting()
GlStateManager.popMatrix()
}
+ private object AdjustStandardItemLighting {
+
+ private const val lightScaling = 2.47f // Adjust as needed
+ private const val g = 0.6f // Original Value taken from RenderHelper
+ private const val lightIntensity = lightScaling * g
+ private val itemLightBuffer = GLAllocation.createDirectFloatBuffer(16);
+
+ init {
+ itemLightBuffer.clear()
+ itemLightBuffer.put(lightIntensity).put(lightIntensity).put(lightIntensity).put(1.0f)
+ itemLightBuffer.flip()
+ }
+
+ fun adjust() {
+ GL11.glLight(16384, 4609, itemLightBuffer)
+ GL11.glLight(16385, 4609, itemLightBuffer)
+ }
+ }
+
fun allNeuRepoItems(): Map = NotEnoughUpdates.INSTANCE.manager.itemInformation
fun getMultiplier(internalName: NEUInternalName, tryCount: Int = 0): Pair {
@@ -326,11 +352,11 @@ object NEUItems {
val name = group("name").trim { it <= ' ' }
val ultimate = group("format").lowercase().contains("§l")
((if (ultimate && name != "Ultimate Wise") "ULTIMATE_" else "")
- + turboCheck(name).replace(" ", "_").replace("-", "_").uppercase()
- + ";" + group("level").romanToDecimal())
+ + turboCheck(name).replace(" ", "_").replace("-", "_").uppercase()
+ + ";" + group("level").romanToDecimal())
}
- //Uses NEU
+ // Uses NEU
fun saveNBTData(item: ItemStack, removeLore: Boolean = true): String {
val jsonObject = manager.getJsonForItem(item)
if (!jsonObject.has("internalname")) {
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 9367e5ee13bf..01f9941aa7c6 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/renderables/Renderable.kt
@@ -62,7 +62,7 @@ interface Renderable {
text: String,
onClick: () -> Unit,
bypassChecks: Boolean = false,
- condition: () -> Boolean = { true }
+ condition: () -> Boolean = { true },
): Renderable =
link(string(text), onClick, bypassChecks, condition)
@@ -70,7 +70,7 @@ interface Renderable {
renderable: Renderable,
onClick: () -> Unit,
bypassChecks: Boolean = false,
- condition: () -> Boolean = { true }
+ condition: () -> Boolean = { true },
): Renderable {
return clickable(
hoverable(underlined(renderable), renderable, bypassChecks, condition = condition),
@@ -85,7 +85,7 @@ interface Renderable {
text: String,
tips: List,
bypassChecks: Boolean = false,
- onClick: () -> Unit
+ onClick: () -> Unit,
): Renderable {
return clickable(hoverTips(text, tips, bypassChecks = bypassChecks), onClick, bypassChecks = bypassChecks)
}
@@ -95,7 +95,7 @@ interface Renderable {
onClick: () -> Unit,
button: Int = 0,
bypassChecks: Boolean = false,
- condition: () -> Boolean = { true }
+ condition: () -> Boolean = { true },
) =
object : Renderable {
override val width: Int
@@ -124,7 +124,7 @@ interface Renderable {
indexes: List = listOf(),
stack: ItemStack? = null,
bypassChecks: Boolean = false,
- condition: () -> Boolean = { true }
+ condition: () -> Boolean = { true },
): Renderable {
val render = string(text)
@@ -211,7 +211,7 @@ interface Renderable {
hovered: Renderable,
unhovered: Renderable,
bypassChecks: Boolean = false,
- condition: () -> Boolean = { true }
+ condition: () -> Boolean = { true },
) =
object : Renderable {
override val width: Int
@@ -233,8 +233,8 @@ interface Renderable {
override fun render(posX: Int, posY: Int) {
GlStateManager.pushMatrix()
- if (Minecraft.getMinecraft().currentScreen == null || Minecraft.getMinecraft().currentScreen is GuiChat)
- GlStateManager.translate(0F, 0F, -145F)
+ if (Minecraft.getMinecraft().currentScreen is GuiChat)
+ GlStateManager.translate(0F, 0F, -3F)
any.renderOnScreen(0F, 0F, scaleMultiplier = scale)
GlStateManager.popMatrix()
}
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 8dab120fa78a..b831ade3fa55 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniItemTracker.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/tracker/SkyHanniItemTracker.kt
@@ -172,4 +172,18 @@ class SkyHanniItemTracker(
}
}
+ fun addTotalProfit(profit: Double, totalAmount: Long, action: String): Renderable {
+ val profitFormat = profit.addSeparators()
+ val profitPrefix = if (profit < 0) "§c" else "§6"
+
+ val tips = if (totalAmount > 0) {
+ val profitPerCatch = profit / totalAmount
+ val profitPerCatchFormat = NumberUtil.format(profitPerCatch)
+ listOf("§7Profit per $action: $profitPrefix$profitPerCatchFormat")
+ } else emptyList()
+
+ val text = "§eTotal Profit: $profitPrefix$profitFormat coins"
+ return Renderable.hoverTips(text, tips)
+ }
+
}