diff options
-rw-r--r-- | src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt | 12 | ||||
-rw-r--r-- | src/main/kotlin/commands/rome.kt | 4 | ||||
-rw-r--r-- | src/main/kotlin/repo/SBItemStack.kt | 30 | ||||
-rw-r--r-- | src/main/kotlin/repo/item/SBItemStats.kt | 19 | ||||
-rw-r--r-- | src/main/kotlin/repo/item/SBReforge.kt | 66 | ||||
-rw-r--r-- | src/main/kotlin/repo/item/StatBlock.kt | 163 | ||||
-rw-r--r-- | src/main/kotlin/util/skyblock/stats/BuffKind.kt | 15 | ||||
-rw-r--r-- | src/main/kotlin/util/skyblock/stats/StatBlock.kt | 61 | ||||
-rw-r--r-- | src/main/kotlin/util/skyblock/stats/StatFormatting.kt | 63 | ||||
-rw-r--r-- | src/main/kotlin/util/skyblock/stats/StatLine.kt | 71 |
10 files changed, 309 insertions, 195 deletions
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt index 8e86967..7a289b9 100644 --- a/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt @@ -17,6 +17,7 @@ import me.shedaniel.rei.api.common.display.Display import me.shedaniel.rei.api.common.display.DisplaySerializer import me.shedaniel.rei.api.common.entry.EntryIngredient import me.shedaniel.rei.api.common.entry.EntryStack +import util.skyblock.stats.StatFormatting import net.minecraft.entity.EntityType import net.minecraft.entity.SpawnReason import net.minecraft.text.Text @@ -31,7 +32,7 @@ import moe.nea.firmament.repo.ReforgeStore import moe.nea.firmament.repo.RepoItemTypeCache import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.repo.SBItemStack -import moe.nea.firmament.repo.item.StatBlock +import moe.nea.firmament.util.skyblock.stats.StatBlock import moe.nea.firmament.util.AprilFoolsUtil import moe.nea.firmament.util.FirmFormatters import moe.nea.firmament.util.SkyblockId @@ -40,6 +41,7 @@ import moe.nea.firmament.util.grey import moe.nea.firmament.util.skyblock.ItemType import moe.nea.firmament.util.skyblock.Rarity import moe.nea.firmament.util.skyblock.SkyBlockItems +import moe.nea.firmament.util.skyblock.stats.StatLine import moe.nea.firmament.util.skyblockId import moe.nea.firmament.util.tr @@ -107,8 +109,8 @@ class SBReforgeRecipe( for ((i, statId) in display.reforge.statUniverse.withIndex()) { val label = Widgets.createLabel( Point(bounds.minX + 10 + 24 + 24 + 20, bounds.minY + 8 + i * 11), - StatBlock.StatLine( // TODO: add helper methods for constructing stat lines - StatBlock.findStatFormatting(SBItemStack.statIdToName(statId)), + StatLine( + StatFormatting.findForId(statId), 0.0 ).reconstitute(7)) .horizontalAlignment(Label.LEFT_ALIGNED) @@ -120,8 +122,8 @@ class SBReforgeRecipe( val stats = display.reforge.reforgeStats?.get(entry.rarity) ?: mapOf() for ((stat, label) in statToLineMappings) { label.message = - StatBlock.StatLine( - StatBlock.findStatFormatting(SBItemStack.statIdToName(stat)), + StatLine( + StatFormatting.findForId(stat), stats[stat] ?: 0.0 ).reconstitute(7) } diff --git a/src/main/kotlin/commands/rome.kt b/src/main/kotlin/commands/rome.kt index 3b3ab7a..5bdd0ed 100644 --- a/src/main/kotlin/commands/rome.kt +++ b/src/main/kotlin/commands/rome.kt @@ -257,8 +257,10 @@ fun firmamentCommand() = literal("firmament") { dataT.gold() else if (oldData == data) dataT.lime() - else + else { + println("Mismatched prop ${prop}:\nExpected: ${oldData}\nActual : ${data}") dataT.red() + } source.sendFeedback(Text.literal("${prop.javaClass.simpleName}") .blue() .append(Text.literal(": ").grey()) diff --git a/src/main/kotlin/repo/SBItemStack.kt b/src/main/kotlin/repo/SBItemStack.kt index 93cf52c..5644901 100644 --- a/src/main/kotlin/repo/SBItemStack.kt +++ b/src/main/kotlin/repo/SBItemStack.kt @@ -5,6 +5,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder import io.github.moulberry.repo.constants.PetNumbers import io.github.moulberry.repo.data.NEUIngredient import io.github.moulberry.repo.data.NEUItem +import util.skyblock.stats.StatFormatting import net.minecraft.item.ItemStack import net.minecraft.network.RegistryByteBuf import net.minecraft.network.codec.PacketCodec @@ -14,7 +15,7 @@ import net.minecraft.text.Text import net.minecraft.util.Formatting import moe.nea.firmament.repo.ItemCache.asItemStack import moe.nea.firmament.repo.ItemCache.withFallback -import moe.nea.firmament.repo.item.StatBlock +import moe.nea.firmament.util.skyblock.stats.StatBlock import moe.nea.firmament.util.FirmFormatters import moe.nea.firmament.util.LegacyFormattingCode import moe.nea.firmament.util.MC @@ -37,6 +38,7 @@ import moe.nea.firmament.util.removeColorCodes import moe.nea.firmament.util.skyBlockId import moe.nea.firmament.util.skyblock.ItemType import moe.nea.firmament.util.skyblock.Rarity +import moe.nea.firmament.util.skyblock.stats.BuffKind import moe.nea.firmament.util.skyblockId import moe.nea.firmament.util.unformattedString import moe.nea.firmament.util.useMatch @@ -112,7 +114,7 @@ data class SBItemStack constructor( buffKind: BuffKind, ) { val namedReforgeStats = reforgeStats - .mapKeysTo(mutableMapOf()) { statIdToName(it.key) } + .mapKeysTo(mutableMapOf()) { StatFormatting.statIdToName(it.key) } val loreMut = itemStack.loreAccordingToNbt.toMutableList() val statBlock = StatBlock.fromLore(loreMut) @@ -122,30 +124,6 @@ data class SBItemStack constructor( statBlock.applyModifications(loreMut) itemStack.loreAccordingToNbt = loreMut } - - data class StatFormatting( - val name: String, - val postFix: String, - val color: Formatting, - val isStarAffected: Boolean = true, - ) - - enum class BuffKind( - val color: Formatting, - val prefix: String, - val postFix: String, - val isHidden: Boolean, - ) { - REFORGE(Formatting.BLUE, "(", ")", false), - STAR_BUFF(Formatting.RESET, "", "", true), - CATA_STAR_BUFF(Formatting.DARK_GRAY, "(", ")", false), - ; - } - - fun statIdToName(statId: String): String { - val segments = statId.split("_") - return segments.joinToString(" ") { it.replaceFirstChar { it.uppercaseChar() } } - } } constructor(skyblockId: SkyblockId, petData: PetData) : this( diff --git a/src/main/kotlin/repo/item/SBItemStats.kt b/src/main/kotlin/repo/item/SBItemStats.kt new file mode 100644 index 0000000..94a40d0 --- /dev/null +++ b/src/main/kotlin/repo/item/SBItemStats.kt @@ -0,0 +1,19 @@ +package moe.nea.firmament.repo.item + +import com.google.auto.service.AutoService +import net.minecraft.item.ItemStack +import moe.nea.firmament.util.mc.loreAccordingToNbt +import moe.nea.firmament.util.skyblock.stats.StatBlock + +@AutoService(SBItemProperty::class) +object SBItemStats : SBItemProperty<StatBlock>() { + override fun fromStack( + stack: ItemStack, + store: SBItemData + ): StatBlock? { + return StatBlock.fromLore(stack.loreAccordingToNbt) + } + + override val order: Int + get() = 100 +} diff --git a/src/main/kotlin/repo/item/SBReforge.kt b/src/main/kotlin/repo/item/SBReforge.kt new file mode 100644 index 0000000..231e3cc --- /dev/null +++ b/src/main/kotlin/repo/item/SBReforge.kt @@ -0,0 +1,66 @@ +package moe.nea.firmament.repo.item + +import com.google.auto.service.AutoService +import net.minecraft.item.ItemStack +import net.minecraft.text.Style +import net.minecraft.text.Text +import moe.nea.firmament.repo.ItemCache +import moe.nea.firmament.repo.ReforgeStore +import moe.nea.firmament.repo.SBItemStack +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.ReforgeId +import moe.nea.firmament.util.blue +import moe.nea.firmament.util.getReforgeId +import moe.nea.firmament.util.grey +import moe.nea.firmament.util.mc.displayNameAccordingToNbt +import moe.nea.firmament.util.mc.modifyLore +import moe.nea.firmament.util.modifyExtraAttributes +import moe.nea.firmament.util.prepend +import moe.nea.firmament.util.reconstitute +import moe.nea.firmament.util.skyblock.Rarity +import moe.nea.firmament.util.skyblock.stats.BuffKind +import moe.nea.firmament.util.unformattedString + +@AutoService(SBItemProperty::class) +object SBReforge : SBItemProperty.State<ReforgeId>() { + override fun applyToStack( + stack: ItemStack, + store: SBItemData, + value: ReforgeId? + ): ItemStack { + val reforgeId = value ?: return stack + stack.modifyExtraAttributes { data -> + data.putString("modifier", reforgeId.id) + } + val rarity = Rarity.fromItem(stack) ?: return stack + val reforge = ReforgeStore.modifierLut[reforgeId] ?: return stack + stack.displayNameAccordingToNbt = stack.displayNameAccordingToNbt.copy() + .prepend(Text.literal(reforge.reforgeName + " ").formatted(rarity.colour())) + val reforgeStats = reforge.reforgeStats?.get(rarity) ?: mapOf() + SBItemStack.appendEnhancedStats(stack, reforgeStats, BuffKind.REFORGE) + reforge.reforgeAbility?.get(rarity)?.let { reforgeAbility -> + val formattedReforgeAbility = ItemCache.un189Lore(reforgeAbility) + .grey() + stack.modifyLore { + val lastBlank = it.indexOfLast { it.unformattedString.isBlank() } + val newList = mutableListOf<Text>() + newList.addAll(it.subList(0, lastBlank)) + newList.add(Text.literal("")) + newList.add(Text.literal("${reforge.reforgeName} Bonus").blue()) + MC.font.textHandler.wrapLines(formattedReforgeAbility, 180, Style.EMPTY).mapTo(newList) { + it.reconstitute() + } + newList.addAll(it.subList(lastBlank, it.size)) + newList + } + } + return stack + } + + override fun fromStack( + stack: ItemStack, + store: SBItemData + ): ReforgeId? { + return stack.getReforgeId() + } +} diff --git a/src/main/kotlin/repo/item/StatBlock.kt b/src/main/kotlin/repo/item/StatBlock.kt deleted file mode 100644 index 94643a2..0000000 --- a/src/main/kotlin/repo/item/StatBlock.kt +++ /dev/null @@ -1,163 +0,0 @@ -package moe.nea.firmament.repo.item - -import kotlin.collections.forEach -import kotlin.collections.plus -import net.minecraft.text.Style -import net.minecraft.text.Text -import net.minecraft.text.TextColor -import net.minecraft.util.Formatting -import moe.nea.firmament.repo.SBItemStack.Companion.BuffKind -import moe.nea.firmament.repo.SBItemStack.Companion.StatFormatting -import moe.nea.firmament.util.FirmFormatters -import moe.nea.firmament.util.directLiteralStringContent -import moe.nea.firmament.util.grey -import moe.nea.firmament.util.useMatch -import moe.nea.firmament.util.withColor - -data class StatBlock( - val indexedByName: Map<String, StatLine>, - val startIndex: Int, - val endIndex: Int, - private val modifiedLines: MutableMap<String, StatLine> = mutableMapOf() -) { - - /** - * Note that the returned stat line must be created by copying from the original stat line (to keep indexes in sync). - */ - fun modify(statName: String, mod: (StatLine) -> StatLine) { - val existing = modifiedLines[statName] ?: indexedByName[statName] ?: StatLine(findStatFormatting(statName), 0.0) - modifiedLines[statName] = mod(existing) - } - - fun applyModifications(lore: MutableList<Text>) { - if (modifiedLines.isEmpty()) return - var nextAppendIndex = endIndex - if (startIndex < 0) // No existing stat block, insert the after space. - lore.add(0, Text.literal("")) - modifiedLines.values.forEach { line -> - val loreLine = if (line.loreIndex < 0) { - lore.add(nextAppendIndex, Text.literal("")) - nextAppendIndex++ - } else line.loreIndex - lore[loreLine] = line.reconstitute() - } - } - - companion object { - fun fromLore(lore: List<Text>): StatBlock { - val map = mutableMapOf<String, StatLine>() - var start = -1 - var end = 0 - for ((index, text) in lore.withIndex()) { - val statLine = parseStatLine(text) - ?.copy(loreIndex = index) - if (statLine == null) { - if (start < 0) continue - else break - } - map[statLine.statName] = statLine - if (start < 0) - start = index - end = index + 1 - } - return StatBlock(map, start, end) - } - - val allFormattingOverrides = listOf( - StatFormatting("Sea Creature Chance", "%", Formatting.RED), - StatFormatting("Strength", "", Formatting.RED), - StatFormatting("Damage", "", Formatting.RED), - StatFormatting("Bonus Attack Speed", "%", Formatting.RED), - StatFormatting("Shot Cooldown", "s", Formatting.GREEN, false), - StatFormatting("Ability Damage", "%", Formatting.RED), - StatFormatting("Crit Damage", "%", Formatting.RED), - StatFormatting("Crit Chance", "%", Formatting.RED), - StatFormatting("Ability Damage", "%", Formatting.RED), - StatFormatting("Trophy Fish Chance", "%", Formatting.GREEN), - StatFormatting("Health", "", Formatting.GREEN), - StatFormatting("Defense", "", Formatting.GREEN), - StatFormatting("Fishing Speed", "", Formatting.GREEN), - StatFormatting("Double Hook Chance", "%", Formatting.GREEN), - StatFormatting("Mining Speed", "", Formatting.GREEN), - StatFormatting("Mining Fortune", "", Formatting.GREEN), - StatFormatting("Heat Resistance", "", Formatting.GREEN), - StatFormatting("Swing Range", "", Formatting.GREEN), - StatFormatting("Rift Time", "", Formatting.GREEN), - StatFormatting("Speed", "", Formatting.GREEN), - StatFormatting("Farming Fortune", "", Formatting.GREEN), - StatFormatting("True Defense", "", Formatting.GREEN), - StatFormatting("Mending", "", Formatting.GREEN), - StatFormatting("Foraging Wisdom", "", Formatting.GREEN), - StatFormatting("Farming Wisdom", "", Formatting.GREEN), - StatFormatting("Foraging Fortune", "", Formatting.GREEN), - StatFormatting("Magic Find", "", Formatting.GREEN), - StatFormatting("Ferocity", "", Formatting.GREEN), - StatFormatting("Bonus Pest Chance", "%", Formatting.GREEN), - StatFormatting("Cold Resistance", "", Formatting.GREEN), - StatFormatting("Pet Luck", "", Formatting.GREEN), - StatFormatting("Fear", "", Formatting.GREEN), - StatFormatting("Mana Regen", "%", Formatting.GREEN), - StatFormatting("Rift Damage", "", Formatting.GREEN), - StatFormatting("Hearts", "", Formatting.GREEN), - StatFormatting("Vitality", "", Formatting.GREEN), - // TODO: make this a repo json - ) - val formattingOverrides = allFormattingOverrides.associateBy { it.name } - fun findStatFormatting(name: String) = - formattingOverrides[name] ?: StatFormatting(name, "", Formatting.GREEN) - - private val statLabelRegex = "(?<statName>.*): ".toPattern() - private fun parseStatLine(line: Text): StatLine? { - val sibs = line.siblings - val stat = sibs.firstOrNull() ?: return null - if (stat.style.color != TextColor.fromFormatting(Formatting.GRAY)) return null - val statLabel = stat.directLiteralStringContent ?: return null - val statName = statLabelRegex.useMatch(statLabel) { group("statName") } ?: return null - return StatLine(findStatFormatting(statName), - sibs[1]?.directLiteralStringContent?.trim(' ', 's', '%', '+')?.toDoubleOrNull() ?: 0.0, - sibs.subList(2, sibs.size)) - } - - } - - data class StatLine( - val stat: StatFormatting, - val value: Double, - val modifiers: List<Text> = listOf(), - val loreIndex: Int = -1, - ) { - fun formatValue() = - Text.literal(FirmFormatters.formatCommas( - value, 1, includeSign = true) + stat.postFix + " ") - .setStyle(Style.EMPTY.withColor(stat.color)) - - val statName get() = stat.name - fun reconstitute(abbreviateTo: Int = Int.MAX_VALUE): Text = - Text.literal("").setStyle(Style.EMPTY.withItalic(false)) - .append(Text.literal("${abbreviate(abbreviateTo)}: ").grey()) - .append(formatValue()) - .also { modifiers.forEach(it::append) } - - fun addStat(amount: Double, buffKind: BuffKind): StatLine { - val formattedAmount = FirmFormatters.formatCommas(amount, 1, includeSign = true) - return copy( - value = value + amount, - modifiers = modifiers + - if (buffKind.isHidden) emptyList() - else listOf( - Text.literal( - buffKind.prefix + formattedAmount + - stat.postFix + - buffKind.postFix + " ") - .withColor(buffKind.color))) - } - - private fun abbreviate(abbreviateTo: Int): String { - if (abbreviateTo >= statName.length) return statName - val segments = statName.split(" ") - return segments.joinToString(" ") { - it.substring(0, maxOf(1, abbreviateTo / segments.size)) - } - } - } -} diff --git a/src/main/kotlin/util/skyblock/stats/BuffKind.kt b/src/main/kotlin/util/skyblock/stats/BuffKind.kt new file mode 100644 index 0000000..c0b45c4 --- /dev/null +++ b/src/main/kotlin/util/skyblock/stats/BuffKind.kt @@ -0,0 +1,15 @@ +package moe.nea.firmament.util.skyblock.stats + +import net.minecraft.util.Formatting + +enum class BuffKind( + val color: Formatting, + val prefix: String, + val postFix: String, + val isHidden: Boolean, +) { + REFORGE(Formatting.BLUE, "(", ")", false), + STAR_BUFF(Formatting.RESET, "", "", true), + CATA_STAR_BUFF(Formatting.DARK_GRAY, "(", ")", false), + ; +} diff --git a/src/main/kotlin/util/skyblock/stats/StatBlock.kt b/src/main/kotlin/util/skyblock/stats/StatBlock.kt new file mode 100644 index 0000000..3865e79 --- /dev/null +++ b/src/main/kotlin/util/skyblock/stats/StatBlock.kt @@ -0,0 +1,61 @@ +package moe.nea.firmament.util.skyblock.stats + +import util.skyblock.stats.StatFormatting +import moe.nea.firmament.util.directLiteralStringContent +import moe.nea.firmament.util.useMatch +import net.minecraft.text.Text +import net.minecraft.text.TextColor +import net.minecraft.util.Formatting + +data class StatBlock( + val indexedByName: Map<String, StatLine>, + val startIndex: Int, + val endIndex: Int, + private val modifiedLines: MutableMap<String, StatLine> = mutableMapOf() +) { + + /** + * Note that the returned stat line must be created by copying from the original stat line (to keep indexes in sync). + */ + fun modify(statName: String, mod: (StatLine) -> StatLine) { + val existing = + modifiedLines[statName] ?: indexedByName[statName] + ?: StatLine(StatFormatting.findForName(statName), 0.0) + modifiedLines[statName] = mod(existing) + } + + fun applyModifications(lore: MutableList<Text>) { + if (modifiedLines.isEmpty()) return + var nextAppendIndex = endIndex + if (startIndex < 0) // No existing stat block, insert the after space. + lore.add(0, Text.literal("")) + modifiedLines.values.forEach { line -> + val loreLine = if (line.loreIndex < 0) { + lore.add(nextAppendIndex, Text.literal("")) + nextAppendIndex++ + } else line.loreIndex + lore[loreLine] = line.reconstitute() + } + } + + companion object { + fun fromLore(lore: List<Text>): StatBlock { + val map = mutableMapOf<String, StatLine>() + var start = -1 + var end = 0 + for ((index, text) in lore.withIndex()) { + val statLine = StatLine.fromLoreLine(text) + ?.copy(loreIndex = index) + if (statLine == null) { + if (start < 0) continue + else break + } + map[statLine.statName] = statLine + if (start < 0) + start = index + end = index + 1 + } + return StatBlock(map, start, end) + } + } +} diff --git a/src/main/kotlin/util/skyblock/stats/StatFormatting.kt b/src/main/kotlin/util/skyblock/stats/StatFormatting.kt new file mode 100644 index 0000000..28a329e --- /dev/null +++ b/src/main/kotlin/util/skyblock/stats/StatFormatting.kt @@ -0,0 +1,63 @@ +package util.skyblock.stats + +import net.minecraft.util.Formatting + +data class StatFormatting( + val name: String, + val postFix: String, + val color: Formatting, + val isStarAffected: Boolean = true, +) { + companion object { + fun statIdToName(statId: String): String { + val segments = statId.split("_") + return segments.joinToString(" ") { it.replaceFirstChar { it.uppercaseChar() } } + } + fun findForName(name: String) = + formattingOverrides[name] ?: StatFormatting(name, "", Formatting.GREEN) + + fun findForId(id: String) = findForName(statIdToName(id)) + + val allFormattingOverrides = listOf( + StatFormatting("Sea Creature Chance", "%", Formatting.RED), + StatFormatting("Strength", "", Formatting.RED), + StatFormatting("Damage", "", Formatting.RED), + StatFormatting("Bonus Attack Speed", "%", Formatting.RED), + StatFormatting("Shot Cooldown", "s", Formatting.GREEN, false), + StatFormatting("Ability Damage", "%", Formatting.RED), + StatFormatting("Crit Damage", "%", Formatting.RED), + StatFormatting("Crit Chance", "%", Formatting.RED), + StatFormatting("Ability Damage", "%", Formatting.RED), + StatFormatting("Trophy Fish Chance", "%", Formatting.GREEN), + StatFormatting("Health", "", Formatting.GREEN), + StatFormatting("Defense", "", Formatting.GREEN), + StatFormatting("Fishing Speed", "", Formatting.GREEN), + StatFormatting("Double Hook Chance", "%", Formatting.GREEN), + StatFormatting("Mining Speed", "", Formatting.GREEN), + StatFormatting("Mining Fortune", "", Formatting.GREEN), + StatFormatting("Heat Resistance", "", Formatting.GREEN), + StatFormatting("Swing Range", "", Formatting.GREEN), + StatFormatting("Rift Time", "", Formatting.GREEN), + StatFormatting("Speed", "", Formatting.GREEN), + StatFormatting("Farming Fortune", "", Formatting.GREEN), + StatFormatting("True Defense", "", Formatting.GREEN), + StatFormatting("Mending", "", Formatting.GREEN), + StatFormatting("Foraging Wisdom", "", Formatting.GREEN), + StatFormatting("Farming Wisdom", "", Formatting.GREEN), + StatFormatting("Foraging Fortune", "", Formatting.GREEN), + StatFormatting("Magic Find", "", Formatting.GREEN), + StatFormatting("Ferocity", "", Formatting.GREEN), + StatFormatting("Bonus Pest Chance", "%", Formatting.GREEN), + StatFormatting("Cold Resistance", "", Formatting.GREEN), + StatFormatting("Pet Luck", "", Formatting.GREEN), + StatFormatting("Fear", "", Formatting.GREEN), + StatFormatting("Mana Regen", "%", Formatting.GREEN), + StatFormatting("Rift Damage", "", Formatting.GREEN), + StatFormatting("Hearts", "", Formatting.GREEN), + StatFormatting("Vitality", "", Formatting.GREEN), + // TODO: make this a repo json + ) + val formattingOverrides = allFormattingOverrides.associateBy { it.name } + + } +} diff --git a/src/main/kotlin/util/skyblock/stats/StatLine.kt b/src/main/kotlin/util/skyblock/stats/StatLine.kt new file mode 100644 index 0000000..5a1c236 --- /dev/null +++ b/src/main/kotlin/util/skyblock/stats/StatLine.kt @@ -0,0 +1,71 @@ +package moe.nea.firmament.util.skyblock.stats + +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.grey +import moe.nea.firmament.util.withColor +import net.minecraft.text.Style +import net.minecraft.text.Text +import util.skyblock.stats.StatFormatting +import net.minecraft.text.TextColor +import net.minecraft.util.Formatting +import moe.nea.firmament.util.directLiteralStringContent +import moe.nea.firmament.util.useMatch + +data class StatLine( + val stat: StatFormatting, + val value: Double, + val modifiers: List<Text> = listOf(), + val loreIndex: Int = -1, +) { + val statName get() = stat.name + + fun formatValue() = + Text.literal( + FirmFormatters.formatCommas(value, 1, includeSign = true) + stat.postFix + " " + ).setStyle(Style.EMPTY.withColor(stat.color)) + + fun reconstitute(abbreviateTo: Int = Int.MAX_VALUE): Text = + Text.literal("").setStyle(Style.EMPTY.withItalic(false)) + .append(Text.literal("${abbreviate(abbreviateTo)}: ").grey()) + .append(formatValue()) + .also { modifiers.forEach(it::append) } + + /* + TODO: fix up the formatting of these + Expected: StatBlock(indexedByName={Speed=StatLine(stat=StatFormatting(name=Speed, postFix=, color=§a, isStarAffected=true), value=5.0, modifiers=[literal{(+5)}[style={color=blue}]], loreIndex=0), Foraging Wisdom=StatLine(stat=StatFormatting(name=Foraging Wisdom, postFix=, color=§a, isStarAffected=true), value=1.5, modifiers=[literal{(+1.5)}[style={color=blue}]], loreIndex=1)}, startIndex=0, endIndex=2, modifiedLines={}) + Actual : StatBlock(indexedByName={Speed=StatLine(stat=StatFormatting(name=Speed, postFix=, color=§a, isStarAffected=true), value=5.0, modifiers=[literal{(+5) }[style={color=blue,!bold,!italic}]], loreIndex=0), Foraging Wisdom=StatLine(stat=StatFormatting(name=Foraging Wisdom, postFix=, color=§a, isStarAffected=true), value=1.2, modifiers=[literal{(+1.2) }[style={color=blue,!bold,!italic}]], loreIndex=1)}, startIndex=0, endIndex=2, modifiedLines={})*/ + fun addStat(amount: Double, buffKind: BuffKind): StatLine { + val formattedAmount = FirmFormatters.formatCommas(amount, 1, includeSign = true) + val modifierText = Text.literal( + buffKind.prefix + formattedAmount + stat.postFix + buffKind.postFix + " ") + .withColor(buffKind.color) + return copy( + value = value + amount, + modifiers = modifiers + + if (buffKind.isHidden) emptyList() + else listOf(modifierText)) + } + + private fun abbreviate(abbreviateTo: Int): String { + if (abbreviateTo >= statName.length) return statName + val segments = statName.split(" ") + return segments.joinToString(" ") { + it.substring(0, maxOf(1, abbreviateTo / segments.size)) + } + } + + companion object { + private val statLabelRegex = "(?<statName>.*): ".toPattern() + fun fromLoreLine(line: Text): StatLine? { + val sibs = line.siblings + if (sibs.size < 2) return null + val stat = sibs.first() ?: return null + if (stat.style.color != TextColor.fromFormatting(Formatting.GRAY)) return null + val statLabel = stat.directLiteralStringContent ?: return null + val statName = statLabelRegex.useMatch(statLabel) { group("statName") } ?: return null + return StatLine(StatFormatting.findForName(statName), + sibs[1]?.directLiteralStringContent?.trim(' ', 's', '%', '+')?.toDoubleOrNull() ?: 0.0, + sibs.subList(2, sibs.size)) + } + } +} |