aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/firmament/features/mining
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-08-28 19:04:24 +0200
committerLinnea Gräf <nea@nea.moe>2024-08-28 19:04:24 +0200
commitd2f240ff0ca0d27f417f837e706c781a98c31311 (patch)
tree0db7aff6cc14deaf36eed83889d59fd6b3a6f599 /src/main/kotlin/moe/nea/firmament/features/mining
parenta6906308163aa3b2d18fa1dc1aa71ac9bbcc83ab (diff)
downloadfirmament-d2f240ff0ca0d27f417f837e706c781a98c31311.tar.gz
firmament-d2f240ff0ca0d27f417f837e706c781a98c31311.tar.bz2
firmament-d2f240ff0ca0d27f417f837e706c781a98c31311.zip
Refactor source layout
Introduce compat source sets and move all kotlin sources to the main directory [no changelog]
Diffstat (limited to 'src/main/kotlin/moe/nea/firmament/features/mining')
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/mining/Histogram.kt81
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt176
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt133
3 files changed, 0 insertions, 390 deletions
diff --git a/src/main/kotlin/moe/nea/firmament/features/mining/Histogram.kt b/src/main/kotlin/moe/nea/firmament/features/mining/Histogram.kt
deleted file mode 100644
index ed48437..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/mining/Histogram.kt
+++ /dev/null
@@ -1,81 +0,0 @@
-
-package moe.nea.firmament.features.mining
-
-import java.util.*
-import kotlin.time.Duration
-import moe.nea.firmament.util.TimeMark
-
-class Histogram<T>(
- val maxSize: Int,
- val maxDuration: Duration,
-) {
-
- data class OrderedTimestamp(val timestamp: TimeMark, val order: Int) : Comparable<OrderedTimestamp> {
- override fun compareTo(other: OrderedTimestamp): Int {
- val o = timestamp.compareTo(other.timestamp)
- if (o != 0) return o
- return order.compareTo(other.order)
- }
- }
-
- val size: Int get() = dataPoints.size
- private val dataPoints: NavigableMap<OrderedTimestamp, T> = TreeMap()
-
- private var order = Int.MIN_VALUE
-
- fun record(entry: T, timestamp: TimeMark = TimeMark.now()) {
- dataPoints[OrderedTimestamp(timestamp, order++)] = entry
- trim()
- }
-
- fun oldestUpdate(): TimeMark {
- trim()
- return if (dataPoints.isEmpty()) TimeMark.now() else dataPoints.firstKey().timestamp
- }
-
- fun latestUpdate(): TimeMark {
- trim()
- return if (dataPoints.isEmpty()) TimeMark.farPast() else dataPoints.lastKey().timestamp
- }
-
- fun averagePer(valueExtractor: (T) -> Double, perDuration: Duration): Double? {
- return aggregate(
- seed = 0.0,
- operator = { accumulator, entry, _ -> accumulator + valueExtractor(entry) },
- finish = { sum, beginning, end ->
- val timespan = end - beginning
- if (timespan > perDuration)
- sum / (timespan / perDuration)
- else null
- })
- }
-
- fun <V, R> aggregate(
- seed: V,
- operator: (V, T, TimeMark) -> V,
- finish: (V, TimeMark, TimeMark) -> R
- ): R? {
- trim()
- var accumulator = seed
- var min: TimeMark? = null
- var max: TimeMark? = null
- dataPoints.forEach { (key, value) ->
- max = key.timestamp
- if (min == null)
- min = key.timestamp
- accumulator = operator(accumulator, value, key.timestamp)
- }
- if (min == null)
- return null
- return finish(accumulator, min!!, max!!)
- }
-
- private fun trim() {
- while (maxSize < dataPoints.size) {
- dataPoints.pollFirstEntry()
- }
- dataPoints.headMap(OrderedTimestamp(TimeMark.ago(maxDuration), Int.MAX_VALUE)).clear()
- }
-
-
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt b/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt
deleted file mode 100644
index 7879f2d..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/mining/PickaxeAbility.kt
+++ /dev/null
@@ -1,176 +0,0 @@
-
-package moe.nea.firmament.features.mining
-
-import java.util.regex.Pattern
-import kotlin.time.Duration
-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.annotations.Subscribe
-import moe.nea.firmament.events.HudRenderEvent
-import moe.nea.firmament.events.ProcessChatEvent
-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
-
-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
- if (sinceLastUsage < cooldown)
- return sinceLastUsage / cooldown
- val sinceLobbyJoin = lobbyJoinTime.passedTime()
- val halfCooldown = cooldown / 2
- if (sinceLobbyJoin < halfCooldown) {
- return (sinceLobbyJoin / halfCooldown)
- }
- 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) {
- lastUsage.clear()
- lobbyJoinTime = TimeMark.now()
- abilityOverride = null
- }
-
- 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") == true })
- 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()
- }
-}
diff --git a/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt b/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt
deleted file mode 100644
index f1bc7e5..0000000
--- a/src/main/kotlin/moe/nea/firmament/features/mining/PristineProfitTracker.kt
+++ /dev/null
@@ -1,133 +0,0 @@
-
-package moe.nea.firmament.features.mining
-
-import io.github.notenoughupdates.moulconfig.xml.Bind
-import moe.nea.jarvis.api.Point
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.serializer
-import kotlin.time.Duration.Companion.seconds
-import net.minecraft.text.Text
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.ProcessChatEvent
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.gui.config.ManagedConfig
-import moe.nea.firmament.gui.hud.MoulConfigHud
-import moe.nea.firmament.util.BazaarPriceStrategy
-import moe.nea.firmament.util.FirmFormatters.formatCommas
-import moe.nea.firmament.util.SkyblockId
-import moe.nea.firmament.util.data.ProfileSpecificDataHolder
-import moe.nea.firmament.util.formattedString
-import moe.nea.firmament.util.parseIntWithComma
-import moe.nea.firmament.util.useMatch
-
-object PristineProfitTracker : FirmamentFeature {
- override val identifier: String
- get() = "pristine-profit"
-
- enum class GemstoneKind(
- val label: String,
- val flawedId: SkyblockId,
- ) {
- SAPPHIRE("Sapphire", SkyblockId("FLAWED_SAPPHIRE_GEM")),
- RUBY("Ruby", SkyblockId("FLAWED_RUBY_GEM")),
- AMETHYST("Amethyst", SkyblockId("FLAWED_AMETHYST_GEM")),
- AMBER("Amber", SkyblockId("FLAWED_AMBER_GEM")),
- TOPAZ("Topaz", SkyblockId("FLAWED_TOPAZ_GEM")),
- JADE("Jade", SkyblockId("FLAWED_JADE_GEM")),
- JASPER("Jasper", SkyblockId("FLAWED_JASPER_GEM")),
- OPAL("Opal", SkyblockId("FLAWED_OPAL_GEM")),
- }
-
- @Serializable
- data class Data(
- var maxMoneyPerSecond: Double = 1.0,
- var maxCollectionPerSecond: Double = 1.0,
- )
-
- object DConfig : ProfileSpecificDataHolder<Data>(serializer(), identifier, ::Data)
-
- override val config: ManagedConfig?
- get() = TConfig
-
- object TConfig : ManagedConfig(identifier) {
- val timeout by duration("timeout", 0.seconds, 120.seconds) { 30.seconds }
- val gui by position("position", 80, 30) { Point(0.05, 0.2) }
- }
-
- val sellingStrategy = BazaarPriceStrategy.SELL_ORDER
-
- val pristineRegex =
- "PRISTINE! You found . Flawed (?<kind>${
- GemstoneKind.entries.joinToString("|") { it.label }
- }) Gemstone x(?<count>[0-9,]+)!".toPattern()
-
- val collectionHistogram = Histogram<Double>(10000, 180.seconds)
- val moneyHistogram = Histogram<Double>(10000, 180.seconds)
-
- object ProfitHud : MoulConfigHud("pristine_profit", TConfig.gui) {
- @field:Bind
- var moneyCurrent: Double = 0.0
-
- @field:Bind
- var moneyMax: Double = 1.0
-
- @field:Bind
- var moneyText = ""
-
- @field:Bind
- var collectionCurrent = 0.0
-
- @field:Bind
- var collectionMax = 1.0
-
- @field:Bind
- var collectionText = ""
- override fun shouldRender(): Boolean = collectionHistogram.latestUpdate().passedTime() < TConfig.timeout
- }
-
- val SECONDS_PER_HOUR = 3600
- val ROUGHS_PER_FLAWED = 80
-
- fun updateUi() {
- val collectionPerSecond = collectionHistogram.averagePer({ it }, 1.seconds)
- val moneyPerSecond = moneyHistogram.averagePer({ it }, 1.seconds)
- if (collectionPerSecond == null || moneyPerSecond == null) return
- ProfitHud.collectionCurrent = collectionPerSecond
- ProfitHud.collectionText = Text.stringifiedTranslatable("firmament.pristine-profit.collection",
- formatCommas(collectionPerSecond * SECONDS_PER_HOUR,
- 1)).formattedString()
- ProfitHud.moneyCurrent = moneyPerSecond
- ProfitHud.moneyText = Text.stringifiedTranslatable("firmament.pristine-profit.money",
- formatCommas(moneyPerSecond * SECONDS_PER_HOUR, 1))
- .formattedString()
- val data = DConfig.data
- if (data != null) {
- if (data.maxCollectionPerSecond < collectionPerSecond && collectionHistogram.oldestUpdate()
- .passedTime() > 30.seconds
- ) {
- data.maxCollectionPerSecond = collectionPerSecond
- DConfig.markDirty()
- }
- if (data.maxMoneyPerSecond < moneyPerSecond && moneyHistogram.oldestUpdate().passedTime() > 30.seconds) {
- data.maxMoneyPerSecond = moneyPerSecond
- DConfig.markDirty()
- }
- ProfitHud.collectionMax = maxOf(data.maxCollectionPerSecond, collectionPerSecond)
- ProfitHud.moneyMax = maxOf(data.maxMoneyPerSecond, moneyPerSecond)
- }
- }
-
-
- @Subscribe
- fun onMessage(it: ProcessChatEvent) {
- pristineRegex.useMatch(it.unformattedString) {
- val gemstoneKind = GemstoneKind.valueOf(group("kind").uppercase())
- val flawedCount = parseIntWithComma(group("count"))
- val moneyAmount = sellingStrategy.getSellPrice(gemstoneKind.flawedId) * flawedCount
- moneyHistogram.record(moneyAmount)
- val collectionAmount = flawedCount * ROUGHS_PER_FLAWED
- collectionHistogram.record(collectionAmount.toDouble())
- updateUi()
- }
- }
-}