Add fuel durability bar

This commit is contained in:
Linnea Gräf
2024-04-26 10:11:23 +02:00
parent c264ca9e8f
commit 041da7c7d1
6 changed files with 179 additions and 15 deletions

View File

@@ -7,11 +7,10 @@
package moe.nea.firmament.features.mining
import java.util.regex.Pattern
import org.intellij.lang.annotations.Language
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
import net.minecraft.item.ItemStack
import net.minecraft.util.DyeColor
import net.minecraft.util.Hand
import net.minecraft.util.Identifier
import moe.nea.firmament.events.HudRenderEvent
@@ -20,11 +19,19 @@ import moe.nea.firmament.events.SlotClickEvent
import moe.nea.firmament.events.WorldReadyEvent
import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.DurabilityBarEvent
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.SHORT_NUMBER_FORMAT
import moe.nea.firmament.util.TIME_PATTERN
import moe.nea.firmament.util.TimeMark
import moe.nea.firmament.util.extraAttributes
import moe.nea.firmament.util.item.displayNameAccordingToNbt
import moe.nea.firmament.util.item.loreAccordingToNbt
import moe.nea.firmament.util.parseShortNumber
import moe.nea.firmament.util.parseTimePattern
import moe.nea.firmament.util.render.RenderCircleProgress
import moe.nea.firmament.util.render.lerp
import moe.nea.firmament.util.toShedaniel
import moe.nea.firmament.util.unformattedString
import moe.nea.firmament.util.useMatch
@@ -36,6 +43,7 @@ object PickaxeAbility : FirmamentFeature {
object TConfig : ManagedConfig(identifier) {
val cooldownEnabled by toggle("ability-cooldown") { true }
val cooldownScale by integer("ability-scale", 16, 64) { 16 }
val drillFuelBar by toggle("fuel-bar") { true }
}
var lobbyJoinTime = TimeMark.farPast()
@@ -73,13 +81,36 @@ object PickaxeAbility : FirmamentFeature {
abilityOverride = null
}
ProcessChatEvent.subscribe {
pattern.useMatch(it.unformattedString) {
abilityUsePattern.useMatch(it.unformattedString) {
lastUsage[group("name")] = TimeMark.now()
}
abilitySwitchPattern.useMatch(it.unformattedString) {
abilityOverride = group("ability")
}
}
DurabilityBarEvent.subscribe {
if (!TConfig.drillFuelBar) return@subscribe
val lore = it.item.loreAccordingToNbt
if (lore.lastOrNull()?.value?.unformattedString?.contains("DRILL") != true) return@subscribe
val maxFuel = lore.firstNotNullOfOrNull {
fuelPattern.useMatch(
it.value?.unformattedString ?: return@firstNotNullOfOrNull null
) {
parseShortNumber(group("maxFuel"))
}
} ?: return@subscribe
val extra = it.item.extraAttributes
if (!extra.contains("drill_fuel")) return@subscribe
val fuel = extra.getInt("drill_fuel")
val percentage = fuel / maxFuel.toFloat()
it.barOverride = DurabilityBarEvent.DurabilityBar(
lerp(
DyeColor.RED.toShedaniel(),
DyeColor.GREEN.toShedaniel(),
percentage
), percentage
)
}
SlotClickEvent.subscribe {
if (MC.screen?.title?.unformattedString == "Heart of the Mountain") {
val name = it.stack.displayNameAccordingToNbt?.unformattedString ?: return@subscribe
@@ -93,7 +124,8 @@ object PickaxeAbility : FirmamentFeature {
}
}
val pattern = Pattern.compile("You used your (?<name>.*) Pickaxe Ability!")
val abilityUsePattern = Pattern.compile("You used your (?<name>.*) Pickaxe Ability!")
val fuelPattern = Pattern.compile("Fuel: .*/(?<maxFuel>$SHORT_NUMBER_FORMAT)")
data class PickaxeAbilityData(
val name: String,
@@ -117,21 +149,12 @@ object PickaxeAbility : FirmamentFeature {
return PickaxeAbilityData(name, cooldown)
}
@Language("RegExp")
val TIME_PATTERN = "[0-9]+[ms]"
val cooldownPattern = Pattern.compile("Cooldown: (?<cooldown>$TIME_PATTERN)")
val abilityPattern = Pattern.compile("Ability: (?<name>.*) {2}RIGHT CLICK")
val abilitySwitchPattern =
Pattern.compile("You selected (?<ability>.*) as your Pickaxe Ability\\. This ability will apply to all of your pickaxes!")
fun parseTimePattern(text: String): Duration {
val length = text.dropLast(1).toInt()
return when (text.last()) {
'm' -> length.minutes
's' -> length.seconds
else -> error("Invalid pattern for time $text")
}
}
private fun renderHud(event: HudRenderEvent) {
if (!TConfig.cooldownEnabled) return

View File

@@ -0,0 +1,25 @@
/*
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package moe.nea.firmament.util
import me.shedaniel.math.Color
import net.minecraft.item.ItemStack
import moe.nea.firmament.events.FirmamentEvent
import moe.nea.firmament.events.FirmamentEventBus
data class DurabilityBarEvent(
val item: ItemStack,
) : FirmamentEvent() {
data class DurabilityBar(
val color: Color,
val percentage: Float,
)
var barOverride: DurabilityBar? = null
companion object : FirmamentEventBus<DurabilityBarEvent>()
}

View File

@@ -1,5 +1,6 @@
/*
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
* SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe>
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
@@ -8,6 +9,10 @@ package moe.nea.firmament.util
import java.util.regex.Matcher
import java.util.regex.Pattern
import org.intellij.lang.annotations.Language
import kotlin.time.Duration
import kotlin.time.Duration.Companion.minutes
import kotlin.time.Duration.Companion.seconds
inline fun <T> String.ifMatches(regex: Regex, block: (MatchResult) -> T): T? =
regex.matchEntire(this)?.let(block)
@@ -16,3 +21,40 @@ inline fun <T> Pattern.useMatch(string: String, block: Matcher.() -> T): T? =
matcher(string)
.takeIf(Matcher::matches)
?.let(block)
@Language("RegExp")
val TIME_PATTERN = "[0-9]+[ms]"
@Language("RegExp")
val SHORT_NUMBER_FORMAT = "[0-9]+(?:,[0-9]+)*(?:\\.[0-9]+)?[kKmMbB]?"
val siScalars = mapOf(
'k' to 1_000.0,
'K' to 1_000.0,
'm' to 1_000_000.0,
'M' to 1_000_000.0,
'b' to 1_000_000_000.0,
'B' to 1_000_000_000.0,
)
fun parseTimePattern(text: String): Duration {
val length = text.dropLast(1).toInt()
return when (text.last()) {
'm' -> length.minutes
's' -> length.seconds
else -> error("Invalid pattern for time $text")
}
}
fun parseShortNumber(string: String): Double {
var k = string.replace(",", "")
val scalar = k.last()
var scalarMultiplier = siScalars[scalar]
if (scalarMultiplier == null) {
scalarMultiplier = 1.0
} else {
k = k.dropLast(1)
}
return k.toDouble() * scalarMultiplier
}

View File

@@ -6,6 +6,8 @@
package moe.nea.firmament.util.render
import me.shedaniel.math.Color
val pi = Math.PI
val tau = Math.PI * 2
fun lerpAngle(a: Float, b: Float, progress: Float): Float {
@@ -17,7 +19,20 @@ fun lerpAngle(a: Float, b: Float, progress: Float): Float {
fun lerp(a: Float, b: Float, progress: Float): Float {
return a + (b - a) * progress
}
fun lerp(a: Int, b: Int, progress: Float): Int {
return (a + (b - a) * progress).toInt()
}
fun ilerp(a: Float, b: Float, value: Float): Float {
return (value - a) / (b - a)
}
fun lerp(a: Color, b: Color, progress: Float): Color {
return Color.ofRGBA(
lerp(a.red, b.red, progress),
lerp(a.green, b.green, progress),
lerp(a.blue, b.blue, progress),
lerp(a.alpha, b.alpha, progress),
)
}