aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhannibal2 <24389977+hannibal00212@users.noreply.github.com>2023-04-28 19:34:18 +0200
committerhannibal2 <24389977+hannibal00212@users.noreply.github.com>2023-04-28 19:34:18 +0200
commitb649d65c7597ff3a2174ab752143b997cddebf40 (patch)
tree5cbc196bfa74f53efc4d9f1f7d555cf93c9e0366 /src
parentd4e51f2a49d267290f2cf5e0065ca3ffa8531d04 (diff)
downloadskyhanni-b649d65c7597ff3a2174ab752143b997cddebf40.tar.gz
skyhanni-b649d65c7597ff3a2174ab752143b997cddebf40.tar.bz2
skyhanni-b649d65c7597ff3a2174ab752143b997cddebf40.zip
FF for Contest - Show the minimum needed Farming Fortune for reaching a medal in the Jacob's Farming Contest inventory
Diffstat (limited to 'src')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Garden.java11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt4
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/contest/ContestRank.kt11
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContest.kt5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContestAPI.kt65
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestFFNeededDisplay.kt102
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobFarmingContestsInventory.kt (renamed from src/main/java/at/hannibal2/skyhanni/features/inventory/JacobFarmingContestsInventory.kt)29
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt6
9 files changed, 218 insertions, 20 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
index 4707bf5eb..66452e7e2 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
@@ -32,6 +32,9 @@ import at.hannibal2.skyhanni.features.garden.composter.ComposterDisplay;
import at.hannibal2.skyhanni.features.garden.composter.ComposterInventoryNumbers;
import at.hannibal2.skyhanni.features.garden.composter.ComposterOverlay;
import at.hannibal2.skyhanni.features.garden.composter.GardenComposterInventoryFeatures;
+import at.hannibal2.skyhanni.features.garden.contest.FarmingContestAPI;
+import at.hannibal2.skyhanni.features.garden.contest.JacobContestFFNeededDisplay;
+import at.hannibal2.skyhanni.features.garden.contest.JacobFarmingContestsInventory;
import at.hannibal2.skyhanni.features.garden.farming.*;
import at.hannibal2.skyhanni.features.garden.inventory.*;
import at.hannibal2.skyhanni.features.garden.visitor.GardenVisitorColorNames;
@@ -157,6 +160,7 @@ public class SkyHanniMod {
loadModule(new BazaarApi());
loadModule(GardenAPI.INSTANCE);
loadModule(new CollectionAPI());
+ loadModule(FarmingContestAPI.INSTANCE);
// features
loadModule(new BazaarOrderHelper());
@@ -280,6 +284,7 @@ public class SkyHanniMod {
loadModule(new GardenCropMilestoneFix());
loadModule(new GardenBurrowingSporesNotifier());
loadModule(new WildStrawberryDyeNotification());
+ loadModule(new JacobContestFFNeededDisplay());
Commands.INSTANCE.init();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java
index 392223d53..825b2b3bf 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java
@@ -1013,6 +1013,17 @@ public class Garden {
public boolean wildStrawberryDyeNotification = true;
@Expose
+ @ConfigOption(
+ name = "FF for Contest",
+ desc = "Show the minimum needed Farming Fortune for reaching a medal in the Jacob's Farming Contest inventory."
+ )
+ @ConfigEditorBoolean
+ public boolean farmingFortuneForContest = true;
+
+ @Expose
+ public Position farmingFortuneForContestPos = new Position(180, 156, false, true);
+
+ @Expose
@ConfigOption(name = "Always Finnegan", desc = "Forcefully set the Finnegan Farming Simulator perk to be active. This is useful if the auto mayor detection fails.")
@ConfigEditorBoolean
public boolean forcefullyEnabledAlwaysFinnegan = false;
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 dd149b5dd..bd393589a 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenAPI.kt
@@ -5,6 +5,7 @@ import at.hannibal2.skyhanni.data.IslandType
import at.hannibal2.skyhanni.data.ScoreboardData
import at.hannibal2.skyhanni.events.*
import at.hannibal2.skyhanni.features.garden.composter.ComposterOverlay
+import at.hannibal2.skyhanni.features.garden.contest.FarmingContestAPI
import at.hannibal2.skyhanni.features.garden.farming.GardenBestCropTime
import at.hannibal2.skyhanni.features.garden.inventory.SkyMartCopperPrice
import at.hannibal2.skyhanni.utils.ItemUtils.getInternalName
@@ -161,7 +162,8 @@ object GardenAPI {
fun isSpeedDataEmpty() = cropsPerSecond.values.sum() < 0
- fun hideExtraGuis() = ComposterOverlay.inInventory || AnitaMedalProfit.inInventory || SkyMartCopperPrice.inInventory
+ fun hideExtraGuis() = ComposterOverlay.inInventory || AnitaMedalProfit.inInventory ||
+ SkyMartCopperPrice.inInventory || FarmingContestAPI.inInventory
fun clearCropSpeed() {
for (type in CropType.values()) {
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/ContestRank.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/ContestRank.kt
new file mode 100644
index 000000000..5bae5ef0d
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/ContestRank.kt
@@ -0,0 +1,11 @@
+package at.hannibal2.skyhanni.features.garden.contest
+
+enum class ContestRank(val color: String) {
+ GOLD("6"),
+ SILVER("f"),
+ BRONZE("c"),
+ ;
+
+ val displayName = "§$color§l$name"
+ val pattern = "$displayName §7\\(§bTop \\d{1,2}%§7\\): §$color(?<amount>.*)".toPattern()
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContest.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContest.kt
new file mode 100644
index 000000000..03fb4b0a8
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContest.kt
@@ -0,0 +1,5 @@
+package at.hannibal2.skyhanni.features.garden.contest
+
+import at.hannibal2.skyhanni.features.garden.CropType
+
+data class FarmingContest(val time: Long, val crop: CropType, val ranks: Map<ContestRank, Int>) \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContestAPI.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContestAPI.kt
new file mode 100644
index 000000000..27a6d1515
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/FarmingContestAPI.kt
@@ -0,0 +1,65 @@
+package at.hannibal2.skyhanni.features.garden.contest
+
+import at.hannibal2.skyhanni.events.GuiContainerEvent
+import at.hannibal2.skyhanni.events.InventoryOpenEvent
+import at.hannibal2.skyhanni.features.garden.CropType
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.StringUtils.matchMatcher
+import io.github.moulberry.notenoughupdates.util.SkyBlockTime
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+object FarmingContestAPI {
+ private val timePattern = "§a(?<month>.*) (?<day>.*)(?:rd|st|nd|th), Year (?<year>.*)".toPattern()
+ private val contests = mutableMapOf<Long, FarmingContest>()
+ private val cropPattern = "§8(?<crop>.*) Contest".toPattern()
+
+ var inInventory = false
+
+ @SubscribeEvent
+ fun onInventoryOpen(event: InventoryOpenEvent) {
+ if (event.inventoryName == "Your Contests") {
+ inInventory = true
+ }
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: GuiContainerEvent.CloseWindowEvent) {
+ inInventory = false
+ }
+
+ fun getSbTimeFor(text: String) = timePattern.matchMatcher(text) {
+ val month = group("month")
+ val monthNr = LorenzUtils.getSBMonthByName(month)
+
+ val year = group("year").toInt()
+ val day = group("day").toInt()
+ SkyBlockTime(year, monthNr, day).toMillis()
+ }
+
+ fun addContest(time: Long, item: ItemStack) {
+ contests.putIfAbsent(time, createContest(time, item))
+ }
+
+ private fun createContest(time: Long, item: ItemStack): FarmingContest {
+ val lore = item.getLore()
+ val crop = lore.firstNotNullOfOrNull {
+ cropPattern.matchMatcher(it) { CropType.getByName(group("crop")) }
+ } ?: error("Crop not found in lore!")
+
+ val ranks = ContestRank.values().associateWith { rank ->
+ lore.firstNotNullOfOrNull {
+ rank.pattern.matchMatcher(it) {
+ group("amount").replace(",", "").toInt()
+ }
+ } ?: error("Farming contest rank not found in lore!")
+ }
+
+ return FarmingContest(time, crop, ranks)
+ }
+
+ fun getContestAtTime(time: Long) = contests[time]
+
+ fun getContestsOfType(crop: CropType) = contests.values.filter { it.crop == crop }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestFFNeededDisplay.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestFFNeededDisplay.kt
new file mode 100644
index 000000000..e80c0a03f
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobContestFFNeededDisplay.kt
@@ -0,0 +1,102 @@
+package at.hannibal2.skyhanni.features.garden.contest
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.RenderItemTooltipEvent
+import at.hannibal2.skyhanni.features.garden.CropType
+import at.hannibal2.skyhanni.utils.InventoryUtils
+import at.hannibal2.skyhanni.utils.ItemUtils.name
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.LorenzUtils.addAsSingletonList
+import at.hannibal2.skyhanni.utils.LorenzUtils.sortedDesc
+import at.hannibal2.skyhanni.utils.NumberUtil.addSeparators
+import at.hannibal2.skyhanni.utils.RenderUtils.renderStringsAndItems
+import net.minecraft.item.ItemStack
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import kotlin.math.ceil
+
+class JacobContestFFNeededDisplay {
+ private val config get() = SkyHanniMod.feature.garden
+ private var display = listOf<List<Any>>()
+ private var lastToolTipTime = 0L
+ private val cache = mutableMapOf<ItemStack, List<List<Any>>>()
+
+ @SubscribeEvent
+ fun onTooltip(event: RenderItemTooltipEvent) {
+ if (!isEnabled()) return
+
+ if (!InventoryUtils.openInventoryName().contains("Your Contests")) return
+ val stack = event.stack
+
+ val oldData = cache[stack]
+ if (oldData != null) {
+ display = oldData
+ lastToolTipTime = System.currentTimeMillis()
+ return
+ }
+
+ val name = stack.name ?: return
+ val time = FarmingContestAPI.getSbTimeFor(name) ?: return
+ val contest = FarmingContestAPI.getContestAtTime(time) ?: return
+
+ val newDisplay = drawDisplay(contest)
+ display = newDisplay
+ cache[stack] = newDisplay
+ lastToolTipTime = System.currentTimeMillis()
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ cache.clear()
+ }
+
+ private fun drawDisplay(contest: FarmingContest) = buildList<List<Any>> {
+ addAsSingletonList("§6Minimum Farming Fortune needed")
+ addAsSingletonList("")
+
+ val crop = contest.crop
+ add(listOf("For this ", crop.icon, "${crop.cropName} contest:"))
+ for (rank in ContestRank.values()) {
+ addAsSingletonList(getLine(rank, contest.ranks, crop))
+ }
+ addAsSingletonList("")
+
+ val (size, averages) = calculateAverages(crop)
+ add(listOf("For the last $size ", crop.icon, "${crop.cropName} contests:"))
+ for (rank in ContestRank.values()) {
+ addAsSingletonList(getLine(rank, averages, crop))
+ }
+ }
+
+ private fun getLine(rank: ContestRank, map: Map<ContestRank, Int>, crop: CropType): String {
+ val counter = map[rank]!!
+ val cropsPerSecond = counter.toDouble() / 20 / 60
+ val farmingFortune = ceil(cropsPerSecond * 100 / 20 / crop.baseDrops)
+ return " ${rank.displayName}§f: §6${farmingFortune.addSeparators()} FF §7(${counter.addSeparators()} crops)"
+ }
+
+ private fun calculateAverages(crop: CropType): Pair<Int, Map<ContestRank, Int>> {
+ var amount = 0
+ val map = mutableMapOf<ContestRank, Int>()
+ for (entry in FarmingContestAPI.getContestsOfType(crop).associateWith { it.time }.sortedDesc().keys) {
+ amount++
+ for ((rank, count) in entry.ranks) {
+ val old = map.getOrDefault(rank, 0)
+ map[rank] = count + old
+ }
+ if (amount == 10) break
+ }
+ return Pair(amount, map.mapValues { (_, counter) -> counter / amount })
+ }
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.ChestBackgroundRenderEvent) {
+ if (!isEnabled()) return
+ if (!FarmingContestAPI.inInventory) return
+ if (System.currentTimeMillis() > lastToolTipTime + 200) return
+ config.farmingFortuneForContestPos.renderStringsAndItems(display, posLabel = "Estimated Item Value")
+ }
+
+ fun isEnabled() = LorenzUtils.inSkyBlock && config.farmingFortuneForContest
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/features/inventory/JacobFarmingContestsInventory.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobFarmingContestsInventory.kt
index 3eccc0cfe..5efe01d9e 100644
--- a/src/main/java/at/hannibal2/skyhanni/features/inventory/JacobFarmingContestsInventory.kt
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/contest/JacobFarmingContestsInventory.kt
@@ -1,4 +1,4 @@
-package at.hannibal2.skyhanni.features.inventory
+package at.hannibal2.skyhanni.features.garden.contest
import at.hannibal2.skyhanni.SkyHanniMod
import at.hannibal2.skyhanni.events.GuiContainerEvent
@@ -11,7 +11,6 @@ import at.hannibal2.skyhanni.utils.ItemUtils.name
import at.hannibal2.skyhanni.utils.LorenzColor
import at.hannibal2.skyhanni.utils.LorenzUtils
import at.hannibal2.skyhanni.utils.RenderUtils.highlight
-import io.github.moulberry.notenoughupdates.util.SkyBlockTime
import net.minecraft.client.gui.inventory.GuiChest
import net.minecraft.inventory.ContainerChest
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
@@ -25,7 +24,6 @@ class JacobFarmingContestsInventory {
private val formatDay = SimpleDateFormat("dd MMMM yyyy", Locale.US)
private val formatTime = SimpleDateFormat("HH:mm", Locale.US)
- private val pattern = "§a(.*) (.*)(?:rd|st|nd|th), Year (.*)".toPattern()
private val config get() = SkyHanniMod.feature.inventory
// Render the contests a tick delayed to feel smoother
@@ -59,27 +57,19 @@ class JacobFarmingContestsInventory {
} else {
foundEvents.add(name)
}
+ val time = FarmingContestAPI.getSbTimeFor(name) ?: continue
+ FarmingContestAPI.addContest(time, item)
if (config.jacobFarmingContestRealTime) {
- readRealTime(name, slot)
+ readRealTime(time, slot)
}
}
hideEverything = false
}
- private fun readRealTime(name: String, slot: Int) {
- val matcher = pattern.matcher(name)
- if (!matcher.matches()) return
-
- val month = matcher.group(1)
- val day = matcher.group(2).toInt()
- val year = matcher.group(3).toInt()
-
- val monthNr = LorenzUtils.getSBMonthByName(month)
- val time = SkyBlockTime(year, monthNr, day)
- val toMillis = time.toMillis()
- val dayFormat = formatDay.format(toMillis)
- val startTimeFormat = formatTime.format(toMillis)
- val endTimeFormat = formatTime.format(toMillis + 1000 * 60 * 20)
+ private fun readRealTime(time: Long, slot: Int) {
+ val dayFormat = formatDay.format(time)
+ val startTimeFormat = formatTime.format(time)
+ val endTimeFormat = formatTime.format(time + 1000 * 60 * 20)
realTime[slot] = "$dayFormat $startTimeFormat-$endTimeFormat"
}
@@ -137,7 +127,8 @@ class JacobFarmingContestsInventory {
if (config.jacobFarmingContestHideDuplicates) {
if (duplicateSlots.contains(slot)) {
event.toolTip.clear()
- event.toolTip.add("§7Duplicate contest!")
+ event.toolTip.add("§7Duplicate contest")
+ event.toolTip.add("§7hidden by SkyHanni!")
return
}
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
index 659f93ecf..06187da3c 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/StringUtils.kt
@@ -2,6 +2,8 @@ package at.hannibal2.skyhanni.utils
import org.intellij.lang.annotations.Language
import java.util.*
+import java.util.regex.Matcher
+import java.util.regex.Pattern
object StringUtils {
fun String.firstLetterUppercase(): String {
@@ -56,4 +58,8 @@ object StringUtils {
fun String.matchRegex(@Language("RegExp") regex: String): Boolean = regex.toRegex().matches(this)
private fun String.removeAtBeginning(text: String): String = if (this.startsWith(text)) substring(text.length) else this
+
+ // TODO find better name for this method
+ inline fun <T> Pattern.matchMatcher(text: String, consumer: Matcher.() -> T) =
+ matcher(text).let { if (it.matches()) consumer(it) else null }
}