From f43e45e79d91e15e787545efb8421814318ba2b6 Mon Sep 17 00:00:00 2001
From: "Erymanthus[#5074] | (u/)RayDeeUx"
<51521765+RayDeeUx@users.noreply.github.com>
Date: Fri, 10 Nov 2023 22:19:38 -0500
Subject: Fixes: Countdown Calculator Improvements (#923)
---
.../miscfeatures/CountdownCalculator.kt | 110 --------------------
.../miscfeatures/WardrobeMouseButtons.kt | 108 --------------------
.../notenoughupdates/miscgui/CalendarOverlay.java | 57 +++++++----
.../miscfeatures/CountdownCalculator.kt | 111 +++++++++++++++++++++
.../miscfeatures/WardrobeMouseButtons.kt | 108 ++++++++++++++++++++
5 files changed, 257 insertions(+), 237 deletions(-)
delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt
delete mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt
create mode 100644 src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt
create mode 100644 src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt
(limited to 'src/main')
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt
deleted file mode 100644
index 11c6b721..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt
+++ /dev/null
@@ -1,110 +0,0 @@
-/*
- * Copyright (C) 2022-2023 NotEnoughUpdates contributors
- *
- * This file is part of NotEnoughUpdates.
- *
- * NotEnoughUpdates is free software: you can redistribute it
- * and/or modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * NotEnoughUpdates is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with NotEnoughUpdates. If not, see .
- */
-package io.github.moulberry.notenoughupdates.miscfeatures
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates
-import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
-import net.minecraft.client.Minecraft
-import net.minecraftforge.event.entity.player.ItemTooltipEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-import java.time.ZonedDateTime
-import java.time.format.DateTimeFormatter
-
-/*
- * CountdownCalculator.kt
- * A Kotlin class by:
- * — Erymanthus / RayDeeUx (code base, math, timestamp wrangling, adaptation into overall NEU codebase)
- * — nea89 (enum, regex wrangling, ItemTooltipEvent integration, cleanup)
- *
- * Intended to detect countdowns within item tooltips, converting the time remaining into
- * units of seconds, and then adding that result to the user's current system time
- * in Unix epoch form converted into a human readable timestamp, timezones included.
- *
- * Formerly a feature from SkyBlockCatia, then later attempted to be ported into Skytils.
- * Now has a comfy home in the NotEnoughUpdates codebase.
- */
-
-@NEUAutoSubscribe
-class CountdownCalculator {
-
- val regex =
- "(?:(?\\d+)d)? ?(?:(?\\d+)h)? ?(?:(?\\d+)m)? ?(?:(?\\d+)s)?\\b".toRegex()
- val formatter12h = DateTimeFormatter.ofPattern("EEEE, MMM d h:mm a")!!
- val formatter24h = DateTimeFormatter.ofPattern("EEEE, MMM d HH:mm")!!
-
- @Suppress("unused")
- private enum class CountdownTypes(
- val match: String,
- val label: String,
- val isRelative: Boolean = false,
- ) {
- STARTING("Starting in:", "Starts at"),
- STARTS("Starts in:", "Starts at"),
- INTEREST("Interest in:", "Interest at"),
- UNTILINTEREST("Until interest:", "Interest at"),
- ENDS("Ends in:", "Ends at"),
- REMAINING("Remaining:", "Ends at"),
- DURATION("Duration:", "Finishes at"),
- TIMELEFT("Time left:", "Ends at"),
- EVENTTIMELEFT("Event lasts for", "Ends at", isRelative = true),
- SHENSUCKS("Auction ends in:", "Auction ends at"),
- CALENDARDETAILS("(§e", "Starts at"); // Calendar details
- }
-
- @SubscribeEvent
- fun onTooltip(event: ItemTooltipEvent) {
- val useFormatter = when (NotEnoughUpdates.INSTANCE.config.misc.showWhenCountdownEnds) {
- 1 -> formatter12h
- 2 -> formatter24h
- else -> return
- }
- if (event.itemStack != null && Minecraft.getMinecraft().thePlayer?.openContainer != null) {
- var i = -1
- var lastTimer: ZonedDateTime? = null
- while (++i < event.toolTip.size) {
- val tooltipLine = event.toolTip[i]
- val countdownKind = CountdownTypes.values().find { it.match in tooltipLine } ?: continue
- val match = regex.findAll(tooltipLine).maxByOrNull { it.value.length } ?: continue
-
- val days = match.groups["days"]?.value?.toInt() ?: 0
- val hours = match.groups["hours"]?.value?.toInt() ?: 0
- val minutes = match.groups["minutes"]?.value?.toInt() ?: 0
- val seconds = match.groups["seconds"]?.value?.toInt() ?: 0
- val totalSeconds = days * 86400L + hours * 3600L + minutes * 60L + seconds
- if (totalSeconds == 0L) continue
- val countdownTarget = if (countdownKind.isRelative) {
- if (lastTimer == null) {
- event.toolTip.add(
- ++i,
- "§r§cThe above countdown is relative, but I can't find another countdown. [NEU]"
- )
- continue
- } else lastTimer.plusSeconds(totalSeconds)
- } else ZonedDateTime.now().plusSeconds(totalSeconds)
- val countdownTargetFormatted = useFormatter.format(countdownTarget)
- event.toolTip.add(
- ++i,
- "§r§b${countdownKind.label}: $countdownTargetFormatted"
- )
- lastTimer = countdownTarget
- }
- }
- }
-
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt
deleted file mode 100644
index ea01eb2e..00000000
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (C) 2022-2023 NotEnoughUpdates contributors
- *
- * This file is part of NotEnoughUpdates.
- *
- * NotEnoughUpdates is free software: you can redistribute it
- * and/or modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation, either
- * version 3 of the License, or (at your option) any later version.
- *
- * NotEnoughUpdates is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with NotEnoughUpdates. If not, see .
- */
-package io.github.moulberry.notenoughupdates.miscfeatures
-
-import io.github.moulberry.notenoughupdates.NotEnoughUpdates
-import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
-import io.github.moulberry.notenoughupdates.core.config.KeybindHelper
-import io.github.moulberry.notenoughupdates.util.Utils
-import net.minecraft.client.gui.inventory.GuiChest
-import net.minecraft.inventory.ContainerChest
-import net.minecraftforge.client.event.GuiScreenEvent
-import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
-
-@NEUAutoSubscribe
-class WardrobeMouseButtons {
-
- private val keybinds: List get() = listOf(
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot1,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot2,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot3,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot4,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot5,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot6,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot7,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot8,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot9,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePageUnequip,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePagePrevious,
- NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePageNext,
- )
- private var lastClick = -1L
-
- @SubscribeEvent
- fun onGuiKeyboardInput(event: GuiScreenEvent.KeyboardInputEvent.Pre) {
- checkKeybinds(event)
- }
-
- @SubscribeEvent
- fun onGuiMouseInput(event: GuiScreenEvent.MouseInputEvent.Pre) {
- checkKeybinds(event)
- }
-
- @Suppress("InvalidSubscribeEvent")
- private fun checkKeybinds(event: GuiScreenEvent) {
- if (!NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.enableWardrobeKeybinds || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return
- val gui = event.gui as? GuiChest ?: return
- if (!Utils.getOpenChestName().contains("Wardrobe")) return
- val chestName = Utils.getOpenChestName()
- val chestNameRegex = "Wardrobe (\\((?[0-9]+)\\/(?[0-9]+)\\))".toRegex()
- val chestNameMatch = chestNameRegex.matchEntire(chestName)
- if (chestNameMatch == null) return
- val totalPages = chestNameMatch.groups["total"]!!.value.toInt()
- val currentPage = chestNameMatch.groups["current"]!!.value.toInt()
- val guiChes = event.gui as GuiChest
- val container = guiChes.inventorySlots as ContainerChest
- var slotNum = 0
-
- if ((currentPage != totalPages) && KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePageNext)) {
- slotNum = 53
- } else if ((currentPage != 1) && KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePagePrevious)) {
- slotNum = 45
- } else if (KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePageUnequip)) {
- var notEquipped = 0
- for (j in 36..44) {
- val stackItem = container.getSlot(j).getStack() ?: return
- if (stackItem.getDisplayName().contains("Equipped")) {
- slotNum = j
- }
- else {
- notEquipped++
- }
- }
- if (notEquipped == 9) return
- } else {
- for (i in keybinds.indices) {
- if (KeybindHelper.isKeyDown(keybinds[i])) {
- if (System.currentTimeMillis() - lastClick > 300) {
- slotNum = (36 + i)
- }
- }
- }
- }
-
- val thatItemStack = container.getSlot(slotNum).getStack() ?: return
- if (thatItemStack.getDisplayName().isEmpty()) return
- if (slotNum < 36 || ((slotNum > 45) && (slotNum != 53))) return
- Utils.sendLeftMouseClick(gui.inventorySlots.windowId, slotNum)
- lastClick = System.currentTimeMillis()
- event.isCanceled = true
- }
-
-}
diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
index 4e4b147e..1a50dfe4 100644
--- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
+++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java
@@ -311,8 +311,8 @@ public class CalendarOverlay {
STAR_CULT_STACK,
Arrays.asList(
"§3The Cult of the Fallen Star meets then.",
- "§3Attending may give a reward",
- "§3You can find them near the Star in the Dwarven Mines"
+ "§3Attending may give a reward.",
+ "§3You can find them near the Star in the Dwarven Mines."
),
STAR_CULT_DURATION,
true
@@ -352,7 +352,6 @@ public class CalendarOverlay {
)
);
}
-
}
}
@@ -453,42 +452,42 @@ public class CalendarOverlay {
addEvent(
new SkyBlockTime(thisBaseYear + scorpiusOffset, 3, 27, 0, 0, 0),
new SBEvent("special_mayor:scorpius",
- "§dScorpius",
+ "§dScorpius' Candidacy",
true,
Utils.createSkull(
"Scorpius",
"ba2cd37d-a0e4-4dc5-b15c-d79ee1051aae",
"ewogICJ0aW1lc3RhbXAiIDogMTU5Nzc4MTc1NzIxOSwKICAicHJvZmlsZUlkIiA6ICI0MWQzYWJjMmQ3NDk0MDBjOTA5MGQ1NDM0ZDAzODMxYiIsCiAgInByb2ZpbGVOYW1lIiA6ICJNZWdha2xvb24iLAogICJzaWduYXR1cmVSZXF1aXJlZCIgOiB0cnVlLAogICJ0ZXh0dXJlcyIgOiB7CiAgICAiU0tJTiIgOiB7CiAgICAgICJ1cmwiIDogImh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGYyNmZhMGM0NzUzNmU3OGUzMzcyNTdkODk4YWY4YjFlYmM4N2MwODk0NTAzMzc1MjM0MDM1ZmYyYzdlZjhmMCIKICAgIH0KICB9Cn0"
),
- Arrays.asList("§eScorpius is a special Mayor candidate"), -1, true
+ Arrays.asList("§eScorpius becomes a special Mayor candidate"), -1, true
)
);
addEvent(
new SkyBlockTime(thisBaseYear + derpyOffset, 3, 27, 0, 0, 0),
new SBEvent(
"special_mayor:derpy",
- "§dDerpy",
+ "§dDerpy's Candidacy",
true,
Utils.createSkull(
"Derpy",
"ab36a707-96d3-3db1-ab36-a70796d3adb1",
"e3RleHR1cmVzOntTS0lOOnt1cmw6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjQ1MGQxMjY5Mjg4NmM0N2IwNzhhMzhmNGQ0OTJhY2ZlNjEyMTZlMmQwMjM3YWI4MjQzMzQwOWIzMDQ2YjQ2NCJ9fX0"
),
- Arrays.asList("§eDerpy is a special Mayor candidate"), -1, true
+ Arrays.asList("§eDerpy becomes a special Mayor candidate"), -1, true
)
);
addEvent(
new SkyBlockTime(thisBaseYear + jerryOffset, 3, 27, 0, 0, 0),
new SBEvent(
"special_mayor:jerry",
- "§dJerry",
+ "§dJerry's Candidacy",
true,
Utils.createSkull(
"Jerry",
"0a9e8efb-9191-4c81-80f5-e27ca5433156",
"eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODIyZDhlNzUxYzhmMmZkNGM4OTQyYzQ0YmRiMmY1Y2E0ZDhhZThlNTc1ZWQzZWIzNGMxOGE4NmU5M2IifX19"
),
- Arrays.asList("§eJerry is a special Mayor candidate"), -1, true
+ Arrays.asList("§eJerry becomes a special Mayor candidate"), -1, true
)
);
}
@@ -734,15 +733,21 @@ public class CalendarOverlay {
sbEvent.display,
EnumChatFormatting.GRAY + "Starts in: " + EnumChatFormatting.YELLOW + prettyTime(timeUntilMillis, false)
);
- addCountdownCalculatorToTooltip(timeUntilMillis, tooltipToDisplay);
+ if (!(prettyTime(timeUntilMillis, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(timeUntilMillis, tooltipToDisplay);
+ }
if (sbEvent.lastsFor >= 0) {
tooltipToDisplay.add(EnumChatFormatting.GRAY + "Lasts for: " + EnumChatFormatting.YELLOW +
prettyTime(sbEvent.lastsFor, true));
- addCountdownCalculatorToTooltip(sbEvent.lastsFor + timeUntilMillis, tooltipToDisplay);
+ if (!(prettyTime(timeUntilMillis, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(sbEvent.lastsFor + timeUntilMillis, tooltipToDisplay);
+ }
if (timeUntilMillis < 0) {
tooltipToDisplay.add(EnumChatFormatting.GRAY + "Time left: " + EnumChatFormatting.YELLOW +
prettyTime(sbEvent.lastsFor + timeUntilMillis, true));
- addCountdownCalculatorToTooltip(timeUntilMillis, tooltipToDisplay);
+ if ((prettyTime(timeUntilMillis, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(sbEvent.lastsFor + timeUntilMillis, tooltipToDisplay);
+ }
}
}
if (sbEvent.desc != null) {
@@ -788,7 +793,9 @@ public class CalendarOverlay {
if (mouseX >= x && mouseX <= x + 16) {
if (mouseY >= y && mouseY <= y + 16) {
- tooltipToDisplay = new ArrayList<>(sbEvent.desc);
+ tooltipToDisplay = new ArrayList<>();
+ tooltipToDisplay.add(sbEvent.display);
+ tooltipToDisplay.addAll(sbEvent.desc);
tooltipToDisplay.add(Utils.prettyTime(Duration.between(
Instant.now(),
Instant.ofEpochMilli(pair.getFirst())
@@ -841,15 +848,21 @@ public class CalendarOverlay {
nextEvent.display,
EnumChatFormatting.GRAY + "Starts in: " + EnumChatFormatting.YELLOW + prettyTime(timeUntilNext, false)
);
- addCountdownCalculatorToTooltip(timeUntilNext, tooltipToDisplay);
+ if (!(prettyTime(timeUntilNext, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(timeUntilNext, tooltipToDisplay);
+ }
if (nextEvent.lastsFor >= 0) {
tooltipToDisplay.add(EnumChatFormatting.GRAY + "Lasts for: " + EnumChatFormatting.YELLOW +
prettyTime(nextEvent.lastsFor, true));
- addCountdownCalculatorToTooltip(nextEvent.lastsFor + timeUntilNext, tooltipToDisplay);
+ if (!(prettyTime(timeUntilNext, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(nextEvent.lastsFor + timeUntilNext, tooltipToDisplay);
+ }
if (timeUntilNext < 0) {
tooltipToDisplay.add(EnumChatFormatting.GRAY + "Time left: " + EnumChatFormatting.YELLOW +
prettyTime(nextEvent.lastsFor + timeUntilNext, true));
- addCountdownCalculatorToTooltip(nextEvent.lastsFor + timeUntilNext, tooltipToDisplay);
+ if ((prettyTime(timeUntilNext, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(nextEvent.lastsFor + timeUntilNext, tooltipToDisplay);
+ }
}
}
@@ -1485,15 +1498,21 @@ public class CalendarOverlay {
tooltipToDisplay.add(sbEvent.display);
tooltipToDisplay.add(
EnumChatFormatting.GRAY + "Starts in: " + EnumChatFormatting.YELLOW + prettyTime(timeUntil, false));
- addCountdownCalculatorToTooltip(timeUntil, tooltipToDisplay);
+ if (!(prettyTime(timeUntil, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(timeUntil, tooltipToDisplay);
+ }
if (sbEvent.lastsFor >= 0) {
tooltipToDisplay.add(EnumChatFormatting.GRAY + "Lasts for: " + EnumChatFormatting.YELLOW +
prettyTime(sbEvent.lastsFor, true));
- addCountdownCalculatorToTooltip(sbEvent.lastsFor + timeUntil, tooltipToDisplay);
+ if (!(prettyTime(timeUntilNext, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(sbEvent.lastsFor + timeUntil, tooltipToDisplay);
+ }
if (timeUntil < 0) {
tooltipToDisplay.add(EnumChatFormatting.GRAY + "Time left: " + EnumChatFormatting.YELLOW +
prettyTime(sbEvent.lastsFor + timeUntil, true));
- addCountdownCalculatorToTooltip(sbEvent.lastsFor + timeUntil, tooltipToDisplay);
+ if ((prettyTime(timeUntil, false).equals("Now!"))) {
+ addCountdownCalculatorToTooltip(sbEvent.lastsFor + timeUntil, tooltipToDisplay);
+ }
}
}
if (sbEvent.id.split(":")[0].equals("jacob_farming") && sbEvent.desc != null) {
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt
new file mode 100644
index 00000000..068e735b
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2022-2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see .
+ */
+package io.github.moulberry.notenoughupdates.miscfeatures
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates
+import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
+import net.minecraft.client.Minecraft
+import net.minecraftforge.event.entity.player.ItemTooltipEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+import java.time.ZonedDateTime
+import java.time.format.DateTimeFormatter
+
+/*
+ CountdownCalculator.kt
+ A Kotlin class by:
+ — Erymanthus / RayDeeUx (code base, math, timestamp wrangling, adaptation into overall NEU codebase)
+ — nea89 (enum, regex wrangling, ItemTooltipEvent integration, cleanup)
+
+ Intended to detect countdowns within item tooltips, converting the time remaining into
+ units of seconds, and then adding that result to the user's current system time
+ in Unix epoch form converted into a human-readable timestamp, timezones included.
+
+ Formerly a feature from SkyBlockCatia, then later attempted to be ported into Skytils.
+ Now has a comfy home in the NotEnoughUpdates codebase.
+ */
+
+@NEUAutoSubscribe
+class CountdownCalculator {
+
+ private val regex =
+ "(?:(?\\d+)y )?(?:(?\\d+)d)? ?(?:(?\\d+)h)? ?(?:(?\\d+)m)? ?(?:(?\\d+)s)?\\b".toRegex()
+
+ @Suppress("unused")
+ private enum class CountdownTypes(
+ val match: String,
+ val label: String,
+ val isRelative: Boolean = false,
+ ) {
+ STARTING("Starting in:", "Starts at"),
+ STARTS("Starts in:", "Starts at"),
+ INTEREST("Interest in:", "Interest at"),
+ UNTILINTEREST("Until interest:", "Interest at"),
+ ENDS("Ends in:", "Ends at"),
+ REMAINING("Remaining:", "Ends at"),
+ DURATION("Duration:", "Finishes at"),
+ TIMELEFT("Time left:", "Ends at"),
+ EVENTTIMELEFT("Event lasts for", "Ends at", isRelative = true),
+ SHENSUCKS("Auction ends in:", "Auction ends at"),
+ CALENDARDETAILS(" (§e", "Starts at"); // Calendar details
+ }
+
+ @SubscribeEvent
+ fun onTooltip(event: ItemTooltipEvent) {
+ var formatterAsString = when (NotEnoughUpdates.INSTANCE.config.misc.showWhenCountdownEnds) {
+ 1 -> "EEEE, MMM d h:mm a"
+ 2 -> "EEEE, MMM d HH:mm"
+ else -> return
+ }
+ if (event.itemStack != null && Minecraft.getMinecraft().thePlayer?.openContainer != null) {
+ var i = -1
+ var lastTimer: ZonedDateTime? = null
+ while (++i < event.toolTip.size) {
+ val tooltipLine = event.toolTip[i]
+ val countdownKind = CountdownTypes.values().find { it.match in tooltipLine } ?: continue
+ val match = regex.findAll(tooltipLine).maxByOrNull { it.value.length } ?: continue
+
+ val years = match.groups["years"]?.value?.toInt() ?: 0
+ val days = match.groups["days"]?.value?.toInt() ?: 0
+ val hours = match.groups["hours"]?.value?.toInt() ?: 0
+ val minutes = match.groups["minutes"]?.value?.toInt() ?: 0
+ val seconds = match.groups["seconds"]?.value?.toInt() ?: 0
+ val totalSeconds = (years * 31_536_000L) + (days * 86_400L) + (hours * 3_600L) + (minutes * 60L) + seconds
+ if (totalSeconds == 0L) continue
+ if (years != 0) formatterAsString = "${formatterAsString} yyyy"
+ val useFormatter = DateTimeFormatter.ofPattern(formatterAsString)!!
+ val countdownTarget = if (countdownKind.isRelative) {
+ if (lastTimer == null) {
+ event.toolTip.add(
+ ++i,
+ "§r§cThe above countdown is relative, but I can't find another countdown. [NEU]"
+ )
+ continue
+ } else lastTimer.plusSeconds(totalSeconds)
+ } else ZonedDateTime.now().plusSeconds(totalSeconds)
+ val countdownTargetFormatted = useFormatter.format(countdownTarget)
+ event.toolTip.add(
+ ++i,
+ "§r§b${countdownKind.label}: $countdownTargetFormatted"
+ )
+ lastTimer = countdownTarget
+ }
+ }
+ }
+
+}
diff --git a/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt
new file mode 100644
index 00000000..ea01eb2e
--- /dev/null
+++ b/src/main/kotlin/io/github/moulberry/notenoughupdates/miscfeatures/WardrobeMouseButtons.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2022-2023 NotEnoughUpdates contributors
+ *
+ * This file is part of NotEnoughUpdates.
+ *
+ * NotEnoughUpdates is free software: you can redistribute it
+ * and/or modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation, either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * NotEnoughUpdates is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with NotEnoughUpdates. If not, see .
+ */
+package io.github.moulberry.notenoughupdates.miscfeatures
+
+import io.github.moulberry.notenoughupdates.NotEnoughUpdates
+import io.github.moulberry.notenoughupdates.autosubscribe.NEUAutoSubscribe
+import io.github.moulberry.notenoughupdates.core.config.KeybindHelper
+import io.github.moulberry.notenoughupdates.util.Utils
+import net.minecraft.client.gui.inventory.GuiChest
+import net.minecraft.inventory.ContainerChest
+import net.minecraftforge.client.event.GuiScreenEvent
+import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
+
+@NEUAutoSubscribe
+class WardrobeMouseButtons {
+
+ private val keybinds: List get() = listOf(
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot1,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot2,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot3,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot4,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot5,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot6,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot7,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot8,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobeSlot9,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePageUnequip,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePagePrevious,
+ NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePageNext,
+ )
+ private var lastClick = -1L
+
+ @SubscribeEvent
+ fun onGuiKeyboardInput(event: GuiScreenEvent.KeyboardInputEvent.Pre) {
+ checkKeybinds(event)
+ }
+
+ @SubscribeEvent
+ fun onGuiMouseInput(event: GuiScreenEvent.MouseInputEvent.Pre) {
+ checkKeybinds(event)
+ }
+
+ @Suppress("InvalidSubscribeEvent")
+ private fun checkKeybinds(event: GuiScreenEvent) {
+ if (!NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.enableWardrobeKeybinds || !NotEnoughUpdates.INSTANCE.hasSkyblockScoreboard()) return
+ val gui = event.gui as? GuiChest ?: return
+ if (!Utils.getOpenChestName().contains("Wardrobe")) return
+ val chestName = Utils.getOpenChestName()
+ val chestNameRegex = "Wardrobe (\\((?[0-9]+)\\/(?[0-9]+)\\))".toRegex()
+ val chestNameMatch = chestNameRegex.matchEntire(chestName)
+ if (chestNameMatch == null) return
+ val totalPages = chestNameMatch.groups["total"]!!.value.toInt()
+ val currentPage = chestNameMatch.groups["current"]!!.value.toInt()
+ val guiChes = event.gui as GuiChest
+ val container = guiChes.inventorySlots as ContainerChest
+ var slotNum = 0
+
+ if ((currentPage != totalPages) && KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePageNext)) {
+ slotNum = 53
+ } else if ((currentPage != 1) && KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePagePrevious)) {
+ slotNum = 45
+ } else if (KeybindHelper.isKeyDown(NotEnoughUpdates.INSTANCE.config.wardrobeKeybinds.wardrobePageUnequip)) {
+ var notEquipped = 0
+ for (j in 36..44) {
+ val stackItem = container.getSlot(j).getStack() ?: return
+ if (stackItem.getDisplayName().contains("Equipped")) {
+ slotNum = j
+ }
+ else {
+ notEquipped++
+ }
+ }
+ if (notEquipped == 9) return
+ } else {
+ for (i in keybinds.indices) {
+ if (KeybindHelper.isKeyDown(keybinds[i])) {
+ if (System.currentTimeMillis() - lastClick > 300) {
+ slotNum = (36 + i)
+ }
+ }
+ }
+ }
+
+ val thatItemStack = container.getSlot(slotNum).getStack() ?: return
+ if (thatItemStack.getDisplayName().isEmpty()) return
+ if (slotNum < 36 || ((slotNum > 45) && (slotNum != 53))) return
+ Utils.sendLeftMouseClick(gui.inventorySlots.windowId, slotNum)
+ lastClick = System.currentTimeMillis()
+ event.isCanceled = true
+ }
+
+}
--
cgit