Add armor texture overrides

This commit is contained in:
Linnea Gräf
2024-05-28 22:25:27 +02:00
parent 8c66016bb3
commit fac6103658
4 changed files with 144 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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
}
})
}
}

View File

@@ -35,6 +35,7 @@ object CustomSkyBlockTextures : FirmamentFeature {
val skullsEnabled by toggle("skulls-enabled") { true } val skullsEnabled by toggle("skulls-enabled") { true }
val cacheDuration by integer("cache-duration", 0, 20) { 1 } val cacheDuration by integer("cache-duration", 0, 20) { 1 }
val enableModelOverrides by toggle("model-overrides") { true } val enableModelOverrides by toggle("model-overrides") { true }
val enableArmorOverrides by toggle("armor-overrides") { true }
} }
override val config: ManagedConfig override val config: ManagedConfig

View File

@@ -145,6 +145,8 @@
"firmament.fixes.auto-sprint.not-sprinting": "Not Sprinting", "firmament.fixes.auto-sprint.not-sprinting": "Not Sprinting",
"firmament.config.custom-skyblock-textures": "Custom SkyBlock Item Textures", "firmament.config.custom-skyblock-textures": "Custom SkyBlock Item Textures",
"firmament.config.custom-skyblock-textures.cache-duration": "Model Cache Duration", "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.enabled": "Enable Custom Item Textures",
"firmament.config.custom-skyblock-textures.skulls-enabled": "Enable Custom Placed Skull Textures", "firmament.config.custom-skyblock-textures.skulls-enabled": "Enable Custom Placed Skull Textures",
"firmament.config.fixes": "Fixes", "firmament.config.fixes": "Fixes",