aboutsummaryrefslogtreecommitdiff
path: root/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt
blob: 4529d1d5353abe8c87fd5309594230ed0635730b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package moe.nea.firmament.features.texturepack

import com.google.gson.JsonObject
import com.mojang.datafixers.util.Pair
import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import com.mojang.serialization.Decoder
import com.mojang.serialization.DynamicOps
import com.mojang.serialization.Encoder
import net.minecraft.client.render.item.model.ItemModelTypes
import net.minecraft.item.ItemStack
import net.minecraft.util.Identifier
import moe.nea.firmament.Firmament
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.FinalizeResourceManagerEvent
import moe.nea.firmament.features.texturepack.predicates.AndPredicate
import moe.nea.firmament.features.texturepack.predicates.CastPredicate
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 moe.nea.firmament.features.texturepack.predicates.PullingPredicate
import moe.nea.firmament.util.json.KJsonOps

object CustomModelOverrideParser {

	val LEGACY_CODEC: Codec<FirmamentModelPredicate> =
		Codec.of(
			Encoder.error("cannot encode legacy firmament model predicates"),
			object : Decoder<FirmamentModelPredicate> {
				override fun <T : Any?> decode(
					ops: DynamicOps<T>,
					input: T
				): DataResult<Pair<FirmamentModelPredicate, T>> {
					try {
						val pred = Firmament.json.decodeFromJsonElement(
							FirmamentRootPredicateSerializer,
							ops.convertTo(KJsonOps.INSTANCE, input))
						return DataResult.success(Pair.of(pred, ops.empty()))
					} catch (ex: Exception) {
						return DataResult.error { "Could not deserialize ${ex.message}" }
					}
				}
			}
		)

	val predicateParsers = mutableMapOf<Identifier, FirmamentModelPredicateParser>()


	fun registerPredicateParser(name: String, parser: FirmamentModelPredicateParser) {
		predicateParsers[Identifier.of("firmament", name)] = parser
	}

	init {
		registerPredicateParser("display_name", DisplayNamePredicate.Parser)
		registerPredicateParser("lore", LorePredicate.Parser)
		registerPredicateParser("all", AndPredicate.Parser)
		registerPredicateParser("any", OrPredicate.Parser)
		registerPredicateParser("not", NotPredicate.Parser)
		registerPredicateParser("item", ItemPredicate.Parser)
		registerPredicateParser("extra_attributes", ExtraAttributesPredicate.Parser)
		registerPredicateParser("pet", PetPredicate.Parser)
	}

	private val neverPredicate = listOf(
		object : FirmamentModelPredicate {
			override fun test(stack: ItemStack): Boolean {
				return false
			}
		}
	)

	fun parsePredicates(predicates: JsonObject?): List<FirmamentModelPredicate> {
		if (predicates == null) return neverPredicate
		val parsedPredicates = mutableListOf<FirmamentModelPredicate>()
		for (predicateName in predicates.keySet()) {
			if (predicateName == "cast") { // 1.21.4
				parsedPredicates.add(CastPredicate.Parser.parse(predicates[predicateName]) ?: return neverPredicate)
			}
			if (predicateName == "pull") {
				parsedPredicates.add(PullingPredicate.Parser.parse(predicates[predicateName]) ?: return neverPredicate)
			}
			if (predicateName == "pulling") {
				parsedPredicates.add(PullingPredicate.AnyPulling)
			}
			if (!predicateName.startsWith("firmament:")) continue
			val identifier = Identifier.of(predicateName)
			val parser = predicateParsers[identifier] ?: return neverPredicate
			val parsedPredicate = parser.parse(predicates[predicateName]) ?: return neverPredicate
			parsedPredicates.add(parsedPredicate)
		}
		return parsedPredicates
	}

	@JvmStatic
	fun parseCustomModelOverrides(jsonObject: JsonObject): Array<FirmamentModelPredicate>? {
		val predicates = (jsonObject["predicate"] as? JsonObject) ?: return null
		val parsedPredicates = parsePredicates(predicates)
		if (parsedPredicates.isEmpty())
			return null
		return parsedPredicates.toTypedArray()
	}

	@Subscribe
	fun finalizeResources(event: FinalizeResourceManagerEvent) {
		ItemModelTypes.ID_MAPPER.put(
			Firmament.identifier("predicates/legacy"),
			PredicateModel.Unbaked.CODEC
		)
	}

}