feat: Add lore timers

This commit is contained in:
Linnea Gräf
2024-12-24 01:58:46 +01:00
parent 24110c24af
commit fbab19b40f
3 changed files with 199 additions and 56 deletions

View File

@@ -0,0 +1,130 @@
package moe.nea.firmament.features.inventory
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.time.format.DateTimeFormatterBuilder
import java.time.format.FormatStyle
import java.time.format.TextStyle
import java.time.temporal.ChronoField
import net.minecraft.text.Text
import net.minecraft.util.StringIdentifiable
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.ItemTooltipEvent
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.SBData
import moe.nea.firmament.util.aqua
import moe.nea.firmament.util.grey
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.tr
import moe.nea.firmament.util.unformattedString
object TimerInLore {
object TConfig : ManagedConfig("lore-timers", Category.INVENTORY) {
val showTimers by toggle("show") { true }
val timerFormat by choice("format") { TimerFormat.SOCIALIST }
}
enum class TimerFormat(val formatter: DateTimeFormatter) : StringIdentifiable {
RFC(DateTimeFormatter.RFC_1123_DATE_TIME),
LOCAL(DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)),
SOCIALIST(
{
appendText(ChronoField.DAY_OF_WEEK, TextStyle.SHORT)
appendLiteral(" ")
appendValue(ChronoField.DAY_OF_MONTH, 2)
appendLiteral(".")
appendValue(ChronoField.MONTH_OF_YEAR, 2)
appendLiteral(".")
appendValue(ChronoField.YEAR, 4)
appendLiteral(" ")
appendValue(ChronoField.HOUR_OF_DAY, 2)
appendLiteral(":")
appendValue(ChronoField.MINUTE_OF_HOUR, 2)
appendLiteral(":")
appendValue(ChronoField.SECOND_OF_MINUTE, 2)
}),
AMERICAN("EEEE, MMM d h:mm a yyyy"),
;
constructor(block: DateTimeFormatterBuilder.() -> Unit)
: this(DateTimeFormatterBuilder().also(block).toFormatter())
constructor(format: String) : this(DateTimeFormatter.ofPattern(format))
override fun asString(): String {
return name
}
}
enum class CountdownTypes(
val match: String,
val label: String, // TODO: convert to a 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"),
ENDS_PET_LEVELING(
"Ends:",
"Finishes at"
),
CALENDARDETAILS(" (§e", "Starts at"),
COMMUNITYPROJECTS("Contribute again", "Come back at"),
CHOCOLATEFACTORY("Next Charge", "Available at"),
STONKSAUCTION("Auction ends in", "Ends at"),
LIZSTONKREDEMPTION("Resets in:", "Resets at");
}
val regex =
"(?i)(?:(?<years>[0-9]+) ?(y|years?) )?(?:(?<days>[0-9]+) ?(d|days?))? ?(?:(?<hours>[0-9]+) ?(h|hours?))? ?(?:(?<minutes>[0-9]+) ?(m|minutes?))? ?(?:(?<seconds>[0-9]+) ?(s|seconds?))?\\b".toRegex()
@Subscribe
fun modifyLore(event: ItemTooltipEvent) {
if (!TConfig.showTimers) return
var lastTimer: ZonedDateTime? = null
for (i in event.lines.indices) {
val line = event.lines[i].unformattedString
val countdownType = CountdownTypes.entries.find { it.match in line } ?: continue
if (countdownType == CountdownTypes.CALENDARDETAILS
&& !event.stack.displayNameAccordingToNbt.unformattedString.startsWith("Day ")
) continue
val countdownMatch = regex.findAll(line).filter { it.value.isNotBlank() }.lastOrNull() ?: continue
val (years, days, hours, minutes, seconds) =
listOf("years", "days", "hours", "minutes", "seconds")
.map {
countdownMatch.groups[it]?.value?.toLong() ?: 0L
}
if (years + days + hours + minutes + seconds == 0L) continue
var baseLine = ZonedDateTime.now(SBData.hypixelTimeZone)
if (countdownType.isRelative) {
if (lastTimer == null) {
event.lines.add(i + 1,
tr("firmament.loretimer.missingrelative",
"Found a relative countdown with no baseline (Firmament)").grey())
continue
}
baseLine = lastTimer
}
val timer =
baseLine.plusYears(years).plusDays(days).plusHours(hours).plusMinutes(minutes).plusSeconds(seconds)
lastTimer = timer
val localTimer = timer.withZoneSameInstant(ZoneId.systemDefault())
// TODO: install approximate time stabilization algorithm
event.lines.add(i + 1,
Text.literal("${countdownType.label}: ")
.grey()
.append(Text.literal(TConfig.timerFormat.formatter.format(localTimer)).aqua())
)
}
}
}