diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aea2e591d5b..7b781b9e2056 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,30 +6,78 @@ #### Fishing Features ++ Show sack item amount to the visitor shopping list. - CalMWolfs + +#### Fishing Features + + Added Sea Creature Tracker. - hannibal2 + Allows to only show single variants, e.g. water or lava or winter. ### Changed +#### Garden Changes + ++ Renamed Visitor Items Needed to Visitor Shopping List. - hannibal2 ++ Added biofuel support to the Composter Overlay get from sack logic. - obsidian ++ Updated max reforge fortune for Fungi Cutter. - alexia + + Hypixel has increased the base rarity to Epic. + #### Rift Changes + Rift time now updates correctly in wizard tower and instantly updates the format when toggling max time or percentage. - hannibal2 -#### Fishing Fixes +#### Fishing Changes -+ Fixed Reindrake mob, Frosty NPC and frosty the snow blaster shop counting as sea creatures in the barn fishing - timer. - hannibal2 ++ Odger highlight feature tells in description that it is only useful for users without abiphone. - hannibal2 + +#### Bingo Changes + ++ Show the guide text when hovering over the missing bingo goal list. - hannibal2 + +#### Inventory Changes + ++ Removed flawless gemstones from sack display. - CalMWolfs + + Hypixel removed them from sacks. ### Fixes +#### Garden Fixes + ++ Fixed mushrooms being counted with Common/Uncommon Mooshroom Cow Pet. - alexia ++ Fixed progress to maxed milestone appearing twice in the crop milestone menu when having milestone 20. - Empa ++ Fixed max crop milestone display being too long in the crop milestone menu. - obsidian ++ Fixed Mooshroom Cow Perk counter when farming sugar cane/cactus with Mooshroom Cow. - alexia + #### Rift Fixes + Fixed vampire slayer damage indicator not working during Derpy. - hannibal2 +#### Fishing Fixes + ++ Fixed Reindrake mob, Frosty NPC and frosty the snow blaster shop counting as sea creatures in the barn fishing + timer. - hannibal2 + +#### Invenory Fixes + ++ Fixed hide non-clickable items not working in some bazaar pages. - hannibal2 ++ Fixed rogue sword ability taking into account mage cooldown reduction. - Empa + +#### Bingo Fixes + ++ Fixed detecting bingo profile while visiting other players bingo island. - hannibal2 + +#### Misc Fixes + ++ Maybe fixed Tia Relay Helper. - Thunderblade73 + ### Technical Changes + Migrate Hypixel API to v2. - hannibal2 ++ Added SackDataUpdateEvent. - CalMWolfs ++ Fixing a mac crash in dev environment automatically. - CalMWolfs ++ Bingo repo change: Make note of an alternative title, and create a guide field for the actual guide text. - hannibal2 ++ Moved Tia Relay Helper chat messages into repo patterns. - Thunderblade73 ## Version 0.22 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b33db983ddbd..1b439bc15204 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -119,9 +119,14 @@ All data sent is anonymonized and opt-in. ### Mixin A system to inject code into the original Minecraft code. -This library is not part of SkyHanni itself; it comes preinstalled with Forge. +This library is not part of SkyHanni or Forge, but we bundle it. -For more information, see https://github.com/SpongePowered/Mixin. +It allows to easily modify methods in Minecraft itself, without conflicting with other mods. + +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 +possible. ### Repo @@ -143,7 +148,7 @@ at [DiscordRPCManager.kt](https://github.com/hannibal002/SkyHanni/blob/beta/src/ ### Auto Updater -We use the [auto update library](https://repo.nea.moe/#/releases/moe/nea/libautoupdate) from nea. +We use the [auto update library](https://github.com/nea89o/libautoupdate) from nea89. ## Additional Useful Developement Tools diff --git a/FEATURES.md b/FEATURES.md index 5b962638ff1f..d681c89ec5a7 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -551,6 +551,7 @@ Use `/sh` or `/skyhanni` to open the SkyHanni config in game. + If you don't want to share anything, you can disable the chat message in the config with /sh copy milestone data. + Garden Vacuum Pests in Pest bag to item number as stack size. - hannibal2 + Enable via /sh vacuum. ++ Show sack item amount to the visitor shopping list. - CalMWolfs ### Garden Pests diff --git a/build.gradle.kts b/build.gradle.kts index 4b2d7eb1e48a..4a72ae61bea7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,3 +1,4 @@ +import org.apache.commons.lang3.SystemUtils import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.io.ByteArrayOutputStream @@ -12,7 +13,7 @@ plugins { } group = "at.hannibal2.skyhanni" -version = "0.23.Beta.1" +version = "0.23.Beta.3" val gitHash by lazy { val baos = ByteArrayOutputStream() @@ -153,6 +154,11 @@ loom { defaultRefmapName.set("mixins.skyhanni.refmap.json") } runConfigs { + "client" { + if (SystemUtils.IS_OS_MAC_OSX) { + vmArgs.remove("-XstartOnFirstThread") + } + } "server" { isIdeConfigGenerated = false } diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt index 666a15f4bbb5..2c4deb534e91 100644 --- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt +++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.kt @@ -364,7 +364,7 @@ import org.apache.logging.log4j.Logger clientSideOnly = true, useMetadata = true, guiFactory = "at.hannibal2.skyhanni.config.ConfigGuiForgeInterop", - version = "0.23.Beta.1", + version = "0.23.Beta.3", ) class SkyHanniMod { @Mod.EventHandler diff --git a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt index f98373ea3ff7..e73f63813a93 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt +++ b/src/main/java/at/hannibal2/skyhanni/config/ConfigUpdaterMigrator.kt @@ -9,7 +9,7 @@ import com.google.gson.JsonPrimitive object ConfigUpdaterMigrator { val logger = LorenzLogger("ConfigMigration") - const val CONFIG_VERSION = 17 + const val CONFIG_VERSION = 18 fun JsonElement.at(chain: List, init: Boolean): JsonElement? { if (chain.isEmpty()) return this if (this !is JsonObject) return null 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 ce774a72f130..b3990ca515ac 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 @@ -20,7 +20,11 @@ public class TrophyFishingConfig { public boolean filletTooltip = true; @Expose - @ConfigOption(name = "Odger Waypoint", desc = "Show the Odger waypoint when Trophy Fishes are in the inventory and no lava rod in hand.") + @ConfigOption( + name = "Odger Waypoint", + desc = "Show the Odger waypoint when Trophy Fishes are in the inventory and no lava rod in hand. " + + "§cOnly useful for users without abiohone contact." + ) @ConfigEditorBoolean @FeatureToggle public boolean odgerLocation = true; diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/composter/ComposterConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/composter/ComposterConfig.java index a2be38643b48..2d3da1ce5ce8 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/composter/ComposterConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/composter/ComposterConfig.java @@ -55,7 +55,7 @@ public String toString() { @Expose @ConfigOption(name = "Retrieve From", desc = "Change where to retrieve the materials from in the composter overlay: The Bazaar or Sacks.") @ConfigEditorDropdown() - public RetrieveFromEntry retrieveFrom = RetrieveFromEntry.BAZAAR; + public RetrieveFromEntry retrieveFrom = RetrieveFromEntry.SACKS; public enum RetrieveFromEntry implements HasLegacyId { BAZAAR("Bazaar", 0), diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/NeedsConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/ShoppingListConfig.java similarity index 72% rename from src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/NeedsConfig.java rename to src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/ShoppingListConfig.java index b60b6207f7ea..cbfa9e451d11 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/NeedsConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/ShoppingListConfig.java @@ -6,18 +6,20 @@ import io.github.moulberry.moulconfig.annotations.ConfigEditorBoolean; import io.github.moulberry.moulconfig.annotations.ConfigOption; -public class NeedsConfig { +public class ShoppingListConfig { @Expose - @ConfigOption(name = "Items Needed", desc = "Show all items needed for the visitors.") + @ConfigOption(name = "Enable", desc = "Show all items required for the visitors.") @ConfigEditorBoolean @FeatureToggle + // TODO rename "enabled" public boolean display = true; @Expose + // TODO renmae "postion" public Position pos = new Position(180, 170, false, true); @Expose - @ConfigOption(name = "Only when Close", desc = "Only show the needed items when close to the visitors.") + @ConfigOption(name = "Only when Close", desc = "Only show the shopping list when close to the visitors.") @ConfigEditorBoolean public boolean onlyWhenClose = false; @@ -28,10 +30,16 @@ public class NeedsConfig { public boolean inBazaarAlley = true; @Expose - @ConfigOption(name = "Show Price", desc = "Show the coin price in the items needed list.") + @ConfigOption(name = "Show Price", desc = "Show the coin price in the shopping list.") @ConfigEditorBoolean public boolean showPrice = true; + @Expose + @ConfigOption(name = "Show Sack Count", desc = "Show the amount of this item that you already have in your sacks. " + + "§eOnly updates on sack change messages.") + @ConfigEditorBoolean + public boolean showSackCount = true; + @Expose @ConfigOption(name = "Item Preview", desc = "Show the base type for the required items next to new visitors. §cNote that some visitors may require any crop.") @ConfigEditorBoolean diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/VisitorConfig.java b/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/VisitorConfig.java index 7aca44b89222..654dcf511812 100644 --- a/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/VisitorConfig.java +++ b/src/main/java/at/hannibal2/skyhanni/config/features/garden/visitor/VisitorConfig.java @@ -17,9 +17,9 @@ public class VisitorConfig { public TimerConfig timer = new TimerConfig(); @Expose - @ConfigOption(name = "Visitor Items Needed", desc = "") + @ConfigOption(name = "Visitor Shopping List", desc = "") @Accordion - public NeedsConfig needs = new NeedsConfig(); + public ShoppingListConfig shoppingList = new ShoppingListConfig(); @Expose @ConfigOption(name = "Visitor Inventory", desc = "") diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt index e38854ba35a6..60630a675131 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt @@ -15,6 +15,7 @@ import at.hannibal2.skyhanni.utils.LorenzUtils 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 com.google.gson.JsonObject import io.github.moulberry.notenoughupdates.NotEnoughUpdates import net.minecraft.client.Minecraft @@ -25,9 +26,10 @@ import net.minecraftforge.fml.common.network.FMLNetworkEvent import kotlin.concurrent.thread class HypixelData { - // TODO USE SH-REPO - private val tabListProfilePattern = "§e§lProfile: §r§a(?.*)".toPattern() - private val lobbyTypePattern = "(?.*lobby)\\d+".toPattern() + private val group = RepoPattern.group("data.hypixeldata") + private val tabListProfilePattern by group.pattern("tablistprofile", "§e§lProfile: §r§a(?.*)") + private val lobbyTypePattern by group.pattern("lobbytype", "(?.*lobby)\\d+") + private val islandNamePattern by group.pattern("islandname", "§b§l(Area|Dungeon): §r§7(?.*)") private var lastLocRaw = 0L @@ -188,7 +190,7 @@ class HypixelData { bingo = false for (line in ScoreboardData.sidebarLinesFormatted) { - if (BingoAPI.getRank(line) != null) { + if (BingoAPI.getRankFromScoreboard(line) != null) { bingo = true } when (line) { @@ -209,8 +211,8 @@ class HypixelData { var newIsland = "" var guesting = false for (line in TabListData.getTabList()) { - if (line.startsWith("§b§lArea: ")) { - newIsland = line.split(": ")[1].removeColor() + islandNamePattern.matchMatcher(line) { + newIsland = group("island") } if (line == " Status: §r§9Guest") { guesting = true diff --git a/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt b/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt index 7e1ac4159495..aa942f5bc651 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/IslandType.kt @@ -12,6 +12,7 @@ enum class IslandType(val displayName: String, val modeName: String = "null") { CATACOMBS("Catacombs", "dungeon"), HUB("Hub", "village"), + DARK_AUCTION("Dark Auction"), THE_FARMING_ISLANDS("The Farming Islands"), CRYSTAL_HOLLOWS("Crystal Hollows"), THE_PARK("The Park", "floating_islands_1"), @@ -20,7 +21,7 @@ enum class IslandType(val displayName: String, val modeName: String = "null") { GARDEN("Garden"), GARDEN_GUEST("Garden Guest"), SPIDER_DEN("Spider's Den"), - WINTER("Jerry's Workshop"), //todo confirm + WINTER("Jerry's Workshop"), THE_RIFT("The Rift"), NONE(""), diff --git a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt index 8a2c511b3e77..454074d3dad8 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/data/SackAPI.kt @@ -7,6 +7,7 @@ import at.hannibal2.skyhanni.events.InventoryCloseEvent import at.hannibal2.skyhanni.events.InventoryFullyOpenedEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.SackChangeEvent +import at.hannibal2.skyhanni.events.SackDataUpdateEvent import at.hannibal2.skyhanni.features.fishing.FishingAPI import at.hannibal2.skyhanni.features.fishing.trophy.TrophyRarity import at.hannibal2.skyhanni.features.inventory.SackDisplay @@ -140,12 +141,6 @@ object SackAPI { gem.finePrice = internalName.sackPrice(stored) if (savingSacks) setSackItem(internalName, stored.formatNumber()) } - - "Flawless" -> { - gem.flawless = stored - gem.flawlessPrice = internalName.sackPrice(stored) - if (savingSacks) setSackItem(internalName, stored.formatNumber()) - } } gemstoneItem[name] = gem } @@ -300,6 +295,8 @@ object SackAPI { private fun saveSackData() { ProfileStorageData.sackProfiles?.sackContents = sackData SkyHanniMod.configManager.saveConfig(ConfigFileType.SACKS, "saving-data") + + SackDataUpdateEvent().postAndCatch() } data class SackGemstone( @@ -307,11 +304,9 @@ object SackAPI { var rough: String = "0", var flawed: String = "0", var fine: String = "0", - var flawless: String = "0", var roughPrice: Long = 0, var flawedPrice: Long = 0, var finePrice: Long = 0, - var flawlessPrice: Long = 0, ) data class SackRune( diff --git a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/BingoJson.java b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/BingoJson.java index babe7cc9e493..f9e8406ebbcb 100644 --- a/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/BingoJson.java +++ b/src/main/java/at/hannibal2/skyhanni/data/jsonobjects/repo/BingoJson.java @@ -7,14 +7,18 @@ public class BingoJson { @Expose - public Map bingo_tips; + public Map bingo_tips; - public static class BingoTip { + public static class BingoData { @Expose public String difficulty; @Expose public List note; + + @Expose + public List guide; + @Expose public String found; } diff --git a/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt b/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt new file mode 100644 index 000000000000..f9e3831d15f0 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/events/SackDataUpdateEvent.kt @@ -0,0 +1,3 @@ +package at.hannibal2.skyhanni.events + +class SackDataUpdateEvent : LorenzEvent() diff --git a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt index 241d208a3261..840253166604 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bazaar/BazaarApi.kt @@ -16,6 +16,7 @@ import at.hannibal2.skyhanni.utils.NEUInternalName import at.hannibal2.skyhanni.utils.NEUItems import at.hannibal2.skyhanni.utils.OSUtils import at.hannibal2.skyhanni.utils.RenderUtils.highlight +import at.hannibal2.skyhanni.utils.StringUtils.equalsIgnoreColor import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher import at.hannibal2.skyhanni.utils.StringUtils.removeColor import net.minecraft.client.gui.inventory.GuiChest @@ -119,14 +120,9 @@ class BazaarApi { } private fun checkIfInBazaar(event: InventoryFullyOpenedEvent): Boolean { - val returnItem = event.inventorySize - 5 - for ((slot, item) in event.inventoryItems) { - if (slot == returnItem && item.name?.removeColor().let { it == "Go Back" }) { - val lore = item.getLore() - if (lore.getOrNull(0)?.removeColor().let { it == "To Bazaar" }) { - return true - } - } + val items = event.inventorySize.let { listOf(it - 5, it - 6) }.mapNotNull { event.inventoryItems[it] } + if (items.any { it.name.equalsIgnoreColor("Go Back") && it.getLore().firstOrNull() == "§7To Bazaar" }) { + return true } if (event.inventoryName.startsWith("Bazaar ➜ ")) return true diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt index 76ed7c68463d..282791154359 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/BingoAPI.kt @@ -9,7 +9,9 @@ import at.hannibal2.skyhanni.features.bingo.card.goals.BingoGoal import at.hannibal2.skyhanni.features.bingo.card.goals.GoalType import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.SimpleTimeMark +import at.hannibal2.skyhanni.utils.StringUtils.matches import at.hannibal2.skyhanni.utils.TimeUtils +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern import net.minecraftforge.fml.common.eventhandler.SubscribeEvent import java.time.LocalTime import java.time.OffsetDateTime @@ -17,31 +19,35 @@ import java.time.ZoneOffset object BingoAPI { private var ranks = mapOf() - private var tips: Map = emptyMap() + private var data: Map = emptyMap() val bingoGoals get() = bingoStorage.goals val personalGoals get() = bingoGoals.values.filter { it.type == GoalType.PERSONAL } val communityGoals get() = bingoGoals.values.filter { it.type == GoalType.COMMUNITY } var lastBingoCardOpenTime = SimpleTimeMark.farPast() + private val detectionPattern by RepoPattern.pattern("bingo.detection.scoreboard", " §.Ⓑ §.Bingo") + @SubscribeEvent fun onRepoReload(event: RepositoryReloadEvent) { ranks = event.getConstant("BingoRanks").ranks - tips = event.getConstant("Bingo").bingo_tips + data = event.getConstant("Bingo").bingo_tips } + fun getRankFromScoreboard(text: String) = if (detectionPattern.matches(text)) getRank(text) else null + fun getRank(text: String) = ranks.entries.find { text.contains(it.key) }?.value fun getIcon(searchRank: Int) = ranks.entries.find { it.value == searchRank }?.key // We added the suffix (Community Goal) so that older skyhanni versions don't crash with the new repo data. - fun getTip(itemName: String) = - tips.filter { itemName.startsWith(it.key.split(" (Community Goal)")[0]) }.values.firstOrNull() + fun getData(itemName: String) = + data.filter { itemName.startsWith(it.key.split(" (Community Goal)")[0]) }.values.firstOrNull() - fun BingoGoal.getTip(): BingoJson.BingoTip? = if (type == GoalType.COMMUNITY) { - getTip(displayName) + fun BingoGoal.getData(): BingoJson.BingoData? = if (type == GoalType.COMMUNITY) { + getData(displayName) } else { - tips[displayName] + data[displayName] } val bingoStorage: BingoSession by lazy { diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt index 520e93b27b06..94490b1d8777 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardDisplay.kt @@ -188,16 +188,20 @@ class BingoCardDisplay { val clickName = if (currentlyHighlighted) "remove" else "add" Renderable.clickAndHover( display, - listOf( - "§a" + it.displayName, - "", - "§eClick to $clickName this goal as highlight!", - ), + buildList { + add("§a" + it.displayName) + for (s in it.guide) { + add(s) + } + add("") + add("§eClick to $clickName this goal as highlight!") + }, onClick = { if (lastClick.passedSince() < 300.milliseconds) return@clickAndHover lastClick = SimpleTimeMark.now() it.highlight = !currentlyHighlighted + it.displayName update() } ) diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt index 0c94a0d15001..9dc7ee907abb 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardReader.kt @@ -63,16 +63,18 @@ class BingoCardReader { val done = lore.any { it.contains("GOAL REACHED") } val communtyGoalPercentage = readCommuntyGoalPercentage(lore) - val hiddenGoalData = getHiddenGoalData(name, description, goalType) val visualDescription = hiddenGoalData.tipNote + val guide = BingoAPI.getData(name)?.guide?.map { "§7$it" } ?: listOf("§cNo guide yet!") + val bingoGoal = BingoAPI.bingoGoals.getOrPut(slot) { BingoGoal() } with(bingoGoal) { this.type = goalType this.displayName = name this.description = visualDescription + this.guide = guide this.done = done this.hiddenGoalData = hiddenGoalData } @@ -130,7 +132,7 @@ class BingoCardReader { } } - val description = BingoAPI.getTip(name)?.getDescriptionLine() + val description = BingoAPI.getData(name)?.getDescriptionLine() val tipNote = description?.let { unknownTip = false it @@ -153,5 +155,5 @@ class BingoCardReader { BingoCardUpdateEvent().postAndCatch() } - private fun BingoJson.BingoTip.getDescriptionLine() = "§7" + note.joinToString(" ") + private fun BingoJson.BingoData.getDescriptionLine() = "§7" + note.joinToString(" ") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt index dd4639234d45..b219f7d44730 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/BingoCardTips.kt @@ -4,7 +4,7 @@ import at.hannibal2.skyhanni.SkyHanniMod import at.hannibal2.skyhanni.events.GuiContainerEvent import at.hannibal2.skyhanni.events.LorenzToolTipEvent import at.hannibal2.skyhanni.features.bingo.BingoAPI -import at.hannibal2.skyhanni.features.bingo.BingoAPI.getTip +import at.hannibal2.skyhanni.features.bingo.BingoAPI.getData import at.hannibal2.skyhanni.features.bingo.card.goals.GoalType import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.LorenzColor @@ -28,7 +28,7 @@ class BingoCardTips { val goal = BingoAPI.bingoGoals[slot.slotNumber] ?: return val toolTip = event.toolTip - val bingoTip = goal.getTip() ?: return + val bingoTip = goal.getData() ?: return val communityGoal = goal.type == GoalType.COMMUNITY val difficulty = Difficulty.valueOf(bingoTip.difficulty.uppercase()) @@ -42,7 +42,7 @@ class BingoCardTips { toolTip.add(index++, "") toolTip.add(index++, "§eGuide:") - for (line in bingoTip.note) { + for (line in bingoTip.guide) { toolTip.add(index++, " $line") } bingoTip.found?.let { @@ -63,7 +63,7 @@ class BingoCardTips { val goal = BingoAPI.bingoGoals[slot.slotNumber] ?: continue if (config.hideDoneDifficulty && goal.done) continue - val color = goal.getTip()?.let { + val color = goal.getData()?.let { val difficulty = Difficulty.valueOf(it.difficulty.uppercase()) difficulty.color } ?: LorenzColor.GRAY diff --git a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/BingoGoal.kt b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/BingoGoal.kt index 58b56090534f..f6758360bb4a 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/BingoGoal.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/bingo/card/goals/BingoGoal.kt @@ -12,6 +12,9 @@ class BingoGoal { @Expose var description = "" + @Expose + var guide = emptyList() + @Expose var done = false diff --git a/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt index a873854b522e..a3bc56396f0e 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/event/UniqueGiftingOpportunitiesFeatures.kt @@ -1,7 +1,6 @@ package at.hannibal2.skyhanni.features.event import at.hannibal2.skyhanni.SkyHanniMod -import at.hannibal2.skyhanni.data.HypixelData import at.hannibal2.skyhanni.data.ProfileStorageData import at.hannibal2.skyhanni.data.WinterAPI import at.hannibal2.skyhanni.events.EntityCustomNameUpdateEvent @@ -79,7 +78,7 @@ object UniqueGiftingOpportunitiesFeatures { } private fun isBingo(entity: EntityLivingBase) = - !HypixelData.bingo && entity.displayName.formattedText.endsWith("Ⓑ§r") + !LorenzUtils.isBingoProfile && entity.displayName.formattedText.endsWith("Ⓑ§r") private fun isIronman(entity: EntityLivingBase) = !LorenzUtils.noTradeMode && entity.displayName.formattedText.endsWith("♲§r") diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt index 78ca8f2b7c28..dffb6f0ef991 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt @@ -20,13 +20,16 @@ import at.hannibal2.skyhanni.features.garden.contest.FarmingContestAPI import at.hannibal2.skyhanni.features.garden.farming.GardenBestCropTime import at.hannibal2.skyhanni.features.garden.farming.GardenCropSpeed import at.hannibal2.skyhanni.features.garden.fortuneguide.FFGuideGUI +import at.hannibal2.skyhanni.features.garden.fortuneguide.FarmingItems import at.hannibal2.skyhanni.features.garden.inventory.SkyMartCopperPrice import at.hannibal2.skyhanni.features.garden.visitor.VisitorAPI import at.hannibal2.skyhanni.utils.BlockUtils.isBabyCrop import at.hannibal2.skyhanni.utils.DelayedRun import at.hannibal2.skyhanni.utils.InventoryUtils import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName +import at.hannibal2.skyhanni.utils.ItemUtils.getItemRarityOrNull import at.hannibal2.skyhanni.utils.LocationUtils.isPlayerInside +import at.hannibal2.skyhanni.utils.LorenzRarity import at.hannibal2.skyhanni.utils.LorenzUtils import at.hannibal2.skyhanni.utils.LorenzUtils.isInIsland import at.hannibal2.skyhanni.utils.LorenzVec @@ -45,7 +48,10 @@ object GardenAPI { var toolInHand: String? = null var itemInHand: ItemStack? = null var cropInHand: CropType? = null - val mushroomCowPet get() = PetAPI.isCurrentPet("Mooshroom Cow") + val mushroomCowPet + get() = PetAPI.isCurrentPet("Mooshroom Cow") && + storage?.fortune?.farmingItems?.get(FarmingItems.MOOSHROOM_COW) + ?.let { it.getItemRarityOrNull()?.isAtLeast(LorenzRarity.RARE) } ?: false private var inBarn = false val onBarnPlot get() = inBarn && inGarden() val storage get() = ProfileStorageData.profileSpecific?.garden diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt index c9ff17c5b56e..bdbc94ee7cba 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/composter/ComposterOverlay.kt @@ -469,8 +469,8 @@ object ComposterOverlay { } private fun retrieveMaterials(internalName: NEUInternalName, itemName: String, itemsNeeded: Int) { - if (itemsNeeded == 0 || internalName.equals("BIOFUEL")) return - if (config.retrieveFrom == ComposterConfig.RetrieveFromEntry.BAZAAR && !LorenzUtils.noTradeMode) { + if (itemsNeeded == 0) return + if (config.retrieveFrom == ComposterConfig.RetrieveFromEntry.BAZAAR && !LorenzUtils.noTradeMode && !internalName.equals("BIOFUEL")) { BazaarApi.searchForBazaarItem(itemName, itemsNeeded) return } @@ -485,9 +485,9 @@ object ComposterOverlay { val sackStatus = sackItem.getStatus() if (sackStatus == SackStatus.MISSING || sackStatus == SackStatus.OUTDATED) { - if (sackStatus == SackStatus.OUTDATED) LorenzUtils.sendCommandToServer("gfs ${internalName.asString()} ${itemsNeeded - having}") + LorenzUtils.sendCommandToServer("gfs ${internalName.asString()} ${itemsNeeded - having}") // TODO Add sack type repo data - val sackType = if (internalName.equals("VOLTA") || internalName.equals("OIL_BARREL")) "Mining" + val sackType = if (internalName.equals("VOLTA") || internalName.equals("OIL_BARREL") || internalName.equals("BIOFUEL")) "Mining §eor §9Dwarven" else "Enchanted Agronomy" LorenzUtils.clickableChat( "Sacks could not be loaded. Click here and open your §9$sackType Sack §eto update the data!", diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt index a21f5769812b..d44dcf359cb8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/farming/GardenCropSpeed.kt @@ -42,7 +42,7 @@ object GardenCropSpeed { fixedRateTimer(name = "skyhanni-crop-milestone-speed", period = 1000L) { if (isEnabled()) { if (GardenAPI.mushroomCowPet) { - CropType.MUSHROOM.setCounter(CropType.MUSHROOM.getCounter() + blocksBroken) + CropType.MUSHROOM.setCounter(CropType.MUSHROOM.getCounter() + blocksBroken * (lastBrokenCrop?.multiplier ?: 1)) } checkSpeed() update() diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt index 051e6ae3a9be..fdef21a09f21 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/fortuneguide/FFStats.kt @@ -15,8 +15,6 @@ import net.minecraft.item.ItemStack import kotlin.math.floor object FFStats { - private val toolHasBountiful get() = GardenAPI.storage?.toolWithBountiful - private val mathCrops = listOf(CropType.WHEAT, CropType.CARROT, CropType.POTATO, CropType.SUGAR_CANE, CropType.NETHER_WART) private val dicerCrops = listOf(CropType.PUMPKIN, CropType.MELON) @@ -103,49 +101,29 @@ object FFStats { cropPage[FortuneStats.COUNTER] = Pair(FarmingFortuneDisplay.getCounterFortune(tool), 96.0) cropPage[FortuneStats.HARVESTING] = Pair(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) cropPage[FortuneStats.COLLECTION] = Pair(FarmingFortuneDisplay.getCollectionFortune(tool), 48.0) - if (toolHasBountiful?.get(crop) == true) { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 10.0) - } else { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 20.0) - } + cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 20.0) } in dicerCrops -> { cropPage[FortuneStats.SUNDER] = Pair(FarmingFortuneDisplay.getSunderFortune(tool), 75.0) - if (toolHasBountiful?.get(crop) == true) { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 10.0) - } else { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 20.0) - } + cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 20.0) } CropType.MUSHROOM -> { cropPage[FortuneStats.BASE_TOOL] = Pair(FarmingFortuneDisplay.getToolFortune(tool), 30.0) cropPage[FortuneStats.HARVESTING] = Pair(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) - if (toolHasBountiful?.get(crop) == true) { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 5.0) - } else { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 13.0) - } + cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 16.0) } CropType.COCOA_BEANS -> { cropPage[FortuneStats.BASE_TOOL] = Pair(FarmingFortuneDisplay.getToolFortune(tool), 20.0) cropPage[FortuneStats.SUNDER] = Pair(FarmingFortuneDisplay.getSunderFortune(tool), 75.0) - if (toolHasBountiful?.get(crop) == true) { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 7.0) - } else { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 16.0) - } + cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 16.0) } CropType.CACTUS -> { cropPage[FortuneStats.HARVESTING] = Pair(FarmingFortuneDisplay.getHarvestingFortune(tool), 75.0) - if (toolHasBountiful?.get(crop) == true) { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 7.0) - } else { - cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 16.0) - } + cropPage[FortuneStats.REFORGE] = Pair(FarmingFortuneDisplay.reforgeFortune, 16.0) } else -> {} diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt index 6c4aa678793b..ded515cecd47 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/inventory/GardenCropMilestoneInventory.kt @@ -58,7 +58,7 @@ class GardenCropMilestoneInventory { val crop = GardenCropMilestones.getCropTypeByLore(event.itemStack) ?: return val tier = GardenCropMilestones.getTierForCropCount(crop.getCounter(), crop) - if (tier > 20) return + if (tier >= 20) return val maxTier = GardenCropMilestones.getMaxTier() val maxCounter = GardenCropMilestones.getCropsForTier(maxTier, crop) @@ -72,7 +72,7 @@ class GardenCropMilestoneInventory { val percentageFormat = LorenzUtils.formatPercentage(percentage) event.toolTip.add(index, " ") - val progressBar = StringUtils.progressBar(percentage) + val progressBar = StringUtils.progressBar(percentage, 19) event.toolTip.add(index, "$progressBar §e${counter.addSeparators()}§6/§e${NumberUtil.format(maxCounter)}") event.toolTip.add(index, "§7Progress to Tier $maxTier: §e$percentageFormat") } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt index 8607a12afb2d..1c17d38f60a8 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/GardenVisitorFeatures.kt @@ -3,11 +3,14 @@ package at.hannibal2.skyhanni.features.garden.visitor import at.hannibal2.skyhanni.config.ConfigUpdaterMigrator import at.hannibal2.skyhanni.config.features.garden.visitor.VisitorConfig.HighlightMode import at.hannibal2.skyhanni.data.IslandType +import at.hannibal2.skyhanni.data.SackAPI +import at.hannibal2.skyhanni.data.SackStatus import at.hannibal2.skyhanni.events.GuiRenderEvent import at.hannibal2.skyhanni.events.LorenzChatEvent import at.hannibal2.skyhanni.events.LorenzTickEvent import at.hannibal2.skyhanni.events.OwnInventoryItemUpdateEvent import at.hannibal2.skyhanni.events.PreProfileSwitchEvent +import at.hannibal2.skyhanni.events.SackDataUpdateEvent import at.hannibal2.skyhanni.events.garden.visitor.VisitorAcceptEvent import at.hannibal2.skyhanni.events.garden.visitor.VisitorAcceptedEvent import at.hannibal2.skyhanni.events.garden.visitor.VisitorArrivalEvent @@ -92,7 +95,7 @@ class GardenVisitorFeatures { val pair = ItemUtils.readItemAmount(line) if (pair == null) { ErrorManager.logErrorStateWithData( - "Could not read items required in Visitor Inventory", "ItemUtils.readItemAmount returns null", + "Could not read Shopping List in Visitor Inventory", "ItemUtils.readItemAmount returns null", "line" to line, "offerItem" to offerItem, "lore" to lore, @@ -102,7 +105,7 @@ class GardenVisitorFeatures { } val (itemName, amount) = pair val internalName = NEUInternalName.fromItemName(itemName) - visitor.items[internalName] = amount + visitor.shoppingList[internalName] = amount } readToolTip(visitor, offerItem) @@ -125,36 +128,36 @@ class GardenVisitorFeatures { } private fun drawDisplay() = buildList { - if (!config.needs.display) return@buildList - val (requiredItems, newVisitors) = prepareDrawingData() + if (!config.shoppingList.display) return@buildList + val (shoppingList, newVisitors) = prepareDrawingData() - drawRequiredItems(requiredItems) - drawVisitors(newVisitors, requiredItems) + drawShoppingList(shoppingList) + drawVisitors(newVisitors, shoppingList) } private fun prepareDrawingData(): Pair, MutableList> { - val requiredItems = mutableMapOf() + val globalShoppingList = mutableMapOf() val newVisitors = mutableListOf() for ((visitorName, visitor) in VisitorAPI.getVisitorsMap()) { if (visitor.status == VisitorAPI.VisitorStatus.ACCEPTED || visitor.status == VisitorAPI.VisitorStatus.REFUSED) continue - val items = visitor.items - if (items.isEmpty()) { + val shoppingList = visitor.shoppingList + if (shoppingList.isEmpty()) { newVisitors.add(visitorName) } - for ((internalName, amount) in items) { - val old = requiredItems.getOrDefault(internalName, 0) - requiredItems[internalName] = old + amount + for ((internalName, amount) in shoppingList) { + val old = globalShoppingList.getOrDefault(internalName, 0) + globalShoppingList[internalName] = old + amount } } - return requiredItems to newVisitors + return globalShoppingList to newVisitors } - private fun MutableList>.drawRequiredItems(requiredItems: MutableMap) { - if (requiredItems.isNotEmpty()) { + private fun MutableList>.drawShoppingList(shoppingList: MutableMap) { + if (shoppingList.isNotEmpty()) { var totalPrice = 0.0 - addAsSingletonList("§7Visitor items needed:") - for ((internalName, amount) in requiredItems) { + addAsSingletonList("§7Visitor Shopping List:") + for ((internalName, amount) in shoppingList) { val name = internalName.getItemName() val itemStack = internalName.getItemStack() @@ -170,28 +173,38 @@ class GardenVisitorFeatures { } }) { GardenAPI.inGarden() && !NEUItems.neuHasFocus() }) - if (config.needs.showPrice) { + if (config.shoppingList.showPrice) { val price = internalName.getPrice() * amount totalPrice += price val format = NumberUtil.format(price) list.add(" §7(§6$format§7)") } + if (config.shoppingList.showSackCount) { + val sackItemData = SackAPI.fetchSackItem(internalName) + val itemStatus = sackItemData.getStatus() + val itemAmount = sackItemData.amount + if (itemStatus != SackStatus.OUTDATED) { + val textColour = if (itemAmount > amount) "a" else "e" + list.add(" §${textColour}x${sackItemData.amount.addSeparators()} §7in your sack") + } + } + add(list) } if (totalPrice > 0) { val format = NumberUtil.format(totalPrice) - this[0] = listOf("§7Visitor items needed: §7(§6$format§7)") + this[0] = listOf("§7Visitor Shopping List: §7(§6$format§7)") } } } private fun MutableList>.drawVisitors( newVisitors: MutableList, - requiredItems: MutableMap + shoppingList: MutableMap ) { if (newVisitors.isNotEmpty()) { - if (requiredItems.isNotEmpty()) { + if (shoppingList.isNotEmpty()) { addAsSingletonList("") } val amount = newVisitors.size @@ -203,7 +216,7 @@ class GardenVisitorFeatures { val list = mutableListOf() list.add(" §7- $displayName") - if (config.needs.itemPreview) { + if (config.shoppingList.itemPreview) { val items = GardenVisitorColorNames.visitorItems[visitor.removeColor()] if (items == null) { val text = "Visitor '$visitor' has no items in repo!" @@ -239,6 +252,11 @@ class GardenVisitorFeatures { } } + @SubscribeEvent + fun onSackUpdate(event: SackDataUpdateEvent) { + update() + } + @SubscribeEvent fun onVisitorRefused(event: VisitorRefusedEvent) { update() @@ -287,14 +305,14 @@ class GardenVisitorFeatures { private fun readToolTip(visitor: VisitorAPI.Visitor, itemStack: ItemStack?) { val stack = itemStack ?: error("Accept offer item not found for visitor ${visitor.visitorName}") var totalPrice = 0.0 - var timeRequired = -1L - var readingItemsNeeded = true + var farmingTimeRequired = -1L + var readingShoppingList = true lastFullPrice = 0.0 val foundRewards = mutableListOf() for (formattedLine in stack.getLore()) { if (formattedLine.contains("Rewards")) { - readingItemsNeeded = false + readingShoppingList = false } val (itemName, amount) = ItemUtils.readItemAmount(formattedLine) ?: continue @@ -304,7 +322,7 @@ class GardenVisitorFeatures { if (internalName.startsWith("SKYBLOCK_")) continue val price = internalName.getPrice() * amount - if (readingItemsNeeded) { + if (readingShoppingList) { totalPrice += price lastFullPrice += price } else { @@ -328,7 +346,7 @@ class GardenVisitorFeatures { } } - readingItemsNeeded = true + readingShoppingList = true val finalList = stack.getLore().toMutableList() var offset = 0 for ((i, formattedLine) in finalList.toMutableList().withIndex()) { @@ -344,17 +362,17 @@ class GardenVisitorFeatures { copperPattern.matchMatcher(formattedLine) { val copper = group("amount").replace(",", "").toInt() val pricePerCopper = NumberUtil.format((totalPrice / copper).toInt()) - val timePerCopper = TimeUtils.formatDuration((timeRequired / copper) * 1000) + val timePerCopper = TimeUtils.formatDuration((farmingTimeRequired / copper) * 1000) var copperLine = formattedLine if (config.inventory.copperPrice) copperLine += " §7(§6$pricePerCopper §7per)" if (config.inventory.copperTime) { - copperLine += if (timeRequired != -1L) " §7(§b$timePerCopper §7per)" else " §7(§cno speed data!§7)" + copperLine += if (farmingTimeRequired != -1L) " §7(§b$timePerCopper §7per)" else " §7(§cno speed data!§7)" } finalList.set(index, copperLine) } if (formattedLine.contains("Rewards")) { - readingItemsNeeded = false + readingShoppingList = false } val (itemName, amount) = ItemUtils.readItemAmount(formattedLine) ?: continue @@ -368,7 +386,7 @@ class GardenVisitorFeatures { val format = NumberUtil.format(price) finalList[index] = "$formattedLine §7(§6$format§7)" } - if (!readingItemsNeeded) continue + if (!readingShoppingList) continue val multiplier = NEUItems.getMultiplier(internalName) val rawName = multiplier.first.getItemNameOrNull()?.removeColor() ?: continue @@ -378,8 +396,8 @@ class GardenVisitorFeatures { val formattedAmount = LorenzUtils.formatInteger(cropAmount) val formattedName = "§e$formattedAmount§7x ${cropType.cropName} " val formattedSpeed = cropType.getSpeed()?.let { speed -> - timeRequired = cropAmount / speed - val duration = TimeUtils.formatDuration(timeRequired * 1000) + farmingTimeRequired = cropAmount / speed + val duration = TimeUtils.formatDuration(farmingTimeRequired * 1000) "in §b$duration" } ?: "§cno speed data!" if (config.inventory.exactAmountAndTime) { @@ -393,7 +411,7 @@ class GardenVisitorFeatures { @SubscribeEvent fun onTick(event: LorenzTickEvent) { if (!GardenAPI.inGarden()) return - if (!config.needs.display && config.highlightStatus == HighlightMode.DISABLED) return + if (!config.shoppingList.display && config.highlightStatus == HighlightMode.DISABLED) return if (!event.isMod(10)) return if (GardenAPI.onBarnPlot && config.highlightStatus != HighlightMode.DISABLED) { @@ -527,9 +545,9 @@ class GardenVisitorFeatures { private fun hasItemsInInventory(visitor: VisitorAPI.Visitor): Boolean { var ready = true - for ((internalName, need) in visitor.items) { + for ((internalName, required) in visitor.shoppingList) { val having = InventoryUtils.countItemsInLowerInventory { it.getInternalName() == internalName } - if (having < need) { + if (having < required) { ready = false } } @@ -539,14 +557,14 @@ class GardenVisitorFeatures { @SubscribeEvent fun onRenderInSigns(event: DrawScreenEvent.Post) { if (!GardenAPI.inGarden()) return - if (!config.needs.display) return + if (!config.shoppingList.display) return val gui = event.gui if (gui !is GuiEditSign) return - if (config.needs.onlyWhenClose && !GardenAPI.onBarnPlot) return + if (config.shoppingList.onlyWhenClose && !GardenAPI.onBarnPlot) return if (!hideExtraGuis()) { - config.needs.pos.renderStringsAndItems(display, posLabel = "Visitor Items Needed") + config.shoppingList.pos.renderStringsAndItems(display, posLabel = "Visitor Shopping List") } } @@ -554,22 +572,22 @@ class GardenVisitorFeatures { @SubscribeEvent fun onRenderOverlay(event: GuiRenderEvent) { - if (!config.needs.display) return + if (!config.shoppingList.display) return if (showGui()) { - config.needs.pos.renderStringsAndItems(display, posLabel = "Visitor Items Needed") + config.shoppingList.pos.renderStringsAndItems(display, posLabel = "Visitor Shopping List") } } private fun showGui(): Boolean { - if (config.needs.inBazaarAlley && IslandType.HUB.isInIsland() && LorenzUtils.skyBlockArea == "Bazaar Alley") { + if (config.shoppingList.inBazaarAlley && IslandType.HUB.isInIsland() && LorenzUtils.skyBlockArea == "Bazaar Alley") { return true } if (hideExtraGuis()) return false if (GardenAPI.inGarden()) { if (GardenAPI.onBarnPlot) return true - if (!config.needs.onlyWhenClose) return true + if (!config.shoppingList.onlyWhenClose) return true } return false } @@ -635,6 +653,8 @@ class GardenVisitorFeatures { event.transform(15, "garden.visitors.highlightStatus") { element -> ConfigUtils.migrateIntToEnum(element, HighlightMode::class.java) } + + event.move(18, "garden.visitors.needs", "garden.visitors.shoppingList") } } diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorAPI.kt index a74793fbe4e7..c3c832d787c9 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorAPI.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/garden/visitor/VisitorAPI.kt @@ -108,7 +108,7 @@ object VisitorAPI { var nameTagEntityId: Int = -1, var status: VisitorStatus, var inSacks: Boolean = false, - val items: MutableMap = mutableMapOf(), + val shoppingList: MutableMap = mutableMapOf(), var offer: VisitorOffer? = null, ) { var lore: List = emptyList() diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt index 510b62dd163b..3c90ee398b51 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/SackDisplay.kt @@ -194,15 +194,15 @@ object SackDisplay { if (SackAPI.gemstoneItem.isNotEmpty()) { newDisplay.addAsSingletonList("§7Gemstones:") for ((name, gem) in SackAPI.gemstoneItem) { - val (internalName, rough, flawed, fine, flawless, roughprice, flawedprice, fineprice, flawlessprice) = gem + val (internalName, rough, flawed, fine, roughprice, flawedprice, fineprice) = gem newDisplay.add(buildList { add(" §7- ") add(internalName.getItemStack()) add(Renderable.optionalLink("$name: ", { BazaarApi.searchForBazaarItem(name.dropLast(1)) }) { !NEUItems.neuHasFocus() }) - add(" ($rough-§a$flawed-§9$fine-§5$flawless)") - val price = roughprice + flawedprice + fineprice + flawlessprice + add(" ($rough-§a$flawed-§9$fine)") + val price = roughprice + flawedprice + fineprice totalPrice += price if (config.showPrice && price != 0L) add(" §7(§6${format(price)}§7)") }) diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/Relay.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/Relay.kt index f634fffa97fb..505898460794 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/Relay.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/Relay.kt @@ -2,47 +2,52 @@ package at.hannibal2.skyhanni.features.inventory.tiarelay import at.hannibal2.skyhanni.data.IslandType import at.hannibal2.skyhanni.utils.LorenzVec +import at.hannibal2.skyhanni.utils.StringUtils.matches +import at.hannibal2.skyhanni.utils.repopatterns.RepoPattern enum class Relay( val relayName: String, val waypoint: LorenzVec, val island: IslandType, - val chatMessage: String + chatMessage: String, ) { RELAY_1( "1st Relay", LorenzVec(143.5, 108.0, 93.0), IslandType.HUB, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rThe first relay is on a branch of the large tree on the north-east of the fairy pond." + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fThe first relay is on a branch of the large tree on the north-east of the fairy pond." ), RELAY_2( "2nd Relay", LorenzVec(-246.5, 123.0, 55.5), IslandType.HUB, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rThe next relay is in the castle ruins!" + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fThe next relay is in the castle ruins!" ), RELAY_3( "3rd Relay", LorenzVec(128.5, 232.0, 200.5), IslandType.DWARVEN_MINES, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rThe next relay is in the §bRoyal Palace §rwithin the Dwarven Mines." + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fThe next relay is in the §bRoyal Palace §rwithin the Dwarven Mines." ), RELAY_4( "4th Relay", LorenzVec(-560, 164, -287), IslandType.THE_END, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rThe next relay is on the highest spike of §dThe End§r." + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fThe next relay is on the highest spike of §dThe End§r." ), RELAY_5( "5th Relay", LorenzVec(-375, 207, -799), IslandType.CRIMSON_ISLE, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rThe next relay was placed by our consultant, Odger." + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fThe next relay was placed by our consultant, Odger." ), RELAY_6( "6th Relay", LorenzVec(-69, 157, -879), IslandType.CRIMSON_ISLE, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rScarleton itself has one of the most robust connection to the 9f™ Network." + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fScarleton itself has one of the most robust connection to the 9f™ Network." ), RELAY_7( "7th Relay", LorenzVec(93, 86, 187), IslandType.HUB, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rThe next relay is on top of the shack next to the shady inn right here close to the pond." + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fThe next relay is on top of the shack next to the shady inn right here close to the pond." ), RELAY_8( "8th Relay", LorenzVec(0, 146, -75), IslandType.DUNGEON_HUB, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rThe next relay is on top of a statue in the dungeon hub." + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fThe next relay is on top of a statue in the dungeon hub." ), RELAY_9( "9th Relay", LorenzVec(-19.0, 88.5, -91.0), IslandType.HUB, - "§e[NPC] §dTia the Fairy§f: §b✆ §f§rThe next relay is on top of the Auction House." - ), + "§e[NPC] §dTia the Fairy§f: §b✆ §f§r§fThe next relay is on top of the Auction House." + ); + + val chatPattern by RepoPattern.pattern("relay.chat." + relayName.takeWhile { it != ' ' }, chatMessage) + fun checkChatMessage(string: String) = chatPattern.matches(string) } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/TiaRelayHelper.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/TiaRelayHelper.kt index 4d648c16cd8a..e0193eaaadaf 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/TiaRelayHelper.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/TiaRelayHelper.kt @@ -71,7 +71,8 @@ class TiaRelayHelper { val name = sounds.values.first().name for (sound in sounds.toMutableMap()) { if (sound.value.name != name) { - LorenzUtils.error("Tia Relay Helper error: Too much background noise! Please try again.") + LorenzUtils.error("Tia Relay Helper error: Too much background noise! Try turning off the music and then try again.") + LorenzUtils.clickableChat("Click here to run /togglemusic", "togglemusic") sounds.clear() return } diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/TiaRelayWaypoints.kt b/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/TiaRelayWaypoints.kt index 5b9e8fa6fe3e..4fa33ad2b010 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/TiaRelayWaypoints.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/inventory/tiarelay/TiaRelayWaypoints.kt @@ -17,19 +17,21 @@ class TiaRelayWaypoints { private var waypointName: String? = null private var island = IslandType.NONE + init { + Relay.entries.forEach { it.chatPattern } + } + @SubscribeEvent fun onChatMessage(event: LorenzChatEvent) { if (!LorenzUtils.inSkyBlock) return if (!config.nextWaypoint) return val message = event.message - for (relay in Relay.entries) { - if (relay.chatMessage == message) { - waypoint = relay.waypoint - waypointName = relay.relayName - island = relay.island - return - } + Relay.entries.firstOrNull { it.checkChatMessage(message) }?.let { relay -> + waypoint = relay.waypoint + waypointName = relay.relayName + island = relay.island + return } if (message == "§aYou completed the maintenance on the relay!") { @@ -60,4 +62,4 @@ class TiaRelayWaypoints { event.drawDynamicText(it, "§d" + waypointName!!, 1.5) } } -} \ No newline at end of file +} diff --git a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbility.kt b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbility.kt index ff34048ce245..2e252892c854 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbility.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/itemabilities/abilitycooldown/ItemAbility.kt @@ -52,7 +52,7 @@ enum class ItemAbility( LIVID_DAGGER("Throw", 5, "Livid Dagger"), FIRE_VEIL("Fire Veil", 5, "Fire Veil Wand"), INK_WAND("Ink Bomb", 30, "Ink Wand"), - ROUGE_SWORD("Speed Boost", 30, "Rogue Sword"), + ROGUE_SWORD("Speed Boost", 30, "Rogue Sword", ignoreMageCooldownReduction = true), // doesn't have a consistent sound ECHO("Echo", 3, "Ancestral Spade"); diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt index cc2a09b9da46..2f7be15ec76d 100644 --- a/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt +++ b/src/main/java/at/hannibal2/skyhanni/features/misc/discordrpc/DiscordStatus.kt @@ -206,9 +206,10 @@ enum class DiscordStatus(private val displayMessageSupplier: Supplier?) var profile = "SkyBlock Level: [$sbLevel] on " profile += when { - HypixelData.ironman -> "♲" - HypixelData.bingo -> "Ⓑ" - HypixelData.stranded -> "☀" + + LorenzUtils.isIronmanProfile -> "♲" + LorenzUtils.isBingoProfile -> "Ⓑ" + LorenzUtils.isStrandedProfile -> "☀" else -> "" } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzRarity.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzRarity.kt index b0aca2439561..64d5f85389bc 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzRarity.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzRarity.kt @@ -51,6 +51,8 @@ enum class LorenzRarity(val color: LorenzColor, val id: Int) { return rarityBelow } + fun isAtLeast(other: LorenzRarity): Boolean = this.ordinal >= other.ordinal + companion object { fun getById(id: Int) = entries.firstOrNull { it.ordinal == id } fun getByName(name: String) = entries.firstOrNull { it.name == name } diff --git a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt index 23d0251cde02..9f6dd9f7cc23 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/LorenzUtils.kt @@ -67,10 +67,12 @@ object LorenzUtils { val noTradeMode get() = HypixelData.noTrade - val isStrandedProfile get() = HypixelData.stranded + val isStrandedProfile get() = inSkyBlock && HypixelData.stranded val isBingoProfile get() = inSkyBlock && (HypixelData.bingo || TestBingo.testBingo) + val isIronmanProfile get() = inSkyBlock && HypixelData.ironman + val lastWorldSwitch get() = HypixelData.joinedWorld // TODO log based on chat category (error, warning, debug, user error, normal) @@ -532,7 +534,7 @@ object LorenzUtils { && tileSign.signText[3].unformattedText.removeColor() == "speed cap!") } - fun IslandType.isInIsland() = inSkyBlock && (skyBlockIsland == this || this == IslandType.CATACOMBS && inDungeons) + fun IslandType.isInIsland() = inSkyBlock && skyBlockIsland == this fun MutableMap.addOrPut(key: K, number: Int): Int { val currentValue = this[key] ?: 0 diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt index 4e85267ca02f..7c33cd1b2f5c 100644 --- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt +++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt @@ -286,4 +286,6 @@ object StringUtils { fun Pattern.find(string: String) = matcher(string).find() fun String.allLettersFirstUppercase() = split("_").joinToString(" ") { it.firstLetterUppercase() } + + fun String?.equalsIgnoreColor(string: String?) = this?.let { it.removeColor() == string?.removeColor() } ?: false }