aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2025-07-06 00:37:46 +0200
committerLinnea Gräf <nea@nea.moe>2025-07-06 00:37:46 +0200
commit44b817f7b9852f8974b652c126e1e9aacc5475ac (patch)
treec4f1f4df6ebd5f8a8bf16b6eb7c741da03db1ea3
parent4140a24a0b15b9d3a112ebe934ed7929ce5ffd04 (diff)
downloadFirmament-44b817f7b9852f8974b652c126e1e9aacc5475ac.tar.gz
Firmament-44b817f7b9852f8974b652c126e1e9aacc5475ac.tar.bz2
Firmament-44b817f7b9852f8974b652c126e1e9aacc5475ac.zip
fix: potion effects in exporter
-rw-r--r--src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt14
-rw-r--r--src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt22
-rw-r--r--src/main/kotlin/util/SkyblockId.kt7
-rw-r--r--src/main/kotlin/util/StringUtil.kt6
-rw-r--r--src/main/resources/legacy_data/effects.json140
5 files changed, 185 insertions, 4 deletions
diff --git a/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt b/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt
index c0f48ca..bc8c618 100644
--- a/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt
+++ b/src/main/kotlin/features/debug/itemeditor/LegacyItemData.kt
@@ -9,6 +9,7 @@ import moe.nea.firmament.Firmament
import moe.nea.firmament.repo.ExpensiveItemCacheApi
import moe.nea.firmament.repo.ItemCache
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)
@@ -58,6 +59,7 @@ object LegacyItemData {
val enchantmentLut = enchantmentData.associateBy { Identifier.ofVanilla(it.name) }
val itemDat = getLegacyData<List<ItemData>>("items")
+
@OptIn(ExpensiveItemCacheApi::class) // This is fine, we get loaded in a thread.
val itemLut = itemDat.flatMap { item ->
item.allVariants().map { legacyItemType ->
@@ -72,4 +74,16 @@ object LegacyItemData {
}
}.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("_")
+ }
}
diff --git a/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt b/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt
index c35a892..ad03b16 100644
--- a/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt
+++ b/src/main/kotlin/features/debug/itemeditor/LegacyItemExporter.kt
@@ -7,11 +7,12 @@ import kotlinx.serialization.json.put
import kotlin.concurrent.thread
import net.minecraft.component.DataComponentTypes
import net.minecraft.item.ItemStack
+import net.minecraft.nbt.NbtByte
import net.minecraft.nbt.NbtCompound
import net.minecraft.nbt.NbtElement
import net.minecraft.nbt.NbtInt
+import net.minecraft.nbt.NbtList
import net.minecraft.nbt.NbtOps
-import net.minecraft.nbt.NbtPrimitive
import net.minecraft.nbt.NbtString
import net.minecraft.text.Text
import net.minecraft.util.Unit
@@ -135,6 +136,7 @@ class LegacyItemExporter private constructor(var itemStack: ItemStack) {
legacyNbt.put("HideFlags", NbtInt.of(254))
copyUnbreakable()
copyItemModel()
+ copyPotion()
copyExtraAttributes()
copyLegacySkullNbt()
copyDisplay()
@@ -144,6 +146,24 @@ class LegacyItemExporter private constructor(var itemStack: ItemStack) {
// 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 {
val compound = getCompoundOrEmpty(name)
put(name, compound)
diff --git a/src/main/kotlin/util/SkyblockId.kt b/src/main/kotlin/util/SkyblockId.kt
index b4d583a..051ca86 100644
--- a/src/main/kotlin/util/SkyblockId.kt
+++ b/src/main/kotlin/util/SkyblockId.kt
@@ -251,10 +251,11 @@ val ItemStack.skyBlockId: SkyblockId?
val potionName = extraAttributes.getString("potion_name").getOrNull()
val potionLevel = extraAttributes.getInt("potion_level").getOrNull()
val potionType = extraAttributes.getString("potion_type").getOrNull()
+ fun String.potionNormalize() = uppercase().replace(" ", "_")
when {
- potionName != null -> SkyblockId("POTION_${potionName.uppercase()};$potionLevel")
- potionData != null -> SkyblockId("POTION_${potionData.uppercase()};$potionLevel")
- potionType != null -> SkyblockId("POTION_${potionType.uppercase()}")
+ potionName != null -> SkyblockId("POTION_${potionName.potionNormalize()};$potionLevel")
+ potionData != null -> SkyblockId("POTION_${potionData.potionNormalize()};$potionLevel")
+ potionType != null -> SkyblockId("POTION_${potionType.potionNormalize()}")
else -> SkyblockId("WATER_BOTTLE")
}
}
diff --git a/src/main/kotlin/util/StringUtil.kt b/src/main/kotlin/util/StringUtil.kt
index dc98dc0..50c5367 100644
--- a/src/main/kotlin/util/StringUtil.kt
+++ b/src/main/kotlin/util/StringUtil.kt
@@ -5,6 +5,12 @@ object StringUtil {
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 {
return string.replace(",", "").toInt()
}
diff --git a/src/main/resources/legacy_data/effects.json b/src/main/resources/legacy_data/effects.json
new file mode 100644
index 0000000..0b885b5
--- /dev/null
+++ b/src/main/resources/legacy_data/effects.json
@@ -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"
+ }
+]