fix: potion effects in exporter

This commit is contained in:
Linnea Gräf
2025-07-06 00:37:46 +02:00
parent 4140a24a0b
commit 44b817f7b9
5 changed files with 185 additions and 4 deletions

View File

@@ -9,6 +9,7 @@ import moe.nea.firmament.Firmament
import moe.nea.firmament.repo.ExpensiveItemCacheApi import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.ItemCache import moe.nea.firmament.repo.ItemCache
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.StringUtil.camelWords
/** /**
* Load data based on [prismarine.js' 1.8 item data](https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/1.8/items.json) * Load data based on [prismarine.js' 1.8 item data](https://github.com/PrismarineJS/minecraft-data/blob/master/data/pc/1.8/items.json)
@@ -58,6 +59,7 @@ object LegacyItemData {
val enchantmentLut = enchantmentData.associateBy { Identifier.ofVanilla(it.name) } val enchantmentLut = enchantmentData.associateBy { Identifier.ofVanilla(it.name) }
val itemDat = getLegacyData<List<ItemData>>("items") val itemDat = getLegacyData<List<ItemData>>("items")
@OptIn(ExpensiveItemCacheApi::class) // This is fine, we get loaded in a thread. @OptIn(ExpensiveItemCacheApi::class) // This is fine, we get loaded in a thread.
val itemLut = itemDat.flatMap { item -> val itemLut = itemDat.flatMap { item ->
item.allVariants().map { legacyItemType -> item.allVariants().map { legacyItemType ->
@@ -72,4 +74,16 @@ object LegacyItemData {
} }
}.toMap() }.toMap()
@Serializable
data class LegacyEffect(
val id: Int,
val name: String,
val displayName: String,
val type: String
)
val effectList = getLegacyData<List<LegacyEffect>>("effects")
.associateBy {
it.name.camelWords().map { it.trim().lowercase() }.joinToString("_")
}
} }

View File

@@ -7,11 +7,12 @@ import kotlinx.serialization.json.put
import kotlin.concurrent.thread import kotlin.concurrent.thread
import net.minecraft.component.DataComponentTypes import net.minecraft.component.DataComponentTypes
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtByte
import net.minecraft.nbt.NbtCompound import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtElement import net.minecraft.nbt.NbtElement
import net.minecraft.nbt.NbtInt import net.minecraft.nbt.NbtInt
import net.minecraft.nbt.NbtList
import net.minecraft.nbt.NbtOps import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.NbtPrimitive
import net.minecraft.nbt.NbtString import net.minecraft.nbt.NbtString
import net.minecraft.text.Text import net.minecraft.text.Text
import net.minecraft.util.Unit import net.minecraft.util.Unit
@@ -135,6 +136,7 @@ class LegacyItemExporter private constructor(var itemStack: ItemStack) {
legacyNbt.put("HideFlags", NbtInt.of(254)) legacyNbt.put("HideFlags", NbtInt.of(254))
copyUnbreakable() copyUnbreakable()
copyItemModel() copyItemModel()
copyPotion()
copyExtraAttributes() copyExtraAttributes()
copyLegacySkullNbt() copyLegacySkullNbt()
copyDisplay() copyDisplay()
@@ -144,6 +146,24 @@ class LegacyItemExporter private constructor(var itemStack: ItemStack) {
// TODO: copyDisplay // TODO: copyDisplay
} }
private fun copyPotion() {
val effects = itemStack.get(DataComponentTypes.POTION_CONTENTS) ?: return
legacyNbt.put("CustomPotionEffects", NbtList().also {
effects.effects.forEach { effect ->
val effectId = effect.effectType.key.get().value.path
val duration = effect.duration
val legacyId = LegacyItemData.effectList[effectId]!!
it.add(NbtCompound().apply {
put("Ambient", NbtByte.of(false))
put("Duration", NbtInt.of(duration))
put("Id", NbtByte.of(legacyId.id.toByte()))
put("Amplifier", NbtByte.of(effect.amplifier.toByte()))
})
}
})
}
fun NbtCompound.getOrPutCompound(name: String): NbtCompound { fun NbtCompound.getOrPutCompound(name: String): NbtCompound {
val compound = getCompoundOrEmpty(name) val compound = getCompoundOrEmpty(name)
put(name, compound) put(name, compound)

View File

@@ -251,10 +251,11 @@ val ItemStack.skyBlockId: SkyblockId?
val potionName = extraAttributes.getString("potion_name").getOrNull() val potionName = extraAttributes.getString("potion_name").getOrNull()
val potionLevel = extraAttributes.getInt("potion_level").getOrNull() val potionLevel = extraAttributes.getInt("potion_level").getOrNull()
val potionType = extraAttributes.getString("potion_type").getOrNull() val potionType = extraAttributes.getString("potion_type").getOrNull()
fun String.potionNormalize() = uppercase().replace(" ", "_")
when { when {
potionName != null -> SkyblockId("POTION_${potionName.uppercase()};$potionLevel") potionName != null -> SkyblockId("POTION_${potionName.potionNormalize()};$potionLevel")
potionData != null -> SkyblockId("POTION_${potionData.uppercase()};$potionLevel") potionData != null -> SkyblockId("POTION_${potionData.potionNormalize()};$potionLevel")
potionType != null -> SkyblockId("POTION_${potionType.uppercase()}") potionType != null -> SkyblockId("POTION_${potionType.potionNormalize()}")
else -> SkyblockId("WATER_BOTTLE") else -> SkyblockId("WATER_BOTTLE")
} }
} }

View File

@@ -5,6 +5,12 @@ object StringUtil {
return splitToSequence(" ") // TODO: better boundaries return splitToSequence(" ") // TODO: better boundaries
} }
fun String.camelWords(): Sequence<String> {
return splitToSequence(camelWordStart)
}
private val camelWordStart = Regex("((?<=[a-z])(?=[A-Z]))| ")
fun parseIntWithComma(string: String): Int { fun parseIntWithComma(string: String): Int {
return string.replace(",", "").toInt() return string.replace(",", "").toInt()
} }

View File

@@ -0,0 +1,140 @@
[
{
"id": 1,
"name": "Speed",
"displayName": "Speed",
"type": "good"
},
{
"id": 2,
"name": "Slowness",
"displayName": "Slowness",
"type": "bad"
},
{
"id": 3,
"name": "Haste",
"displayName": "Haste",
"type": "good"
},
{
"id": 4,
"name": "MiningFatigue",
"displayName": "Mining Fatigue",
"type": "bad"
},
{
"id": 5,
"name": "Strength",
"displayName": "Strength",
"type": "good"
},
{
"id": 6,
"name": "InstantHealth",
"displayName": "Instant Health",
"type": "good"
},
{
"id": 7,
"name": "InstantDamage",
"displayName": "Instant Damage",
"type": "bad"
},
{
"id": 8,
"name": "JumpBoost",
"displayName": "Jump Boost",
"type": "good"
},
{
"id": 9,
"name": "Nausea",
"displayName": "Nausea",
"type": "bad"
},
{
"id": 10,
"name": "Regeneration",
"displayName": "Regeneration",
"type": "good"
},
{
"id": 11,
"name": "Resistance",
"displayName": "Resistance",
"type": "good"
},
{
"id": 12,
"name": "FireResistance",
"displayName": "Fire Resistance",
"type": "good"
},
{
"id": 13,
"name": "WaterBreathing",
"displayName": "Water Breathing",
"type": "good"
},
{
"id": 14,
"name": "Invisibility",
"displayName": "Invisibility",
"type": "good"
},
{
"id": 15,
"name": "Blindness",
"displayName": "Blindness",
"type": "bad"
},
{
"id": 16,
"name": "NightVision",
"displayName": "Night Vision",
"type": "good"
},
{
"id": 17,
"name": "Hunger",
"displayName": "Hunger",
"type": "bad"
},
{
"id": 18,
"name": "Weakness",
"displayName": "Weakness",
"type": "bad"
},
{
"id": 19,
"name": "Poison",
"displayName": "Poison",
"type": "bad"
},
{
"id": 20,
"name": "Wither",
"displayName": "Wither",
"type": "bad"
},
{
"id": 21,
"name": "HealthBoost",
"displayName": "Health Boost",
"type": "good"
},
{
"id": 22,
"name": "Absorption",
"displayName": "Absorption",
"type": "good"
},
{
"id": 23,
"name": "Saturation",
"displayName": "Saturation",
"type": "good"
}
]