Fix global textures not working in hotbar

This commit is contained in:
Linnea Gräf
2024-06-14 15:02:09 +02:00
parent db2b96bd98
commit cd1826a498
6 changed files with 54 additions and 25 deletions

View File

@@ -43,5 +43,8 @@ public abstract class CustomModelBakerPatch {
public void onBake(BiFunction<Identifier, SpriteIdentifier, Sprite> spriteLoader, CallbackInfo ci) { public void onBake(BiFunction<Identifier, SpriteIdentifier, Sprite> spriteLoader, CallbackInfo ci) {
BakeExtraModelsEvent.Companion.publish(new BakeExtraModelsEvent(this::addModel)); BakeExtraModelsEvent.Companion.publish(new BakeExtraModelsEvent(this::addModel));
modelsToBake.values().forEach(model -> model.setParents(this::getOrLoadModel)); 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));
} }
} }

View File

@@ -6,7 +6,6 @@
package moe.nea.firmament.apis.ingame package moe.nea.firmament.apis.ingame
import net.hypixel.modapi.fabric.event.HypixelModAPICallback
import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket import net.minecraft.network.packet.c2s.common.CustomPayloadC2SPacket
import net.minecraft.text.Text import net.minecraft.text.Text
import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.annotations.Subscribe
@@ -31,9 +30,6 @@ object HypixelModAPI : SubscriptionOwner {
InGameCodecWrapper.createStealthyCodec( InGameCodecWrapper.createStealthyCodec(
PartyInfoResponse.intoType() PartyInfoResponse.intoType()
) )
HypixelModAPICallback.EVENT.register(HypixelModAPICallback {
MC.sendChat(Text.literal("Official API: $it"))
})
} }
@JvmStatic @JvmStatic

View File

@@ -25,6 +25,8 @@ import moe.nea.firmament.events.subscription.SubscriptionOwner
import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger
import moe.nea.firmament.util.IdentifierSerializer import moe.nea.firmament.util.IdentifierSerializer
import moe.nea.firmament.util.IdentityCharacteristics
import moe.nea.firmament.util.computeNullableFunction
import moe.nea.firmament.util.skyBlockId import moe.nea.firmament.util.skyBlockId
object CustomGlobalArmorOverrides : SubscriptionOwner { object CustomGlobalArmorOverrides : SubscriptionOwner {
@@ -62,17 +64,21 @@ object CustomGlobalArmorOverrides : SubscriptionOwner {
override val delegateFeature: FirmamentFeature override val delegateFeature: FirmamentFeature
get() = CustomSkyBlockTextures get() = CustomSkyBlockTextures
val overrideCache = mutableMapOf<IdentityCharacteristics<ItemStack>, Any>()
@JvmStatic @JvmStatic
fun overrideArmor(stack: ItemStack): List<ArmorMaterial.Layer>? { fun overrideArmor(stack: ItemStack): List<ArmorMaterial.Layer>? {
if (!CustomSkyBlockTextures.TConfig.enableArmorOverrides) return null if (!CustomSkyBlockTextures.TConfig.enableArmorOverrides) return null
val id = stack.skyBlockId ?: return null return overrideCache.computeNullableFunction(IdentityCharacteristics(stack)) {
val override = overrides[id.neuItem] ?: return null val id = stack.skyBlockId ?: return@computeNullableFunction null
for (suboverride in override.overrides) { val override = overrides[id.neuItem] ?: return@computeNullableFunction null
if (suboverride.predicate.test(stack)) { for (suboverride in override.overrides) {
return suboverride.bakedLayers if (suboverride.predicate.test(stack)) {
return@computeNullableFunction suboverride.bakedLayers
}
} }
return@computeNullableFunction override.bakedLayers
} }
return override.bakedLayers
} }
var overrides: Map<String, ArmorOverride> = mapOf() var overrides: Map<String, ArmorOverride> = mapOf()

View File

@@ -21,6 +21,7 @@ import net.minecraft.client.util.ModelIdentifier
import net.minecraft.item.ItemStack import net.minecraft.item.ItemStack
import net.minecraft.resource.ResourceManager import net.minecraft.resource.ResourceManager
import net.minecraft.resource.SinglePreparationResourceReloader import net.minecraft.resource.SinglePreparationResourceReloader
import net.minecraft.text.Text
import net.minecraft.util.Identifier import net.minecraft.util.Identifier
import net.minecraft.util.profiler.Profiler import net.minecraft.util.profiler.Profiler
import moe.nea.firmament.Firmament 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.events.subscription.SubscriptionOwner
import moe.nea.firmament.features.FirmamentFeature import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.util.IdentifierSerializer import moe.nea.firmament.util.IdentifierSerializer
import moe.nea.firmament.util.IdentityCharacteristics
import moe.nea.firmament.util.MC import moe.nea.firmament.util.MC
import moe.nea.firmament.util.computeNullableFunction
import moe.nea.firmament.util.json.SingletonSerializableList import moe.nea.firmament.util.json.SingletonSerializableList
import moe.nea.firmament.util.runNull import moe.nea.firmament.util.runNull
@@ -137,26 +140,32 @@ object CustomGlobalTextures : SinglePreparationResourceReloader<CustomGlobalText
@Subscribe @Subscribe
fun onOpenGui(event: ScreenChangeEvent) { fun onOpenGui(event: ScreenChangeEvent) {
val newTitle = event.new?.title val newTitle = event.new?.title ?: Text.empty()
matchingOverrides = matchingOverrides = guiClassOverrides.classes
if (newTitle == null) setOf() .filterTo(mutableSetOf()) { it.screenFilter.title.matches(newTitle) }
else guiClassOverrides.classes.filterTo(mutableSetOf()) { it.screenFilter.title.matches(newTitle) }
} }
val overrideCache = mutableMapOf<IdentityCharacteristics<ItemStack>, Any>()
@JvmStatic @JvmStatic
fun replaceGlobalModel( fun replaceGlobalModel(
models: ItemModels, models: ItemModels,
stack: ItemStack, stack: ItemStack,
cir: CallbackInfoReturnable<BakedModel> cir: CallbackInfoReturnable<BakedModel>
) { ) {
for (guiClassOverride in matchingOverrides) { val value = overrideCache.computeNullableFunction(IdentityCharacteristics(stack)) {
for (override in guiClassOverride.overrides) { for (guiClassOverride in matchingOverrides) {
if (override.predicate.test(stack)) { for (override in guiClassOverride.overrides) {
cir.returnValue = models.modelManager.getModel(ModelIdentifier(override.model, "inventory")) if (override.predicate.test(stack)) {
return return@computeNullableFunction models.modelManager.getModel(
ModelIdentifier(override.model, "inventory"))
}
} }
} }
null
} }
if (value != null)
cir.returnValue = value
} }

View File

@@ -9,6 +9,7 @@ package moe.nea.firmament.features.texturepack
import com.mojang.authlib.minecraft.MinecraftProfileTexture import com.mojang.authlib.minecraft.MinecraftProfileTexture
import com.mojang.authlib.properties.Property 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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable
import net.minecraft.block.SkullBlock import net.minecraft.block.SkullBlock
import net.minecraft.client.MinecraftClient import net.minecraft.client.MinecraftClient
@@ -44,8 +45,11 @@ object CustomSkyBlockTextures : FirmamentFeature {
@Subscribe @Subscribe
fun onTick(it: TickEvent) { fun onTick(it: TickEvent) {
if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) { if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) {
// TODO: unify all of those caches somehow
CustomItemModelEvent.clearCache() CustomItemModelEvent.clearCache()
skullTextureCache.clear() skullTextureCache.clear()
CustomGlobalTextures.overrideCache.clear()
CustomGlobalArmorOverrides.overrideCache.clear()
} }
} }

View File

@@ -19,14 +19,25 @@ fun <T, R> ((T) -> R).memoizeIdentity(maxCacheSize: Int): (T) -> R {
return { memoized(IdentityCharacteristics(it)) } 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 <T, R> MutableMap<T, Any>.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> ((T) -> R).memoize(maxCacheSize: Int): (T) -> R { fun <T, R> ((T) -> R).memoize(maxCacheSize: Int): (T) -> R {
val map = mutableMapWithMaxSize<T, Any>(maxCacheSize) val map = mutableMapWithMaxSize<T, Any>(maxCacheSize)
return { return {
val value = map.computeIfAbsent(it) { innerValue -> map.computeNullableFunction(it) { this@memoize(it) }
this(innerValue) ?: SENTINEL_NULL
}
if (value == SENTINEL_NULL) null as R
else value as R
} }
} }