WIP: Reforge Recipes
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
10
src/main/kotlin/util/AprilFoolsUtil.kt
Normal file
10
src/main/kotlin/util/AprilFoolsUtil.kt
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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))
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user