diff options
author | Linnea Gräf <nea@nea.moe> | 2024-12-25 16:15:20 +0100 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2024-12-25 16:15:20 +0100 |
commit | ddebaf47900dfab41590c97c202984142ae5b9f6 (patch) | |
tree | 498859e320b19d3bc7559f5585174afb78e132b4 | |
parent | e16c60169bf192b79991176b5f9cee66b5b16e7d (diff) | |
download | Firmament-ddebaf47900dfab41590c97c202984142ae5b9f6.tar.gz Firmament-ddebaf47900dfab41590c97c202984142ae5b9f6.tar.bz2 Firmament-ddebaf47900dfab41590c97c202984142ae5b9f6.zip |
WIP: Reforge Recipes
-rw-r--r-- | src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt | 34 | ||||
-rw-r--r-- | src/compat/rei/java/moe/nea/firmament/compat/rei/recipes/SBReforgeRecipe.kt | 52 | ||||
-rw-r--r-- | src/main/kotlin/features/inventory/ItemRarityCosmetics.kt | 13 | ||||
-rw-r--r-- | src/main/kotlin/gui/entity/EntityRenderer.kt | 13 | ||||
-rw-r--r-- | src/main/kotlin/repo/ItemCache.kt | 2 | ||||
-rw-r--r-- | src/main/kotlin/repo/Reforge.kt | 14 | ||||
-rw-r--r-- | src/main/kotlin/repo/SBItemStack.kt | 136 | ||||
-rw-r--r-- | src/main/kotlin/util/AprilFoolsUtil.kt | 10 | ||||
-rw-r--r-- | src/main/kotlin/util/FirmFormatters.kt | 14 | ||||
-rw-r--r-- | src/main/kotlin/util/SkyblockId.kt | 5 | ||||
-rw-r--r-- | src/main/kotlin/util/mc/NbtItemData.kt | 4 | ||||
-rw-r--r-- | src/main/kotlin/util/skyblock/Rarity.kt | 17 | ||||
-rw-r--r-- | src/main/kotlin/util/skyblock/SkyBlockItems.kt | 1 | ||||
-rw-r--r-- | src/main/kotlin/util/textutil.kt | 6 |
14 files changed, 273 insertions, 48 deletions
diff --git a/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt b/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt index d8238be..2b9e4bf 100644 --- a/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt +++ b/src/compat/rei/java/moe/nea/firmament/compat/rei/EntityWidget.kt @@ -1,19 +1,22 @@ package moe.nea.firmament.compat.rei import me.shedaniel.math.Dimension +import me.shedaniel.math.FloatingDimension import me.shedaniel.math.Point import me.shedaniel.math.Rectangle import me.shedaniel.rei.api.client.gui.widgets.WidgetWithBounds import net.minecraft.client.gui.DrawContext -import net.minecraft.client.gui.Drawable import net.minecraft.client.gui.Element -import net.minecraft.client.gui.ParentElement import net.minecraft.entity.LivingEntity import moe.nea.firmament.gui.entity.EntityRenderer import moe.nea.firmament.util.ErrorUtil -class EntityWidget(val entity: LivingEntity?, val point: Point) : WidgetWithBounds() { +class EntityWidget( + val entity: LivingEntity?, + val point: Point, + val size: FloatingDimension = FloatingDimension(defaultSize) +) : WidgetWithBounds() { override fun children(): List<Element> { return emptyList() } @@ -22,18 +25,35 @@ class EntityWidget(val entity: LivingEntity?, val point: Point) : WidgetWithBoun override fun render(context: DrawContext, mouseX: Int, mouseY: Int, delta: Float) { try { - if (!hasErrored) - EntityRenderer.renderEntity(entity!!, context, point.x, point.y, mouseX.toFloat(), mouseY.toFloat()) + context.matrices.push() + if (!hasErrored) { + context.matrices.translate(point.x.toDouble(), point.y.toDouble(), 0.0) + val xScale = size.width / defaultSize.width.toDouble() + val yScale = size.height / defaultSize.height.toDouble() + context.matrices.scale(xScale.toFloat(), yScale.toFloat(), 1.0F) + EntityRenderer.renderEntity( + entity!!, + context, + 0, 0, + (mouseX - point.x) * xScale, + (mouseY - point.y) * yScale) + } } catch (ex: Exception) { ErrorUtil.softError("Failed to render constructed entity: $entity", ex) hasErrored = true + } finally { + context.matrices.pop() } if (hasErrored) { - context.fill(point.x, point.y, point.x + 50, point.y + 80, 0xFFAA2222.toInt()) + context.fill(point.x, point.y, point.x + size.width.toInt(), point.y + size.height.toInt(), 0xFFAA2222.toInt()) } } + companion object { + val defaultSize = Dimension(50, 80) + } + override fun getBounds(): Rectangle { - return Rectangle(point, Dimension(50, 80)) + return Rectangle(point, size) } } 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 2805132..232f04f 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 @@ -1,6 +1,8 @@ package moe.nea.firmament.compat.rei.recipes import java.util.Optional +import me.shedaniel.math.Dimension +import me.shedaniel.math.FloatingDimension import me.shedaniel.math.Point import me.shedaniel.math.Rectangle import me.shedaniel.rei.api.client.gui.Renderer @@ -14,17 +16,27 @@ 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 net.minecraft.entity.EntityType +import net.minecraft.entity.SpawnReason import net.minecraft.text.Text import net.minecraft.util.Identifier +import net.minecraft.village.VillagerProfession import moe.nea.firmament.Firmament +import moe.nea.firmament.compat.rei.EntityWidget import moe.nea.firmament.compat.rei.SBItemEntryDefinition +import moe.nea.firmament.gui.entity.EntityRenderer import moe.nea.firmament.repo.Reforge 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.util.AprilFoolsUtil +import moe.nea.firmament.util.FirmFormatters import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.gold 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.skyblockId import moe.nea.firmament.util.tr @@ -46,21 +58,44 @@ class SBReforgeRecipe( } override fun getIcon(): Renderer { - return SBItemEntryDefinition.getEntry(SkyblockId("REFORGE_ANVIL")) + return SBItemEntryDefinition.getEntry(SkyBlockItems.REFORGE_ANVIL) } override fun setupDisplay(display: SBReforgeRecipe, bounds: Rectangle): MutableList<Widget> { val list = mutableListOf<Widget>() list.add(Widgets.createRecipeBase(bounds)) // TODO: actual layout after christmas, probably - list.add(Widgets.createSlot(Point(bounds.minX + 10, bounds.centerY)) + list.add(Widgets.createSlot(Point(bounds.minX + 10, bounds.centerY - 9)) .markInput().entries(display.inputItems)) - val stoneSlot = Widgets.createSlot(Point(bounds.minX + 38, bounds.centerY)) - .markInput() - if (display.reforgeStone != null) - stoneSlot.entry(display.reforgeStone) - list.add(stoneSlot) - list.add(Widgets.createSlot(Point(bounds.minX + 38 + 18, bounds.centerY)) + if (display.reforgeStone != null) { + list.add(Widgets.createSlot(Point(bounds.minX + 10 + 24, bounds.centerY - 9 - 10)) + .markInput().entry(display.reforgeStone)) + list.add(Widgets.withTooltip( + Widgets.withTranslate(Widgets.wrapRenderer( + Rectangle(Point(bounds.minX + 10 + 24, bounds.centerY - 9 + 10), Dimension(18, 18)), + SBItemEntryDefinition.getEntry(SkyBlockItems.REFORGE_ANVIL)), 0.0, 0.0, 150.0), + Rarity.entries.mapNotNull { rarity -> + display.reforge.reforgeCosts?.get(rarity)?.let { rarity to it } + }.map { (rarity, cost) -> + Text.literal("") + .append(rarity.text) + .append(": ") + .append(Text.literal("${FirmFormatters.formatCommas(cost, 0)} Coins").gold()) + } + )) + } else { + val size = if (AprilFoolsUtil.isAprilFoolsDay) 1.2 else 0.6 + val dimension = + FloatingDimension(EntityWidget.defaultSize.width * size, EntityWidget.defaultSize.height * size) + list.add(EntityWidget( + EntityType.VILLAGER.create(EntityRenderer.fakeWorld, SpawnReason.COMMAND) + ?.also { it.villagerData = it.villagerData.withProfession(VillagerProfession.WEAPONSMITH) }, + Point(bounds.minX + 10 + 24 + 8 - dimension.width / 2, bounds.centerY - dimension.height / 2), + dimension + )) +// TODO: render a blacksmith entity or smth + } + list.add(Widgets.createSlot(Point(bounds.minX + 10 + 24 + 24, bounds.centerY - 9)) .markInput().entries(display.outputItems)) return list } @@ -106,6 +141,7 @@ class SBReforgeRecipe( when (it) { is Reforge.ReforgeEligibilityFilter.AllowsInternalName -> listOfNotNull(RepoManager.getNEUItem(it.internalName)) + is Reforge.ReforgeEligibilityFilter.AllowsItemType -> ReforgeStore.resolveItemType(it.itemType) .flatMap { diff --git a/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt b/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt index d2c555b..fdc378a 100644 --- a/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt +++ b/src/main/kotlin/features/inventory/ItemRarityCosmetics.kt @@ -29,18 +29,7 @@ object ItemRarityCosmetics : FirmamentFeature { override val config: ManagedConfig get() = TConfig - private val rarityToColor = mapOf( - Rarity.COMMON to Formatting.WHITE, - Rarity.UNCOMMON to Formatting.GREEN, - Rarity.RARE to Formatting.BLUE, - Rarity.EPIC to Formatting.DARK_PURPLE, - Rarity.LEGENDARY to Formatting.GOLD, - Rarity.MYTHIC to Formatting.LIGHT_PURPLE, - Rarity.DIVINE to Formatting.AQUA, - Rarity.SPECIAL to Formatting.RED, - Rarity.VERY_SPECIAL to Formatting.RED, - Rarity.SUPREME to Formatting.DARK_RED, - ).mapValues { + private val rarityToColor = Rarity.colourMap.mapValues { val c = Color(it.value.colorValue!!) c.rgb } diff --git a/src/main/kotlin/gui/entity/EntityRenderer.kt b/src/main/kotlin/gui/entity/EntityRenderer.kt index 022b9a3..9a09fc6 100644 --- a/src/main/kotlin/gui/entity/EntityRenderer.kt +++ b/src/main/kotlin/gui/entity/EntityRenderer.kt @@ -111,8 +111,9 @@ object EntityRenderer { renderContext: DrawContext, posX: Int, posY: Int, - mouseX: Float, - mouseY: Float + // TODO: Add width, height properties here + mouseX: Double, + mouseY: Double ) { var bottomOffset = 0.0F var currentEntity = entity @@ -148,15 +149,15 @@ object EntityRenderer { y2: Int, size: Float, bottomOffset: Float, - mouseX: Float, - mouseY: Float, + mouseX: Double, + mouseY: Double, entity: LivingEntity ) { context.enableScissorWithTranslation(x1.toFloat(), y1.toFloat(), x2.toFloat(), y2.toFloat()) val centerX = (x1 + x2) / 2f val centerY = (y1 + y2) / 2f - val targetYaw = atan(((centerX - mouseX) / 40.0f).toDouble()).toFloat() - val targetPitch = atan(((centerY - mouseY) / 40.0f).toDouble()).toFloat() + val targetYaw = atan(((centerX - mouseX) / 40.0f)).toFloat() + val targetPitch = atan(((centerY - mouseY) / 40.0f)).toFloat() val rotateToFaceTheFront = Quaternionf().rotateZ(Math.PI.toFloat()) val rotateToFaceTheCamera = Quaternionf().rotateX(targetPitch * 20.0f * (Math.PI.toFloat() / 180)) rotateToFaceTheFront.mul(rotateToFaceTheCamera) diff --git a/src/main/kotlin/repo/ItemCache.kt b/src/main/kotlin/repo/ItemCache.kt index f88dd48..9f1d45c 100644 --- a/src/main/kotlin/repo/ItemCache.kt +++ b/src/main/kotlin/repo/ItemCache.kt @@ -39,6 +39,7 @@ import moe.nea.firmament.util.TestUtil import moe.nea.firmament.util.directLiteralStringContent import moe.nea.firmament.util.mc.FirmamentDataComponentTypes import moe.nea.firmament.util.mc.appendLore +import moe.nea.firmament.util.mc.displayNameAccordingToNbt import moe.nea.firmament.util.mc.loreAccordingToNbt import moe.nea.firmament.util.mc.modifyLore import moe.nea.firmament.util.mc.setCustomName @@ -131,6 +132,7 @@ object ItemCache : IReloadable { val itemInstance = ItemStack.fromNbt(MC.defaultRegistries, modernItemTag).getOrNull() ?: return brokenItemStack(this) itemInstance.loreAccordingToNbt = lore.map { un189Lore(it) } + itemInstance.displayNameAccordingToNbt = un189Lore(displayName) val extraAttributes = oldItemTag.getCompound("tag").getCompound("ExtraAttributes") if (extraAttributes != null) itemInstance.set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(extraAttributes)) diff --git a/src/main/kotlin/repo/Reforge.kt b/src/main/kotlin/repo/Reforge.kt index ea01818..b52adc6 100644 --- a/src/main/kotlin/repo/Reforge.kt +++ b/src/main/kotlin/repo/Reforge.kt @@ -108,6 +108,8 @@ data class Reforge( @Serializable(with = RarityMapped.Serializer::class) sealed interface RarityMapped<T> { + fun get(rarity: Rarity): T? + class Serializer<T>( val values: KSerializer<T> ) : KSerializer<RarityMapped<T>> { @@ -137,10 +139,18 @@ data class Reforge( } @Serializable - data class Direct<T>(val value: T) : RarityMapped<T> + data class Direct<T>(val value: T) : RarityMapped<T> { + override fun get(rarity: Rarity): T { + return value + } + } @Serializable - data class PerRarity<T>(val values: Map<Rarity, T>) : RarityMapped<T> + data class PerRarity<T>(val values: Map<Rarity, T>) : RarityMapped<T> { + override fun get(rarity: Rarity): T? { + return values[rarity] + } + } } } diff --git a/src/main/kotlin/repo/SBItemStack.kt b/src/main/kotlin/repo/SBItemStack.kt index e5cacaa..a5f54ae 100644 --- a/src/main/kotlin/repo/SBItemStack.kt +++ b/src/main/kotlin/repo/SBItemStack.kt @@ -9,22 +9,31 @@ import net.minecraft.item.ItemStack import net.minecraft.network.RegistryByteBuf import net.minecraft.network.codec.PacketCodec import net.minecraft.network.codec.PacketCodecs +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.ItemCache.asItemStack import moe.nea.firmament.util.FirmFormatters import moe.nea.firmament.util.LegacyFormattingCode import moe.nea.firmament.util.ReforgeId import moe.nea.firmament.util.SkyblockId +import moe.nea.firmament.util.blue +import moe.nea.firmament.util.directLiteralStringContent +import moe.nea.firmament.util.extraAttributes import moe.nea.firmament.util.getReforgeId import moe.nea.firmament.util.getUpgradeStars +import moe.nea.firmament.util.grey import moe.nea.firmament.util.mc.appendLore import moe.nea.firmament.util.mc.displayNameAccordingToNbt import moe.nea.firmament.util.mc.loreAccordingToNbt import moe.nea.firmament.util.petData +import moe.nea.firmament.util.prepend 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.skyblockId +import moe.nea.firmament.util.useMatch import moe.nea.firmament.util.withColor data class SBItemStack constructor( @@ -84,6 +93,117 @@ data class SBItemStack constructor( } return SBItemStack(neuIngredient.skyblockId, neuIngredient.amount.toInt()) } + + fun appendEnhancedStats( + itemStack: ItemStack, + reforgeStats: Map<String, Double>, + buffKind: BuffKind, + ) { + val namedReforgeStats = reforgeStats + .mapKeysTo(mutableMapOf()) { statIdToName(it.key) } + val loreMut = itemStack.loreAccordingToNbt.toMutableList() + var statBlockLastIndex = -1 + for (i in loreMut.indices) { + val statLine = parseStatLine(loreMut[i]) + if (statLine == null && statBlockLastIndex >= 0) { + break + } + if (statLine == null) { + continue + } + statBlockLastIndex = i + val statBuff = namedReforgeStats.remove(statLine.statName) ?: continue + loreMut[i] = statLine.addStat(statBuff, buffKind).reconstitute() + } + if (namedReforgeStats.isNotEmpty() && statBlockLastIndex == -1) { + loreMut.add(0, Text.literal("")) + } + // If there is no stat block the statBlockLastIndex falls through to -1 + // TODO: this is good enough for some items. some other items might have their stats at a different place. + for ((statName, statBuff) in namedReforgeStats) { + val statLine = StatLine(statName, null).addStat(statBuff, buffKind) + loreMut.add(statBlockLastIndex + 1, statLine.reconstitute()) + } + itemStack.loreAccordingToNbt = loreMut + } + + data class StatFormatting( + val postFix: String, + val color: Formatting, + ) + + val formattingOverrides = mapOf( + "Sea Creature Chance" to StatFormatting("%", Formatting.RED), + "Strength" to StatFormatting("", Formatting.RED), + "Damage" to StatFormatting("", Formatting.RED), + "Bonus Attack Speed" to StatFormatting("%", Formatting.RED), + "Shot Cooldown" to StatFormatting("s", Formatting.RED), + "Ability Damage" to StatFormatting("%", Formatting.RED), + "Crit Damage" to StatFormatting("%", Formatting.RED), + "Crit Chance" to StatFormatting("%", Formatting.RED), + "Trophy Fish Chance" to StatFormatting("%", Formatting.GREEN), + // TODO: add other types and make this a repo json + ) + + + private val statLabelRegex = "(?<statName>.*): ".toPattern() + + enum class BuffKind( + val color: Formatting, + val prefix: String, + val postFix: String, + ) { + REFORGE(Formatting.BLUE, "(", ")"), + + ; + } + + data class StatLine( + val statName: String, + val value: Text?, + val rest: List<Text> = listOf(), + val valueNum: Double? = value?.directLiteralStringContent?.trim(' ', '%', '+')?.toDoubleOrNull() + ) { + fun addStat(amount: Double, buffKind: BuffKind): StatLine { + val formattedAmount = FirmFormatters.formatCommas(amount, 1, includeSign = true) + return copy( + valueNum = (valueNum ?: 0.0) + amount, + value = null, + rest = rest + + listOf( + Text.literal( + buffKind.prefix + formattedAmount + + statFormatting.postFix + + buffKind.postFix + " ") + .withColor(buffKind.color))) + } + + fun formatValue() = + Text.literal(FirmFormatters.formatCommas(valueNum ?: 0.0, 1, includeSign = true) + statFormatting.postFix + " ") + .setStyle(Style.EMPTY.withColor(statFormatting.color)) + + val statFormatting = formattingOverrides[statName] ?: StatFormatting("", Formatting.GREEN) + fun reconstitute(): Text = + Text.literal("").setStyle(Style.EMPTY.withItalic(false)) + .append(Text.literal("$statName: ").grey()) + .append(value ?: formatValue()) + .also { rest.forEach(it::append) } + } + + private fun statIdToName(statId: String): String { + return statId.split("_").joinToString(" ") { + it.replaceFirstChar { it.uppercaseChar() } + } + } + + 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(statName, sibs[1], sibs.subList(2, sibs.size)) + } } constructor(skyblockId: SkyblockId, petData: PetData) : this( @@ -134,11 +254,19 @@ data class SBItemStack constructor( } - private fun appendReforgeStatsToLore( + private fun appendReforgeInfo( itemStack: ItemStack, ) { - val rarity = itemStack.rarity - val lore = itemStack.loreAccordingToNbt + val rarity = Rarity.fromItem(itemStack) ?: return + val reforgeId = this.reforge ?: return + val reforge = ReforgeStore.modifierLut[reforgeId] ?: return + val reforgeStats = reforge.reforgeStats?.get(rarity) ?: mapOf() + itemStack.displayNameAccordingToNbt = itemStack.displayNameAccordingToNbt.copy() + .prepend(Text.literal(reforge.reforgeName + " ").formatted(Rarity.colourMap[rarity] ?: Formatting.WHITE)) + val data = itemStack.extraAttributes.copy() + data.putString("modifier", reforgeId.id) + itemStack.extraAttributes = data + appendEnhancedStats(itemStack, reforgeStats, BuffKind.REFORGE) } // TODO: avoid instantiating the item stack here @@ -156,8 +284,8 @@ data class SBItemStack constructor( injectReplacementDataForPets(replacementData) return@run neuItem.asItemStack(idHint = skyblockId, replacementData) .copyWithCount(stackSize) + .also { appendReforgeInfo(it) } .also { it.appendLore(extraLore) } - .also { if (reforge != null) it.appendLore(listOf(Text.literal("Reforge: $reforge"))) } // TODO: use this for proper rendering .also { enhanceStatsByStars(it, stars) } } if (itemStack_ == null) diff --git a/src/main/kotlin/util/AprilFoolsUtil.kt b/src/main/kotlin/util/AprilFoolsUtil.kt new file mode 100644 index 0000000..a940fa1 --- /dev/null +++ b/src/main/kotlin/util/AprilFoolsUtil.kt @@ -0,0 +1,10 @@ +package moe.nea.firmament.util + +import java.time.LocalDateTime +import java.time.Month + +object AprilFoolsUtil { + val isAprilFoolsDay = LocalDateTime.now().let { + it.dayOfMonth == 1 && it.month == Month.APRIL + } +} diff --git a/src/main/kotlin/util/FirmFormatters.kt b/src/main/kotlin/util/FirmFormatters.kt index 92fb9e5..4b32c2a 100644 --- a/src/main/kotlin/util/FirmFormatters.kt +++ b/src/main/kotlin/util/FirmFormatters.kt @@ -15,21 +15,25 @@ import net.minecraft.text.Text object FirmFormatters { fun formatCommas(int: Int, segments: Int = 3): String = formatCommas(int.toLong(), segments) - fun formatCommas(long: Long, segments: Int = 3): String { + fun formatCommas(long: Long, segments: Int = 3, includeSign: Boolean = false): String { + if (long < 0 && long != Long.MIN_VALUE) { + return "-" + formatCommas(-long, segments, false) + } + val prefix = if (includeSign) "+" else "" val α = long / 1000 if (α != 0L) { - return formatCommas(α, segments) + "," + (long - α * 1000).toString().padStart(3, '0') + return prefix + formatCommas(α, segments) + "," + (long - α * 1000).toString().padStart(3, '0') } - return long.toString() + return prefix + long.toString() } fun formatCommas(float: Float, fractionalDigits: Int): String = formatCommas(float.toDouble(), fractionalDigits) - fun formatCommas(double: Double, fractionalDigits: Int): String { + fun formatCommas(double: Double, fractionalDigits: Int, includeSign: Boolean = false): String { val long = double.toLong() val δ = (double - long).absoluteValue val μ = pow(10, fractionalDigits) val digits = (μ * δ).toInt().toString().padStart(fractionalDigits, '0').trimEnd('0') - return formatCommas(long) + (if (digits.isEmpty()) "" else ".$digits") + return formatCommas(long, includeSign = includeSign) + (if (digits.isEmpty()) "" else ".$digits") } fun formatDistance(distance: Double): String { diff --git a/src/main/kotlin/util/SkyblockId.kt b/src/main/kotlin/util/SkyblockId.kt index 497a2d2..631b444 100644 --- a/src/main/kotlin/util/SkyblockId.kt +++ b/src/main/kotlin/util/SkyblockId.kt @@ -106,7 +106,10 @@ data class HypixelPetInfo( private val jsonparser = Json { ignoreUnknownKeys = true } -val ItemStack.extraAttributes: NbtCompound +var ItemStack.extraAttributes: NbtCompound + set(value) { + set(DataComponentTypes.CUSTOM_DATA, NbtComponent.of(value)) + } get() { val customData = get(DataComponentTypes.CUSTOM_DATA) ?: run { val component = NbtComponent.of(NbtCompound()) diff --git a/src/main/kotlin/util/mc/NbtItemData.kt b/src/main/kotlin/util/mc/NbtItemData.kt index e8a908f..0c49862 100644 --- a/src/main/kotlin/util/mc/NbtItemData.kt +++ b/src/main/kotlin/util/mc/NbtItemData.kt @@ -5,8 +5,8 @@ import net.minecraft.component.type.LoreComponent import net.minecraft.item.ItemStack import net.minecraft.text.Text -var ItemStack.loreAccordingToNbt - get() = get(DataComponentTypes.LORE)?.lines ?: listOf() +var ItemStack.loreAccordingToNbt: List<Text> + get() = get(DataComponentTypes.LORE)?.lines ?: listOf() set(value) { set(DataComponentTypes.LORE, LoreComponent(value)) } diff --git a/src/main/kotlin/util/skyblock/Rarity.kt b/src/main/kotlin/util/skyblock/Rarity.kt index 0244630..b19f371 100644 --- a/src/main/kotlin/util/skyblock/Rarity.kt +++ b/src/main/kotlin/util/skyblock/Rarity.kt @@ -8,7 +8,9 @@ import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import net.minecraft.item.ItemStack +import net.minecraft.text.Style import net.minecraft.text.Text +import net.minecraft.util.Formatting import moe.nea.firmament.util.StringUtil.words import moe.nea.firmament.util.collections.lastNotNullOfOrNull import moe.nea.firmament.util.mc.loreAccordingToNbt @@ -46,10 +48,23 @@ enum class Rarity(vararg altNames: String) { } val names = setOf(name) + altNames - + val text: Text get() = Text.literal(name).setStyle(Style.EMPTY.withColor(colourMap[this])) val neuRepoRarity: RepoRarity? = RepoRarity.entries.find { it.name == name } companion object { + // TODO: inline those formattings as fields + val colourMap = mapOf( + Rarity.COMMON to Formatting.WHITE, + Rarity.UNCOMMON to Formatting.GREEN, + Rarity.RARE to Formatting.BLUE, + Rarity.EPIC to Formatting.DARK_PURPLE, + Rarity.LEGENDARY to Formatting.GOLD, + Rarity.MYTHIC to Formatting.LIGHT_PURPLE, + Rarity.DIVINE to Formatting.AQUA, + Rarity.SPECIAL to Formatting.RED, + Rarity.VERY_SPECIAL to Formatting.RED, + Rarity.SUPREME to Formatting.DARK_RED, + ) val byName = entries.flatMap { en -> en.names.map { it to en } }.toMap() val fromNeuRepo = entries.associateBy { it.neuRepoRarity } diff --git a/src/main/kotlin/util/skyblock/SkyBlockItems.kt b/src/main/kotlin/util/skyblock/SkyBlockItems.kt index c94ebfe..cfd8429 100644 --- a/src/main/kotlin/util/skyblock/SkyBlockItems.kt +++ b/src/main/kotlin/util/skyblock/SkyBlockItems.kt @@ -7,4 +7,5 @@ object SkyBlockItems { val ENCHANTED_DIAMOND = SkyblockId("ENCHANTED_DIAMOND") val DIAMOND = SkyblockId("DIAMOND") val ANCESTRAL_SPADE = SkyblockId("ANCESTRAL_SPADE") + val REFORGE_ANVIL = SkyblockId("REFORGE_ANVIL") } diff --git a/src/main/kotlin/util/textutil.kt b/src/main/kotlin/util/textutil.kt index 06ed8c8..ab3de43 100644 --- a/src/main/kotlin/util/textutil.kt +++ b/src/main/kotlin/util/textutil.kt @@ -133,6 +133,7 @@ fun MutableText.darkGreen() = withColor(Formatting.DARK_GREEN) fun MutableText.purple() = withColor(Formatting.DARK_PURPLE) fun MutableText.pink() = withColor(Formatting.LIGHT_PURPLE) fun MutableText.yellow() = withColor(Formatting.YELLOW) +fun MutableText.gold() = withColor(Formatting.GOLD) fun MutableText.grey() = withColor(Formatting.GRAY) fun MutableText.red() = withColor(Formatting.RED) fun MutableText.white() = withColor(Formatting.WHITE) @@ -146,6 +147,11 @@ fun MutableText.clickCommand(command: String): MutableText { } } +fun MutableText.prepend(text: Text): MutableText { + siblings.addFirst(text) + return this +} + fun Text.transformEachRecursively(function: (Text) -> Text): Text { val c = this.content if (c is TranslatableTextContent) { |