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 | 111 +++++++++++++++++++++ .../miscfeatures/WardrobeMouseButtons.kt | 108 ++++++++++++++++++++ 2 files changed, 219 insertions(+) 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/kotlin') 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