From 5e3a573493a47f9a6208093925a8c4b5d1f324ce Mon Sep 17 00:00:00 2001 From: "Erymanthus[#5074] | (u/)RayDeeUx" <51521765+RayDeeUx@users.noreply.github.com> Date: Fri, 20 Oct 2023 10:46:58 -0400 Subject: Feature: CountdownCalculator (collab with @nea89o) (#874) * COUNTDOWNCALCULATOR IS COMING HOME * COUNTDOWNCALCULATOR IS COMING HOME LESGO * condense labels * fix compile * fix compile (ty nopo) + fix mismatch in .kt class * remove timezone * consistency with nopo's changes * prevent empty lines from being added to neucal * remove seconds, fix math for calendaroverlay.java * shen label mayhaps? * attempt to fix calculation errors * bloody fuckoing hell * ok this *SHOULD* fix everything * rm debug msgs * add ampm back to ampx format overlay * forogt what the emdyhmas format was * rm useless conditional --------- Co-authored-by: nopo --- .../miscfeatures/CountdownCalculator.kt | 110 +++++++++++++++++++++ .../notenoughupdates/miscgui/CalendarOverlay.java | 29 ++++++ .../options/separatesections/Misc.java | 10 ++ 3 files changed, 149 insertions(+) create mode 100644 src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt diff --git a/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt new file mode 100644 index 00000000..11c6b721 --- /dev/null +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscfeatures/CountdownCalculator.kt @@ -0,0 +1,110 @@ +/* + * 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/miscgui/CalendarOverlay.java b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java index c83b310c..4e4b147e 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/miscgui/CalendarOverlay.java @@ -63,6 +63,8 @@ import org.lwjgl.opengl.GL11; import java.io.File; import java.time.Duration; import java.time.Instant; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Arrays; @@ -140,6 +142,8 @@ public class CalendarOverlay { "NEU Calendar Item" ); // Star Cult Stack + private boolean canAddcountdownCalc = (NotEnoughUpdates.INSTANCE.config.misc.showWhenCountdownEnds == 1 || NotEnoughUpdates.INSTANCE.config.misc.showWhenCountdownEnds == 2); + static { NBTTagCompound tag = new NBTTagCompound(); tag.setString("event_id", "dark_auction"); @@ -730,12 +734,15 @@ public class CalendarOverlay { sbEvent.display, EnumChatFormatting.GRAY + "Starts in: " + EnumChatFormatting.YELLOW + prettyTime(timeUntilMillis, false) ); + 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 (timeUntilMillis < 0) { tooltipToDisplay.add(EnumChatFormatting.GRAY + "Time left: " + EnumChatFormatting.YELLOW + prettyTime(sbEvent.lastsFor + timeUntilMillis, true)); + addCountdownCalculatorToTooltip(timeUntilMillis, tooltipToDisplay); } } if (sbEvent.desc != null) { @@ -786,6 +793,10 @@ public class CalendarOverlay { Instant.now(), Instant.ofEpochMilli(pair.getFirst()) ))); + addCountdownCalculatorToTooltip(Duration.between( + Instant.now(), + Instant.ofEpochMilli(pair.getFirst()) + ).toMillis(), tooltipToDisplay); } } } @@ -830,12 +841,15 @@ public class CalendarOverlay { nextEvent.display, EnumChatFormatting.GRAY + "Starts in: " + EnumChatFormatting.YELLOW + prettyTime(timeUntilNext, false) ); + 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 (timeUntilNext < 0) { tooltipToDisplay.add(EnumChatFormatting.GRAY + "Time left: " + EnumChatFormatting.YELLOW + prettyTime(nextEvent.lastsFor + timeUntilNext, true)); + addCountdownCalculatorToTooltip(nextEvent.lastsFor + timeUntilNext, tooltipToDisplay); } } @@ -1471,12 +1485,15 @@ public class CalendarOverlay { tooltipToDisplay.add(sbEvent.display); tooltipToDisplay.add( EnumChatFormatting.GRAY + "Starts in: " + EnumChatFormatting.YELLOW + prettyTime(timeUntil, false)); + 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 (timeUntil < 0) { tooltipToDisplay.add(EnumChatFormatting.GRAY + "Time left: " + EnumChatFormatting.YELLOW + prettyTime(sbEvent.lastsFor + timeUntil, true)); + addCountdownCalculatorToTooltip(sbEvent.lastsFor + timeUntil, tooltipToDisplay); } } if (sbEvent.id.split(":")[0].equals("jacob_farming") && sbEvent.desc != null) { @@ -1491,9 +1508,11 @@ public class CalendarOverlay { tooltipToDisplay.add(nextMayorEvent.display); tooltipToDisplay.add(EnumChatFormatting.GRAY + "Starts in: " + EnumChatFormatting.YELLOW + prettyTime(timeUntilMayor, false)); + addCountdownCalculatorToTooltip(timeUntilMayor, tooltipToDisplay); if (nextMayorEvent.lastsFor >= 0) { tooltipToDisplay.add(EnumChatFormatting.GRAY + "Lasts for: " + EnumChatFormatting.YELLOW + prettyTime(nextMayorEvent.lastsFor, true)); + addCountdownCalculatorToTooltip(nextMayorEvent.lastsFor + timeUntilMayor, tooltipToDisplay); } } @@ -1636,4 +1655,14 @@ public class CalendarOverlay { return endsIn; } + + private List addCountdownCalculatorToTooltip(long millis, List tooltipToModify) { + if (NotEnoughUpdates.INSTANCE.config.misc.showWhenCountdownEnds == 1 || NotEnoughUpdates.INSTANCE.config.misc.showWhenCountdownEnds == 2) { + String formatString = "EEEE, MMM d h:mm a"; + if (NotEnoughUpdates.INSTANCE.config.misc.showWhenCountdownEnds == 2) { formatString = "EEEE, MMM d HH:mm"; } + tooltipToModify.add("§b" + DateTimeFormatter.ofPattern(formatString).format(ZonedDateTime.now().plusSeconds(((millis / 1000))))); + + } + return tooltipToModify; + } } diff --git a/src/main/java/io/github/moulberry/notenoughupdates/options/separatesections/Misc.java b/src/main/java/io/github/moulberry/notenoughupdates/options/separatesections/Misc.java index a9a0856e..52df50f7 100644 --- a/src/main/java/io/github/moulberry/notenoughupdates/options/separatesections/Misc.java +++ b/src/main/java/io/github/moulberry/notenoughupdates/options/separatesections/Misc.java @@ -345,4 +345,14 @@ public class Misc { ) @ConfigEditorKeybind(defaultKey = Keyboard.KEY_M) public int openAHKeybind = Keyboard.KEY_M; + + @Expose + @ConfigOption( + name = "Countdown Calculations", + desc = "Shows a(n estimated) timestamp for when a countdown in an item's tooltip will end, relative to your timezone. Also applies to §e/neucalendar§r." + ) + @ConfigEditorDropdown( + values = {"Off", "AM/PM [1PM]", "24hr [13:00]"} + ) + public int showWhenCountdownEnds = 1; } -- cgit