diff options
4 files changed, 144 insertions, 0 deletions
diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java b/src/main/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java new file mode 100644 index 0000000..bfbfcc5 --- /dev/null +++ b/src/main/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java @@ -0,0 +1,36 @@ +/* + * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.llamalad7.mixinextras.sugar.Local; +import moe.nea.firmament.features.texturepack.CustomGlobalArmorOverrides; +import net.minecraft.client.render.entity.feature.ArmorFeatureRenderer; +import net.minecraft.item.ArmorMaterial; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.List; + +@Mixin(ArmorFeatureRenderer.class) +public class PatchArmorTexture { + @WrapOperation( + method = "renderArmor", + at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ArmorMaterial;layers()Ljava/util/List;")) + private List<ArmorMaterial.Layer> overrideLayers( + ArmorMaterial instance, + Operation<List<ArmorMaterial.Layer>> original, + @Local ItemStack itemStack + ) { + var overrides = CustomGlobalArmorOverrides.overrideArmor(itemStack); + if (overrides == null) + return original.call(instance); + return overrides; + } +} diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt new file mode 100644 index 0000000..c28c0c8 --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt @@ -0,0 +1,105 @@ +/* + * SPDX-FileCopyrightText: 2024 Linnea Gräf <nea@nea.moe> + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ + +@file:UseSerializers(IdentifierSerializer::class) + +package moe.nea.firmament.features.texturepack + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import kotlinx.serialization.Transient +import kotlinx.serialization.UseSerializers +import net.minecraft.item.ArmorMaterial +import net.minecraft.item.ItemStack +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.events.subscription.SubscriptionOwner +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger +import moe.nea.firmament.util.IdentifierSerializer +import moe.nea.firmament.util.skyBlockId + +object CustomGlobalArmorOverrides : SubscriptionOwner { + @Serializable + data class ArmorOverride( + @SerialName("item_ids") + val itemIds: List<String>, + val layers: List<ArmorOverrideLayer>, + val overrides: List<ArmorOverrideOverride> = listOf(), + ) { + @Transient + val bakedLayers = bakeLayers(layers) + } + + fun bakeLayers(layers: List<ArmorOverrideLayer>): List<ArmorMaterial.Layer> { + return layers.map { ArmorMaterial.Layer(it.identifier, it.suffix, it.tint) } + } + + @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>, + ) { + @Transient + val bakedLayers = bakeLayers(layers) + } + + override val delegateFeature: FirmamentFeature + get() = CustomSkyBlockTextures + + @JvmStatic + fun overrideArmor(stack: ItemStack): List<ArmorMaterial.Layer>? { + if (!CustomSkyBlockTextures.TConfig.enableArmorOverrides) return null + val id = stack.skyBlockId ?: return null + val override = overrides[id.neuItem] ?: return null + for (suboverride in override.overrides) { + if (suboverride.predicate.test(stack)) { + return suboverride.bakedLayers + } + } + return override.bakedLayers + } + + var overrides: Map<String, ArmorOverride> = mapOf() + + @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) { + overrides = prepared + } + }) + } + +} diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt index 7c2d5ab..63ebf89 100644 --- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt +++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt @@ -35,6 +35,7 @@ object CustomSkyBlockTextures : FirmamentFeature { val skullsEnabled by toggle("skulls-enabled") { true } val cacheDuration by integer("cache-duration", 0, 20) { 1 } val enableModelOverrides by toggle("model-overrides") { true } + val enableArmorOverrides by toggle("armor-overrides") { true } } override val config: ManagedConfig diff --git a/src/main/resources/assets/firmament/lang/en_us.json b/src/main/resources/assets/firmament/lang/en_us.json index b5615c4..d20fd8e 100644 --- a/src/main/resources/assets/firmament/lang/en_us.json +++ b/src/main/resources/assets/firmament/lang/en_us.json @@ -145,6 +145,8 @@ "firmament.fixes.auto-sprint.not-sprinting": "Not Sprinting", "firmament.config.custom-skyblock-textures": "Custom SkyBlock Item Textures", "firmament.config.custom-skyblock-textures.cache-duration": "Model Cache Duration", + "firmament.config.custom-skyblock-textures.model-overrides": "Enable model overrides/predicates", + "firmament.config.custom-skyblock-textures.armor-overrides": "Enable Armor re-texturing", "firmament.config.custom-skyblock-textures.enabled": "Enable Custom Item Textures", "firmament.config.custom-skyblock-textures.skulls-enabled": "Enable Custom Placed Skull Textures", "firmament.config.fixes": "Fixes", |