aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/repo
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-12-25 16:15:20 +0100
committerLinnea Gräf <nea@nea.moe>2024-12-25 16:15:20 +0100
commitddebaf47900dfab41590c97c202984142ae5b9f6 (patch)
tree498859e320b19d3bc7559f5585174afb78e132b4 /src/main/kotlin/repo
parente16c60169bf192b79991176b5f9cee66b5b16e7d (diff)
downloadFirmament-ddebaf47900dfab41590c97c202984142ae5b9f6.tar.gz
Firmament-ddebaf47900dfab41590c97c202984142ae5b9f6.tar.bz2
Firmament-ddebaf47900dfab41590c97c202984142ae5b9f6.zip
WIP: Reforge Recipes
Diffstat (limited to 'src/main/kotlin/repo')
-rw-r--r--src/main/kotlin/repo/ItemCache.kt2
-rw-r--r--src/main/kotlin/repo/Reforge.kt14
-rw-r--r--src/main/kotlin/repo/SBItemStack.kt136
3 files changed, 146 insertions, 6 deletions
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)