Add custom texture pack support
This commit is contained in:
@@ -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")
|
||||||
|
}
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
27
src/main/java/moe/nea/firmament/mixins/MixinItemModels.java
Normal file
27
src/main/java/moe/nea/firmament/mixins/MixinItemModels.java
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/main/java/moe/nea/firmament/mixins/MixinModelLoader.java
Normal file
44
src/main/java/moe/nea/firmament/mixins/MixinModelLoader.java
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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)
|
||||||
|
|||||||
@@ -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()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user