aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-05-28 22:25:27 +0200
committerLinnea Gräf <nea@nea.moe>2024-05-28 22:25:27 +0200
commitfac6103658b2c8d6bab3598606d57041cfe16e0c (patch)
treefe7b5079075762c5028616802eed96a9e88f10f8
parent8c66016bb3041793961375178d470546519e0e69 (diff)
downloadFirmament-fac6103658b2c8d6bab3598606d57041cfe16e0c.tar.gz
Firmament-fac6103658b2c8d6bab3598606d57041cfe16e0c.tar.bz2
Firmament-fac6103658b2c8d6bab3598606d57041cfe16e0c.zip
Add armor texture overrides
-rw-r--r--src/main/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java36
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt105
-rw-r--r--src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt1
-rw-r--r--src/main/resources/assets/firmament/lang/en_us.json2
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",