feat: Add skull parser

This commit is contained in:
Linnea Gräf
2025-05-04 15:40:08 +02:00
parent 3743ae88d9
commit cea5cd65cc
5 changed files with 93 additions and 4 deletions

View File

@@ -10,6 +10,7 @@ import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import moe.nea.firmament.util.parseDashlessUUID
import moe.nea.firmament.util.parsePotentiallyDashlessUUID
object DashlessUUIDSerializer : KSerializer<UUID> {
override val descriptor: SerialDescriptor =
@@ -17,10 +18,7 @@ object DashlessUUIDSerializer : KSerializer<UUID> {
override fun deserialize(decoder: Decoder): UUID {
val str = decoder.decodeString()
if ("-" in str) {
return UUID.fromString(str)
}
return parseDashlessUUID(str)
return parsePotentiallyDashlessUUID(str)
}
override fun serialize(encoder: Encoder, value: UUID) {

View File

@@ -3,6 +3,12 @@ package moe.nea.firmament.util
import java.math.BigInteger
import java.util.UUID
fun parsePotentiallyDashlessUUID(unknownFormattedUUID: String): UUID {
if ("-" in unknownFormattedUUID)
return UUID.fromString(unknownFormattedUUID)
return parseDashlessUUID(unknownFormattedUUID)
}
fun parseDashlessUUID(dashlessUuid: String): UUID {
val most = BigInteger(dashlessUuid.substring(0, 16), 16)
val least = BigInteger(dashlessUuid.substring(16, 32), 16)

View File

@@ -24,6 +24,7 @@ import moe.nea.firmament.features.texturepack.predicates.NotPredicate
import moe.nea.firmament.features.texturepack.predicates.OrPredicate
import moe.nea.firmament.features.texturepack.predicates.PetPredicate
import moe.nea.firmament.features.texturepack.predicates.PullingPredicate
import moe.nea.firmament.features.texturepack.predicates.SkullPredicate
import moe.nea.firmament.util.json.KJsonOps
object CustomModelOverrideParser {
@@ -65,6 +66,7 @@ object CustomModelOverrideParser {
registerPredicateParser("extra_attributes", ExtraAttributesPredicate.Parser)
registerPredicateParser("pet", PetPredicate.Parser)
registerPredicateParser("component", GenericComponentPredicate.Parser)
registerPredicateParser("skull", SkullPredicate.Parser)
}
private val neverPredicate = listOf(

View File

@@ -0,0 +1,63 @@
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.mojang.authlib.minecraft.MinecraftProfileTexture
import java.util.UUID
import kotlin.jvm.optionals.getOrNull
import net.minecraft.component.DataComponentTypes
import net.minecraft.entity.LivingEntity
import net.minecraft.item.ItemStack
import net.minecraft.item.Items
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.StringMatcher
import moe.nea.firmament.util.mc.decodeProfileTextureProperty
import moe.nea.firmament.util.parsePotentiallyDashlessUUID
class SkullPredicate(
val profileId: UUID?,
val textureProfileId: UUID?,
val skinUrl: StringMatcher?,
val textureValue: StringMatcher?,
) : FirmamentModelPredicate {
object Parser : FirmamentModelPredicateParser {
override fun parse(jsonElement: JsonElement): FirmamentModelPredicate? {
val obj = jsonElement.asJsonObject
val profileId = obj.getAsJsonPrimitive("profileId")
?.asString?.let(::parsePotentiallyDashlessUUID)
val textureProfileId = obj.getAsJsonPrimitive("textureProfileId")
?.asString?.let(::parsePotentiallyDashlessUUID)
val textureValue = obj.get("textureValue")?.let(StringMatcher::parse)
val skinUrl = obj.get("skinUrl")?.let(StringMatcher::parse)
return SkullPredicate(profileId, textureProfileId, skinUrl, textureValue)
}
}
override fun test(stack: ItemStack, holder: LivingEntity?): Boolean {
if (!stack.isOf(Items.PLAYER_HEAD)) return false
val profile = stack.get(DataComponentTypes.PROFILE) ?: return false
val textureProperty = profile.properties["textures"].firstOrNull()
val textureMode = lazy(LazyThreadSafetyMode.NONE) {
decodeProfileTextureProperty(textureProperty ?: return@lazy null)
}
when {
profileId != null
&& profileId != profile.id.getOrNull() ->
return false
textureValue != null
&& !textureValue.matches(textureProperty?.value ?: "") ->
return false
skinUrl != null
&& !skinUrl.matches(textureMode.value?.textures?.get(MinecraftProfileTexture.Type.SKIN)?.url ?: "") ->
return false
textureProfileId != null
&& textureProfileId != textureMode.value?.profileId ->
return false
else -> return true
}
}
}