Add tint override to texture packs

This commit is contained in:
Linnea Gräf
2024-11-01 23:00:53 +01:00
parent 653454e290
commit 8b410fbdf2
29 changed files with 466 additions and 156 deletions

View File

@@ -4,6 +4,8 @@ package moe.nea.firmament.features.texturepack
import net.minecraft.client.render.model.BakedModel
interface BakedModelExtra {
fun getHeadModel_firmament(): BakedModel?
var tintOverrides_firmament: TintOverrides?
fun getHeadModel_firmament(): BakedModel?
fun setHeadModel_firmament(headModel: BakedModel?)
}

View File

@@ -6,6 +6,14 @@ import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import moe.nea.firmament.features.texturepack.predicates.AndPredicate
import moe.nea.firmament.features.texturepack.predicates.DisplayNamePredicate
import moe.nea.firmament.features.texturepack.predicates.ExtraAttributesPredicate
import moe.nea.firmament.features.texturepack.predicates.ItemPredicate
import moe.nea.firmament.features.texturepack.predicates.LorePredicate
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 net.minecraft.item.ItemStack
import net.minecraft.util.Identifier

View File

@@ -7,4 +7,8 @@ interface JsonUnbakedModelFirmExtra {
fun setHeadModel_firmament(identifier: Identifier?)
fun getHeadModel_firmament(): Identifier?
fun setTintOverrides_firmament(tintOverrides: TintOverrides?)
fun getTintOverrides_firmament(): TintOverrides
}

View File

@@ -1,19 +0,0 @@
package moe.nea.firmament.features.texturepack
import com.google.gson.JsonElement
import moe.nea.firmament.util.filter.IteratorFilterSet
class ModelOverrideFilterSet(original: java.util.Set<Map.Entry<String, JsonElement>>) :
IteratorFilterSet<Map.Entry<String, JsonElement>>(original) {
companion object {
@JvmStatic
fun createFilterSet(set: java.util.Set<*>): java.util.Set<*> {
return ModelOverrideFilterSet(set as java.util.Set<Map.Entry<String, JsonElement>>) as java.util.Set<*>
}
}
override fun shouldKeepElement(element: Map.Entry<String, JsonElement>): Boolean {
return !element.key.startsWith("firmament:")
}
}

View File

@@ -0,0 +1,75 @@
package moe.nea.firmament.features.texturepack
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import moe.nea.firmament.util.ErrorUtil
import moe.nea.firmament.util.assertNotNullOr
data class TintOverrides(
val layerMap: Map<Int, TintOverride> = mapOf()
) {
val hasOverrides by lazy { layerMap.values.any { it !is Reset } }
companion object {
val EMPTY = TintOverrides()
private val threadLocal = object : ThreadLocal<TintOverrides>() {}
fun enter(overrides: TintOverrides?) {
ErrorUtil.softCheck("Double entered tintOverrides") {
threadLocal.get() == null
}
threadLocal.set(overrides ?: EMPTY)
}
fun exit(overrides: TintOverrides?) {
ErrorUtil.softCheck("Exited with non matching enter tintOverrides") {
threadLocal.get() == (overrides ?: EMPTY)
}
threadLocal.remove()
}
fun getCurrentOverrides() =
assertNotNullOr(threadLocal.get(), "Got current tintOverrides without entering") { EMPTY }
fun parse(jsonObject: JsonObject): TintOverrides {
val map = mutableMapOf<Int, TintOverride>()
for ((key, value) in jsonObject.entrySet()) {
val layerIndex =
ErrorUtil.notNullOr(key.toIntOrNull(),
"Unknown layer index $value. Should be integer") { continue }
if (value.isJsonNull) {
map[layerIndex] = Reset
continue
}
val override = (value as? JsonPrimitive)
?.takeIf(JsonPrimitive::isNumber)
?.asInt
?.let(::Fixed)
if (override == null) {
ErrorUtil.softError("Invalid tint override for a layer: $value")
continue
}
map[layerIndex] = override
}
return TintOverrides(map)
}
}
fun mergeWithParent(parent: TintOverrides): TintOverrides {
val mergedMap = parent.layerMap.toMutableMap()
mergedMap.putAll(this.layerMap)
return TintOverrides(mergedMap)
}
fun hasOverrides(): Boolean = hasOverrides
fun getOverride(tintIndex: Int): Int? {
return when (val tint = layerMap[tintIndex]) {
is Reset -> null
is Fixed -> tint.color
null -> null
}
}
sealed interface TintOverride
data object Reset : TintOverride
data class Fixed(val color: Int) : TintOverride
}

View File

@@ -1,7 +1,9 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import net.minecraft.item.ItemStack
object AlwaysPredicate : FirmamentModelPredicate {

View File

@@ -1,8 +1,11 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import moe.nea.firmament.features.texturepack.CustomModelOverrideParser
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import net.minecraft.item.ItemStack
class AndPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {
@@ -15,7 +18,7 @@ class AndPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentMode
val children =
(jsonElement as JsonArray)
.flatMap {
CustomModelOverrideParser.parsePredicates(it as JsonObject)
CustomModelOverrideParser.parsePredicates(it as JsonObject)
}
.toTypedArray()
return AndPredicate(children)

View File

@@ -1,12 +1,12 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.StringMatcher
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtElement
import net.minecraft.nbt.NbtString
import moe.nea.firmament.util.mc.displayNameAccordingToNbt
import moe.nea.firmament.util.mc.loreAccordingToNbt
data class DisplayNamePredicate(val stringMatcher: StringMatcher) : FirmamentModelPredicate {
override fun test(stack: ItemStack): Boolean {

View File

@@ -1,10 +1,13 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonPrimitive
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.StringMatcher
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NbtByte
import net.minecraft.nbt.NbtCompound
@@ -210,8 +213,8 @@ fun interface NbtMatcher {
}
data class ExtraAttributesPredicate(
val path: NbtPrism,
val matcher: NbtMatcher,
val path: NbtPrism,
val matcher: NbtMatcher,
) : FirmamentModelPredicate {
object Parser : FirmamentModelPredicateParser {

View File

@@ -1,8 +1,10 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import kotlin.jvm.optionals.getOrNull
import net.minecraft.item.Item
import net.minecraft.item.ItemStack

View File

@@ -1,7 +1,10 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.StringMatcher
import net.minecraft.item.ItemStack
import moe.nea.firmament.util.mc.loreAccordingToNbt

View File

@@ -1,8 +1,11 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import moe.nea.firmament.features.texturepack.CustomModelOverrideParser
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import net.minecraft.item.ItemStack
class NotPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {

View File

@@ -1,4 +1,4 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive

View File

@@ -1,9 +1,12 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import moe.nea.firmament.features.texturepack.CustomModelOverrideParser
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import net.minecraft.item.ItemStack
class OrPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModelPredicate {
@@ -16,7 +19,7 @@ class OrPredicate(val children: Array<FirmamentModelPredicate>) : FirmamentModel
val children =
(jsonElement as JsonArray)
.flatMap {
CustomModelOverrideParser.parsePredicates(it as JsonObject)
CustomModelOverrideParser.parsePredicates(it as JsonObject)
}
.toTypedArray()
return OrPredicate(children)

View File

@@ -1,18 +1,22 @@
package moe.nea.firmament.features.texturepack
package moe.nea.firmament.features.texturepack.predicates
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import moe.nea.firmament.features.texturepack.FirmamentModelPredicate
import moe.nea.firmament.features.texturepack.FirmamentModelPredicateParser
import moe.nea.firmament.features.texturepack.RarityMatcher
import moe.nea.firmament.features.texturepack.StringMatcher
import net.minecraft.item.ItemStack
import moe.nea.firmament.repo.ExpLadders
import moe.nea.firmament.util.petData
class PetPredicate(
val petId: StringMatcher?,
val tier: RarityMatcher?,
val exp: NumberMatcher?,
val candyUsed: NumberMatcher?,
val level: NumberMatcher?,
data class PetPredicate(
val petId: StringMatcher?,
val tier: RarityMatcher?,
val exp: NumberMatcher?,
val candyUsed: NumberMatcher?,
val level: NumberMatcher?,
) : FirmamentModelPredicate {
override fun test(stack: ItemStack): Boolean {
@@ -59,8 +63,4 @@ class PetPredicate(
)
}
}
override fun toString(): String {
return super.toString()
}
}