WIP: Reforge Recipes

This commit is contained in:
Linnea Gräf
2024-12-25 16:15:20 +01:00
parent e16c60169b
commit ddebaf4790
14 changed files with 273 additions and 48 deletions

View File

@@ -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))

View File

@@ -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]
}
}
}
}

View File

@@ -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)