aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/features')
-rw-r--r--src/main/kotlin/features/debug/PowerUserTools.kt7
-rw-r--r--src/main/kotlin/features/mining/PickaxeAbility.kt262
-rw-r--r--src/main/kotlin/features/texturepack/NumberMatcher.kt231
3 files changed, 247 insertions, 253 deletions
diff --git a/src/main/kotlin/features/debug/PowerUserTools.kt b/src/main/kotlin/features/debug/PowerUserTools.kt
index 7ce14c0..529f011 100644
--- a/src/main/kotlin/features/debug/PowerUserTools.kt
+++ b/src/main/kotlin/features/debug/PowerUserTools.kt
@@ -28,6 +28,7 @@ import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
import moe.nea.firmament.util.ClipboardUtils
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.focusedItemStack
+import moe.nea.firmament.util.mc.SNbtFormatter.Companion.toPrettyString
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.loreAccordingToNbt
import moe.nea.firmament.util.skyBlockId
@@ -44,6 +45,7 @@ object PowerUserTools : FirmamentFeature {
val copyLoreData by keyBindingWithDefaultUnbound("copy-lore")
val copySkullTexture by keyBindingWithDefaultUnbound("copy-skull-texture")
val copyEntityData by keyBindingWithDefaultUnbound("entity-data")
+ val copyItemStack by keyBindingWithDefaultUnbound("copy-item-stack")
}
override val config
@@ -125,7 +127,7 @@ object PowerUserTools : FirmamentFeature {
Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.modelid", model.toString()))
} else if (it.matches(TConfig.copyNbtData)) {
// TODO: copy full nbt
- val nbt = item.get(DataComponentTypes.CUSTOM_DATA)?.nbt?.toString() ?: "<empty>"
+ val nbt = item.get(DataComponentTypes.CUSTOM_DATA)?.nbt?.toPrettyString() ?: "<empty>"
ClipboardUtils.setTextContent(nbt)
lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.nbt"))
} else if (it.matches(TConfig.copyLoreData)) {
@@ -157,6 +159,9 @@ object PowerUserTools : FirmamentFeature {
Text.stringifiedTranslatable("firmament.tooltip.copied.skull-id", skullTexture.toString())
)
println("Copied skull id: $skullTexture")
+ } else if (it.matches(TConfig.copyItemStack)) {
+ ClipboardUtils.setTextContent(item.encode(MC.currentOrDefaultRegistries).toPrettyString())
+ lastCopiedStack = Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.stack"))
}
}
diff --git a/src/main/kotlin/features/mining/PickaxeAbility.kt b/src/main/kotlin/features/mining/PickaxeAbility.kt
index 192419f..1853d65 100644
--- a/src/main/kotlin/features/mining/PickaxeAbility.kt
+++ b/src/main/kotlin/features/mining/PickaxeAbility.kt
@@ -1,4 +1,3 @@
-
package moe.nea.firmament.features.mining
import java.util.regex.Pattern
@@ -30,155 +29,146 @@ 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.skyblock.AbilityUtils
import moe.nea.firmament.util.toShedaniel
import moe.nea.firmament.util.unformattedString
import moe.nea.firmament.util.useMatch
object PickaxeAbility : FirmamentFeature {
- override val identifier: String
- get() = "pickaxe-info"
-
-
- 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()
- var lastUsage = mutableMapOf<String, TimeMark>()
- var abilityOverride: String? = null
- var defaultAbilityDurations = mutableMapOf<String, Duration>(
- "Mining Speed Boost" to 120.seconds,
- "Pickobulus" to 110.seconds,
- "Gemstone Infusion" to 140.seconds,
- "Hazardous Miner" to 140.seconds,
- "Maniac Miner" to 59.seconds,
- "Vein Seeker" to 60.seconds
- )
-
- override val config: ManagedConfig
- get() = TConfig
-
- fun getCooldownPercentage(name: String, cooldown: Duration): Double {
- val sinceLastUsage = lastUsage[name]?.passedTime() ?: Duration.INFINITE
- val sinceLobbyJoin = lobbyJoinTime.passedTime()
+ override val identifier: String
+ get() = "pickaxe-info"
+
+
+ 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()
+ var lastUsage = mutableMapOf<String, TimeMark>()
+ var abilityOverride: String? = null
+ var defaultAbilityDurations = mutableMapOf<String, Duration>(
+ "Mining Speed Boost" to 120.seconds,
+ "Pickobulus" to 110.seconds,
+ "Gemstone Infusion" to 140.seconds,
+ "Hazardous Miner" to 140.seconds,
+ "Maniac Miner" to 59.seconds,
+ "Vein Seeker" to 60.seconds
+ )
+
+ override val config: ManagedConfig
+ get() = TConfig
+
+ fun getCooldownPercentage(name: String, cooldown: Duration): Double {
+ val sinceLastUsage = lastUsage[name]?.passedTime() ?: Duration.INFINITE
+ val sinceLobbyJoin = lobbyJoinTime.passedTime()
if (SBData.skyblockLocation == SkyBlockIsland.MINESHAFT) {
if (sinceLobbyJoin < sinceLastUsage) {
return 1.0
}
}
- if (sinceLastUsage < cooldown)
- return sinceLastUsage / cooldown
- return 1.0
- }
-
- @Subscribe
- fun onSlotClick(it: SlotClickEvent) {
- if (MC.screen?.title?.unformattedString == "Heart of the Mountain") {
- val name = it.stack.displayNameAccordingToNbt?.unformattedString ?: return
- val cooldown = it.stack.loreAccordingToNbt.firstNotNullOfOrNull {
- cooldownPattern.useMatch(it.unformattedString) {
- parseTimePattern(group("cooldown"))
- }
- } ?: return
- defaultAbilityDurations[name] = cooldown
- }
- }
-
- @Subscribe
- fun onDurabilityBar(it: DurabilityBarEvent) {
- if (!TConfig.drillFuelBar) return
- val lore = it.item.loreAccordingToNbt
- if (lore.lastOrNull()?.unformattedString?.contains("DRILL") != true) return
- val maxFuel = lore.firstNotNullOfOrNull {
- fuelPattern.useMatch(it.unformattedString) {
- parseShortNumber(group("maxFuel"))
- }
- } ?: return
- val extra = it.item.extraAttributes
- if (!extra.contains("drill_fuel")) return
- val fuel = extra.getInt("drill_fuel")
- val percentage = fuel / maxFuel.toFloat()
- it.barOverride = DurabilityBarEvent.DurabilityBar(
- lerp(
- DyeColor.RED.toShedaniel(),
- DyeColor.GREEN.toShedaniel(),
- percentage
- ), percentage
- )
- }
-
- @Subscribe
- fun onChatMessage(it: ProcessChatEvent) {
- abilityUsePattern.useMatch(it.unformattedString) {
- lastUsage[group("name")] = TimeMark.now()
- }
- abilitySwitchPattern.useMatch(it.unformattedString) {
- abilityOverride = group("ability")
- }
- }
-
- @Subscribe
- fun onWorldReady(event: WorldReadyEvent) {
- lobbyJoinTime = TimeMark.now()
- abilityOverride = null
- }
+ if (sinceLastUsage < cooldown)
+ return sinceLastUsage / cooldown
+ return 1.0
+ }
+
+ @Subscribe
+ fun onSlotClick(it: SlotClickEvent) {
+ if (MC.screen?.title?.unformattedString == "Heart of the Mountain") {
+ val name = it.stack.displayNameAccordingToNbt.unformattedString
+ val cooldown = it.stack.loreAccordingToNbt.firstNotNullOfOrNull {
+ cooldownPattern.useMatch(it.unformattedString) {
+ parseTimePattern(group("cooldown"))
+ }
+ } ?: return
+ defaultAbilityDurations[name] = cooldown
+ }
+ }
+
+ @Subscribe
+ fun onDurabilityBar(it: DurabilityBarEvent) {
+ if (!TConfig.drillFuelBar) return
+ val lore = it.item.loreAccordingToNbt
+ if (lore.lastOrNull()?.unformattedString?.contains("DRILL") != true) return
+ val maxFuel = lore.firstNotNullOfOrNull {
+ fuelPattern.useMatch(it.unformattedString) {
+ parseShortNumber(group("maxFuel"))
+ }
+ } ?: return
+ val extra = it.item.extraAttributes
+ if (!extra.contains("drill_fuel")) return
+ val fuel = extra.getInt("drill_fuel")
+ val percentage = fuel / maxFuel.toFloat()
+ it.barOverride = DurabilityBarEvent.DurabilityBar(
+ lerp(
+ DyeColor.RED.toShedaniel(),
+ DyeColor.GREEN.toShedaniel(),
+ percentage
+ ), percentage
+ )
+ }
+
+ @Subscribe
+ fun onChatMessage(it: ProcessChatEvent) {
+ abilityUsePattern.useMatch(it.unformattedString) {
+ lastUsage[group("name")] = TimeMark.now()
+ }
+ abilitySwitchPattern.useMatch(it.unformattedString) {
+ abilityOverride = group("ability")
+ }
+ }
+
+ @Subscribe
+ fun onWorldReady(event: WorldReadyEvent) {
+ lobbyJoinTime = TimeMark.now()
+ abilityOverride = null
+ }
@Subscribe
fun onProfileSwitch(event: ProfileSwitchEvent) {
lastUsage.clear()
}
- 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,
- val cooldown: Duration,
- )
-
- fun getCooldownFromLore(itemStack: ItemStack): PickaxeAbilityData? {
- val lore = itemStack.loreAccordingToNbt
- if (!lore.any { it.unformattedString.contains("Breaking Power") })
- return null
- val cooldown = lore.firstNotNullOfOrNull {
- cooldownPattern.useMatch(it.unformattedString) {
- parseTimePattern(group("cooldown"))
- }
- } ?: return null
- val name = lore.firstNotNullOfOrNull {
- abilityPattern.useMatch(it.unformattedString) {
- group("name")
- }
- } ?: return null
- return PickaxeAbilityData(name, cooldown)
- }
-
-
- 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!")
-
-
- @Subscribe
- fun renderHud(event: HudRenderEvent) {
- if (!TConfig.cooldownEnabled) return
- var ability = getCooldownFromLore(MC.player?.getStackInHand(Hand.MAIN_HAND) ?: return) ?: return
- defaultAbilityDurations[ability.name] = ability.cooldown
- val ao = abilityOverride
- if (ao != ability.name && ao != null) {
- ability = PickaxeAbilityData(ao, defaultAbilityDurations[ao] ?: 120.seconds)
- }
- event.context.matrices.push()
- event.context.matrices.translate(MC.window.scaledWidth / 2F, MC.window.scaledHeight / 2F, 0F)
- event.context.matrices.scale(TConfig.cooldownScale.toFloat(), TConfig.cooldownScale.toFloat(), 1F)
- RenderCircleProgress.renderCircle(
- event.context, Identifier.of("firmament", "textures/gui/circle.png"),
- getCooldownPercentage(ability.name, ability.cooldown).toFloat(),
- 0f, 1f, 0f, 1f
- )
- event.context.matrices.pop()
- }
+ val abilityUsePattern = Pattern.compile("You used your (?<name>.*) Pickaxe Ability!")
+ val fuelPattern = Pattern.compile("Fuel: .*/(?<maxFuel>$SHORT_NUMBER_FORMAT)")
+ val pickaxeAbilityCooldownPattern = Pattern.compile("Your pickaxe ability is on cooldown for (?<remainingCooldown>$TIME_PATTERN)\\.")
+
+ data class PickaxeAbilityData(
+ val name: String,
+ val cooldown: Duration,
+ )
+
+ fun getCooldownFromLore(itemStack: ItemStack): PickaxeAbilityData? {
+ val lore = itemStack.loreAccordingToNbt
+ if (!lore.any { it.unformattedString.contains("Breaking Power") })
+ return null
+ val ability = AbilityUtils.getAbilities(itemStack).firstOrNull() ?: return null
+ return PickaxeAbilityData(ability.name, ability.cooldown ?: return null)
+ }
+
+ val cooldownPattern = Pattern.compile("Cooldown: (?<cooldown>$TIME_PATTERN)")
+ val abilitySwitchPattern =
+ Pattern.compile("You selected (?<ability>.*) as your Pickaxe Ability\\. This ability will apply to all of your pickaxes!")
+
+ @Subscribe
+ fun renderHud(event: HudRenderEvent) {
+ if (!TConfig.cooldownEnabled) return
+ if (!event.isRenderingCursor) return
+ var ability = getCooldownFromLore(MC.player?.getStackInHand(Hand.MAIN_HAND) ?: return) ?: return
+ defaultAbilityDurations[ability.name] = ability.cooldown
+ val ao = abilityOverride
+ if (ao != ability.name && ao != null) {
+ ability = PickaxeAbilityData(ao, defaultAbilityDurations[ao] ?: 120.seconds)
+ }
+ event.context.matrices.push()
+ event.context.matrices.translate(MC.window.scaledWidth / 2F, MC.window.scaledHeight / 2F, 0F)
+ event.context.matrices.scale(TConfig.cooldownScale.toFloat(), TConfig.cooldownScale.toFloat(), 1F)
+ RenderCircleProgress.renderCircle(
+ event.context, Identifier.of("firmament", "textures/gui/circle.png"),
+ getCooldownPercentage(ability.name, ability.cooldown).toFloat(),
+ 0f, 1f, 0f, 1f
+ )
+ event.context.matrices.pop()
+ }
}
diff --git a/src/main/kotlin/features/texturepack/NumberMatcher.kt b/src/main/kotlin/features/texturepack/NumberMatcher.kt
index 7e6665f..e6f2d01 100644
--- a/src/main/kotlin/features/texturepack/NumberMatcher.kt
+++ b/src/main/kotlin/features/texturepack/NumberMatcher.kt
@@ -1,4 +1,3 @@
-
package moe.nea.firmament.features.texturepack
import com.google.gson.JsonElement
@@ -6,120 +5,120 @@ import com.google.gson.JsonPrimitive
import moe.nea.firmament.util.useMatch
abstract class NumberMatcher {
- abstract fun test(number: Number): Boolean
-
-
- companion object {
- fun parse(jsonElement: JsonElement): NumberMatcher? {
- if (jsonElement is JsonPrimitive) {
- if (jsonElement.isString) {
- val string = jsonElement.asString
- return parseRange(string) ?: parseOperator(string)
- }
- if (jsonElement.isNumber) {
- val number = jsonElement.asNumber
- val hasDecimals = (number.toString().contains("."))
- return MatchNumberExact(if (hasDecimals) number.toLong() else number.toDouble())
- }
- }
- return null
- }
-
- private val intervalSpec =
- "(?<beginningOpen>[\\[\\(])(?<beginning>[0-9.]+)?,(?<ending>[0-9.]+)?(?<endingOpen>[\\]\\)])"
- .toPattern()
-
- fun parseRange(string: String): RangeMatcher? {
- intervalSpec.useMatch<Nothing>(string) {
- // Open in the set-theory sense, meaning does not include its end.
- val beginningOpen = group("beginningOpen") == "("
- val endingOpen = group("endingOpen") == ")"
- val beginning = group("beginning")?.toDouble()
- val ending = group("ending")?.toDouble()
- return RangeMatcher(beginning, !beginningOpen, ending, !endingOpen)
- }
- return null
- }
-
- enum class Operator(val operator: String) {
- LESS("<") {
- override fun matches(comparisonResult: Int): Boolean {
- return comparisonResult < 0
- }
- },
- LESS_EQUALS("<=") {
- override fun matches(comparisonResult: Int): Boolean {
- return comparisonResult <= 0
- }
- },
- GREATER(">") {
- override fun matches(comparisonResult: Int): Boolean {
- return comparisonResult > 0
- }
- },
- GREATER_EQUALS(">=") {
- override fun matches(comparisonResult: Int): Boolean {
- return comparisonResult >= 0
- }
- },
- ;
-
- abstract fun matches(comparisonResult: Int): Boolean
- }
-
- private val operatorPattern = "(?<operator>${Operator.entries.joinToString("|") {it.operator}})(?<value>[0-9.]+)".toPattern()
-
- fun parseOperator(string: String): OperatorMatcher? {
- operatorPattern.useMatch<Nothing>(string) {
- val operatorName = group("operator")
- val operator = Operator.entries.find { it.operator == operatorName }!!
- val value = group("value").toDouble()
- return OperatorMatcher(operator, value)
- }
- return null
- }
-
- data class OperatorMatcher(val operator: Operator, val value: Double) : NumberMatcher() {
- override fun test(number: Number): Boolean {
- return operator.matches(number.toDouble().compareTo(value))
- }
- }
-
-
- data class MatchNumberExact(val number: Number) : NumberMatcher() {
- override fun test(number: Number): Boolean {
- return when (this.number) {
- is Double -> number.toDouble() == this.number.toDouble()
- else -> number.toLong() == this.number.toLong()
- }
- }
- }
-
- data class RangeMatcher(
- val beginning: Double?,
- val beginningInclusive: Boolean,
- val ending: Double?,
- val endingInclusive: Boolean,
- ) : NumberMatcher() {
- override fun test(number: Number): Boolean {
- val value = number.toDouble()
- if (beginning != null) {
- if (beginningInclusive) {
- if (value < beginning) return false
- } else {
- if (value <= beginning) return false
- }
- }
- if (ending != null) {
- if (endingInclusive) {
- if (value > ending) return false
- } else {
- if (value >= ending) return false
- }
- }
- return true
- }
- }
- }
+ abstract fun test(number: Number): Boolean
+
+
+ companion object {
+ fun parse(jsonElement: JsonElement): NumberMatcher? {
+ if (jsonElement is JsonPrimitive) {
+ if (jsonElement.isString) {
+ val string = jsonElement.asString
+ return parseRange(string) ?: parseOperator(string)
+ }
+ if (jsonElement.isNumber) {
+ val number = jsonElement.asNumber
+ val hasDecimals = (number.toString().contains("."))
+ return MatchNumberExact(if (hasDecimals) number.toLong() else number.toDouble())
+ }
+ }
+ return null
+ }
+
+ private val intervalSpec =
+ "(?<beginningOpen>[\\[\\(])(?<beginning>[0-9.]+)?,(?<ending>[0-9.]+)?(?<endingOpen>[\\]\\)])"
+ .toPattern()
+
+ fun parseRange(string: String): RangeMatcher? {
+ intervalSpec.useMatch<Nothing>(string) {
+ // Open in the set-theory sense, meaning does not include its end.
+ val beginningOpen = group("beginningOpen") == "("
+ val endingOpen = group("endingOpen") == ")"
+ val beginning = group("beginning")?.toDouble()
+ val ending = group("ending")?.toDouble()
+ return RangeMatcher(beginning, !beginningOpen, ending, !endingOpen)
+ }
+ return null
+ }
+
+ enum class Operator(val operator: String) {
+ LESS("<") {
+ override fun matches(comparisonResult: Int): Boolean {
+ return comparisonResult < 0
+ }
+ },
+ LESS_EQUALS("<=") {
+ override fun matches(comparisonResult: Int): Boolean {
+ return comparisonResult <= 0
+ }
+ },
+ GREATER(">") {
+ override fun matches(comparisonResult: Int): Boolean {
+ return comparisonResult > 0
+ }
+ },
+ GREATER_EQUALS(">=") {
+ override fun matches(comparisonResult: Int): Boolean {
+ return comparisonResult >= 0
+ }
+ },
+ ;
+
+ abstract fun matches(comparisonResult: Int): Boolean
+ }
+
+ private val operatorPattern =
+ "(?<operator>${Operator.entries.joinToString("|") { it.operator }})(?<value>[0-9.]+)".toPattern()
+
+ fun parseOperator(string: String): OperatorMatcher? {
+ return operatorPattern.useMatch(string) {
+ val operatorName = group("operator")
+ val operator = Operator.entries.find { it.operator == operatorName }!!
+ val value = group("value").toDouble()
+ OperatorMatcher(operator, value)
+ }
+ }
+
+ data class OperatorMatcher(val operator: Operator, val value: Double) : NumberMatcher() {
+ override fun test(number: Number): Boolean {
+ return operator.matches(number.toDouble().compareTo(value))
+ }
+ }
+
+
+ data class MatchNumberExact(val number: Number) : NumberMatcher() {
+ override fun test(number: Number): Boolean {
+ return when (this.number) {
+ is Double -> number.toDouble() == this.number.toDouble()
+ else -> number.toLong() == this.number.toLong()
+ }
+ }
+ }
+
+ data class RangeMatcher(
+ val beginning: Double?,
+ val beginningInclusive: Boolean,
+ val ending: Double?,
+ val endingInclusive: Boolean,
+ ) : NumberMatcher() {
+ override fun test(number: Number): Boolean {
+ val value = number.toDouble()
+ if (beginning != null) {
+ if (beginningInclusive) {
+ if (value < beginning) return false
+ } else {
+ if (value <= beginning) return false
+ }
+ }
+ if (ending != null) {
+ if (endingInclusive) {
+ if (value > ending) return false
+ } else {
+ if (value >= ending) return false
+ }
+ }
+ return true
+ }
+ }
+ }
}