aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/at')
-rw-r--r--src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java1
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/Features.java5
-rw-r--r--src/main/java/at/hannibal2/skyhanni/config/features/Garden.java17
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt187
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt9
5 files changed, 219 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
index d5f9a3929..d61c57812 100644
--- a/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
+++ b/src/main/java/at/hannibal2/skyhanni/SkyHanniMod.java
@@ -222,6 +222,7 @@ public class SkyHanniMod {
loadModule(new DicerRngDropCounter());
loadModule(new CropMoneyDisplay());
loadModule(new JacobFarmingContestsInventory());
+ loadModule(new GardenNextJacobContest());
Commands.INSTANCE.init();
diff --git a/src/main/java/at/hannibal2/skyhanni/config/Features.java b/src/main/java/at/hannibal2/skyhanni/config/Features.java
index e087b790c..8110b1003 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/Features.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/Features.java
@@ -223,6 +223,11 @@ public class Features extends Config {
editOverlay(activeConfigCategory, 200, 16, garden.moneyPerHourPos);
return;
}
+
+ if (runnableId.equals("nextJacobContest")) {
+ editOverlay(activeConfigCategory, 200, 16, garden.nextJacobContestPos);
+ return;
+ }
}
@Expose
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 423705358..34c24dbb2 100644
--- a/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java
+++ b/src/main/java/at/hannibal2/skyhanni/config/features/Garden.java
@@ -401,6 +401,23 @@ public class Garden {
public Position moneyPerHourPos = new Position(16, -232, false, true);
@Expose
+ @ConfigOption(name = "Next Jacob Contest", desc = "")
+ @ConfigEditorAccordion(id = 12)
+ public boolean nextJacobContest = false;
+
+ @Expose
+ @ConfigOption(name = "Rng Drop Counter", desc = "Count RNG drops for Melon Dicer and Pumpkin Dicer.")
+ @ConfigEditorBoolean
+ @ConfigAccordionId(id = 12)
+ public boolean nextJacobContestDisplay = true;
+
+ @Expose
+ @ConfigOption(name = "Dicer Counter Position", desc = "")
+ @ConfigEditorButton(runnableId = "nextJacobContest", buttonText = "Edit")
+ @ConfigAccordionId(id = 12)
+ public Position nextJacobContestPos = new Position(16, -232, false, true);
+
+ @Expose
@ConfigOption(name = "Plot Price", desc = "Show the price of the plot in coins when inside the Configure Plots inventory.")
@ConfigEditorBoolean
public boolean plotPrice = true;
diff --git a/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt
new file mode 100644
index 000000000..193efecc6
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/garden/GardenNextJacobContest.kt
@@ -0,0 +1,187 @@
+package at.hannibal2.skyhanni.features.garden
+
+import at.hannibal2.skyhanni.SkyHanniMod
+import at.hannibal2.skyhanni.events.GuiRenderEvent
+import at.hannibal2.skyhanni.events.InventoryCloseEvent
+import at.hannibal2.skyhanni.events.InventoryOpenEvent
+import at.hannibal2.skyhanni.utils.ItemUtils.getLore
+import at.hannibal2.skyhanni.utils.ItemUtils.name
+import at.hannibal2.skyhanni.utils.LorenzUtils
+import at.hannibal2.skyhanni.utils.RenderUtils.renderSingleLineWithItems
+import at.hannibal2.skyhanni.utils.TimeUtils
+import io.github.moulberry.notenoughupdates.util.SkyBlockTime
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import net.minecraftforge.fml.common.gameevent.TickEvent
+import java.time.Instant
+import java.util.regex.Pattern
+
+class GardenNextJacobContest {
+ private val config get() = SkyHanniMod.feature.garden
+ private val display = mutableListOf<Any>()
+ private var tick = 0
+ private var contests = mutableMapOf<Long, FarmingContest>()
+ private var inCalendar = false
+
+ private val maxContestsPerYear = 124
+ private val contestDuration = 1_000 * 60 * 20
+
+ @SubscribeEvent
+ fun onTick(event: TickEvent.ClientTickEvent) {
+ if (!isEnabled()) return
+ if (tick++ % (40) != 0) return
+
+ if (inCalendar) return
+ update()
+ }
+
+ @SubscribeEvent
+ fun onInventoryClose(event: InventoryCloseEvent) {
+ if (inCalendar) {
+ inCalendar = false
+ update()
+ }
+ }
+
+ @SubscribeEvent
+ fun onInventoryOpen(event: InventoryOpenEvent) {
+ if (!config.nextJacobContestDisplay) return
+
+ val backItem = event.inventoryItems[48] ?: return
+ val backName = backItem.name
+ if (backName != "§aGo Back") return
+ val lore = backItem.getLore()
+ if (lore.size != 1) return
+ if (lore[0] != "§7To Calendar and Events") return
+
+ inCalendar = true
+ readCalendar(event)
+ }
+
+ private fun readCalendar(event: InventoryOpenEvent) {
+ val inventoryName = event.inventoryName
+
+ val patternMonth = Pattern.compile("(.*), Year (.*)")
+ val matcher = patternMonth.matcher(inventoryName)
+ if (!matcher.matches()) return
+ val rawMonth = matcher.group(1)
+ val year = matcher.group(2).toInt()
+
+ if (contests.isNotEmpty()) {
+ val contest = contests.values.first()
+ val endTime = contest.endTime
+ val lastYear = SkyBlockTime.fromInstant(Instant.ofEpochMilli(endTime)).year
+ if (year != lastYear) {
+ contests.clear()
+ LorenzUtils.chat("§e[SkyHanni] New year detected, open all calendar months again!")
+ }
+ }
+
+
+ val month = LorenzUtils.getSBMonthByName(rawMonth)
+
+ val patternDay = Pattern.compile("§aDay (.*)")
+ val patternCrop = Pattern.compile("§e○ §7(.*)")
+ for (item in event.inventoryItems.values) {
+ val lore = item.getLore()
+ if (!lore.any { it.contains("§6§eJacob's Farming Contest") }) continue
+
+ val name = item.name ?: continue
+ val matcherDay = patternDay.matcher(name)
+ if (!matcherDay.matches()) continue
+
+ val day = matcherDay.group(1).toInt()
+
+ val sbTime = SkyBlockTime(year, month, day)
+ val startTime = sbTime.toMillis()
+ val crops = mutableListOf<String>()
+ for (line in lore) {
+ val matcherCrop = patternCrop.matcher(line)
+ if (!matcherCrop.matches()) continue
+
+ val crop = matcherCrop.group(1)
+ crops.add(crop)
+ }
+ val contest = FarmingContest(startTime + contestDuration, crops)
+ contests[startTime] = contest
+ }
+
+ update()
+ }
+
+ class FarmingContest(val endTime: Long, val crops: List<String>)
+
+ private fun update() {
+ val newDisplay = drawDisplay()
+ display.clear()
+ display.addAll(newDisplay)
+ }
+
+ private fun drawDisplay(): List<Any> {
+ val list = mutableListOf<Any>()
+
+ if (inCalendar) {
+ val size = contests.size
+ val percentage = size.toDouble() / maxContestsPerYear
+ val formatted = LorenzUtils.formatPercentage(percentage)
+ list.add("§eDetected $formatted of farming contests this year")
+
+ return list
+ }
+
+ if (contests.isEmpty()) {
+ list.add("§cOpen calendar to read jacob contest times!")
+ return list
+ }
+
+ val nextContest =
+ contests.filter { it.value.endTime > System.currentTimeMillis() }.toSortedMap().firstNotNullOfOrNull { it.value }
+ if (nextContest == null) {
+ if (contests.size == maxContestsPerYear) {
+ list.add("§cNew SkyBlock Year! Open calendar again!")
+ } else {
+ list.add("§cOpen calendar to read jacob contest times!")
+ }
+ return list
+ }
+
+ return drawNextContest(nextContest, list)
+ }
+
+ private fun drawNextContest(
+ nextContest: FarmingContest,
+ list: MutableList<Any>,
+ ): MutableList<Any> {
+ for (crop in nextContest.crops) {
+ GardenAPI.addGardenCropToList(crop, list)
+ list.add(" ")
+ }
+ var duration = nextContest.endTime - System.currentTimeMillis()
+ if (duration < contestDuration) {
+ list.add("§aActive ")
+ } else {
+ list.add("§eNext ")
+ duration -= contestDuration
+ }
+ val format = TimeUtils.formatDuration(duration)
+ list.add("§b$format ")
+
+ return list
+ }
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.GameOverlayRenderEvent) {
+ if (!isEnabled()) return
+
+ config.nextJacobContestPos.renderSingleLineWithItems(display)
+ }
+
+ @SubscribeEvent
+ fun onRenderOverlay(event: GuiRenderEvent.ChestBackgroundRenderEvent) {
+ if (!config.nextJacobContestDisplay) return
+ if (!inCalendar) return
+
+ config.nextJacobContestPos.renderSingleLineWithItems(display)
+ }
+
+ private fun isEnabled() = GardenAPI.inGarden() && config.nextJacobContestDisplay
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
index 62a8c2c61..e5c06a6a8 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
@@ -492,6 +492,15 @@ object RenderUtils {
}
}
+ /**
+ * Accepts a single line to print.
+ * This line is a list of things to print. Can print String or ItemStack objects.
+ */
+ fun Position.renderSingleLineWithItems(list: List<Any?>) {
+ if (list.isEmpty()) return
+ renderLine(list, 0)
+ }
+
private fun Position.renderLine(line: List<Any?>, offsetY: Int) {
val renderer = Minecraft.getMinecraft().fontRendererObj
val resolution = ScaledResolution(Minecraft.getMinecraft())