Add custom texture pack support

This commit is contained in:
nea
2023-07-25 17:34:07 +02:00
parent 1a07394887
commit 0aacb6b965
9 changed files with 161 additions and 4 deletions

View File

@@ -10,7 +10,7 @@ plugins {
id("dev.architectury.loom") version "1.1.336" id("dev.architectury.loom") version "1.1.336"
id("com.github.johnrengelman.shadow") version "7.1.2" id("com.github.johnrengelman.shadow") version "7.1.2"
id("moe.nea.licenseextractificator") id("moe.nea.licenseextractificator")
id("io.github.juuxel.loom-quiltflower") version "1.10.0" id("io.github.juuxel.loom-vineflower") version "1.11.0"
id("io.shcm.shsupercm.fabric.fletchingtable") version "1.5" id("io.shcm.shsupercm.fabric.fletchingtable") version "1.5"
} }
@@ -210,3 +210,7 @@ tasks.create("printAllLicenses", LicenseDiscoveryTask::class.java, licensing).ap
licensing.addExtraLicenseMatchers() licensing.addExtraLicenseMatchers()
fletchingTable.defaultMixinEnvironment.set("client") fletchingTable.defaultMixinEnvironment.set("client")
vineflower {
toolVersion.set("1.9.1")
}

View File

@@ -19,7 +19,7 @@ sodium = "mc1.20-0.4.10"
freecammod = "1.2.0-mc1.20" freecammod = "1.2.0-mc1.20"
ncr = "Fabric-1.20-v2.2.0" ncr = "Fabric-1.20-v2.2.0"
mixinextras = "0.2.0-beta.9" mixinextras = "0.2.0-beta.9"
jarvis = "1.1.0" jarvis = "1.0.0"
[libraries] [libraries]

View File

@@ -0,0 +1,27 @@
package moe.nea.firmament.mixins;
import moe.nea.firmament.events.CustomItemModelEvent;
import net.minecraft.client.render.item.ItemModels;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.render.model.BakedModelManager;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(ItemModels.class)
public class MixinItemModels {
@Shadow
@Final
private BakedModelManager modelManager;
@Inject(method = "getModel(Lnet/minecraft/item/ItemStack;)Lnet/minecraft/client/render/model/BakedModel;", at = @At("HEAD"), cancellable = true)
public void onGetModel(ItemStack stack, CallbackInfoReturnable<BakedModel> cir) {
var model = CustomItemModelEvent.getModel(stack, modelManager);
if (model != null)
cir.setReturnValue(model);
}
}

View File

@@ -0,0 +1,44 @@
package moe.nea.firmament.mixins;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.model.ModelLoader;
import net.minecraft.client.render.model.UnbakedModel;
import net.minecraft.client.texture.Sprite;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.client.util.SpriteIdentifier;
import net.minecraft.resource.Resource;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
import java.util.function.BiFunction;
@Mixin(ModelLoader.class)
public abstract class MixinModelLoader {
@Shadow
protected abstract void addModel(ModelIdentifier modelId);
@Shadow
@Final
private Map<Identifier, UnbakedModel> modelsToBake;
@Shadow
public abstract UnbakedModel getOrLoadModel(Identifier id);
@Inject(method = "bake", at = @At("HEAD"))
public void onBake(BiFunction<Identifier, SpriteIdentifier, Sprite> spriteLoader, CallbackInfo ci) {
Map<Identifier, Resource> resources =
MinecraftClient.getInstance().getResourceManager().findResources("models/item", it -> "firmskyblock".equals(it.getNamespace()) && it.getPath().endsWith(".json"));
for (Identifier identifier : resources.keySet()) {
ModelIdentifier modelId = new ModelIdentifier("firmskyblock", identifier.getPath().substring("models/item/".length(), identifier.getPath().length() - ".json".length()), "inventory");
addModel(modelId);
}
modelsToBake.values().forEach(model -> model.setParents(this::getOrLoadModel));
}
}

View File

@@ -0,0 +1,41 @@
package moe.nea.firmament.events
import java.util.*
import net.minecraft.client.render.model.BakedModel
import net.minecraft.client.render.model.BakedModelManager
import net.minecraft.client.util.ModelIdentifier
import net.minecraft.item.ItemStack
data class CustomItemModelEvent(
val itemStack: ItemStack,
var overrideModel: ModelIdentifier? = null,
) : FirmamentEvent() {
companion object : FirmamentEventBus<CustomItemModelEvent>() {
private val cache = IdentityHashMap<ItemStack?, Any>()
private val sentinelNull = Object()
fun clearCache() {
cache.clear()
}
@JvmStatic
fun getModelIdentifier(itemStack: ItemStack?): ModelIdentifier? {
if (itemStack == null) return null
return publish(CustomItemModelEvent(itemStack)).overrideModel
}
@JvmStatic
fun getModel(itemStack: ItemStack?, thing: BakedModelManager): BakedModel? {
if (itemStack == null) return null
val cachedValue = cache.getOrPut(itemStack) {
val modelId = getModelIdentifier(itemStack) ?: return@getOrPut sentinelNull
val bakedModel = thing.getModel(modelId)
if (bakedModel === thing.missingModel) return@getOrPut sentinelNull
bakedModel
}
if (cachedValue === sentinelNull)
return null
return cachedValue as BakedModel
}
}
}

View File

@@ -29,6 +29,7 @@ import moe.nea.firmament.features.inventory.CraftingOverlay
import moe.nea.firmament.features.inventory.SaveCursorPosition import moe.nea.firmament.features.inventory.SaveCursorPosition
import moe.nea.firmament.features.inventory.SlotLocking import moe.nea.firmament.features.inventory.SlotLocking
import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlay import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlay
import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures
import moe.nea.firmament.features.world.FairySouls import moe.nea.firmament.features.world.FairySouls
import moe.nea.firmament.util.data.DataHolder import moe.nea.firmament.util.data.DataHolder
@@ -58,6 +59,7 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
loadFeature(CraftingOverlay) loadFeature(CraftingOverlay)
loadFeature(ImagePreview) loadFeature(ImagePreview)
loadFeature(SaveCursorPosition) loadFeature(SaveCursorPosition)
loadFeature(CustomSkyBlockTextures)
if (Firmament.DEBUG) { if (Firmament.DEBUG) {
loadFeature(DeveloperFeatures) loadFeature(DeveloperFeatures)
loadFeature(DebugView) loadFeature(DebugView)

View File

@@ -0,0 +1,35 @@
package moe.nea.firmament.features.texturepack
import net.minecraft.client.util.ModelIdentifier
import moe.nea.firmament.events.CustomItemModelEvent
import moe.nea.firmament.events.TickEvent
import moe.nea.firmament.features.FirmamentFeature
import moe.nea.firmament.gui.config.ManagedConfig
import moe.nea.firmament.util.extraAttributes
object CustomSkyBlockTextures : FirmamentFeature {
override val identifier: String
get() = "custom-skyblock-textures"
object TConfig : ManagedConfig(identifier) {
val enabled by toggle("enabled") { true }
val cacheDuration by integer("cache-duration", 0, 20) { 1 }
}
override val config: ManagedConfig
get() = TConfig
override fun onLoad() {
CustomItemModelEvent.subscribe {
if (!TConfig.enabled) return@subscribe
val extra = it.itemStack.extraAttributes
val id = extra.getString("id")
if (id.isNotBlank())
it.overrideModel = ModelIdentifier("firmskyblock", id.lowercase(), "inventory")
}
TickEvent.subscribe {
if (it.tickCount % TConfig.cacheDuration == 0)
CustomItemModelEvent.clearCache()
}
}
}

View File

@@ -73,5 +73,8 @@
"firmament.config.image-preview.allowed-hosts": "Allowed Image Hosts", "firmament.config.image-preview.allowed-hosts": "Allowed Image Hosts",
"firmament.config.image-preview.percentage": "Image Width (Percentage of screen)", "firmament.config.image-preview.percentage": "Image Width (Percentage of screen)",
"firmament.config.image-preview.position": "Chat Image Preview", "firmament.config.image-preview.position": "Chat Image Preview",
"firmament.hud.edit": "Edit %s" "firmament.hud.edit": "Edit %s",
"firmament.config.custom-skyblock-textures": "Custom SkyBlock Item Textures",
"firmament.config.custom-skyblock-textures.cache-duration": "Model Cache Duration",
"firmament.config.custom-skyblock-textures.enabled": "Enable Custom Item Textures"
} }

View File

@@ -2,4 +2,5 @@ accessWidener v2 named
accessible class net/minecraft/client/render/RenderLayer$MultiPhase accessible class net/minecraft/client/render/RenderLayer$MultiPhase
accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters
accessible class net/minecraft/client/font/TextRenderer$Drawer accessible class net/minecraft/client/font/TextRenderer$Drawer
accessible class net/minecraft/client/render/model/ModelLoader$BakerImpl
accessible method net/minecraft/client/render/model/ModelLoader$BakerImpl <init> (Lnet/minecraft/client/render/model/ModelLoader;Ljava/util/function/BiFunction;Lnet/minecraft/util/Identifier;)V