From cd1826a49822e7be0fb583e7b540270560fb657d Mon Sep 17 00:00:00 2001 From: Linnea Gräf Date: Fri, 14 Jun 2024 15:02:09 +0200 Subject: Fix global textures not working in hotbar --- .../firmament/mixins/CustomModelBakerPatch.java | 3 +++ .../moe/nea/firmament/apis/ingame/HypixelModAPI.kt | 4 ---- .../texturepack/CustomGlobalArmorOverrides.kt | 18 ++++++++++----- .../features/texturepack/CustomGlobalTextures.kt | 27 ++++++++++++++-------- .../features/texturepack/CustomSkyBlockTextures.kt | 4 ++++ .../nea/firmament/util/MutableMapWithMaxSize.kt | 23 +++++++++++++----- 6 files changed, 54 insertions(+), 25 deletions(-) diff --git a/src/main/java/moe/nea/firmament/mixins/CustomModelBakerPatch.java b/src/main/java/moe/nea/firmament/mixins/CustomModelBakerPatch.java index 6bd9ba1..012a215 100644 --- a/src/main/java/moe/nea/firmament/mixins/CustomModelBakerPatch.java +++ b/src/main/java/moe/nea/firmament/mixins/CustomModelBakerPatch.java @@ -43,5 +43,8 @@ public abstract class CustomModelBakerPatch { public void onBake(BiFunction spriteLoader, CallbackInfo ci) { BakeExtraModelsEvent.Companion.publish(new BakeExtraModelsEvent(this::addModel)); modelsToBake.values().forEach(model -> model.setParents(this::getOrLoadModel)); + modelsToBake.keySet().stream() + .filter(it -> !it.getNamespace().equals("minecraft")) + .forEach(it -> System.out.println("Non minecraft texture is being loaded: " + it)); } } diff --git a/src/main/kotlin/moe/nea/firmament/apis/ingame/HypixelModAPI.kt b/src/main/kotlin/moe/nea/firmament/apis/ingame/HypixelModAPI.kt index 00e6aa9..460df91 100644 --- a/src/main/kotlin/moe/nea/firmament/apis/ingame/HypixelModAPI.kt +++ b/src/main/kotlin/moe/nea/firmament/apis/ingame/HypixelModAPI.kt @@ -6,7 +6,6 @@ package moe.nea.firmament.apis.ingame -import net.hypixel.modapi.fabric.event.HypixelModAPICallback import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket import net.minecraft.text.Text import moe.nea.firmament.annotations.Subscribe @@ -31,9 +30,6 @@ object HypixelModAPI : SubscriptionOwner { InGameCodecWrapper.createStealthyCodec( PartyInfoResponse.intoType() ) - HypixelModAPICallback.EVENT.register(HypixelModAPICallback { - MC.sendChat(Text.literal("Official API: $it")) - }) } @JvmStatic diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt index c28c0c8..99e0683 100644 --- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt +++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt @@ -25,6 +25,8 @@ 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.IdentityCharacteristics +import moe.nea.firmament.util.computeNullableFunction import moe.nea.firmament.util.skyBlockId object CustomGlobalArmorOverrides : SubscriptionOwner { @@ -62,17 +64,21 @@ object CustomGlobalArmorOverrides : SubscriptionOwner { override val delegateFeature: FirmamentFeature get() = CustomSkyBlockTextures + val overrideCache = mutableMapOf, Any>() + @JvmStatic fun overrideArmor(stack: ItemStack): List? { 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 overrideCache.computeNullableFunction(IdentityCharacteristics(stack)) { + val id = stack.skyBlockId ?: return@computeNullableFunction null + val override = overrides[id.neuItem] ?: return@computeNullableFunction null + for (suboverride in override.overrides) { + if (suboverride.predicate.test(stack)) { + return@computeNullableFunction suboverride.bakedLayers + } } + return@computeNullableFunction override.bakedLayers } - return override.bakedLayers } var overrides: Map = mapOf() diff --git a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt index c2a003a..147697b 100644 --- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt +++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt @@ -21,6 +21,7 @@ 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 @@ -32,7 +33,9 @@ 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.IdentityCharacteristics import moe.nea.firmament.util.MC +import moe.nea.firmament.util.computeNullableFunction import moe.nea.firmament.util.json.SingletonSerializableList import moe.nea.firmament.util.runNull @@ -137,26 +140,32 @@ object CustomGlobalTextures : SinglePreparationResourceReloader, Any>() + @JvmStatic fun replaceGlobalModel( models: ItemModels, stack: ItemStack, cir: CallbackInfoReturnable ) { - for (guiClassOverride in matchingOverrides) { - for (override in guiClassOverride.overrides) { - if (override.predicate.test(stack)) { - cir.returnValue = models.modelManager.getModel(ModelIdentifier(override.model, "inventory")) - return + val value = overrideCache.computeNullableFunction(IdentityCharacteristics(stack)) { + for (guiClassOverride in matchingOverrides) { + for (override in guiClassOverride.overrides) { + if (override.predicate.test(stack)) { + return@computeNullableFunction models.modelManager.getModel( + ModelIdentifier(override.model, "inventory")) + } } } + null } + if (value != null) + cir.returnValue = value } 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 63ebf89..82989e4 100644 --- a/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt +++ b/src/main/kotlin/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt @@ -9,6 +9,7 @@ package moe.nea.firmament.features.texturepack import com.mojang.authlib.minecraft.MinecraftProfileTexture import com.mojang.authlib.properties.Property +import net.fabricmc.fabric.api.entity.event.v1.EntityElytraEvents.Custom import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable import net.minecraft.block.SkullBlock import net.minecraft.client.MinecraftClient @@ -44,8 +45,11 @@ object CustomSkyBlockTextures : FirmamentFeature { @Subscribe fun onTick(it: TickEvent) { if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) { + // TODO: unify all of those caches somehow CustomItemModelEvent.clearCache() skullTextureCache.clear() + CustomGlobalTextures.overrideCache.clear() + CustomGlobalArmorOverrides.overrideCache.clear() } } diff --git a/src/main/kotlin/moe/nea/firmament/util/MutableMapWithMaxSize.kt b/src/main/kotlin/moe/nea/firmament/util/MutableMapWithMaxSize.kt index 72e2dc1..098ce7a 100644 --- a/src/main/kotlin/moe/nea/firmament/util/MutableMapWithMaxSize.kt +++ b/src/main/kotlin/moe/nea/firmament/util/MutableMapWithMaxSize.kt @@ -19,14 +19,25 @@ fun ((T) -> R).memoizeIdentity(maxCacheSize: Int): (T) -> R { return { memoized(IdentityCharacteristics(it)) } } -private val SENTINEL_NULL = java.lang.Object() +@PublishedApi +internal val SENTINEL_NULL = java.lang.Object() + +/** + * Requires the map to only contain values of type [R] or [SENTINEL_NULL]. This is ensured if the map is only ever + * accessed via this function. + */ +inline fun MutableMap.computeNullableFunction(key: T, crossinline func: () -> R): R { + val value = this.getOrPut(key) { + func() ?: SENTINEL_NULL + } + @Suppress("UNCHECKED_CAST") + return if (value === SENTINEL_NULL) null as R + else value as R +} + fun ((T) -> R).memoize(maxCacheSize: Int): (T) -> R { val map = mutableMapWithMaxSize(maxCacheSize) return { - val value = map.computeIfAbsent(it) { innerValue -> - this(innerValue) ?: SENTINEL_NULL - } - if (value == SENTINEL_NULL) null as R - else value as R + map.computeNullableFunction(it) { this@memoize(it) } } } -- cgit