aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/features/texturepack
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/features/texturepack')
-rw-r--r--src/main/kotlin/features/texturepack/BakedModelExtra.kt30
-rw-r--r--src/main/kotlin/features/texturepack/BakedOverrideData.kt14
-rw-r--r--src/main/kotlin/features/texturepack/CustomBlockTextures.kt301
-rw-r--r--src/main/kotlin/features/texturepack/CustomGlobalArmorOverrides.kt155
-rw-r--r--src/main/kotlin/features/texturepack/CustomGlobalTextures.kt164
-rw-r--r--src/main/kotlin/features/texturepack/CustomModelOverrideParser.kt82
-rw-r--r--src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt135
-rw-r--r--src/main/kotlin/features/texturepack/CustomTextColors.kt66
-rw-r--r--src/main/kotlin/features/texturepack/FirmamentModelPredicate.kt8
-rw-r--r--src/main/kotlin/features/texturepack/FirmamentModelPredicateParser.kt8
-rw-r--r--src/main/kotlin/features/texturepack/JsonUnbakedModelFirmExtra.kt16
-rw-r--r--src/main/kotlin/features/texturepack/ModelOverrideData.kt15
-rw-r--r--src/main/kotlin/features/texturepack/RarityMatcher.kt69
-rw-r--r--src/main/kotlin/features/texturepack/StringMatcher.kt159
-rw-r--r--src/main/kotlin/features/texturepack/TintOverrides.kt75
-rw-r--r--src/main/kotlin/features/texturepack/predicates/AlwaysPredicate.kt19
-rw-r--r--src/main/kotlin/features/texturepack/predicates/AndPredicate.kt28
-rw-r--r--src/main/kotlin/features/texturepack/predicates/DisplayNamePredicate.kt22
-rw-r--r--src/main/kotlin/features/texturepack/predicates/ExtraAttributesPredicate.kt271
-rw-r--r--src/main/kotlin/features/texturepack/predicates/ItemPredicate.kt34
-rw-r--r--src/main/kotlin/features/texturepack/predicates/LorePredicate.kt22
-rw-r--r--src/main/kotlin/features/texturepack/predicates/NotPredicate.kt21
-rw-r--r--src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt124
-rw-r--r--src/main/kotlin/features/texturepack/predicates/OrPredicate.kt29
-rw-r--r--src/main/kotlin/features/texturepack/predicates/PetPredicate.kt66
25 files changed, 0 insertions, 1933 deletions
diff --git a/src/main/kotlin/features/texturepack/BakedModelExtra.kt b/src/main/kotlin/features/texturepack/BakedModelExtra.kt
deleted file mode 100644
index 6305748..0000000
--- a/src/main/kotlin/features/texturepack/BakedModelExtra.kt
+++ /dev/null
@@ -1,30 +0,0 @@
-package moe.nea.firmament.features.texturepack
-
-import net.fabricmc.fabric.api.renderer.v1.model.WrapperBakedModel as WrapperBakedModelFabric
-import net.minecraft.client.render.model.BakedModel
-import net.minecraft.client.render.model.WrapperBakedModel
-import moe.nea.firmament.util.ErrorUtil
-
-interface BakedModelExtra {
- companion object {
- @JvmStatic
- fun cast(originalModel: BakedModel): BakedModelExtra? {
- var p = originalModel
- for (i in 0..256) {
- p = when (p) {
- is BakedModelExtra -> return p
- is WrapperBakedModel -> p.wrapped
- is WrapperBakedModelFabric -> WrapperBakedModelFabric.unwrap(p)
- else -> break
- }
- }
- ErrorUtil.softError("Could not find a baked model for $originalModel")
- return null
- }
- }
-
- var tintOverrides_firmament: TintOverrides?
-
- fun getHeadModel_firmament(): BakedModel?
- fun setHeadModel_firmament(headModel: BakedModel?)
-}
diff --git a/src/main/kotlin/features/texturepack/BakedOverrideData.kt b/src/main/kotlin/features/texturepack/BakedOverrideData.kt
deleted file mode 100644
index e9391f1..0000000
--- a/src/main/kotlin/features/texturepack/BakedOverrideData.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import net.minecraft.client.render.model.json.ModelOverrideList
-
-interface BakedOverrideData {
- fun getFirmamentOverrides(): Array<FirmamentModelPredicate>?
- fun setFirmamentOverrides(overrides: Array<FirmamentModelPredicate>?)
- companion object{
- @Suppress("CAST_NEVER_SUCCEEDS")
- @JvmStatic
- fun cast(bakedOverride: ModelOverrideList.BakedOverride): BakedOverrideData = bakedOverride as BakedOverrideData
- }
-}
diff --git a/src/main/kotlin/features/texturepack/CustomBlockTextures.kt b/src/main/kotlin/features/texturepack/CustomBlockTextures.kt
deleted file mode 100644
index 2f7f084..0000000
--- a/src/main/kotlin/features/texturepack/CustomBlockTextures.kt
+++ /dev/null
@@ -1,301 +0,0 @@
-@file:UseSerializers(BlockPosSerializer::class, IdentifierSerializer::class)
-
-package moe.nea.firmament.features.texturepack
-
-import java.util.concurrent.CompletableFuture
-import net.fabricmc.loader.api.FabricLoader
-import kotlinx.serialization.ExperimentalSerializationApi
-import kotlinx.serialization.KSerializer
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.Transient
-import kotlinx.serialization.UseSerializers
-import kotlinx.serialization.descriptors.SerialDescriptor
-import kotlinx.serialization.encoding.Decoder
-import kotlinx.serialization.encoding.Encoder
-import kotlinx.serialization.json.JsonDecoder
-import kotlinx.serialization.json.JsonElement
-import kotlinx.serialization.json.JsonPrimitive
-import kotlinx.serialization.serializer
-import kotlin.jvm.optionals.getOrNull
-import net.minecraft.block.Block
-import net.minecraft.block.BlockState
-import net.minecraft.client.render.model.BakedModel
-import net.minecraft.client.util.ModelIdentifier
-import net.minecraft.registry.RegistryKey
-import net.minecraft.registry.RegistryKeys
-import net.minecraft.resource.ResourceManager
-import net.minecraft.resource.SinglePreparationResourceReloader
-import net.minecraft.util.Identifier
-import net.minecraft.util.math.BlockPos
-import net.minecraft.util.profiler.Profiler
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.BakeExtraModelsEvent
-import moe.nea.firmament.events.EarlyResourceReloadEvent
-import moe.nea.firmament.events.FinalizeResourceManagerEvent
-import moe.nea.firmament.events.SkyblockServerUpdateEvent
-import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger
-import moe.nea.firmament.util.IdentifierSerializer
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.SBData
-import moe.nea.firmament.util.SkyBlockIsland
-import moe.nea.firmament.util.json.BlockPosSerializer
-import moe.nea.firmament.util.json.SingletonSerializableList
-
-
-object CustomBlockTextures {
- @Serializable
- data class CustomBlockOverride(
- val modes: @Serializable(SingletonSerializableList::class) List<String>,
- val area: List<Area>? = null,
- val replacements: Map<Identifier, Replacement>,
- )
-
- @Serializable(with = Replacement.Serializer::class)
- data class Replacement(
- val block: Identifier,
- val sound: Identifier?,
- ) {
-
- @Transient
- val blockModelIdentifier get() = ModelIdentifier(block.withPrefixedPath("block/"), "firmament")
-
- @Transient
- val bakedModel: BakedModel by lazy(LazyThreadSafetyMode.NONE) {
- MC.instance.bakedModelManager.getModel(blockModelIdentifier)
- }
-
- @OptIn(ExperimentalSerializationApi::class)
- @kotlinx.serialization.Serializer(Replacement::class)
- object DefaultSerializer : KSerializer<Replacement>
-
- object Serializer : KSerializer<Replacement> {
- val delegate = serializer<JsonElement>()
- override val descriptor: SerialDescriptor
- get() = delegate.descriptor
-
- override fun deserialize(decoder: Decoder): Replacement {
- val jsonElement = decoder.decodeSerializableValue(delegate)
- if (jsonElement is JsonPrimitive) {
- require(jsonElement.isString)
- return Replacement(Identifier.tryParse(jsonElement.content)!!, null)
- }
- return (decoder as JsonDecoder).json.decodeFromJsonElement(DefaultSerializer, jsonElement)
- }
-
- override fun serialize(encoder: Encoder, value: Replacement) {
- encoder.encodeSerializableValue(DefaultSerializer, value)
- }
- }
- }
-
- @Serializable
- data class Area(
- val min: BlockPos,
- val max: BlockPos,
- ) {
- @Transient
- val realMin = BlockPos(
- minOf(min.x, max.x),
- minOf(min.y, max.y),
- minOf(min.z, max.z),
- )
-
- @Transient
- val realMax = BlockPos(
- maxOf(min.x, max.x),
- maxOf(min.y, max.y),
- maxOf(min.z, max.z),
- )
-
- fun roughJoin(other: Area): Area {
- return Area(
- BlockPos(
- minOf(realMin.x, other.realMin.x),
- minOf(realMin.y, other.realMin.y),
- minOf(realMin.z, other.realMin.z),
- ),
- BlockPos(
- maxOf(realMax.x, other.realMax.x),
- maxOf(realMax.y, other.realMax.y),
- maxOf(realMax.z, other.realMax.z),
- )
- )
- }
-
- fun contains(blockPos: BlockPos): Boolean {
- return (blockPos.x in realMin.x..realMax.x) &&
- (blockPos.y in realMin.y..realMax.y) &&
- (blockPos.z in realMin.z..realMax.z)
- }
- }
-
- data class LocationReplacements(
- val lookup: Map<Block, List<BlockReplacement>>
- )
-
- data class BlockReplacement(
- val checks: List<Area>?,
- val replacement: Replacement,
- ) {
- val roughCheck by lazy(LazyThreadSafetyMode.NONE) {
- if (checks == null || checks.size < 3) return@lazy null
- checks.reduce { acc, next -> acc.roughJoin(next) }
- }
- }
-
- data class BakedReplacements(val data: Map<SkyBlockIsland, LocationReplacements>)
-
- var allLocationReplacements: BakedReplacements = BakedReplacements(mapOf())
- var currentIslandReplacements: LocationReplacements? = null
-
- fun refreshReplacements() {
- val location = SBData.skyblockLocation
- val replacements =
- if (CustomSkyBlockTextures.TConfig.enableBlockOverrides) location?.let(allLocationReplacements.data::get)
- else null
- val lastReplacements = currentIslandReplacements
- currentIslandReplacements = replacements
- if (lastReplacements != replacements) {
- MC.nextTick {
- MC.worldRenderer.chunks?.chunks?.forEach {
- // false schedules rebuilds outside a 27 block radius to happen async
- it.scheduleRebuild(false)
- }
- sodiumReloadTask?.run()
- }
- }
- }
-
- private val sodiumReloadTask = runCatching {
- val r = Class.forName("moe.nea.firmament.compat.sodium.SodiumChunkReloader")
- .getConstructor()
- .newInstance() as Runnable
- r.run()
- r
- }.getOrElse {
- if (FabricLoader.getInstance().isModLoaded("sodium"))
- logger.error("Could not create sodium chunk reloader")
- null
- }
-
-
- fun matchesPosition(replacement: BlockReplacement, blockPos: BlockPos?): Boolean {
- if (blockPos == null) return true
- val rc = replacement.roughCheck
- if (rc != null && !rc.contains(blockPos)) return false
- val areas = replacement.checks
- if (areas != null && !areas.any { it.contains(blockPos) }) return false
- return true
- }
-
- @JvmStatic
- fun getReplacementModel(block: BlockState, blockPos: BlockPos?): BakedModel? {
- return getReplacement(block, blockPos)?.bakedModel
- }
-
- @JvmStatic
- fun getReplacement(block: BlockState, blockPos: BlockPos?): Replacement? {
- if (isInFallback() && blockPos == null) {
- return null
- }
- val replacements = currentIslandReplacements?.lookup?.get(block.block) ?: return null
- for (replacement in replacements) {
- if (replacement.checks == null || matchesPosition(replacement, blockPos))
- return replacement.replacement
- }
- return null
- }
-
-
- @Subscribe
- fun onLocation(event: SkyblockServerUpdateEvent) {
- refreshReplacements()
- }
-
- @Volatile
- var preparationFuture: CompletableFuture<BakedReplacements> = CompletableFuture.completedFuture(BakedReplacements(
- mapOf()))
-
- val insideFallbackCall = ThreadLocal.withInitial { 0 }
-
- @JvmStatic
- fun enterFallbackCall() {
- insideFallbackCall.set(insideFallbackCall.get() + 1)
- }
-
- fun isInFallback() = insideFallbackCall.get() > 0
-
- @JvmStatic
- fun exitFallbackCall() {
- insideFallbackCall.set(insideFallbackCall.get() - 1)
- }
-
- @Subscribe
- fun onEarlyReload(event: EarlyResourceReloadEvent) {
- preparationFuture = CompletableFuture
- .supplyAsync(
- { prepare(event.resourceManager) }, event.preparationExecutor)
- }
-
- @Subscribe
- fun bakeExtraModels(event: BakeExtraModelsEvent) {
- preparationFuture.join().data.values
- .flatMap { it.lookup.values }
- .flatten()
- .mapTo(mutableSetOf()) { it.replacement.blockModelIdentifier }
- .forEach { event.addNonItemModel(it, it.id) }
- }
-
- private fun prepare(manager: ResourceManager): BakedReplacements {
- val resources = manager.findResources("overrides/blocks") {
- it.namespace == "firmskyblock" && it.path.endsWith(".json")
- }
- val map = mutableMapOf<SkyBlockIsland, MutableMap<Block, MutableList<BlockReplacement>>>()
- for ((file, resource) in resources) {
- val json =
- Firmament.tryDecodeJsonFromStream<CustomBlockOverride>(resource.inputStream)
- .getOrElse { ex ->
- logger.error("Failed to load block texture override at $file", ex)
- continue
- }
- for (mode in json.modes) {
- val island = SkyBlockIsland.forMode(mode)
- val islandMpa = map.getOrPut(island, ::mutableMapOf)
- for ((blockId, replacement) in json.replacements) {
- val block = MC.defaultRegistries.getOrThrow(RegistryKeys.BLOCK)
- .getOptional(RegistryKey.of(RegistryKeys.BLOCK, blockId))
- .getOrNull()
- if (block == null) {
- logger.error("Failed to load block texture override at ${file}: unknown block '$blockId'")
- continue
- }
- val replacements = islandMpa.getOrPut(block.value(), ::mutableListOf)
- replacements.add(BlockReplacement(json.area, replacement))
- }
- }
- }
-
- return BakedReplacements(map.mapValues { LocationReplacements(it.value) })
- }
-
- @JvmStatic
- fun patchIndigo(orig: BakedModel, pos: BlockPos, state: BlockState): BakedModel {
- return getReplacementModel(state, pos) ?: orig
- }
-
- @Subscribe
- fun onStart(event: FinalizeResourceManagerEvent) {
- event.resourceManager.registerReloader(object :
- SinglePreparationResourceReloader<BakedReplacements>() {
- override fun prepare(manager: ResourceManager, profiler: Profiler): BakedReplacements {
- return preparationFuture.join()
- }
-
- override fun apply(prepared: BakedReplacements, manager: ResourceManager, profiler: Profiler?) {
- allLocationReplacements = prepared
- refreshReplacements()
- }
- })
- }
-}
diff --git a/src/main/kotlin/features/texturepack/CustomGlobalArmorOverrides.kt b/src/main/kotlin/features/texturepack/CustomGlobalArmorOverrides.kt
deleted file mode 100644
index 54e9e11..0000000
--- a/src/main/kotlin/features/texturepack/CustomGlobalArmorOverrides.kt
+++ /dev/null
@@ -1,155 +0,0 @@
-@file:UseSerializers(IdentifierSerializer::class)
-
-package moe.nea.firmament.features.texturepack
-
-import java.util.Optional
-import java.util.concurrent.atomic.AtomicInteger
-import kotlinx.serialization.SerialName
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.Transient
-import kotlinx.serialization.UseSerializers
-import net.minecraft.item.ItemStack
-import net.minecraft.item.equipment.EquipmentModel
-import net.minecraft.resource.ResourceManager
-import net.minecraft.resource.SinglePreparationResourceReloader
-import net.minecraft.util.Identifier
-import net.minecraft.util.profiler.Profiler
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.FinalizeResourceManagerEvent
-import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger
-import moe.nea.firmament.util.IdentifierSerializer
-import moe.nea.firmament.util.collections.WeakCache
-import moe.nea.firmament.util.skyBlockId
-
-object CustomGlobalArmorOverrides {
- @Serializable
- data class ArmorOverride(
- @SerialName("item_ids")
- val itemIds: List<String>,
- val layers: List<ArmorOverrideLayer>? = null,
- val model: Identifier? = null,
- val overrides: List<ArmorOverrideOverride> = listOf(),
- ) {
- @Transient
- lateinit var modelIdentifier: Identifier
- fun bake() {
- modelIdentifier = bakeModel(model, layers)
- overrides.forEach { it.bake() }
- }
-
- init {
- require(layers != null || model != null) { "Either model or layers must be specified for armor override" }
- require(layers == null || model == null) { "Can't specify both model and layers for armor override" }
- }
- }
-
- @Serializable
- data class ArmorOverrideLayer(
- val tint: Boolean = false,
- val identifier: Identifier,
- val suffix: String = "",
- )
-
- @Serializable
- data class ArmorOverrideOverride(
- val predicate: FirmamentModelPredicate,
- val layers: List<ArmorOverrideLayer>? = null,
- val model: Identifier? = null,
- ) {
- init {
- require(layers != null || model != null) { "Either model or layers must be specified for armor override override" }
- require(layers == null || model == null) { "Can't specify both model and layers for armor override override" }
- }
-
- @Transient
- lateinit var modelIdentifier: Identifier
- fun bake() {
- modelIdentifier = bakeModel(model, layers)
- }
- }
-
-
- val overrideCache = WeakCache.memoize<ItemStack, Optional<Identifier>>("ArmorOverrides") { stack ->
- val id = stack.skyBlockId ?: return@memoize Optional.empty()
- val override = overrides[id.neuItem] ?: return@memoize Optional.empty()
- for (suboverride in override.overrides) {
- if (suboverride.predicate.test(stack)) {
- return@memoize Optional.of(suboverride.modelIdentifier)
- }
- }
- return@memoize Optional.of(override.modelIdentifier)
- }
-
- var overrides: Map<String, ArmorOverride> = mapOf()
- private var bakedOverrides: MutableMap<Identifier, EquipmentModel> = mutableMapOf()
- private val sentinelFirmRunning = AtomicInteger()
-
- private fun bakeModel(model: Identifier?, layers: List<ArmorOverrideLayer>?): Identifier {
- require(model == null || layers == null)
- if (model != null) {
- return model
- } else if (layers != null) {
- val idNumber = sentinelFirmRunning.incrementAndGet()
- val identifier = Identifier.of("firmament:sentinel/$idNumber")
- val equipmentLayers = layers.map {
- EquipmentModel.Layer(
- it.identifier, if (it.tint) {
- Optional.of(EquipmentModel.Dyeable(Optional.empty()))
- } else {
- Optional.empty()
- },
- false
- )
- }
- bakedOverrides[identifier] = EquipmentModel(
- mapOf(
- EquipmentModel.LayerType.HUMANOID to equipmentLayers,
- EquipmentModel.LayerType.HUMANOID_LEGGINGS to equipmentLayers,
- )
- )
- return identifier
- } else {
- error("Either model or layers must be non null")
- }
- }
-
-
- @Subscribe
- fun onStart(event: FinalizeResourceManagerEvent) {
- event.resourceManager.registerReloader(object :
- SinglePreparationResourceReloader<Map<String, ArmorOverride>>() {
- override fun prepare(manager: ResourceManager, profiler: Profiler): Map<String, ArmorOverride> {
- val overrideFiles = manager.findResources("overrides/armor_models") {
- it.namespace == "firmskyblock" && it.path.endsWith(".json")
- }
- val overrides = overrideFiles.mapNotNull {
- Firmament.tryDecodeJsonFromStream<ArmorOverride>(it.value.inputStream).getOrElse { ex ->
- logger.error("Failed to load armor texture override at ${it.key}", ex)
- null
- }
- }
- val associatedMap = overrides.flatMap { obj -> obj.itemIds.map { it to obj } }
- .toMap()
- return associatedMap
- }
-
- override fun apply(prepared: Map<String, ArmorOverride>, manager: ResourceManager, profiler: Profiler) {
- bakedOverrides.clear()
- prepared.forEach { it.value.bake() }
- overrides = prepared
- }
- })
- }
-
- @JvmStatic
- fun overrideArmor(itemStack: ItemStack): Optional<Identifier> {
- return overrideCache.invoke(itemStack)
- }
-
- @JvmStatic
- fun overrideArmorLayer(id: Identifier): EquipmentModel? {
- return bakedOverrides[id]
- }
-
-}
diff --git a/src/main/kotlin/features/texturepack/CustomGlobalTextures.kt b/src/main/kotlin/features/texturepack/CustomGlobalTextures.kt
deleted file mode 100644
index 9ad8bc1..0000000
--- a/src/main/kotlin/features/texturepack/CustomGlobalTextures.kt
+++ /dev/null
@@ -1,164 +0,0 @@
-@file:UseSerializers(IdentifierSerializer::class, CustomModelOverrideParser.FirmamentRootPredicateSerializer::class)
-
-package moe.nea.firmament.features.texturepack
-
-
-import java.util.Optional
-import java.util.concurrent.CompletableFuture
-import org.slf4j.LoggerFactory
-import kotlinx.serialization.Serializable
-import kotlinx.serialization.UseSerializers
-import kotlin.jvm.optionals.getOrNull
-import net.minecraft.client.render.item.ItemModels
-import net.minecraft.client.render.model.BakedModel
-import net.minecraft.client.util.ModelIdentifier
-import net.minecraft.item.ItemStack
-import net.minecraft.resource.ResourceManager
-import net.minecraft.resource.SinglePreparationResourceReloader
-import net.minecraft.text.Text
-import net.minecraft.util.Identifier
-import net.minecraft.util.profiler.Profiler
-import moe.nea.firmament.Firmament
-import moe.nea.firmament.annotations.Subscribe
-import moe.nea.firmament.events.BakeExtraModelsEvent
-import moe.nea.firmament.events.EarlyResourceReloadEvent
-import moe.nea.firmament.events.FinalizeResourceManagerEvent
-import moe.nea.firmament.events.ScreenChangeEvent
-import moe.nea.firmament.events.subscription.SubscriptionOwner
-import moe.nea.firmament.features.FirmamentFeature
-import moe.nea.firmament.util.IdentifierSerializer
-import moe.nea.firmament.util.MC
-import moe.nea.firmament.util.collections.WeakCache
-import moe.nea.firmament.util.intoOptional
-import moe.nea.firmament.util.json.SingletonSerializableList
-import moe.nea.firmament.util.runNull
-
-object CustomGlobalTextures : SinglePreparationResourceReloader<CustomGlobalTextures.CustomGuiTextureOverride>(),
- SubscriptionOwner {
- override val delegateFeature: FirmamentFeature
- get() = CustomSkyBlockTextures
-
- class CustomGuiTextureOverride(
- val classes: List<ItemOverrideCollection>
- )
-
- @Serializable
- data class GlobalItemOverride(
- val screen: @Serializable(SingletonSerializableList::class) List<Identifier>,
- val model: Identifier,
- val predicate: FirmamentModelPredicate,
- )
-
- @Serializable
- data class ScreenFilter(
- val title: StringMatcher,
- )
-
- data class ItemOverrideCollection(
- val screenFilter: ScreenFilter,
- val overrides: List<GlobalItemOverride>,
- )
-
- @Subscribe
- fun onStart(event: FinalizeResourceManagerEvent) {
- MC.resourceManager.registerReloader(this)
- }
-
- @Subscribe
- fun onEarlyReload(event: EarlyResourceReloadEvent) {
- preparationFuture = CompletableFuture
- .supplyAsync(
- {
- prepare(event.resourceManager)
- }, event.preparationExecutor)
- }
-
- @Subscribe
- fun onBakeModels(event: BakeExtraModelsEvent) {
- for (guiClassOverride in preparationFuture.join().classes) {
- for (override in guiClassOverride.overrides) {
- event.addItemModel(ModelIdentifier(override.model, "inventory"))
- }
- }
- }
-
- @Volatile
- var preparationFuture: CompletableFuture<CustomGuiTextureOverride> = CompletableFuture.completedFuture(
- CustomGuiTextureOverride(listOf()))
-
- override fun prepare(manager: ResourceManager?, profiler: Profiler?): CustomGuiTextureOverride {
- return preparationFuture.join()
- }
-
- override fun apply(prepared: CustomGuiTextureOverride, manager: ResourceManager?, profiler: Profiler?) {
- this.guiClassOverrides = prepared
- }
-
- val logger = LoggerFactory.getLogger(CustomGlobalTextures::class.java)
- fun prepare(manager: ResourceManager): CustomGuiTextureOverride {
- val overrideResources =
- manager.findResources("overrides/item") { it.namespace == "firmskyblock" && it.path.endsWith(".json") }
- .mapNotNull {
- Firmament.tryDecodeJsonFromStream<GlobalItemOverride>(it.value.inputStream).getOrElse { ex ->
- logger.error("Failed to load global item override at ${it.key}", ex)
- null
- }
- }
-
- val byGuiClass = overrideResources.flatMap { override -> override.screen.toSet().map { it to override } }
- .groupBy { it.first }
- val guiClasses = byGuiClass.entries
- .mapNotNull {
- val key = it.key
- val guiClassResource =
- manager.getResource(Identifier.of(key.namespace, "filters/screen/${key.path}.json"))
- .getOrNull()
- ?: return@mapNotNull runNull {
- logger.error("Failed to locate screen filter at $key")
- }
- val screenFilter =
- Firmament.tryDecodeJsonFromStream<ScreenFilter>(guiClassResource.inputStream)
- .getOrElse { ex ->
- logger.error("Failed to load screen filter at $key", ex)
- return@mapNotNull null
- }
- ItemOverrideCollection(screenFilter, it.value.map { it.second })
- }
- logger.info("Loaded ${overrideResources.size} global item overrides")
- return CustomGuiTextureOverride(guiClasses)
- }
-
- var guiClassOverrides = CustomGuiTextureOverride(listOf())
-
- var matchingOverrides: Set<ItemOverrideCollection> = setOf()
-
- @Subscribe
- fun onOpenGui(event: ScreenChangeEvent) {
- val newTitle = event.new?.title ?: Text.empty()
- matchingOverrides = guiClassOverrides.classes
- .filterTo(mutableSetOf()) { it.screenFilter.title.matches(newTitle) }
- }
-
- val overrideCache =
- WeakCache.memoize<ItemStack, ItemModels, Optional<BakedModel>>("CustomGlobalTextureModelOverrides") { stack, models ->
- matchingOverrides
- .firstNotNullOfOrNull {
- it.overrides
- .asSequence()
- .filter { it.predicate.test(stack) }
- .map { models.getModel(it.model) }
- .firstOrNull()
- }
- .intoOptional()
- }
-
- @JvmStatic
- fun replaceGlobalModel(
- models: ItemModels,
- stack: ItemStack,
- ): BakedModel? {
- return overrideCache.invoke(stack, models).getOrNull()
- }
-
-
-}
diff --git a/src/main/kotlin/features/texturepack/CustomModelOverrideParser.kt b/src/main/kotlin/features/texturepack/CustomModelOverrideParser.kt
deleted file mode 100644
index c5fc20b..0000000
--- a/src/main/kotlin/features/texturepack/CustomModelOverrideParser.kt
+++ /dev/null
@@ -1,82 +0,0 @@
-
-package moe.nea.firmament.features.texturepack
-
-import com.google.gson.JsonObject
-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
-
-object CustomModelOverrideParser {
- object FirmamentRootPredicateSerializer : KSerializer<FirmamentModelPredicate> {
- val delegateSerializer = kotlinx.serialization.json.JsonObject.serializer()
- override val descriptor: SerialDescriptor
- get() = SerialDescriptor("FirmamentModelRootPredicate", delegateSerializer.descriptor)
-
- override fun deserialize(decoder: Decoder): FirmamentModelPredicate {
- val json = decoder.decodeSerializableValue(delegateSerializer).intoGson() as JsonObject
- return AndPredicate(parsePredicates(json).toTypedArray())
- }
-
- override fun serialize(encoder: Encoder, value: FirmamentModelPredicate) {
- TODO("Cannot serialize firmament predicates")
- }
- }
-
- 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> {
- val parsedPredicates = mutableListOf<FirmamentModelPredicate>()
- for (predicateName in predicates.keySet()) {
- 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.toTyped