Align power/matter history by biggest values

This commit is contained in:
DBotThePony 2024-09-11 20:01:54 +07:00
parent 759c9863e2
commit fdf8e47e5e
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 128 additions and 82 deletions

View File

@ -24,6 +24,7 @@ import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.util.formatHistory
import ru.dbotthepony.mc.otm.core.util.formatMatter
import ru.dbotthepony.mc.otm.core.util.formatMatterLevel
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
@ -137,21 +138,6 @@ open class MatterGaugePanel<out S : Screen> @JvmOverloads constructor(
}
}
private fun formatLevel(a: Decimal, b: Decimal): Component {
val diff = a - b
val fa = a.formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN)
val fb = b.formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_RED)
if (diff.isZero) {
return TranslatableComponent("otm.gui.diff", diff.formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.GRAY), fa, fb)
} else if (diff.isPositive) {
return TranslatableComponent("otm.gui.diff", diff.formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN), fa, fb)
} else {
return TranslatableComponent("otm.gui.diff", (-diff).formatMatter(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_RED), fa, fb)
}
}
open class ProfiledMatterGaugePanel<out S : Screen>(
screen: S,
parent: EditablePanel<*>? = null,
@ -161,29 +147,12 @@ open class ProfiledMatterGaugePanel<out S : Screen>(
): MatterGaugePanel<S>(screen, parent, profiledWidget.gauge, x, y) {
override fun makeTooltip(): MutableList<Component> {
return super.makeTooltip().also {
it.add(TextComponent(""))
if (minecraft.window.isShiftDown) {
it.add(formatLevel(profiledWidget.lastTickReceive, profiledWidget.lastTickTransfer))
it.add(TextComponent("---"))
}
it.add(formatLevel(
profiledWidget.weightedReceive,
profiledWidget.weightedTransfer,
))
if (minecraft.window.isShiftDown) {
it.add(TextComponent("---"))
val values = IntArrayList()
values.addAll(profiledWidget.tick downTo 0)
values.addAll(AbstractProfiledStorage.HISTORY_SIZE - 1 downTo profiledWidget.tick + 1)
for (i in values.intIterator()) {
it.add(formatLevel(profiledWidget.historyReceive[i].value, profiledWidget.historyTransfer[i].value))
}
}
formatHistory(
it,
profiledWidget,
verbose = ShiftPressedCond,
suffix = TranslatableComponent("otm.gui.matter.name")
)
}
}
}

View File

@ -15,6 +15,7 @@ import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.util.formatHistory
import ru.dbotthepony.mc.otm.core.util.formatPower
import ru.dbotthepony.mc.otm.core.util.formatPowerLevel
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
@ -94,21 +95,6 @@ fun <S : Screen> WidePowerGaugePanel(
height: Float = 48f
) = PowerGaugePanel(screen, parent, widget, x, y, width, height)
private fun formatLevel(a: Decimal, b: Decimal): Component {
val diff = a - b
val fa = a.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN)
val fb = b.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_RED)
if (diff.isZero) {
return TranslatableComponent("otm.gui.diff", diff.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.GRAY), fa, fb)
} else if (diff.isPositive) {
return TranslatableComponent("otm.gui.diff", diff.formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_GREEN), fa, fb)
} else {
return TranslatableComponent("otm.gui.diff", (-diff).formatPower(formatAsReadable = ShiftPressedCond).copy().withStyle(ChatFormatting.DARK_RED), fa, fb)
}
}
open class ProfiledPowerGaugePanel<out S : Screen>(
screen: S,
parent: EditablePanel<*>? = null,
@ -120,29 +106,12 @@ open class ProfiledPowerGaugePanel<out S : Screen>(
) : PowerGaugePanel<S>(screen, parent, profiledWidget.gauge, x, y, width, height) {
override fun makeTooltip(): MutableList<Component> {
return super.makeTooltip().also {
it.add(TextComponent(""))
if (minecraft.window.isShiftDown) {
it.add(formatLevel(profiledWidget.lastTickReceive, profiledWidget.lastTickTransfer))
it.add(TextComponent("---"))
}
it.add(formatLevel(
profiledWidget.weightedReceive,
profiledWidget.weightedTransfer,
))
if (minecraft.window.isShiftDown) {
it.add(TextComponent("---"))
val values = IntArrayList()
values.addAll(profiledWidget.tick downTo 0)
values.addAll(AbstractProfiledStorage.HISTORY_SIZE - 1 downTo profiledWidget.tick + 1)
for (i in values.intIterator()) {
it.add(formatLevel(profiledWidget.historyReceive[i].value, profiledWidget.historyTransfer[i].value))
}
}
formatHistory(
it,
profiledWidget,
verbose = ShiftPressedCond,
suffix = TranslatableComponent("otm.gui.power.name")
)
}
}
}

View File

@ -1,15 +1,22 @@
package ru.dbotthepony.mc.otm.core.util
import it.unimi.dsi.fastutil.chars.CharArrayList
import it.unimi.dsi.fastutil.ints.IntArrayList
import net.minecraft.ChatFormatting
import net.minecraft.network.chat.Component
import net.minecraft.network.chat.MutableComponent
import ru.dbotthepony.kommons.util.value
import ru.dbotthepony.mc.otm.capability.AbstractProfiledStorage
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.isNegative
import ru.dbotthepony.mc.otm.core.math.isZero
import ru.dbotthepony.mc.otm.menu.widget.ProfiledLevelGaugeWidget
import java.math.BigInteger
import java.util.function.BooleanSupplier
import kotlin.math.absoluteValue
import kotlin.math.max
import kotlin.math.roundToInt
private fun concat(numbers: String, suffix: Any): Component {
@ -127,7 +134,7 @@ private fun reformat(numbers: String): String {
for (i in dot downTo 0) {
if (++c == 4) {
c = 1
result.add(' ')
result.add('')
}
result.add(numbers[i])
@ -138,6 +145,19 @@ private fun reformat(numbers: String): String {
})
}
// because minecraft's font 'Figure Space' (FSP) does not match width of numbers
private fun resplice(number: String, decimals: Int): String {
var i = if (decimals != 0) decimals + 4 else 3
val resplice = number.toCharArray()
while (i < number.length) {
resplice[resplice.size - i - 1] = ''
i += 3
}
return String(resplice)
}
fun Long.formatSiComponent(suffix: Any = "", decimalPlaces: Int = 3, formatAsReadable: BooleanSupplier = never, bias: Int = 0): Component {
require(decimalPlaces >= 0) { "Invalid amount of decimal places required: $decimalPlaces" }
@ -234,3 +254,85 @@ fun formatTickDuration(ticks: Int, longFormat: Boolean = false): String {
return "${padded(minutes)}:$seconds"
}
}
fun formatHistory(
result: MutableList<Component>,
widget: ProfiledLevelGaugeWidget<*>,
bias: Int = 0,
decimals: Int = 3,
verbose: BooleanSupplier = never,
suffix: Any = "",
) {
data class Part(val formatted: String, val number: Decimal, val prefix: SiPrefix)
data class Line(val delta: Part, val incoming: Part, val outgoing: Part)
val lines = ArrayList<Line>()
fun part(number: Decimal): Part {
if (verbose.asBoolean && number.absoluteValue >= Decimal.ONE) {
return Part(reformat(number.toString(decimals)), number, SiPrefix.NONE)
}
val prefix = SiPrefix.determine(number).neighbour(bias)
if (prefix.isEmpty) return Part(number.toString(decimals), number, prefix)
return Part((number / prefix.decimal).toString(decimals), number, prefix)
}
fun addLine(a: Decimal, b: Decimal) {
lines.add(Line(part(a - b), part(a), part(b)))
}
if (verbose.asBoolean) {
addLine(widget.lastTickReceive, widget.lastTickTransfer)
val values = IntArrayList()
values.addAll(widget.tick downTo 0)
values.addAll(AbstractProfiledStorage.HISTORY_SIZE - 1 downTo widget.tick + 1)
for (i in values.intIterator()) {
addLine(widget.historyReceive[i].value, widget.historyTransfer[i].value)
}
}
addLine(
widget.weightedReceive,
widget.weightedTransfer
)
val maxWidthDeltaNumber = lines.maxOf { it.delta.formatted.length }
val maxWidthInNumber = lines.maxOf { it.incoming.formatted.length }
val maxWidthOutNumber = lines.maxOf { it.outgoing.formatted.length }
val maxWidthDeltaSi = lines.maxOf { it.delta.prefix.length }
val maxWidthInSi = lines.maxOf { it.incoming.prefix.length }
val maxWidthOutSi = lines.maxOf { it.outgoing.prefix.length }
fun Part.format(widthNumbers: Int, widthSi: Int): MutableComponent {
return TranslatableComponent(
prefix.formatLocaleKey,
resplice("-".repeat(max(widthNumbers - formatted.length, 0)) + formatted, decimals) + "-".repeat(max(widthSi - prefix.length, 0)),
suffix
)
}
fun Line.format(): Component {
val deltaColor = if (delta.number.isZero) ChatFormatting.GRAY else if (delta.number.isPositive) ChatFormatting.DARK_GREEN else ChatFormatting.DARK_RED
return TranslatableComponent(
"otm.gui.diff",
delta.format(maxWidthDeltaNumber, maxWidthDeltaSi).withStyle(deltaColor),
incoming.format(maxWidthInNumber, maxWidthInSi).withStyle(ChatFormatting.DARK_GREEN),
outgoing.format(maxWidthOutNumber, maxWidthOutSi).withStyle(ChatFormatting.DARK_RED),
)
}
result.add(TextComponent(""))
result.add(lines.removeFirst().format())
if (verbose.asBoolean) {
result.add(TextComponent("---"))
result.add(lines.removeFirst().format())
result.add(TextComponent("---"))
lines.forEach { result.add(it.format()) }
}
}

View File

@ -1,6 +1,8 @@
package ru.dbotthepony.mc.otm.core.util
import com.google.common.collect.ImmutableList
import net.minecraft.network.chat.Component
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.Decimal
import ru.dbotthepony.mc.otm.core.math.isZero
import java.math.BigInteger
@ -19,6 +21,9 @@ enum class SiPrefix(val power: Int, val symbol: String) {
NONE(0, "") {
override val isEmpty: Boolean
get() = true
override val length: Int
get() = 0
},
KILO (1, "k"),
@ -35,6 +40,10 @@ enum class SiPrefix(val power: Int, val symbol: String) {
val formatLocaleKey = "otm.suffix.${name.lowercase()}".intern()
val conciseFormatLocaleKey = "otm.suffix_concise.${name.lowercase()}".intern()
val rawLocaleKey = "otm.suffix_raw.${name.lowercase()}".intern()
val rawLocale: Component = TranslatableComponent(rawLocaleKey)
open val length: Int
get() = rawLocale.string.length
val string: String
@ -72,18 +81,15 @@ enum class SiPrefix(val power: Int, val symbol: String) {
if (new < 0) {
return YOCTO
} else if (new >= VALUES.size) {
} else if (new >= entries.size) {
return YOTTA
} else {
return VALUES[new]
return entries[new]
}
}
}
companion object {
@JvmField
val VALUES: ImmutableList<SiPrefix> = ImmutableList.copyOf(values())
@JvmField
val MULTIPLIES: ImmutableList<SiPrefix> = ImmutableList.builder<SiPrefix>()
.add(NONE)