diff options
author | Linnea Gräf <nea@nea.moe> | 2024-12-07 13:26:03 +0100 |
---|---|---|
committer | Linnea Gräf <nea@nea.moe> | 2024-12-07 13:26:03 +0100 |
commit | bf7795df22ca7892fae1238403feebb57c005562 (patch) | |
tree | 3a49db5bade38498f976321b6e9008203f2d4d3b | |
parent | cdb5e60f52eea9030af9ca2d4a49913664023965 (diff) | |
download | Firmament-bf7795df22ca7892fae1238403feebb57c005562.tar.gz Firmament-bf7795df22ca7892fae1238403feebb57c005562.tar.bz2 Firmament-bf7795df22ca7892fae1238403feebb57c005562.zip |
WIP: Port to compilation on 1.21.4
77 files changed, 779 insertions, 1445 deletions
diff --git a/build.gradle.kts b/build.gradle.kts index 1d5478f..c74a424 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -25,7 +25,7 @@ plugins { alias(libs.plugins.kotlin.plugin.ksp) // alias(libs.plugins.loom) // TODO: use arch loom once they update to 1.8 - id("fabric-loom") version "1.8.9" + id("fabric-loom") version "1.9.2" alias(libs.plugins.shadow) id("moe.nea.licenseextractificator") id("moe.nea.mc-auto-translations") version "0.1.0" @@ -129,13 +129,8 @@ val collectTranslations by tasks.registering(CollectTranslations::class) { val compatSourceSets: MutableSet<SourceSet> = mutableSetOf() fun createIsolatedSourceSet(name: String, path: String = "compat/$name", isEnabled: Boolean = true): SourceSet { val ss = sourceSets.create(name) { - if (isEnabled) { - this.java.setSrcDirs(listOf(layout.projectDirectory.dir("src/$path/java"))) - this.kotlin.setSrcDirs(listOf(layout.projectDirectory.dir("src/$path/java"))) - } else { - this.java.setSrcDirs(listOf<File>()) - this.kotlin.setSrcDirs(listOf<File>()) - } + this.java.setSrcDirs(listOf(layout.projectDirectory.dir("src/$path/java"))) + this.kotlin.setSrcDirs(listOf(layout.projectDirectory.dir("src/$path/java"))) } val mainSS = sourceSets.main.get() val upperName = ss.name.capitalizeN() @@ -221,15 +216,16 @@ val testAgent by configurations.creating { val configuredSourceSet = createIsolatedSourceSet("configured", isEnabled = false) // Wait for update (also low prio, because configured sucks) -val sodiumSourceSet = createIsolatedSourceSet("sodium") +val sodiumSourceSet = createIsolatedSourceSet("sodium", isEnabled = false) val citResewnSourceSet = createIsolatedSourceSet("citresewn", isEnabled = false) // TODO: Wait for update -val yaclSourceSet = createIsolatedSourceSet("yacl") +val yaclSourceSet = createIsolatedSourceSet("yacl", isEnabled = false) val explosiveEnhancementSourceSet = createIsolatedSourceSet("explosiveEnhancement", isEnabled = false) // TODO: wait for their port val wildfireGenderSourceSet = createIsolatedSourceSet("wildfireGender", isEnabled = false) // TODO: wait on their port -val modmenuSourceSet = createIsolatedSourceSet("modmenu") -val reiSourceSet = createIsolatedSourceSet("rei") -val moulconfigSourceSet = createIsolatedSourceSet("moulconfig") +val modmenuSourceSet = createIsolatedSourceSet("modmenu", isEnabled = false) +val reiSourceSet = createIsolatedSourceSet("rei", isEnabled = false) +val moulconfigSourceSet = createIsolatedSourceSet("moulconfig", isEnabled = false) +val customTexturesSourceSet = createIsolatedSourceSet("texturePacks", "texturePacks") dependencies { // Minecraft dependencies diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index d89c20e..54719bc 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -3,7 +3,7 @@ // SPDX-License-Identifier: CC0-1.0 plugins { - kotlin("jvm") version "1.8.10" + kotlin("jvm") version "2.1.0" `kotlin-dsl` } repositories { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 74de8e8..b8ed2f1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,21 +3,23 @@ # SPDX-License-Identifier: CC0-1.0 [versions] -minecraft = "1.21.3" +minecraft = "1.21.4" # Update from https://kotlinlang.org/ -kotlin = "2.0.21" +kotlin = "2.1.0" # Update from https://github.com/google/ksp/releases -kotlin_ksp = "2.0.21-1.0.26" +kotlin_ksp = "2.1.0-1.0.29" # Update from https://linkie.shedaniel.me/dependencies?loader=fabric fabric_loader = "0.16.9" -fabric_api = "0.107.0+1.21.3" -fabric_kotlin = "1.12.3+kotlin.2.0.21" -yarn = "1.21.3+build.2" +fabric_api = "0.110.5+1.21.4" +yarn = "1.21.4+build.1" +modmenu = "13.0.0-beta.1" +architectury = "15.0.1" rei = "17.0.789" -modmenu = "12.0.0-beta.1" -architectury = "14.0.4" + +# Update from https://maven.fabricmc.net/net/fabricmc/fabric-language-kotlin/ +fabric_kotlin = "1.13.0+kotlin.2.1.0" # Update from https://maven.architectury.dev/dev/architectury/loom/dev.architectury.loom.gradle.plugin/ loom = "1.7.414" @@ -26,16 +28,16 @@ loom = "1.7.414" qolify = "1.6.0-1.21.1" # Update from https://modrinth.com/mod/sodium/versions?l=fabric -sodium = "mc1.21.3-0.6.0-beta.4-fabric" +sodium = "mc1.21.4-0.6.2-fabric" # Update from https://modrinth.com/mod/freecam/versions?l=fabric -freecammod = "vomskVK3" +freecammod = "1.3.1+mc1.21.3" # Update from https://modrinth.com/mod/no-chat-reports/versions?l=fabric ncr = "Fabric-1.21.3-v2.10.0" # Update from https://modrinth.com/mod/female-gender/versions?l=fabric -femalegender = "kJmjQvAS" +femalegender = "4.3+1.21.4" # Update from https://modrinth.com/mod/explosive-enhancement/versions?l=fabric explosiveenhancement = "1.2.3-1.21.0" @@ -49,12 +51,13 @@ citresewn = "1.2.0+1.21" devauth = "1.2.0" # Update from https://ktor.io/ -ktor = "3.0.1" +ktor = "3.0.2" # Update from https://repo.nea.moe/#/releases/moe/nea/neurepoparser neurepoparser = "1.6.0" # Update from https://github.com/HotswapProjects/HotswapAgent/releases +# TODO: bump to 2.0.1 hotswap_agent = "1.4.2-SNAPSHOT" # Update from https://github.com/LlamaLad7/MixinExtras/tags diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f861d18..6e2ced2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -4,6 +4,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/InitReplacer.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/InitReplacer.java index a0d28ab..7ba3b44 100644 --- a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/InitReplacer.java +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/InitReplacer.java @@ -59,6 +59,14 @@ public class InitReplacer extends TreeScanner<Void, Void> { var target = plugin.utils.getAnnotationValue(jcAnnotation, "value"); var targetClass = plugin.utils.resolveClassLiteralExpression(target).tsym.flatName().toString(); var intermediaryClass = mappingTree.resolveClassToIntermediary(targetClass); + if (intermediaryClass == null){ + plugin.utils.reportError( + compilationUnitTree.getSourceFile(), + jcNode.init, + "Unknown class name " + targetClass + ); + return super.visitVariable(node, unused); + } var remapper = treeMaker.Select(treeMaker.This(classTree.type), names.fromString("remapper")); var remappingCall = treeMaker.Apply( List.nil(), diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryMethodReplacer.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryMethodReplacer.java index d3040b7..cb87b20 100644 --- a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryMethodReplacer.java +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/IntermediaryMethodReplacer.java @@ -57,7 +57,12 @@ public class IntermediaryMethodReplacer extends TreeScanner<Void, Void> { } var head = node.typeargs.head; var resolved = plugin.utils.resolveClassName(head, compilationUnit); - var mappedName = mappings.resolveClassToIntermediary(resolved.tsym.flatName().toString()); + var sourceName = resolved.tsym.flatName().toString(); + var mappedName = mappings.resolveClassToIntermediary(sourceName); + if (mappedName == null) { + plugin.utils.reportError(sourceFile, node, "Unknown class name " + sourceName); + return; + } fieldAccess.name = plugin.names.fromString("id"); node.typeargs = List.nil(); node.args = List.of(plugin.treeMaker.Literal(mappedName)); diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/MappingTree.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/MappingTree.java index 7a270b7..eef5f9a 100644 --- a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/MappingTree.java +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/MappingTree.java @@ -9,40 +9,43 @@ import java.util.stream.Collectors; public class MappingTree { - private final Map<String, TinyClass> classLookup; - private final int targetIndex; - private final int sourceIndex; + private final Map<String, TinyClass> classLookup; + private final int targetIndex; + private final int sourceIndex; - public MappingTree(TinyFile tinyV2File, String sourceNamespace, String targetNamespace) { - sourceIndex = tinyV2File.getHeader().getNamespaces().indexOf(sourceNamespace); - if (sourceIndex < 0) - throw new RuntimeException("Could not find source namespace " + sourceNamespace + " in mappings file."); - this.classLookup = tinyV2File - .getClassEntries() - .stream() - .collect(Collectors.toMap(it -> it.getClassNames().get(sourceIndex), it -> it)); - targetIndex = tinyV2File.getHeader().getNamespaces().indexOf(targetNamespace); - if (targetIndex < 0) - throw new RuntimeException("Could not find target namespace " + targetNamespace + " in mappings file."); - } + public MappingTree(TinyFile tinyV2File, String sourceNamespace, String targetNamespace) { + sourceIndex = tinyV2File.getHeader().getNamespaces().indexOf(sourceNamespace); + if (sourceIndex < 0) + throw new RuntimeException("Could not find source namespace " + sourceNamespace + " in mappings file."); + this.classLookup = tinyV2File + .getClassEntries() + .stream() + .collect(Collectors.toMap(it -> it.getClassNames().get(sourceIndex), it -> it)); + targetIndex = tinyV2File.getHeader().getNamespaces().indexOf(targetNamespace); + if (targetIndex < 0) + throw new RuntimeException("Could not find target namespace " + targetNamespace + " in mappings file."); + } - public String resolveMethodToIntermediary(String className, String methodName) { - var classData = classLookup.get(className.replace(".", "/")); - TinyMethod candidate = null; - for (TinyMethod method : classData.getMethods()) { - if (method.getMethodNames().get(sourceIndex).equals(methodName)) { - if (candidate != null) { - throw new RuntimeException("Found two candidates for method " + className + "." + methodName); - } - candidate = method; - } - } - return candidate.getMethodNames().get(targetIndex); - } + public String resolveMethodToIntermediary(String className, String methodName) { + var classData = classLookup.get(className.replace(".", "/")); + TinyMethod candidate = null; + for (TinyMethod method : classData.getMethods()) { + if (method.getMethodNames().get(sourceIndex).equals(methodName)) { + if (candidate != null) { + throw new RuntimeException("Found two candidates for method " + className + "." + methodName); + } + candidate = method; + } + } + return candidate.getMethodNames().get(targetIndex); + } - public String resolveClassToIntermediary(String className) { - return classLookup.get(className.replace(".", "/")) - .getClassNames().get(targetIndex) - .replace("/", "."); - } + public String resolveClassToIntermediary(String className) { + var cls = classLookup.get(className.replace(".", "/")); + if (cls == null) { + return null; + } + return cls.getClassNames().get(targetIndex) + .replace("/", "."); + } } diff --git a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/Utils.java b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/Utils.java index d9008bd..4c8806d 100644 --- a/javaplugin/src/main/java/moe/nea/firmament/javaplugin/Utils.java +++ b/javaplugin/src/main/java/moe/nea/firmament/javaplugin/Utils.java @@ -111,7 +111,7 @@ public class Utils { var error = diagnostics.error( JCDiagnostic.DiagnosticFlag.API, log.currentSource(), - ((JCTree) node).pos(), + node == null ? null : ((JCTree) node).pos(), "firmament.generic", message ); diff --git a/src/main/java/moe/nea/firmament/init/EarlyRiser.java b/src/main/java/moe/nea/firmament/init/EarlyRiser.java index 9734e94..5441255 100644 --- a/src/main/java/moe/nea/firmament/init/EarlyRiser.java +++ b/src/main/java/moe/nea/firmament/init/EarlyRiser.java @@ -7,6 +7,6 @@ public class EarlyRiser implements Runnable { new ClientPlayerRiser().addTinkerers(); new HandledScreenRiser().addTinkerers(); new SectionBuilderRiser().addTinkerers(); - new ItemColorsSodiumRiser().addTinkerers(); +// TODO: new ItemColorsSodiumRiser().addTinkerers(); } } diff --git a/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java index 355a666..f7db18c 100644 --- a/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java +++ b/src/main/java/moe/nea/firmament/init/HandledScreenRiser.java @@ -3,7 +3,6 @@ package moe.nea.firmament.init; import me.shedaniel.mm.api.ClassTinkerers; import net.minecraft.client.gui.Element; -import net.minecraft.client.gui.ParentElement; import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.ClassNode; diff --git a/src/main/java/moe/nea/firmament/init/ItemColorsSodiumRiser.java b/src/main/java/moe/nea/firmament/init/ItemColorsSodiumRiser.java deleted file mode 100644 index 80ee9aa..0000000 --- a/src/main/java/moe/nea/firmament/init/ItemColorsSodiumRiser.java +++ /dev/null @@ -1,64 +0,0 @@ -package moe.nea.firmament.init; - -import me.shedaniel.mm.api.ClassTinkerers; -import moe.nea.firmament.util.ErrorUtil; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.color.item.ItemColorProvider; -import net.minecraft.client.color.item.ItemColors; -import net.minecraft.item.ItemStack; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.InsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.VarInsnNode; - -public class ItemColorsSodiumRiser extends RiserUtils { - @IntermediaryName(ItemColors.class) - String ItemColors; - @IntermediaryName(ItemColorProvider.class) - String ItemColorProvider; - @IntermediaryName(ItemStack.class) - String ItemStack; - String getColorProvider = "sodium$getColorProvider"; - Type getColorProviderDesc = Type.getMethodType(getTypeForClassName(ItemColorProvider), - getTypeForClassName(ItemStack)); - - @Override - public void addTinkerers() { - ClassTinkerers.addTransformation(ItemColors, this::addSodiumOverride, true); - } - - private void addSodiumOverride(ClassNode classNode) { - var node = findMethod(classNode, getColorProvider, getColorProviderDesc); - if (node == null) { - if (!FabricLoader.getInstance().isModLoaded("sodium")) - ErrorUtil.INSTANCE.softError("Sodium is present, but sodium color override could not be injected."); - return; - } - var p = node.instructions.getFirst(); - while (p != null) { - if (p.getOpcode() == Opcodes.ARETURN) { - node.instructions.insertBefore( - p, - mkOverrideSodiumCall() - ); - } - p = p.getNext(); - } - } - - private InsnList mkOverrideSodiumCall() { - var insnList = new InsnList(); - insnList.add(new VarInsnNode(Opcodes.ALOAD, 0)); - insnList.add(new InsnNode(Opcodes.SWAP)); - insnList.add(new MethodInsnNode(Opcodes.INVOKEVIRTUAL, - getTypeForClassName(ItemColors).getInternalName(), - "overrideSodium_firmament", - Type.getMethodType(getTypeForClassName(ItemColorProvider), - getTypeForClassName(ItemColorProvider)).getDescriptor(), - false)); - return insnList; - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/CustomModelEventPatch.java b/src/main/java/moe/nea/firmament/mixins/CustomModelEventPatch.java deleted file mode 100644 index e0a7544..0000000 --- a/src/main/java/moe/nea/firmament/mixins/CustomModelEventPatch.java +++ /dev/null @@ -1,36 +0,0 @@ - - -package moe.nea.firmament.mixins; - -import moe.nea.firmament.events.CustomItemModelEvent; -import moe.nea.firmament.features.texturepack.CustomGlobalTextures; -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.Item; -import net.minecraft.item.ItemStack; -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.CallbackInfoReturnable; - -import java.util.Map; - -@Mixin(ItemModels.class) -public class CustomModelEventPatch { - - @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 $this = (ItemModels) (Object) this; - var model = CustomItemModelEvent.getModel(stack, $this); - if (model == null) { - model = CustomGlobalTextures.replaceGlobalModel($this, stack); - } - if (model != null) { - cir.setReturnValue(model); - } - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java b/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java index 80a9fd5..a7c3875 100644 --- a/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java +++ b/src/main/java/moe/nea/firmament/mixins/IncomingPacketListenerPatches.java @@ -18,7 +18,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(ClientPlayNetworkHandler.class) public abstract class IncomingPacketListenerPatches { - @ModifyExpressionValue(method = "onCommandTree", at = @At(value = "NEW", target = "(Lcom/mojang/brigadier/tree/RootCommandNode;)Lcom/mojang/brigadier/CommandDispatcher;", remap = false)) public CommandDispatcher onOnCommandTree(CommandDispatcher dispatcher) { MaskCommands.Companion.publish(new MaskCommands(dispatcher)); @@ -31,7 +30,7 @@ public abstract class IncomingPacketListenerPatches { packet.getParameters(), new Vec3d(packet.getX(), packet.getY(), packet.getZ()), new Vector3f(packet.getOffsetX(), packet.getOffsetY(), packet.getOffsetZ()), - packet.isLongDistance(), + packet.isImportant(), packet.getCount(), packet.getSpeed() ); diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java b/src/main/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java deleted file mode 100644 index dac65fe..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java +++ /dev/null @@ -1,35 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import com.llamalad7.mixinextras.sugar.Local; -import com.llamalad7.mixinextras.sugar.ref.LocalRef; -import moe.nea.firmament.features.texturepack.BakedModelExtra; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ModelTransformationMode; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ItemRenderer.class) -public class ApplyHeadModelInItemRenderer { - @Inject(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;ZF)V", - at = @At("HEAD")) - private void applyHeadModel(ItemStack stack, ModelTransformationMode transformationMode, boolean leftHanded, - MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, - BakedModel model, boolean useInventoryModel, float z, CallbackInfo ci, - @Local(argsOnly = true) LocalRef<BakedModel> modelMut - ) { - var extra = BakedModelExtra.cast(model); - if (transformationMode == ModelTransformationMode.HEAD && extra != null) { - var headModel = extra.getHeadModel_firmament(); - if (headModel != null) { - modelMut.set(headModel); - } - } - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/BakedModelDataHolderBasic.java b/src/main/java/moe/nea/firmament/mixins/custommodels/BakedModelDataHolderBasic.java deleted file mode 100644 index 3ed2177..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/BakedModelDataHolderBasic.java +++ /dev/null @@ -1,42 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import moe.nea.firmament.features.texturepack.BakedModelExtra; -import moe.nea.firmament.features.texturepack.TintOverrides; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BasicBakedModel; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -@Mixin(BasicBakedModel.class) -public class BakedModelDataHolderBasic implements BakedModelExtra { - - @Unique - private BakedModel headModel; - - @Unique - @Nullable - private TintOverrides tintOverrides; - - @Nullable - @Override - public BakedModel getHeadModel_firmament() { - return headModel; - } - - @Override - public void setHeadModel_firmament(@Nullable BakedModel headModel) { - this.headModel = headModel; - } - - @Override - public @Nullable TintOverrides getTintOverrides_firmament() { - return tintOverrides; - } - - @Override - public void setTintOverrides_firmament(@Nullable TintOverrides tintOverrides) { - this.tintOverrides = tintOverrides; - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/BakedModelDataHolderBuiltin.java b/src/main/java/moe/nea/firmament/mixins/custommodels/BakedModelDataHolderBuiltin.java deleted file mode 100644 index 87aecb1..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/BakedModelDataHolderBuiltin.java +++ /dev/null @@ -1,43 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import moe.nea.firmament.features.texturepack.BakedModelExtra; -import moe.nea.firmament.features.texturepack.TintOverrides; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.BuiltinBakedModel; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -@Mixin(BuiltinBakedModel.class) -public class BakedModelDataHolderBuiltin implements BakedModelExtra { - - @Unique - @Nullable - private BakedModel headModel; - - @Unique - @Nullable - private TintOverrides tintOverrides; - - @Override - public @Nullable TintOverrides getTintOverrides_firmament() { - return tintOverrides; - } - - @Override - public void setTintOverrides_firmament(@Nullable TintOverrides tintOverrides) { - this.tintOverrides = tintOverrides; - } - - @Nullable - @Override - public BakedModel getHeadModel_firmament() { - return headModel; - } - - @Override - public void setHeadModel_firmament(@Nullable BakedModel headModel) { - this.headModel = headModel; - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/BakedOverrideDataHolder.java b/src/main/java/moe/nea/firmament/mixins/custommodels/BakedOverrideDataHolder.java deleted file mode 100644 index 26972b1..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/BakedOverrideDataHolder.java +++ /dev/null @@ -1,28 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import moe.nea.firmament.features.texturepack.BakedOverrideData; -import moe.nea.firmament.features.texturepack.FirmamentModelPredicate; -import net.minecraft.client.render.model.json.ModelOverrideList; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -@Mixin(ModelOverrideList.BakedOverride.class) -public class BakedOverrideDataHolder implements BakedOverrideData { - - @Unique - private FirmamentModelPredicate[] firmamentOverrides; - - @Nullable - @Override - public FirmamentModelPredicate[] getFirmamentOverrides() { - return firmamentOverrides; - } - - @Override - public void setFirmamentOverrides(@NotNull FirmamentModelPredicate[] overrides) { - this.firmamentOverrides = overrides; - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/HeadModelReplacerPatch.java b/src/main/java/moe/nea/firmament/mixins/custommodels/HeadModelReplacerPatch.java deleted file mode 100644 index 26c331e..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/HeadModelReplacerPatch.java +++ /dev/null @@ -1,57 +0,0 @@ - -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.BakedModelExtra; -import net.minecraft.block.AbstractSkullBlock; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.entity.LivingEntityRenderer; -import net.minecraft.client.render.entity.feature.HeadFeatureRenderer; -import net.minecraft.client.render.entity.model.EntityModel; -import net.minecraft.client.render.entity.model.ModelWithHead; -import net.minecraft.client.render.entity.state.LivingEntityRenderState; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.entity.EquipmentSlot; -import net.minecraft.item.BlockItem; -import net.minecraft.item.ItemStack; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(HeadFeatureRenderer.class) -public class HeadModelReplacerPatch<S extends LivingEntityRenderState, M extends EntityModel<S> & ModelWithHead> { - /** - * This class serves to disable the replacing of head models with the vanilla block model. Vanilla first selects loads - * the model containing the head model regularly in {@link LivingEntityRenderer#updateRenderState}, but then discards - * the model in {@link HeadFeatureRenderer#render(MatrixStack, VertexConsumerProvider, int, LivingEntityRenderState, float, float)} - * if it detects a skull block. This serves to disable that functionality if a head model override is present. - */ - @WrapOperation(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/LivingEntityRenderState;FF)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BlockItem;getBlock()Lnet/minecraft/block/Block;")) - private Block replaceSkull(BlockItem instance, Operation<Block> original, @Local BakedModel bakedModel) { - var oldBlock = original.call(instance); - if (oldBlock instanceof AbstractSkullBlock) { - var extra = BakedModelExtra.cast(bakedModel); - if (extra != null && extra.getHeadModel_firmament() != null) - return Blocks.ENCHANTING_TABLE; // Any non skull block. Let's choose the enchanting table because it is very distinct. - } - return oldBlock; - } - - /** - * We disable the has model override, since texture packs get precedent to server data. - */ - @WrapOperation(method = "render(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/client/render/entity/state/LivingEntityRenderState;FF)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/feature/ArmorFeatureRenderer;hasModel(Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/EquipmentSlot;)Z")) - private boolean replaceHasModel(ItemStack stack, EquipmentSlot slot, Operation<Boolean> original, - @Local BakedModel bakedModel) { - var extra = BakedModelExtra.cast(bakedModel); - if (extra != null && extra.getHeadModel_firmament() != null) - return false; - return original.call(stack, slot); - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ItemColorRemovalPatch.java b/src/main/java/moe/nea/firmament/mixins/custommodels/ItemColorRemovalPatch.java deleted file mode 100644 index 8c76c60..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ItemColorRemovalPatch.java +++ /dev/null @@ -1,39 +0,0 @@ -package moe.nea.firmament.mixins.custommodels; - -import moe.nea.firmament.features.texturepack.TintOverrides; -import moe.nea.firmament.init.ItemColorsSodiumRiser; -import net.minecraft.client.color.item.ItemColorProvider; -import net.minecraft.client.color.item.ItemColors; -import net.minecraft.item.ItemStack; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(ItemColors.class) -public class ItemColorRemovalPatch { - - /** - * @see ItemColorsSodiumRiser - */ - private @Nullable ItemColorProvider overrideSodium_firmament(@Nullable ItemColorProvider original) { - var tintOverrides = TintOverrides.Companion.getCurrentOverrides(); - if (!tintOverrides.hasOverrides()) return original; - return (stack, tintIndex) -> { - var override = tintOverrides.getOverride(tintIndex); - if (override != null) return override; - if (original != null) return original.getColor(stack, tintIndex); - return -1; - }; - } - - - @Inject(method = "getColor", at = @At("HEAD"), cancellable = true) - private void overrideGetColorCall(ItemStack item, int tintIndex, CallbackInfoReturnable<Integer> cir) { - var tintOverrides = TintOverrides.Companion.getCurrentOverrides(); - var override = tintOverrides.getOverride(tintIndex); - if (override != null) - cir.setReturnValue(override); - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ItemModelGeneratorJsonUnbakedModelCopy.java b/src/main/java/moe/nea/firmament/mixins/custommodels/ItemModelGeneratorJsonUnbakedModelCopy.java deleted file mode 100644 index 89d0411..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ItemModelGeneratorJsonUnbakedModelCopy.java +++ /dev/null @@ -1,22 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.llamalad7.mixinextras.sugar.Local; -import moe.nea.firmament.features.texturepack.JsonUnbakedModelFirmExtra; -import net.minecraft.client.render.model.json.ItemModelGenerator; -import net.minecraft.client.render.model.json.JsonUnbakedModel; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(ItemModelGenerator.class) -public class ItemModelGeneratorJsonUnbakedModelCopy { - @ModifyReturnValue(method = "create", at = @At("RETURN")) - private JsonUnbakedModel copyExtraModelData(JsonUnbakedModel original, @Local(argsOnly = true) JsonUnbakedModel oldModel) { - var extra = ((JsonUnbakedModelFirmExtra) original); - var oldExtra = ((JsonUnbakedModelFirmExtra) oldModel); - extra.setHeadModel_firmament(oldExtra.getHeadModel_firmament()); - extra.setTintOverrides_firmament(oldExtra.getTintOverrides_firmament()); - return original; - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ItemRendererTintContextPatch.java b/src/main/java/moe/nea/firmament/mixins/custommodels/ItemRendererTintContextPatch.java deleted file mode 100644 index 8c5411b..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ItemRendererTintContextPatch.java +++ /dev/null @@ -1,35 +0,0 @@ -package moe.nea.firmament.mixins.custommodels; - -import moe.nea.firmament.features.texturepack.BakedModelExtra; -import moe.nea.firmament.features.texturepack.TintOverrides; -import net.minecraft.client.render.VertexConsumerProvider; -import net.minecraft.client.render.item.ItemRenderer; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.util.math.MatrixStack; -import net.minecraft.item.ItemStack; -import net.minecraft.item.ModelTransformationMode; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(value = ItemRenderer.class, priority = 1010) -public class ItemRendererTintContextPatch { - @Inject(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;ZF)V", - at = @At(value = "HEAD"), allow = 1) - private void onStartRendering(ItemStack stack, ModelTransformationMode transformationMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model, boolean useInventoryModel, float z, CallbackInfo ci) { - var extra = BakedModelExtra.cast(model); - if (extra != null) { - TintOverrides.Companion.enter(extra.getTintOverrides_firmament()); - } - } - - @Inject(method = "renderItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;ZLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;IILnet/minecraft/client/render/model/BakedModel;ZF)V", - at = @At("TAIL"), allow = 1) - private void onEndRendering(ItemStack stack, ModelTransformationMode transformationMode, boolean leftHanded, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, int overlay, BakedModel model, boolean useInventoryModel, float z, CallbackInfo ci) { - var extra = BakedModelExtra.cast(model); - if (extra != null) { - TintOverrides.Companion.exit(extra.getTintOverrides_firmament()); - } - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/JsonUnbakedModelDataHolder.java b/src/main/java/moe/nea/firmament/mixins/custommodels/JsonUnbakedModelDataHolder.java deleted file mode 100644 index a5bb34f..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/JsonUnbakedModelDataHolder.java +++ /dev/null @@ -1,130 +0,0 @@ -package moe.nea.firmament.mixins.custommodels; - -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.llamalad7.mixinextras.sugar.Local; -import moe.nea.firmament.features.texturepack.BakedModelExtra; -import moe.nea.firmament.features.texturepack.JsonUnbakedModelFirmExtra; -import moe.nea.firmament.features.texturepack.TintOverrides; -import moe.nea.firmament.util.ErrorUtil; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.ModelRotation; -import net.minecraft.client.render.model.UnbakedModel; -import net.minecraft.client.render.model.json.JsonUnbakedModel; -import net.minecraft.util.Identifier; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; -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.Objects; - -@Mixin(JsonUnbakedModel.class) -public abstract class JsonUnbakedModelDataHolder implements JsonUnbakedModelFirmExtra { - @Shadow - @Nullable - protected JsonUnbakedModel parent; - - @Shadow - public abstract String toString(); - - @Unique - @Nullable - public Identifier headModel; - @Unique - @Nullable - public TintOverrides tintOverrides; - @Unique - @Nullable - public TintOverrides mergedTintOverrides; - - @Override - public void setTintOverrides_firmament(@Nullable TintOverrides tintOverrides) { - this.tintOverrides = tintOverrides; - this.mergedTintOverrides = null; - } - - @Override - public @NotNull TintOverrides getTintOverrides_firmament() { - if (mergedTintOverrides != null) - return mergedTintOverrides; - var mergedTintOverrides = parent == null ? new TintOverrides() - : ((JsonUnbakedModelFirmExtra) parent).getTintOverrides_firmament(); - if (tintOverrides != null) - mergedTintOverrides = tintOverrides.mergeWithParent(mergedTintOverrides); - this.mergedTintOverrides = mergedTintOverrides; - return mergedTintOverrides; - } - - @Override - public void setHeadModel_firmament(@Nullable Identifier identifier) { - this.headModel = identifier; - } - - @Override - public @Nullable Identifier getHeadModel_firmament() { - if (this.headModel != null) return this.headModel; - if (this.parent == null) return null; - return ((JsonUnbakedModelFirmExtra) this.parent).getHeadModel_firmament(); - } - - @Inject(method = "resolve", at = @At("HEAD")) - private void addDependencies(UnbakedModel.Resolver resolver, CallbackInfo ci) { - var headModel = getHeadModel_firmament(); - if (headModel != null) { - resolver.resolve(headModel); - } - } - - private void addExtraBakeInfo(BakedModel bakedModel, Baker baker) { - if (!this.toString().contains("minecraft") && this.toString().contains("crimson")) { - System.out.println("Found non minecraft model " + this); - } - var extra = BakedModelExtra.cast(bakedModel); - if (extra != null) { - var headModel = getHeadModel_firmament(); - if (headModel != null) { - extra.setHeadModel_firmament(baker.bake(headModel, ModelRotation.X0_Y0)); - } - if (getTintOverrides_firmament().hasOverrides()) { - extra.setTintOverrides_firmament(getTintOverrides_firmament()); - } - } - } - - /** - * @see ProvideBakerToJsonUnbakedModelPatch - */ - @Override - public void storeExtraBaker_firmament(@NotNull Baker baker) { - this.storedBaker = baker; - } - - @Unique - private Baker storedBaker; - - @ModifyReturnValue( - method = "bake(Ljava/util/function/Function;Lnet/minecraft/client/render/model/ModelBakeSettings;Z)Lnet/minecraft/client/render/model/BakedModel;", - at = @At("RETURN")) - private BakedModel bakeExtraInfoWithoutBaker(BakedModel original) { - if (storedBaker != null) { - addExtraBakeInfo(original, storedBaker); - storedBaker = null; - } - return original; - } - - @ModifyReturnValue( - method = { - "bake(Lnet/minecraft/client/render/model/Baker;Ljava/util/function/Function;Lnet/minecraft/client/render/model/ModelBakeSettings;)Lnet/minecraft/client/render/model/BakedModel;" - }, - at = @At(value = "RETURN")) - private BakedModel bakeExtraInfo(BakedModel original, @Local(argsOnly = true) Baker baker) { - addExtraBakeInfo(original, baker); - return original; - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ModelOverrideDataHolder.java b/src/main/java/moe/nea/firmament/mixins/custommodels/ModelOverrideDataHolder.java deleted file mode 100644 index 5f9689a..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ModelOverrideDataHolder.java +++ /dev/null @@ -1,28 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import moe.nea.firmament.features.texturepack.FirmamentModelPredicate; -import moe.nea.firmament.features.texturepack.ModelOverrideData; -import net.minecraft.client.render.model.json.ModelOverride; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -@Mixin(ModelOverride.class) -public class ModelOverrideDataHolder implements ModelOverrideData { - - @Unique - private FirmamentModelPredicate[] overrides; - - @Nullable - @Override - public FirmamentModelPredicate[] getFirmamentOverrides() { - return overrides; - } - - @Override - public void setFirmamentOverrides(@NotNull FirmamentModelPredicate[] overrides) { - this.overrides = overrides; - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchJsonUnbakedModelDeserializer.java b/src/main/java/moe/nea/firmament/mixins/custommodels/PatchJsonUnbakedModelDeserializer.java deleted file mode 100644 index d6c25b5..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchJsonUnbakedModelDeserializer.java +++ /dev/null @@ -1,31 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.llamalad7.mixinextras.sugar.Local; -import moe.nea.firmament.features.texturepack.JsonUnbakedModelFirmExtra; -import moe.nea.firmament.features.texturepack.TintOverrides; -import net.minecraft.client.render.model.json.JsonUnbakedModel; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(JsonUnbakedModel.Deserializer.class) -public class PatchJsonUnbakedModelDeserializer { - @ModifyReturnValue(method = "deserialize(Lcom/google/gson/JsonElement;Ljava/lang/reflect/Type;Lcom/google/gson/JsonDeserializationContext;)Lnet/minecraft/client/render/model/json/JsonUnbakedModel;", - at = @At("RETURN")) - private JsonUnbakedModel addHeadModel(JsonUnbakedModel original, @Local JsonObject jsonObject) { - var headModel = jsonObject.get("firmament:head_model"); - var extra = ((JsonUnbakedModelFirmExtra) original); - if (headModel instanceof JsonPrimitive prim && prim.isString()) { - extra.setHeadModel_firmament(Identifier.of(prim.getAsString())); - } - var tintOverrides = jsonObject.get("firmament:tint_overrides"); - if (tintOverrides instanceof JsonObject object) { - extra.setTintOverrides_firmament(TintOverrides.Companion.parse(object)); - } - return original; - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java b/src/main/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java deleted file mode 100644 index 8c0b3f8..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java +++ /dev/null @@ -1,22 +0,0 @@ -package moe.nea.firmament.mixins.custommodels; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import moe.nea.firmament.features.texturepack.CustomGlobalArmorOverrides; -import net.minecraft.client.render.entity.equipment.EquipmentModelLoader; -import net.minecraft.client.render.entity.equipment.EquipmentRenderer; -import net.minecraft.item.equipment.EquipmentModel; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -@Mixin(EquipmentRenderer.class) -public class PatchLegacyArmorLayerSupport { - @WrapOperation(method = "render(Lnet/minecraft/item/equipment/EquipmentModel$LayerType;Lnet/minecraft/util/Identifier;Lnet/minecraft/client/model/Model;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/util/Identifier;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/equipment/EquipmentModelLoader;get(Lnet/minecraft/util/Identifier;)Lnet/minecraft/item/equipment/EquipmentModel;")) - private EquipmentModel patchModelLayers(EquipmentModelLoader instance, Identifier id, Operation<EquipmentModel> original) { - var modelOverride = CustomGlobalArmorOverrides.overrideArmorLayer(id); - if (modelOverride != null) return modelOverride; - return original.call(instance, id); - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchOverrideDeserializer.java b/src/main/java/moe/nea/firmament/mixins/custommodels/PatchOverrideDeserializer.java deleted file mode 100644 index abb1792..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchOverrideDeserializer.java +++ /dev/null @@ -1,50 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonPrimitive; -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.llamalad7.mixinextras.sugar.Local; -import moe.nea.firmament.features.texturepack.CustomModelOverrideParser; -import moe.nea.firmament.features.texturepack.ModelOverrideData; -import net.minecraft.client.render.model.json.ModelOverride; -import net.minecraft.util.Identifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -import java.util.List; -import java.util.Map; - -@Mixin(ModelOverride.Deserializer.class) -public class PatchOverrideDeserializer { - - @ModifyReturnValue( - method = "deserialize(Lcom/google/gson/JsonElement;Ljava/lang/reflect/Type;Lcom/google/gson/JsonDeserializationContext;)Lnet/minecraft/client/render/model/json/ModelOverride;", - at = @At(value = "RETURN")) - private ModelOverride addCustomOverrides(ModelOverride original, @Local JsonObject jsonObject) { - var originalData = (ModelOverrideData) (Object) original; - originalData.setFirmamentOverrides(CustomModelOverrideParser.parseCustomModelOverrides(jsonObject)); - return original; - } - - @ModifyExpressionValue( - method = "deserializeMinPropertyValues(Lcom/google/gson/JsonObject;)Ljava/util/List;", - at = @At(value = "INVOKE", target = "Ljava/util/Map$Entry;getValue()Ljava/lang/Object;")) - private Object removeFirmamentPredicatesFromJsonIteration(Object original, @Local Map.Entry<String, JsonElement> entry) { - if (entry.getKey().startsWith("firmament:")) return new JsonPrimitive(0F); - return original; - } - - @Inject( - method = "deserializeMinPropertyValues", - at = @At(value = "INVOKE", target = "Ljava/util/Map;entrySet()Ljava/util/Set;") - ) - private void whatever(JsonObject object, CallbackInfoReturnable<List<ModelOverride.Condition>> cir, - @Local Map<Identifier, Float> maps) { - maps.entrySet().removeIf(it -> it.getKey().getNamespace().equals("firmament")); - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ProvideBakerToJsonUnbakedModelPatch.java b/src/main/java/moe/nea/firmament/mixins/custommodels/ProvideBakerToJsonUnbakedModelPatch.java deleted file mode 100644 index c1ac119..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ProvideBakerToJsonUnbakedModelPatch.java +++ /dev/null @@ -1,27 +0,0 @@ -package moe.nea.firmament.mixins.custommodels; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import moe.nea.firmament.features.texturepack.JsonUnbakedModelFirmExtra; -import net.minecraft.client.render.model.BakedModel; -import net.minecraft.client.render.model.Baker; -import net.minecraft.client.render.model.ModelBakeSettings; -import net.minecraft.client.render.model.json.JsonUnbakedModel; -import net.minecraft.client.texture.Sprite; -import net.minecraft.client.util.SpriteIdentifier; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; - -import java.util.function.Function; - -/** - * @see JsonUnbakedModelDataHolder#storeExtraBaker_firmament - */ -@Mixin(targets = "net.minecraft.client.render.model.ModelBaker$BakerImpl") -public abstract class ProvideBakerToJsonUnbakedModelPatch implements Baker { - @WrapOperation(method = "bake(Lnet/minecraft/client/render/model/UnbakedModel;Lnet/minecraft/client/render/model/ModelBakeSettings;)Lnet/minecraft/client/render/model/BakedModel;", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/json/JsonUnbakedModel;bake(Ljava/util/function/Function;Lnet/minecraft/client/render/model/ModelBakeSettings;Z)Lnet/minecraft/client/render/model/BakedModel;")) - private BakedModel provideExtraBakerToModel(JsonUnbakedModel instance, Function<SpriteIdentifier, Sprite> function, ModelBakeSettings modelBakeSettings, boolean bl, Operation<BakedModel> original) { - ((JsonUnbakedModelFirmExtra) instance).storeExtraBaker_firmament(this); - return original.call(instance, function, modelBakeSettings, bl); - } -} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/TestForFirmamentOverridePredicatesPatch.java b/src/main/java/moe/nea/firmament/mixins/custommodels/TestForFirmamentOverridePredicatesPatch.java deleted file mode 100644 index 63f3cf0..0000000 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/TestForFirmamentOverridePredicatesPatch.java +++ /dev/null @@ -1,68 +0,0 @@ - -package moe.nea.firmament.mixins.custommodels; - -import com.llamalad7.mixinextras.injector.ModifyExpressionValue; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import com.llamalad7.mixinextras.sugar.Local; -import moe.nea.firmament.Firmament; -import moe.nea.firmament.features.texturepack.BakedOverrideData; -import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures; -import moe.nea.firmament.features.texturepack.FirmamentModelPredicate; -import moe.nea.firmament.features.texturepack.ModelOverrideData; -import net.minecraft.client.render.model.json.ModelOverride; -import net.minecraft.client.render.model.json.ModelOverrideList; -import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; -import org.objectweb.asm.Opcodes; -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.ModifyArg; - -import java.util.List; -import java.util.Objects; - -@Mixin(ModelOverrideList.class) -public class TestForFirmamentOverridePredicatesPatch { - - @Shadow - private Identifier[] conditionTypes; - - @ModifyArg(method = "<init>(Lnet/minecraft/client/render/model/Baker;Ljava/util/List;)V", - at = @At( - value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z" - )) - public Object onInit( - Object element, - @Local ModelOverride modelOverride - ) { - var bakedOverride = (ModelOverrideList.BakedOverride) element; - var modelOverrideData = ModelOverrideData.cast(modelOverride); - BakedOverrideData.cast(bakedOverride) - .setFirmamentOverrides(modelOverrideData.getFirmamentOverrides()); - if (conditionTypes.length == 0 && - modelOverrideData.getFirmamentOverrides() != null && - modelOverrideData.getFirmamentOverrides().length > 0) { - conditionTypes = new Identifier[]{Firmament.INSTANCE.identifier("sentinel/enforce_model_override_evaluation")}; - } - return element; - } - - @ModifyExpressionValue(method = "getModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/model/json/ModelOverrideList$BakedOverride;test([F)Z")) - public boolean testFirmamentOverrides(boolean originalValue, - @Local ModelOverrideList.BakedOverride bakedOverride, - @Local(argsOnly = true) ItemStack stack) { - if (!originalValue) return false; - var overrideData = (BakedOverrideData) (Object) bakedOverride; - var overrides = overrideData.getFirmamentOverrides(); - if (overrides == null) return true; - if (!CustomSkyBlockTextures.TConfig.INSTANCE.getEnableModelOverrides()) return false; - for (FirmamentModelPredicate firmamentOverride : overrides) { - if (!firmamentOverride.test(stack)) - return false; - } - return true; - } -} diff --git a/src/main/kotlin/events/BakeExtraModelsEvent.kt b/src/main/kotlin/events/BakeExtraModelsEvent.kt index adaa495..35bfecb 100644 --- a/src/main/kotlin/events/BakeExtraModelsEvent.kt +++ b/src/main/kotlin/events/BakeExtraModelsEvent.kt @@ -1,11 +1,13 @@ package moe.nea.firmament.events import java.util.function.BiConsumer +import net.minecraft.client.item.ItemAssetsLoader import net.minecraft.client.render.model.ReferencedModelsCollector import net.minecraft.client.util.ModelIdentifier import net.minecraft.util.Identifier -// TODO: Rename this event, since it is not really directly baking models anymore +// TODO: This event may be removed now since ItemAssetsLoader seems to load all item models now (probably to cope with servers setting the item_model component). Check whether this also applies to blocks now. +//@Deprecated(level = DeprecationLevel.ERROR, message = "This is no longer needed, since ItemAssetsLoader loads all item models.") class BakeExtraModelsEvent( private val addAnyModel: BiConsumer<ModelIdentifier, Identifier>, ) : FirmamentEvent() { @@ -15,10 +17,13 @@ class BakeExtraModelsEvent( } fun addItemModel(modelIdentifier: ModelIdentifier) { - addNonItemModel( - modelIdentifier, - modelIdentifier.id.withPrefixedPath(ReferencedModelsCollector.ITEM_DIRECTORY)) + // TODO: If this is still needed: ItemAssetsLoader.FINDER + // addNonItemModel( +// modelIdentifier, +// modelIdentifier.id.withPrefixedPath()) } +// @Deprecated(level = DeprecationLevel.ERROR, message = "This is no longer needed, since ItemAssetsLoader loads all item models.") + @Suppress("DEPRECATION") companion object : FirmamentEventBus<BakeExtraModelsEvent>() } diff --git a/src/main/kotlin/events/CustomItemModelEvent.kt b/src/main/kotlin/events/CustomItemModelEvent.kt index 4328d77..7abdaf7 100644 --- a/src/main/kotlin/events/CustomItemModelEvent.kt +++ b/src/main/kotlin/events/CustomItemModelEvent.kt @@ -1,38 +1,23 @@ package moe.nea.firmament.events -import java.util.Optional -import kotlin.jvm.optionals.getOrNull -import net.minecraft.client.render.item.ItemModels -import net.minecraft.client.render.model.BakedModel -import net.minecraft.client.util.ModelIdentifier import net.minecraft.item.ItemStack -import moe.nea.firmament.util.ErrorUtil -import moe.nea.firmament.util.collections.WeakCache +import net.minecraft.util.Identifier +// TODO: assert an order on these events data class CustomItemModelEvent( val itemStack: ItemStack, - var overrideModel: ModelIdentifier? = null, + var overrideModel: Identifier? = null, ) : FirmamentEvent() { companion object : FirmamentEventBus<CustomItemModelEvent>() { - val cache = - WeakCache.memoize<ItemStack, ItemModels, Optional<BakedModel>>("CustomItemModels") { stack, models -> - val modelId = getModelIdentifier(stack) ?: return@memoize Optional.empty() - ErrorUtil.softCheck("Model Id needs to have an inventory variant", modelId.variant() == "inventory") - val bakedModel = models.getModel(modelId.id) - if (bakedModel == null || bakedModel === models.missingModelSupplier.get()) return@memoize Optional.empty() - Optional.of(bakedModel) - } - @JvmStatic - fun getModelIdentifier(itemStack: ItemStack?): ModelIdentifier? { + fun getModelIdentifier(itemStack: ItemStack?): Identifier? { + // TODO: Re-add memoization and add an error / warning if the model does not exist if (itemStack == null) return null return publish(CustomItemModelEvent(itemStack)).overrideModel } + } - @JvmStatic - fun getModel(itemStack: ItemStack?, thing: ItemModels): BakedModel? { - if (itemStack == null) return null - return cache.invoke(itemStack, thing).getOrNull() - } + fun overrideIfExists(overrideModel: Identifier) { + TODO() } } diff --git a/src/main/kotlin/features/FeatureManager.kt b/src/main/kotlin/features/FeatureManager.kt index 2110d09..0f5ebf8 100644 --- a/src/main/kotlin/features/FeatureManager.kt +++ b/src/main/kotlin/features/FeatureManager.kt @@ -29,7 +29,6 @@ import moe.nea.firmament.features.inventory.buttons.InventoryButtons import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlay import moe.nea.firmament.features.mining.PickaxeAbility import moe.nea.firmament.features.mining.PristineProfitTracker -import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures import moe.nea.firmament.features.world.FairySouls import moe.nea.firmament.features.world.Waypoints import moe.nea.firmament.util.data.DataHolder @@ -70,7 +69,6 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature loadFeature(QuickCommands) loadFeature(PetFeatures) loadFeature(SaveCursorPosition) - loadFeature(CustomSkyBlockTextures) loadFeature(PriceData) loadFeature(Fixes) loadFeature(DianaWaypoints) diff --git a/src/main/kotlin/features/chat/ChatLinks.kt b/src/main/kotlin/features/chat/ChatLinks.kt index 5bce3f4..f85825b 100644 --- a/src/main/kotlin/features/chat/ChatLinks.kt +++ b/src/main/kotlin/features/chat/ChatLinks.kt @@ -1,5 +1,3 @@ - - package moe.nea.firmament.features.chat import io.ktor.client.request.get @@ -7,16 +5,15 @@ import io.ktor.client.statement.bodyAsChannel import io.ktor.utils.io.jvm.javaio.toInputStream import java.net.URL import java.util.Collections +import java.util.concurrent.atomic.AtomicInteger import moe.nea.jarvis.api.Point import kotlinx.coroutines.Deferred import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.async import kotlin.math.min import net.minecraft.client.gui.screen.ChatScreen -import net.minecraft.client.render.RenderLayer import net.minecraft.client.texture.NativeImage import net.minecraft.client.texture.NativeImageBackedTexture -import net.minecraft.scoreboard.ScoreboardCriterion.RenderType import net.minecraft.text.ClickEvent import net.minecraft.text.HoverEvent import net.minecraft.text.Style @@ -35,130 +32,132 @@ import moe.nea.firmament.util.transformEachRecursively import moe.nea.firmament.util.unformattedString object ChatLinks : FirmamentFeature { - override val identifier: String - get() = "chat-links" + override val identifier: String + get() = "chat-links" - object TConfig : ManagedConfig(identifier, Category.CHAT) { - val enableLinks by toggle("links-enabled") { true } - val imageEnabled by toggle("image-enabled") { true } - val allowAllHosts by toggle("allow-all-hosts") { false } - val allowedHosts by string("allowed-hosts") { "cdn.discordapp.com,media.discordapp.com,media.discordapp.net,i.imgur.com" } - val actualAllowedHosts get() = allowedHosts.split(",").map { it.trim() } - val position by position("position", 16 * 20, 9 * 20) { Point(0.0, 0.0) } - } + object TConfig : ManagedConfig(identifier, Category.CHAT) { + val enableLinks by toggle("links-enabled") { true } + val imageEnabled by toggle("image-enabled") { true } + val allowAllHosts by toggle("allow-all-hosts") { false } + val allowedHosts by string("allowed-hosts") { "cdn.discordapp.com,media.discordapp.com,media.discordapp.net,i.imgur.com" } + val actualAllowedHosts get() = allowedHosts.split(",").map { it.trim() } + val position by position("position", 16 * 20, 9 * 20) { Point(0.0, 0.0) } + } - private fun isHostAllowed(host: String) = - TConfig.allowAllHosts || TConfig.actualAllowedHosts.any { it.equals(host, ignoreCase = true) } + private fun isHostAllowed(host: String) = + TConfig.allowAllHosts || TConfig.actualAllowedHosts.any { it.equals(host, ignoreCase = true) } - private fun isUrlAllowed(url: String) = isHostAllowed(url.removePrefix("https://").substringBefore("/")) + private fun isUrlAllowed(url: String) = isHostAllowed(url.removePrefix("https://").substringBefore("/")) - override val config get() = TConfig - val urlRegex = "https://[^. ]+\\.[^ ]+(\\.?( |$))".toRegex() + override val config get() = TConfig + val urlRegex = "https://[^. ]+\\.[^ ]+(\\.?( |$))".toRegex() + val nextTexId = AtomicInteger(0) - data class Image( - val texture: Identifier, - val width: Int, - val height: Int, - ) + data class Image( + val texture: Identifier, + val width: Int, + val height: Int, + ) - val imageCache: MutableMap<String, Deferred<Image?>> = - Collections.synchronizedMap(mutableMapOf<String, Deferred<Image?>>()) + val imageCache: MutableMap<String, Deferred<Image?>> = + Collections.synchronizedMap(mutableMapOf<String, Deferred<Image?>>()) - private fun tryCacheUrl(url: String) { - if (!isUrlAllowed(url)) { - return - } - if (url in imageCache) { - return - } - imageCache[url] = Firmament.coroutineScope.async { - try { - val response = Firmament.httpClient.get(URL(url)) - if (response.status.value == 200) { - val inputStream = response.bodyAsChannel().toInputStream(Firmament.globalJob) - val image = NativeImage.read(inputStream) - val texture = MC.textureManager.registerDynamicTexture( - "dynamic_image_preview", - NativeImageBackedTexture(image) - ) - Image(texture, image.width, image.height) - } else - null - } catch (exc: Exception) { - exc.printStackTrace() - null - } - } - } + private fun tryCacheUrl(url: String) { + if (!isUrlAllowed(url)) { + return + } + if (url in imageCache) { + return + } + imageCache[url] = Firmament.coroutineScope.async { + try { + val response = Firmament.httpClient.get(URL(url)) + if (response.status.value == 200) { + val inputStream = response.bodyAsChannel().toInputStream(Firmament.globalJob) + val image = NativeImage.read(inputStream) + val texId = Firmament.identifier("dynamic_image_preview${nextTexId.getAndIncrement()}") + MC.textureManager.registerTexture( + texId, + NativeImageBackedTexture(image) + ) + Image(texId, image.width, image.height) + } else + null + } catch (exc: Exception) { + exc.printStackTrace() + null + } + } + } - val imageExtensions = listOf("jpg", "png", "gif", "jpeg") - fun isImageUrl(url: String): Boolean { - return (url.substringAfterLast('.').lowercase() in imageExtensions) - } + val imageExtensions = listOf("jpg", "png", "gif", "jpeg") + fun isImageUrl(url: String): Boolean { + return (url.substringAfterLast('.').lowercase() in imageExtensions) + } - @Subscribe - @OptIn(ExperimentalCoroutinesApi::class) - fun onRender(it: ScreenRenderPostEvent) { - if (!TConfig.imageEnabled) return - if (it.screen !is ChatScreen) return - val hoveredComponent = - MC.inGameHud.chatHud.getTextStyleAt(it.mouseX.toDouble(), it.mouseY.toDouble()) ?: return - val hoverEvent = hoveredComponent.hoverEvent ?: return - val value = hoverEvent.getValue(HoverEvent.Action.SHOW_TEXT) ?: return - val url = urlRegex.matchEntire(value.unformattedString)?.groupValues?.get(0) ?: return - if (!isImageUrl(url)) return - val imageFuture = imageCache[url] ?: return - if (!imageFuture.isCompleted) return - val image = imageFuture.getCompleted() ?: return - it.drawContext.matrices.push() - val pos = TConfig.position - pos.applyTransformations(it.drawContext.matrices) - val scale = min(1F, min((9 * 20F) / image.height, (16 * 20F) / image.width)) - it.drawContext.matrices.scale(scale, scale, 1F) - it.drawContext.drawTexture( - image.texture, - 0, - 0, - 1F, - 1F, - image.width, - image.height, - image.width, - image.height, - ) - it.drawContext.matrices.pop() - } + @Subscribe + @OptIn(ExperimentalCoroutinesApi::class) + fun onRender(it: ScreenRenderPostEvent) { + if (!TConfig.imageEnabled) return + if (it.screen !is ChatScreen) return + val hoveredComponent = + MC.inGameHud.chatHud.getTextStyleAt(it.mouseX.toDouble(), it.mouseY.toDouble()) ?: return + val hoverEvent = hoveredComponent.hoverEvent ?: return + val value = hoverEvent.getValue(HoverEvent.Action.SHOW_TEXT) ?: return + val url = urlRegex.matchEntire(value.unformattedString)?.groupValues?.get(0) ?: return + if (!isImageUrl(url)) return + val imageFuture = imageCache[url] ?: return + if (!imageFuture.isCompleted) return + val image = imageFuture.getCompleted() ?: return + it.drawContext.matrices.push() + val pos = TConfig.position + pos.applyTransformations(it.drawContext.matrices) + val scale = min(1F, min((9 * 20F) / image.height, (16 * 20F) / image.width)) + it.drawContext.matrices.scale(scale, scale, 1F) + it.drawContext.drawTexture( + image.texture, + 0, + 0, + 1F, + 1F, + image.width, + image.height, + image.width, + image.height, + ) + it.drawContext.matrices.pop() + } - @Subscribe - fun onModifyChat(it: ModifyChatEvent) { - if (!TConfig.enableLinks) return - it.replaceWith = it.replaceWith.transformEachRecursively { child -> - val text = child.string - if ("://" !in text) return@transformEachRecursively child - val s = Text.empty().setStyle(child.style) - var index = 0 - while (index < text.length) { - val nextMatch = urlRegex.find(text, index) - if (nextMatch == null) { - s.append(Text.literal(text.substring(index, text.length))) - break - } - val range = nextMatch.groups[0]!!.range - val url = nextMatch.groupValues[0] - s.append(Text.literal(text.substring(index, range.first))) - s.append( - Text.literal(url).setStyle( - Style.EMPTY.withUnderline(true).withColor( - Formatting.AQUA - ).withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal(url))) - .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, url)) - ) - ) - if (isImageUrl(url)) - tryCacheUrl(url) - index = range.last + 1 - } - s - } - } + @Subscribe + fun onModifyChat(it: ModifyChatEvent) { + if (!TConfig.enableLinks) return + it.replaceWith = it.replaceWith.transformEachRecursively { child -> + val text = child.string + if ("://" !in text) return@transformEachRecursively child + val s = Text.empty().setStyle(child.style) + var index = 0 + while (index < text.length) { + val nextMatch = urlRegex.find(text, index) + if (nextMatch == null) { + s.append(Text.literal(text.substring(index, text.length))) + break + } + val range = nextMatch.groups[0]!!.range + val url = nextMatch.groupValues[0] + s.append(Text.literal(text.substring(index, range.first))) + s.append( + Text.literal(url).setStyle( + Style.EMPTY.withUnderline(true).withColor( + Formatting.AQUA + ).withHoverEvent(HoverEvent(HoverEvent.Action.SHOW_TEXT, Text.literal(url))) + .withClickEvent(ClickEvent(ClickEvent.Action.OPEN_URL, url)) + ) + ) + if (isImageUrl(url)) + tryCacheUrl(url) + index = range.last + 1 + } + s + } + } } diff --git a/src/main/kotlin/features/debug/PowerUserTools.kt b/src/main/kotlin/features/debug/PowerUserTools.kt index 13320dc..225bc13 100644 --- a/src/main/kotlin/features/debug/PowerUserTools.kt +++ b/src/main/kotlin/features/debug/PowerUserTools.kt @@ -5,6 +5,7 @@ import kotlin.jvm.optionals.getOrNull import net.minecraft.block.SkullBlock import net.minecraft.block.entity.SkullBlockEntity import net.minecraft.component.DataComponentTypes +import net.minecraft.component.type.ProfileComponent import net.minecraft.entity.Entity import net.minecraft.entity.LivingEntity import net.minecraft.item.ItemStack @@ -12,6 +13,7 @@ import net.minecraft.item.Items import net.minecraft.nbt.NbtOps import net.minecraft.text.Text import net.minecraft.text.TextCodecs +import net.minecraft.util.Identifier import net.minecraft.util.hit.BlockHitResult import net.minecraft.util.hit.EntityHitResult import net.minecraft.util.hit.HitResult @@ -23,7 +25,6 @@ import moe.nea.firmament.events.ScreenChangeEvent import moe.nea.firmament.events.TickEvent import moe.nea.firmament.events.WorldKeyboardEvent import moe.nea.firmament.features.FirmamentFeature -import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.mixins.accessor.AccessorHandledScreen import moe.nea.firmament.util.ClipboardUtils @@ -101,6 +102,8 @@ object PowerUserTools : FirmamentFeature { } } + // TODO: leak this through some other way, maybe. + lateinit var getSkullId: (profile: ProfileComponent) -> Identifier? @Subscribe fun copyInventoryInfo(it: HandledScreenKeyPressedEvent) { @@ -116,7 +119,7 @@ object PowerUserTools : FirmamentFeature { lastCopiedStack = Pair(item, Text.stringifiedTranslatable("firmament.tooltip.copied.skyblockid", sbId.neuItem)) } else if (it.matches(TConfig.copyTexturePackId)) { - val model = CustomItemModelEvent.getModelIdentifier(item) + val model = CustomItemModelEvent.getModelIdentifier(item) // TODO: remove global texture overrides, maybe if (model == null) { lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.modelid.fail")) return @@ -146,7 +149,7 @@ object PowerUserTools : FirmamentFeature { lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-profile")) return } - val skullTexture = CustomSkyBlockTextures.getSkullTexture(profile) + val skullTexture = getSkullId(profile) if (skullTexture == null) { lastCopiedStack = Pair(item, Text.translatable("firmament.tooltip.copied.skull-id.fail.no-texture")) return @@ -179,7 +182,7 @@ object PowerUserTools : FirmamentFeature { MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail")) return } - val id = CustomSkyBlockTextures.getSkullTexture(entity.owner!!) + val id = getSkullId(entity.owner!!) if (id == null) { MC.sendChat(Text.translatable("firmament.tooltip.copied.skull.fail")) } else { diff --git a/src/main/kotlin/features/texturepack/BakedModelExtra.kt b/src/main/kotlin/features/texturepack/BakedModelExtra.kt deleted file mode 100644 index 6305748..0000000 --- a/src/main/kotlin/features/texturepack/BakedModelExtra.kt +++ /dev/null @@ -1,30 +0,0 @@ -package moe.nea.firmament.features.texturepack - -import net.fabricmc.fabric.api.renderer.v1.model.WrapperBakedModel as WrapperBakedModelFabric -import net.minecraft.client.render.model.BakedModel -import net.minecraft.client.render.model.WrapperBakedModel -import moe.nea.firmament.util.ErrorUtil - -interface BakedModelExtra { - companion object { - @JvmStatic - fun cast(originalModel: BakedModel): BakedModelExtra? { - var p = originalModel - for (i in 0..256) { - p = when (p) { - is BakedModelExtra -> return p - is WrapperBakedModel -> p.wrapped - is WrapperBakedModelFabric -> WrapperBakedModelFabric.unwrap(p) - else -> break - } - } - ErrorUtil.softError("Could not find a baked model for $originalModel") - return null - } - } - - var tintOverrides_firmament: TintOverrides? - - fun getHeadModel_firmament(): BakedModel? - fun setHeadModel_firmament(headModel: BakedModel?) -} diff --git a/src/main/kotlin/features/texturepack/BakedOverrideData.kt b/src/main/kotlin/features/texturepack/BakedOverrideData.kt deleted file mode 100644 index e9391f1..0000000 --- a/src/main/kotlin/features/texturepack/BakedOverrideData.kt +++ /dev/null @@ -1,14 +0,0 @@ - -package moe.nea.firmament.features.texturepack - -import net.minecraft.client.render.model.json.ModelOverrideList - -interface BakedOverrideData { - fun getFirmamentOverrides(): Array<FirmamentModelPredicate>? - fun setFirmamentOverrides(overrides: Array<FirmamentModelPredicate>?) - companion object{ - @Suppress("CAST_NEVER_SUCCEEDS") - @JvmStatic - fun cast(bakedOverride: ModelOverrideList.BakedOverride): BakedOverrideData = bakedOverride as BakedOverrideData - } -} diff --git a/src/main/kotlin/features/texturepack/CustomModelOverrideParser.kt b/src/main/kotlin/features/texturepack/CustomModelOverrideParser.kt deleted file mode 100644 index c5fc20b..0000000 --- a/src/main/kotlin/features/texturepack/CustomModelOverrideParser.kt +++ /dev/null @@ -1,82 +0,0 @@ - -package moe.nea.firmament.features.texturepack - -import com.google.gson.JsonObject -import kotlinx.serialization.KSerializer -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -import moe.nea.firmament.features.texturepack.predicates.AndPredicate -import moe.nea.firmament.features.texturepack.predicates.DisplayNamePredicate -import moe.nea.firmament.features.texturepack.predicates.ExtraAttributesPredicate -import moe.nea.firmament.features.texturepack.predicates.ItemPredicate -import moe.nea.firmament.features.texturepack.predicates.LorePredicate -import moe.nea.firmament.features.texturepack.predicates.NotPredicate -import moe.nea.firmament.features.texturepack.predicates.OrPredicate -import moe.nea.firmament.features.texturepack.predicates.PetPredicate -import net.minecraft.item.ItemStack -import net.minecraft.util.Identifier - -object CustomModelOverrideParser { - object FirmamentRootPredicateSerializer : KSerializer<FirmamentModelPredicate> { - val delegateSerializer = kotlinx.serialization.json.JsonObject.serializer() - override val descriptor: SerialDescriptor - get() = SerialDescriptor("FirmamentModelRootPredicate", delegateSerializer.descriptor) - - override fun deserialize(decoder: Decoder): FirmamentModelPredicate { - val json = decoder.decodeSerializableValue(delegateSerializer).intoGson() as JsonObject - return AndPredicate(parsePredicates(json).toTypedArray()) - } - - override fun serialize(encoder: Encoder, value: FirmamentModelPredicate) { - TODO("Cannot serialize firmament predicates") - } - } - - val predicateParsers = mutableMapOf<Identifier, FirmamentModelPredicateParser>() - - - fun registerPredicateParser(name: String, parser: FirmamentModelPredicateParser) { - predicateParsers[Identifier.of("firmament", name)] = parser - } - - init { - registerPredicateParser("display_name", DisplayNamePredicate.Parser) - registerPredicateParser("lore", LorePredicate.Parser) - registerPredicateParser("all", AndPredicate.Parser) - registerPredicateParser("any", OrPredicate.Parser) - registerPredicateParser("not", NotPredicate.Parser) - registerPredicateParser("item", ItemPredicate.Parser) - registerPredicateParser("extra_attributes", ExtraAttributesPredicate.Parser) - registerPredicateParser("pet", PetPredicate.Parser) - } - - private val neverPredicate = listOf( - object : FirmamentModelPredicate { - override fun test(stack: ItemStack): Boolean { - return false - } - } - ) - - fun parsePredicates(predicates: JsonObject): List<FirmamentModelPredicate> { - val parsedPredicates = mutableListOf<FirmamentModelPredicate>() - for (predicateName in predicates.keySet()) { - if (!predicateName.startsWith("firmament:")) continue - val identifier = Identifier.of(predicateName) - val parser = predicateParsers[identifier] ?: return neverPredicate - val parsedPredicate = parser.parse(predicates[predicateName]) ?: return neverPredicate - parsedPredicates.add(parsedPredicate) - } - return parsedPredicates - } - - @JvmStatic - fun parseCustomModelOverrides(jsonObject: JsonObject): Array<FirmamentModelPredicate>? { - val predicates = (jsonObject["predicate"] as? JsonObject) ?: return null - val parsedPredicates = parsePredicates(predicates) - if (parsedPredicates.isEmpty()) - return null - return parsedPredicates.toTypedArray() - } -} diff --git a/src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt b/src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt deleted file mode 100644 index 627d39a..0000000 --- a/src/main/kotlin/features/texturepack/CustomSkyBlockTextures.kt +++ /dev/null @@ -1,135 +0,0 @@ -package moe.nea.firmament.features.texturepack - -import com.mojang.authlib.minecraft.MinecraftProfileTexture -import com.mojang.authlib.properties.Property -import java.util.Optional -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable -import kotlin.jvm.optionals.getOrNull -import net.minecraft.block.SkullBlock -import net.minecraft.client.MinecraftClient -import net.minecraft.client.render.RenderLayer -import net.minecraft.client.util.ModelIdentifier -import net.minecraft.component.type.ProfileComponent -import net.minecraft.util.Identifier -import moe.nea.firmament.annotations.Subscribe -import moe.nea.firmament.events.BakeExtraModelsEvent -import moe.nea.firmament.events.CustomItemModelEvent -import moe.nea.firmament.events.FinalizeResourceManagerEvent -import moe.nea.firmament.events.TickEvent -import moe.nea.firmament.features.FirmamentFeature -import moe.nea.firmament.gui.config.ManagedConfig -import moe.nea.firmament.util.collections.WeakCache -import moe.nea.firmament.util.mc.decodeProfileTextureProperty -import moe.nea.firmament.util.skyBlockId - -object CustomSkyBlockTextures : FirmamentFeature { - override val identifier: String - get() = "custom-skyblock-textures" - - object TConfig : ManagedConfig(identifier, Category.INTEGRATIONS) { // TODO: should this be its own thing? - val enabled by toggle("enabled") { true } - val skullsEnabled by toggle("skulls-enabled") { true } - val cacheForever by toggle("cache-forever") { true } - val cacheDuration by integer("cache-duration", 0, 100) { 1 } - val enableModelOverrides by toggle("model-overrides") { true } - val enableArmorOverrides by toggle("armor-overrides") { true } - val enableBlockOverrides by toggle("block-overrides") { true } - val enableLegacyCIT by toggle("legacy-cit") { true } - val allowRecoloringUiText by toggle("recolor-text") { true } - } - - override val config: ManagedConfig - get() = TConfig - - val allItemCaches by lazy { - listOf( - CustomItemModelEvent.cache.cache, - skullTextureCache.cache, - CustomGlobalTextures.overrideCache.cache, - CustomGlobalArmorOverrides.overrideCache.cache - ) - } - - fun clearAllCaches() { - allItemCaches.forEach(WeakCache<*, *, *>::clear) - } - - @Subscribe - fun onTick(it: TickEvent) { - if (TConfig.cacheForever) return - if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) { - clearAllCaches() - } - } - - @Subscribe - fun onStart(event: FinalizeResourceManagerEvent) { - event.registerOnApply("Clear firmament CIT caches") { - clearAllCaches() - } - } - - @Subscribe - fun bakeCustomFirmModels(event: BakeExtraModelsEvent) { - val resources = - MinecraftClient.getInstance().resourceManager.findResources("models/item" - ) { it: Identifier -> - "firmskyblock" == it.namespace && it.path - .endsWith(".json") - } - for (identifier in resources.keys) { - val modelId = ModelIdentifier.ofInventoryVariant( - Identifier.of( - "firmskyblock", - identifier.path.substring( - "models/item/".length, - identifier.path.length - ".json".length), - )) - event.addItemModel(modelId) - } - } - - @Subscribe - fun onCustomModelId(it: CustomItemModelEvent) { - if (!TConfig.enabled) return - val id = it.itemStack.skyBlockId ?: return - it.overrideModel = ModelIdentifier.ofInventoryVariant(Identifier.of("firmskyblock", id.identifier.path)) - } - - private val skullTextureCache = - WeakCache.memoize<ProfileComponent, Optional<Identifier>>("SkullTextureCache") { component -> - val id = getSkullTexture(component) ?: return@memoize Optional.empty() - if (!MinecraftClient.getInstance().resourceManager.getResource(id).isPresent) { - return@memoize Optional.empty() - } - return@memoize Optional.of(id) - } - - private val mcUrlRegex = "https?://textures.minecraft.net/texture/([a-fA-F0-9]+)".toRegex() - - fun getSkullId(textureProperty: Property): String? { - val texture = decodeProfileTextureProperty(textureProperty) ?: return null - val textureUrl = - texture.textures[MinecraftProfileTexture.Type.SKIN]?.url ?: return null - val mcUrlData = mcUrlRegex.matchEntire(textureUrl) ?: return null - return mcUrlData.groupValues[1] - } - - fun getSkullTexture(profile: ProfileComponent): Identifier? { - val id = getSkullId(profile.properties["textures"].firstOrNull() ?: return null) ?: return null - return Identifier.of("firmskyblock", "textures/placedskull/$id.png") - } - - fun modifySkullTexture( - type: SkullBlock.SkullType?, - component: ProfileComponent?, - cir: CallbackInfoReturnable<RenderLayer> - ) { - if (type != SkullBlock.Type.PLAYER) return - if (!TConfig.skullsEnabled) return - if (component == null) return - - val n = skullTextureCache.invoke(component).getOrNull() ?: return - cir.returnValue = RenderLayer.getEntityTranslucent(n) - } -} diff --git a/src/main/kotlin/features/texturepack/JsonUnbakedModelFirmExtra.kt b/src/main/kotlin/features/texturepack/JsonUnbakedModelFirmExtra.kt deleted file mode 100644 index 9f641b8..0000000 --- a/src/main/kotlin/features/texturepack/JsonUnbakedModelFirmExtra.kt +++ /dev/null @@ -1,16 +0,0 @@ - -package moe.nea.firmament.features.texturepack - -import net.minecraft.client.render.model.Baker -import net.minecraft.util.Identifier - -interface JsonUnbakedModelFirmExtra { - fun storeExtraBaker_firmament(baker: Baker) - - fun setHeadModel_firmament(identifier: Identifier?) - fun getHeadModel_firmament(): Identifier? - - fun setTintOverrides_firmament(tintOverrides: TintOverrides?) - fun getTintOverrides_firmament(): TintOverrides - -} diff --git a/src/main/kotlin/features/texturepack/ModelOverrideData.kt b/src/main/kotlin/features/texturepack/ModelOverrideData.kt deleted file mode 100644 index 29d9192..0000000 --- a/src/main/kotlin/features/texturepack/ModelOverrideData.kt +++ /dev/null @@ -1,15 +0,0 @@ -package moe.nea.firmament.features.texturepack - -import net.minecraft.client.render.model.json.ModelOverride - -interface ModelOverrideData { - companion object { - - @JvmStatic - @Suppress("CAST_NEVER_SUCCEEDS") - fun cast(override: ModelOverride) = override as ModelOverrideData - } - - fun getFirmamentOverrides(): Array<FirmamentModelPredicate>? - fun setFirmamentOverrides(overrides: Array<FirmamentModelPredicate>?) -} diff --git a/src/main/kotlin/gui/entity/FakeWorld.kt b/src/main/kotlin/gui/entity/FakeWorld.kt index 7ec385c..ccf6b60 100644 --- a/src/main/kotlin/gui/entity/FakeWorld.kt +++ b/src/main/kotlin/gui/entity/FakeWorld.kt @@ -8,6 +8,7 @@ import net.minecraft.block.BlockState import net.minecraft.client.gui.screen.world.SelectWorldScreen import net.minecraft.component.type.MapIdComponent import net.minecraft.entity.Entity +import net.minecraft.entity.boss.dragon.EnderDragonPart import net.minecraft.entity.damage.DamageSource import net.minecraft.entity.player.PlayerEntity import net.minecraft.fluid.Fluid @@ -262,6 +263,10 @@ class FakeWorld( return null } + override fun getEnderDragonParts(): MutableCollection<EnderDragonPart> { + return mutableListOf() + } + override fun getTickManager(): TickManager { return TickManager() } diff --git a/src/main/kotlin/repo/RepoModResourcePack.kt b/src/main/kotlin/repo/RepoModResourcePack.kt index f92fe4f..617efec 100644 --- a/src/main/kotlin/repo/RepoModResourcePack.kt +++ b/src/main/kotlin/repo/RepoModResourcePack.kt @@ -1,4 +1,3 @@ - package moe.nea.firmament.repo import java.io.InputStream @@ -21,86 +20,86 @@ import net.minecraft.resource.ResourcePackInfo import net.minecraft.resource.ResourcePackSource import net.minecraft.resource.ResourceType import net.minecraft.resource.metadata.ResourceMetadata -import net.minecraft.resource.metadata.ResourceMetadataReader +import net.minecraft.resource.metadata.ResourceMetadataSerializer import net.minecraft.text.Text import net.minecraft.util.Identifier import net.minecraft.util.PathUtil import moe.nea.firmament.Firmament class RepoModResourcePack(val basePath: Path) : ModResourcePack { - companion object { - fun append(packs: MutableList<in ModResourcePack>) { - Firmament.logger.info("Registering mod resource pack") - packs.add(RepoModResourcePack(RepoDownloadManager.repoSavedLocation)) - } + companion object { + fun append(packs: MutableList<in ModResourcePack>) { + Firmament.logger.info("Registering mod resource pack") + packs.add(RepoModResourcePack(RepoDownloadManager.repoSavedLocation)) + } - fun createResourceDirectly(identifier: Identifier): Optional<Resource> { - val pack = RepoModResourcePack(RepoDownloadManager.repoSavedLocation) - return Optional.of( - Resource( - pack, - pack.open(ResourceType.CLIENT_RESOURCES, identifier) ?: return Optional.empty() - ) { - val base = - pack.open(ResourceType.CLIENT_RESOURCES, identifier.withPath(identifier.path + ".mcmeta")) - if (base == null) - ResourceMetadata.NONE - else - NamespaceResourceManager.loadMetadata(base) - } - ) - } - } + fun createResourceDirectly(identifier: Identifier): Optional<Resource> { + val pack = RepoModResourcePack(RepoDownloadManager.repoSavedLocation) + return Optional.of( + Resource( + pack, + pack.open(ResourceType.CLIENT_RESOURCES, identifier) ?: return Optional.empty() + ) { + val base = + pack.open(ResourceType.CLIENT_RESOURCES, identifier.withPath(identifier.path + ".mcmeta")) + if (base == null) + ResourceMetadata.NONE + else + NamespaceResourceManager.loadMetadata(base) + } + ) + } + } - override fun close() { - } + override fun close() { + } - override fun openRoot(vararg segments: String): InputSupplier<InputStream>? { - return getFile(segments)?.let { InputSupplier.create(it) } - } + override fun openRoot(vararg segments: String): InputSupplier<InputStream>? { + return getFile(segments)?.let { InputSupplier.create(it) } + } - fun getFile(segments: Array<out String>): Path? { - PathUtil.validatePath(*segments) - val path = segments.fold(basePath, Path::resolve) - if (!path.isRegularFile()) return null - return path - } + fun getFile(segments: Array<out String>): Path? { + PathUtil.validatePath(*segments) + val path = segments.fold(basePath, Path::resolve) + if (!path.isRegularFile()) return null + return path + } - override fun open(type: ResourceType?, id: Identifier): InputSupplier<InputStream>? { - if (type != ResourceType.CLIENT_RESOURCES) return null - if (id.namespace != "neurepo") return null - val file = getFile(id.path.split("/").toTypedArray()) - return file?.let { InputSupplier.create(it) } - } + override fun open(type: ResourceType?, id: Identifier): InputSupplier<InputStream>? { + if (type != ResourceType.CLIENT_RESOURCES) return null + if (id.namespace != "neurepo") return null + val file = getFile(id.path.split("/").toTypedArray()) + return file?.let { InputSupplier.create(it) } + } - override fun findResources( - type: ResourceType?, - namespace: String, - prefix: String, - consumer: ResourcePack.ResultConsumer - ) { - if (namespace != "neurepo") return - if (type != ResourceType.CLIENT_RESOURCES) return + override fun findResources( + type: ResourceType?, + namespace: String, + prefix: String, + consumer: ResourcePack.ResultConsumer + ) { + if (namespace != "neurepo") return + if (type != ResourceType.CLIENT_RESOURCES) return - val prefixPath = basePath.resolve(prefix) - if (!prefixPath.exists()) - return - Files.walk(prefixPath) - .asSequence() - .map { it.relativeTo(basePath) } - .forEach { - consumer.accept(Identifier.of("neurepo", it.toString()), InputSupplier.create(it)) - } - } + val prefixPath = basePath.resolve(prefix) + if (!prefixPath.exists()) + return + Files.walk(prefixPath) + .asSequence() + .map { it.relativeTo(basePath) } + .forEach { + consumer.accept(Identifier.of("neurepo", it.toString()), InputSupplier.create(it)) + } + } - override fun getNamespaces(type: ResourceType?): Set<String> { - if (type != ResourceType.CLIENT_RESOURCES) return emptySet() - return setOf("neurepo") - } + override fun getNamespaces(type: ResourceType?): Set<String> { + if (type != ResourceType.CLIENT_RESOURCES) return emptySet() + return setOf("neurepo") + } - override fun <T> parseMetadata(metaReader: ResourceMetadataReader<T>): T? { - return AbstractFileResourcePack.parseMetadata( - metaReader, """ + override fun <T : Any?> parseMetadata(metadataSerializer: ResourceMetadataSerializer<T>?): T? { + return AbstractFileResourcePack.parseMetadata( + metadataSerializer, """ { "pack": { "pack_format": 12, @@ -108,19 +107,20 @@ class RepoModResourcePack(val basePath: Path) : ModResourcePack { } } """.trimIndent().byteInputStream() - ) - } + ) + } - override fun getInfo(): ResourcePackInfo { - return ResourcePackInfo("neurepo", Text.literal("NEU Repo"), ResourcePackSource.BUILTIN, Optional.empty()) - } - override fun getFabricModMetadata(): ModMetadata { - return FabricLoader.getInstance().getModContainer("firmament") - .get().metadata - } + override fun getInfo(): ResourcePackInfo { + return ResourcePackInfo("neurepo", Text.literal("NEU Repo"), ResourcePackSource.BUILTIN, Optional.empty()) + } - override fun createOverlay(overlay: String): ModResourcePack { - return RepoModResourcePack(basePath.resolve(overlay)) - } + override fun getFabricModMetadata(): ModMetadata { + return FabricLoader.getInstance().getModContainer("firmament") + .get().metadata + } + + override fun createOverlay(overlay: String): ModResourcePack { + return RepoModResourcePack(basePath.resolve(overlay)) + } } diff --git a/src/main/resources/firmament.accesswidener b/src/main/resources/firmament.accesswidener index 8e7dbab..b045bea 100644 --- a/src/main/resources/firmament.accesswidener +++ b/src/main/resources/firmament.accesswidener @@ -4,12 +4,6 @@ accessible class net/minecraft/client/render/RenderLayer$MultiPhaseParameters accessible class net/minecraft/client/font/TextRenderer$Drawer accessible field net/minecraft/client/gui/hud/InGameHud SCOREBOARD_ENTRY_COMPARATOR Ljava/util/Comparator; -accessible field net/minecraft/client/render/item/HeldItemRenderer itemRenderer Lnet/minecraft/client/render/item/ItemRenderer; -accessible field net/minecraft/client/render/item/ItemModels missingModelSupplier Ljava/util/function/Supplier; -mutable field net/minecraft/client/render/model/json/ModelOverrideList conditionTypes [Lnet/minecraft/util/Identifier; - -accessible class net/minecraft/client/render/model/json/ModelOverride$Deserializer -accessible class net/minecraft/client/render/model/json/ModelOverrideList$BakedOverride accessible field net/minecraft/entity/mob/CreeperEntity CHARGED Lnet/minecraft/entity/data/TrackedData; accessible method net/minecraft/entity/decoration/ArmorStandEntity setSmall (Z)V accessible field net/minecraft/entity/passive/AbstractHorseEntity items Lnet/minecraft/inventory/SimpleInventory; @@ -23,16 +17,3 @@ mutable field net/minecraft/screen/slot/Slot y I accessible field net/minecraft/entity/player/PlayerEntity PLAYER_MODEL_PARTS Lnet/minecraft/entity/data/TrackedData; accessible field net/minecraft/client/render/WorldRenderer chunks Lnet/minecraft/client/render/BuiltChunkStorage; - -# Fix package-private access methods -accessible method net/minecraft/registry/entry/RegistryEntry$Reference setRegistryKey (Lnet/minecraft/registry/RegistryKey;)V -accessible method net/minecraft/entity/LivingEntity getHitbox ()Lnet/minecraft/util/math/Box; -accessible method net/minecraft/registry/entry/RegistryEntryList$Named <init> (Lnet/minecraft/registry/entry/RegistryEntryOwner;Lnet/minecraft/registry/tag/TagKey;)V -accessible method net/minecraft/registry/entry/RegistryEntry$Reference setValue (Ljava/lang/Object;)V -accessible field net/minecraft/client/render/model/WrapperBakedModel wrapped Lnet/minecraft/client/render/model/BakedModel; -accessible method net/minecraft/entity/passive/TameableEntity isInSameTeam (Lnet/minecraft/entity/Entity;)Z -accessible method net/minecraft/entity/Entity isInSameTeam (Lnet/minecraft/entity/Entity;)Z -accessible method net/minecraft/registry/entry/RegistryEntry$Reference setTags (Ljava/util/Collection;)V -accessible method net/minecraft/registry/entry/RegistryEntryList$Named setEntries (Ljava/util/List;)V -accessible method net/minecraft/world/biome/source/util/VanillaBiomeParameters writeOverworldBiomeParameters (Ljava/util/function/Consumer;)V -accessible method net/minecraft/world/gen/densityfunction/DensityFunctions createSurfaceNoiseRouter (Lnet/minecraft/registry/RegistryEntryLookup;Lnet/minecraft/registry/RegistryEntryLookup;ZZ)Lnet/minecraft/world/gen/noise/NoiseRouter; diff --git a/src/main/kotlin/features/texturepack/CustomBlockTextures.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt index 2f7f084..e7c379b 100644 --- a/src/main/kotlin/features/texturepack/CustomBlockTextures.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomBlockTextures.kt @@ -46,9 +46,9 @@ import moe.nea.firmament.util.json.SingletonSerializableList object CustomBlockTextures { @Serializable data class CustomBlockOverride( - val modes: @Serializable(SingletonSerializableList::class) List<String>, - val area: List<Area>? = null, - val replacements: Map<Identifier, Replacement>, + val modes: @Serializable(SingletonSerializableList::class) List<String>, + val area: List<Area>? = null, + val replacements: Map<Identifier, Replacement>, ) @Serializable(with = Replacement.Serializer::class) @@ -135,8 +135,8 @@ object CustomBlockTextures { ) data class BlockReplacement( - val checks: List<Area>?, - val replacement: Replacement, + val checks: List<Area>?, + val replacement: Replacement, ) { val roughCheck by lazy(LazyThreadSafetyMode.NONE) { if (checks == null || checks.size < 3) return@lazy null diff --git a/src/main/kotlin/features/texturepack/CustomGlobalArmorOverrides.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt index 54e9e11..84c04af 100644 --- a/src/main/kotlin/features/texturepack/CustomGlobalArmorOverrides.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalArmorOverrides.kt @@ -8,8 +8,12 @@ import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable import kotlinx.serialization.Transient import kotlinx.serialization.UseSerializers +import net.minecraft.client.render.entity.equipment.EquipmentModel +import net.minecraft.component.type.EquippableComponent +import net.minecraft.entity.EquipmentSlot import net.minecraft.item.ItemStack -import net.minecraft.item.equipment.EquipmentModel +import net.minecraft.item.equipment.EquipmentAssetKeys +import net.minecraft.registry.RegistryKey import net.minecraft.resource.ResourceManager import net.minecraft.resource.SinglePreparationResourceReloader import net.minecraft.util.Identifier @@ -20,6 +24,7 @@ import moe.nea.firmament.events.FinalizeResourceManagerEvent import moe.nea.firmament.features.texturepack.CustomGlobalTextures.logger import moe.nea.firmament.util.IdentifierSerializer import moe.nea.firmament.util.collections.WeakCache +import moe.nea.firmament.util.intoOptional import moe.nea.firmament.util.skyBlockId object CustomGlobalArmorOverrides { @@ -33,9 +38,9 @@ object CustomGlobalArmorOverrides { ) { @Transient lateinit var modelIdentifier: Identifier - fun bake() { + fun bake(manager: ResourceManager) { modelIdentifier = bakeModel(model, layers) - overrides.forEach { it.bake() } + overrides.forEach { it.bake(manager) } } init { @@ -64,22 +69,33 @@ object CustomGlobalArmorOverrides { @Transient lateinit var modelIdentifier: Identifier - fun bake() { + fun bake(manager: ResourceManager) { modelIdentifier = bakeModel(model, layers) } } - val overrideCache = WeakCache.memoize<ItemStack, Optional<Identifier>>("ArmorOverrides") { stack -> - val id = stack.skyBlockId ?: return@memoize Optional.empty() - val override = overrides[id.neuItem] ?: return@memoize Optional.empty() - for (suboverride in override.overrides) { - if (suboverride.predicate.test(stack)) { - return@memoize Optional.of(suboverride.modelIdentifier) + private fun resolveComponent(slot: EquipmentSlot, model: Identifier): EquippableComponent { + return EquippableComponent( + slot, + null, + Optional.of(RegistryKey.of(EquipmentAssetKeys.REGISTRY_KEY, model)), + Optional.empty(), + Optional.empty(), false, false, false + ) + } + + val overrideCache = + WeakCache.memoize<ItemStack, EquipmentSlot, Optional<EquippableComponent>>("ArmorOverrides") { stack, slot -> + val id = stack.skyBlockId ?: return@memoize Optional.empty() + val override = overrides[id.neuItem] ?: return@memoize Optional.empty() + for (suboverride in override.overrides) { + if (suboverride.predicate.test(stack)) { + return@memoize resolveComponent(slot, suboverride.modelIdentifier).intoOptional() + } } + return@memoize resolveComponent(slot, override.modelIdentifier).intoOptional() } - return@memoize Optional.of(override.modelIdentifier) - } var overrides: Map<String, ArmorOverride> = mapOf() private var bakedOverrides: MutableMap<Identifier, EquipmentModel> = mutableMapOf() @@ -131,20 +147,20 @@ object CustomGlobalArmorOverrides { } val associatedMap = overrides.flatMap { obj -> obj.itemIds.map { it to obj } } .toMap() + associatedMap.forEach { it.value.bake(manager) } return associatedMap } override fun apply(prepared: Map<String, ArmorOverride>, manager: ResourceManager, profiler: Profiler) { bakedOverrides.clear() - prepared.forEach { it.value.bake() } overrides = prepared } }) } @JvmStatic - fun overrideArmor(itemStack: ItemStack): Optional<Identifier> { - return overrideCache.invoke(itemStack) + fun overrideArmor(itemStack: ItemStack, slot: EquipmentSlot): Optional<EquippableComponent> { + return overrideCache.invoke(itemStack, slot) } @JvmStatic diff --git a/src/main/kotlin/features/texturepack/CustomGlobalTextures.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt index 9ad8bc1..ad44b03 100644 --- a/src/main/kotlin/features/texturepack/CustomGlobalTextures.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomGlobalTextures.kt @@ -1,18 +1,14 @@ -@file:UseSerializers(IdentifierSerializer::class, CustomModelOverrideParser.FirmamentRootPredicateSerializer::class) +@file:UseSerializers(IdentifierSerializer::class, FirmamentRootPredicateSerializer::class) package moe.nea.firmament.features.texturepack -import java.util.Optional import java.util.concurrent.CompletableFuture import org.slf4j.LoggerFactory import kotlinx.serialization.Serializable import kotlinx.serialization.UseSerializers import kotlin.jvm.optionals.getOrNull -import net.minecraft.client.render.item.ItemModels -import net.minecraft.client.render.model.BakedModel 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 @@ -21,15 +17,15 @@ import net.minecraft.util.profiler.Profiler import moe.nea.firmament.Firmament import moe.nea.firmament.annotations.Subscribe import moe.nea.firmament.events.BakeExtraModelsEvent +import moe.nea.firmament.events.CustomItemModelEvent import moe.nea.firmament.events.EarlyResourceReloadEvent import moe.nea.firmament.events.FinalizeResourceManagerEvent import moe.nea.firmament.events.ScreenChangeEvent import moe.nea.firmament.events.subscription.SubscriptionOwner import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.util.ErrorUtil import moe.nea.firmament.util.IdentifierSerializer import moe.nea.firmament.util.MC -import moe.nea.firmament.util.collections.WeakCache -import moe.nea.firmament.util.intoOptional import moe.nea.firmament.util.json.SingletonSerializableList import moe.nea.firmament.util.runNull @@ -91,7 +87,7 @@ object CustomGlobalTextures : SinglePreparationResourceReloader<CustomGlobalText } override fun apply(prepared: CustomGuiTextureOverride, manager: ResourceManager?, profiler: Profiler?) { - this.guiClassOverrides = prepared + guiClassOverrides = prepared } val logger = LoggerFactory.getLogger(CustomGlobalTextures::class.java) @@ -100,7 +96,7 @@ object CustomGlobalTextures : SinglePreparationResourceReloader<CustomGlobalText manager.findResources("overrides/item") { it.namespace == "firmskyblock" && it.path.endsWith(".json") } .mapNotNull { Firmament.tryDecodeJsonFromStream<GlobalItemOverride>(it.value.inputStream).getOrElse { ex -> - logger.error("Failed to load global item override at ${it.key}", ex) + ErrorUtil.softError("Failed to load global item override at ${it.key}", ex) null } } @@ -114,12 +110,12 @@ object CustomGlobalTextures : SinglePreparationResourceReloader<CustomGlobalText manager.getResource(Identifier.of(key.namespace, "filters/screen/${key.path}.json")) .getOrNull() ?: return@mapNotNull runNull { - logger.error("Failed to locate screen filter at $key") + ErrorUtil.softError("Failed to locate screen filter at $key") } val screenFilter = Firmament.tryDecodeJsonFromStream<ScreenFilter>(guiClassResource.inputStream) .getOrElse { ex -> - logger.error("Failed to load screen filter at $key", ex) + ErrorUtil.softError("Failed to load screen filter at $key", ex) return@mapNotNull null } ItemOverrideCollection(screenFilter, it.value.map { it.second }) @@ -139,25 +135,19 @@ object CustomGlobalTextures : SinglePreparationResourceReloader<CustomGlobalText .filterTo(mutableSetOf()) { it.screenFilter.title.matches(newTitle) } } - val overrideCache = - WeakCache.memoize<ItemStack, ItemModels, Optional<BakedModel>>("CustomGlobalTextureModelOverrides") { stack, models -> - matchingOverrides - .firstNotNullOfOrNull { - it.overrides - .asSequence() - .filter { it.predicate.test(stack) } - .map { models.getModel(it.model) } - .firstOrNull() - } - .intoOptional() - } + @Subscribe + fun replaceGlobalModel(event: CustomItemModelEvent) { + val override = matchingOverrides + .firstNotNullOfOrNull { + it.overrides + .asSequence() + .filter { it.predicate.test(event.itemStack) } + .map { it.model } + .firstOrNull() + } - @JvmStatic - fun replaceGlobalModel( - models: ItemModels, - stack: ItemStack, - ): BakedModel? { - return overrideCache.invoke(stack, models).getOrNull() + if (override != null) + event.overrideIfExists(override) } diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt new file mode 100644 index 0000000..6472993 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomModelOverrideParser.kt @@ -0,0 +1,103 @@ +package moe.nea.firmament.features.texturepack + +import com.google.gson.JsonObject +import com.mojang.datafixers.util.Pair +import com.mojang.serialization.Codec +import com.mojang.serialization.DataResult +import com.mojang.serialization.Decoder +import com.mojang.serialization.DynamicOps +import com.mojang.serialization.Encoder +import net.minecraft.client.render.item.model.ItemModelTypes +import net.minecraft.item.ItemStack +import net.minecraft.util.Identifier +import moe.nea.firmament.Firmament +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.FinalizeResourceManagerEvent +import moe.nea.firmament.features.texturepack.predicates.AndPredicate +import moe.nea.firmament.features.texturepack.predicates.DisplayNamePredicate +import moe.nea.firmament.features.texturepack.predicates.ExtraAttributesPredicate +import moe.nea.firmament.features.texturepack.predicates.ItemPredicate +import moe.nea.firmament.features.texturepack.predicates.LorePredicate +import moe.nea.firmament.features.texturepack.predicates.NotPredicate +import moe.nea.firmament.features.texturepack.predicates.OrPredicate +import moe.nea.firmament.features.texturepack.predicates.PetPredicate +import moe.nea.firmament.util.json.KJsonOps + +object CustomModelOverrideParser { + + val LEGACY_CODEC: Codec<FirmamentModelPredicate> = + Codec.of( + Encoder.error("cannot encode legacy firmament model predicates"), + object : Decoder<FirmamentModelPredicate> { + override fun <T : Any?> decode( + ops: DynamicOps<T>, + input: T + ): DataResult<Pair<FirmamentModelPredicate, T>> { + try { + val pred = Firmament.json.decodeFromJsonElement( + FirmamentRootPredicateSerializer, + ops.convertTo(KJsonOps.INSTANCE, input)) + return DataResult.success(Pair.of(pred, ops.empty())) + } catch (ex: Exception) { + return DataResult.error { "Could not deserialize ${ex.message}" } + } + } + } + ) + + val predicateParsers = mutableMapOf<Identifier, FirmamentModelPredicateParser>() + + + fun registerPredicateParser(name: String, parser: FirmamentModelPredicateParser) { + predicateParsers[Identifier.of("firmament", name)] = parser + } + + init { + registerPredicateParser("display_name", DisplayNamePredicate.Parser) + registerPredicateParser("lore", LorePredicate.Parser) + registerPredicateParser("all", AndPredicate.Parser) + registerPredicateParser("any", OrPredicate.Parser) + registerPredicateParser("not", NotPredicate.Parser) + registerPredicateParser("item", ItemPredicate.Parser) + registerPredicateParser("extra_attributes", ExtraAttributesPredicate.Parser) + registerPredicateParser("pet", PetPredicate.Parser) + } + + private val neverPredicate = listOf( + object : FirmamentModelPredicate { + override fun test(stack: ItemStack): Boolean { + return false + } + } + ) + + fun parsePredicates(predicates: JsonObject): List<FirmamentModelPredicate> { + val parsedPredicates = mutableListOf<FirmamentModelPredicate>() + for (predicateName in predicates.keySet()) { + if (!predicateName.startsWith("firmament:")) continue + val identifier = Identifier.of(predicateName) + val parser = predicateParsers[identifier] ?: return neverPredicate + val parsedPredicate = parser.parse(predicates[predicateName]) ?: return neverPredicate + parsedPredicates.add(parsedPredicate) + } + return parsedPredicates + } + + @JvmStatic + fun parseCustomModelOverrides(jsonObject: JsonObject): Array<FirmamentModelPredicate>? { + val predicates = (jsonObject["predicate"] as? JsonObject) ?: return null + val parsedPredicates = parsePredicates(predicates) + if (parsedPredicates.isEmpty()) + return null + return parsedPredicates.toTypedArray() + } + + @Subscribe + fun finalizeResources(event: FinalizeResourceManagerEvent) { + ItemModelTypes.ID_MAPPER.put( + Firmament.identifier("predicates/legacy"), + PredicateModel.Unbaked.CODEC + ) + } + +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt new file mode 100644 index 0000000..d9ca5b4 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomSkyBlockTextures.kt @@ -0,0 +1,117 @@ +package moe.nea.firmament.features.texturepack + +import com.mojang.authlib.minecraft.MinecraftProfileTexture +import com.mojang.authlib.properties.Property +import java.util.Optional +import org.jetbrains.annotations.Nullable +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable +import kotlin.jvm.optionals.getOrNull +import net.minecraft.block.SkullBlock +import net.minecraft.client.MinecraftClient +import net.minecraft.client.render.RenderLayer +import net.minecraft.component.type.ProfileComponent +import net.minecraft.util.Identifier +import moe.nea.firmament.annotations.Subscribe +import moe.nea.firmament.events.CustomItemModelEvent +import moe.nea.firmament.events.FinalizeResourceManagerEvent +import moe.nea.firmament.events.TickEvent +import moe.nea.firmament.features.FirmamentFeature +import moe.nea.firmament.features.debug.PowerUserTools +import moe.nea.firmament.gui.config.ManagedConfig +import moe.nea.firmament.util.collections.WeakCache +import moe.nea.firmament.util.mc.decodeProfileTextureProperty +import moe.nea.firmament.util.skyBlockId + +object CustomSkyBlockTextures : FirmamentFeature { + override val identifier: String + get() = "custom-skyblock-textures" + + object TConfig : ManagedConfig(identifier, Category.INTEGRATIONS) { // TODO: should this be its own thing? + val enabled by toggle("enabled") { true } + val skullsEnabled by toggle("skulls-enabled") { true } + val cacheForever by toggle("cache-forever") { true } + val cacheDuration by integer("cache-duration", 0, 100) { 1 } + val enableModelOverrides by toggle("model-overrides") { true } + val enableArmorOverrides by toggle("armor-overrides") { true } + val enableBlockOverrides by toggle("block-overrides") { true } + val enableLegacyCIT by toggle("legacy-cit") { true } + val allowRecoloringUiText by toggle("recolor-text") { true } + } + + override val config: ManagedConfig + get() = TConfig + + val allItemCaches by lazy { + listOf( + skullTextureCache.cache, + CustomGlobalArmorOverrides.overrideCache.cache + ) + } + + init { + PowerUserTools.getSkullId = ::getSkullTexture + } + + fun clearAllCaches() { + allItemCaches.forEach(WeakCache<*, *, *>::clear) + } + + @Subscribe + fun onTick(it: TickEvent) { + if (TConfig.cacheForever) return + if (TConfig.cacheDuration < 1 || it.tickCount % TConfig.cacheDuration == 0) { + clearAllCaches() + } + } + + @Subscribe + fun onStart(event: FinalizeResourceManagerEvent) { + event.registerOnApply("Clear firmament CIT caches") { + clearAllCaches() + } + } + + @Subscribe + fun onCustomModelId(it: CustomItemModelEvent) { + if (!TConfig.enabled) return + val id = it.itemStack.skyBlockId ?: return + it.overrideIfExists(Identifier.of("firmskyblock", id.identifier.path)) + } + + private val skullTextureCache = + WeakCache.memoize<ProfileComponent, Optional<Identifier>>("SkullTextureCache") { component -> + val id = getSkullTexture(component) ?: return@memoize Optional.empty() + if (!MinecraftClient.getInstance().resourceManager.getResource(id).isPresent) { + return@memoize Optional.empty() + } + return@memoize Optional.of(id) + } + + private val mcUrlRegex = "https?://textures.minecraft.net/texture/([a-fA-F0-9]+)".toRegex() + + fun getSkullId(textureProperty: Property): String? { + val texture = decodeProfileTextureProperty(textureProperty) ?: return null + val textureUrl = + texture.textures[MinecraftProfileTexture.Type.SKIN]?.url ?: return null + val mcUrlData = mcUrlRegex.matchEntire(textureUrl) ?: return null + return mcUrlData.groupValues[1] + } + + fun getSkullTexture(profile: ProfileComponent): Identifier? { + val id = getSkullId(profile.properties["textures"].firstOrNull() ?: return null) ?: return null + return Identifier.of("firmskyblock", "textures/placedskull/$id.png") + } + + fun modifySkullTexture( + type: SkullBlock.SkullType?, + component: ProfileComponent?, + cir: CallbackInfoReturnable<RenderLayer> + ) { + if (type != SkullBlock.Type.PLAYER) return + if (!TConfig.skullsEnabled) return + if (component == null) return + + val n = skullTextureCache.invoke(component).getOrNull() ?: return + cir.returnValue = RenderLayer.getEntityTranslucent(n) + } +} diff --git a/src/main/kotlin/features/texturepack/CustomTextColors.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomTextColors.kt index 4ca1796..4ca1796 100644 --- a/src/main/kotlin/features/texturepack/CustomTextColors.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/CustomTextColors.kt diff --git a/src/main/kotlin/features/texturepack/FirmamentModelPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt index d11fec0..d11fec0 100644 --- a/src/main/kotlin/features/texturepack/FirmamentModelPredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicate.kt diff --git a/src/main/kotlin/features/texturepack/FirmamentModelPredicateParser.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt index 3ed0c67..3ed0c67 100644 --- a/src/main/kotlin/features/texturepack/FirmamentModelPredicateParser.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentModelPredicateParser.kt diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentRootPredicateSerializer.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentRootPredicateSerializer.kt new file mode 100644 index 0000000..0b8ae8e --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/FirmamentRootPredicateSerializer.kt @@ -0,0 +1,23 @@ +package moe.nea.firmament.features.texturepack + +import com.google.gson.JsonObject +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import moe.nea.firmament.features.texturepack.predicates.AndPredicate + +object FirmamentRootPredicateSerializer : KSerializer<FirmamentModelPredicate> { + val delegateSerializer = kotlinx.serialization.json.JsonObject.serializer() + override val descriptor: SerialDescriptor + get() = SerialDescriptor("FirmamentModelRootPredicate", delegateSerializer.descriptor) + + override fun deserialize(decoder: Decoder): FirmamentModelPredicate { + val json = decoder.decodeSerializableValue(delegateSerializer).intoGson() as JsonObject + return AndPredicate(CustomModelOverrideParser.parsePredicates(json).toTypedArray()) + } + + override fun serialize(encoder: Encoder, value: FirmamentModelPredicate) { + TODO("Cannot serialize firmament predicates") + } +} diff --git a/src/texturePacks/java/moe/nea/firmament/features/texturepack/PredicateModel.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/PredicateModel.kt new file mode 100644 index 0000000..e21e69d --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/PredicateModel.kt @@ -0,0 +1,85 @@ +package moe.nea.firmament.features.texturepack + +import com.mojang.serialization.Codec +import com.mojang.serialization.MapCodec +import com.mojang.serialization.codecs.RecordCodecBuilder +import net.minecraft.client.item.ItemModelManager +import net.minecraft.client.render.item.ItemRenderState +import net.minecraft.client.render.item.model.ItemModel +import net.minecraft.client.render.item.model.ItemModelTypes +import net.minecraft.client.render.model.ResolvableModel +import net.minecraft.client.world.ClientWorld +import net.minecraft.entity.LivingEntity +import net.minecraft.item.ItemStack +import net.minecraft.item.ModelTransformationMode + +class PredicateModel { + data class Baked( + val fallback: ItemModel, + val overrides: List<Override> + ) : ItemModel { + data class Override( + val model: ItemModel, + val predicate: FirmamentModelPredicate, + ) + + override fun update( + state: ItemRenderState, + stack: ItemStack, + resolver: ItemModelManager, + transformationMode: ModelTransformationMode, + world: ClientWorld?, + user: LivingEntity?, + seed: Int + ) { + val model = + overrides + .find { it.predicate.test(stack) } + ?.model + ?: fallback + model.update(state, stack, resolver, transformationMode, world, user, seed) + } + } + + data class Unbaked( + val fallback: ItemModel.Unbaked, + val overrides: List<Override>, + ) : ItemModel.Unbaked { + companion object { + val OVERRIDE_CODEC: Codec<Override> = RecordCodecBuilder.create { + it.group( + ItemModelTypes.CODEC.fieldOf("model").forGetter(Override::model), + CustomModelOverrideParser.LEGACY_CODEC.fieldOf("predicate").forGetter(Override::predicate), + ).apply(it, Unbaked::Override) + } + val CODEC: MapCodec<Unbaked> = + RecordCodecBuilder.mapCodec { + it.group( + ItemModelTypes.CODEC.fieldOf("fallback").forGetter(Unbaked::fallback), + OVERRIDE_CODEC.listOf().fieldOf("overrides").forGetter(Unbaked::overrides), + ).apply(it, ::Unbaked) + } + } + + data class Override( + val model: ItemModel.Unbaked, + val predicate: FirmamentModelPredicate, + ) + + override fun resolve(resolver: ResolvableModel.Resolver) { + fallback.resolve(resolver) + overrides.forEach { it.model.resolve(resolver) } + } + + override fun getCodec(): MapCodec<out Unbaked> { + return CODEC + } + + override fun bake(context: ItemModel.BakeContext): ItemModel { + return Baked( + fallback.bake(context), + overrides.map { Baked.Override(it.model.bake(context), it.predicate) } + ) + } + } +} diff --git a/src/main/kotlin/features/texturepack/RarityMatcher.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/RarityMatcher.kt index 634a171..634a171 100644 --- a/src/main/kotlin/features/texturepack/RarityMatcher.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/RarityMatcher.kt diff --git a/src/main/kotlin/features/texturepack/StringMatcher.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/StringMatcher.kt index 5eb86ac..2b13284 100644 --- a/src/main/kotlin/features/texturepack/StringMatcher.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/StringMatcher.kt @@ -70,7 +70,7 @@ interface StringMatcher { } override fun serialize(encoder: Encoder, value: StringMatcher) { - encoder.encodeSerializableValue(delegateSerializer, Companion.serialize(value).intoKotlinJson()) + encoder.encodeSerializableValue(delegateSerializer, serialize(value).intoKotlinJson()) } } diff --git a/src/main/kotlin/features/texturepack/TintOverrides.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/TintOverrides.kt index 85fcae4..53df184 100644 --- a/src/main/kotlin/features/texturepack/TintOverrides.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/TintOverrides.kt @@ -43,7 +43,7 @@ data class TintOverrides( val override = (value as? JsonPrimitive) ?.takeIf(JsonPrimitive::isNumber) ?.asInt - ?.let(::Fixed) + ?.let(TintOverrides::Fixed) if (override == null) { ErrorUtil.softError("Invalid tint override for a layer: $value") continue diff --git a/src/main/kotlin/features/texturepack/predicates/AlwaysPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AlwaysPredicate.kt index 7e0ddb1..7e0ddb1 100644 --- a/src/main/kotlin/features/texturepack/predicates/AlwaysPredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AlwaysPredicate.kt diff --git a/src/main/kotlin/features/texturepack/predicates/AndPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AndPredicate.kt index 99abaaa..99abaaa 100644 --- a/src/main/kotlin/features/texturepack/predicates/AndPredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/AndPredicate.kt diff --git a/src/main/kotlin/features/texturepack/predicates/DisplayNamePredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/DisplayNamePredicate.kt index 04c7a2b..04c7a2b 100644 --- a/src/main/kotlin/features/texturepack/predicates/DisplayNamePredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/DisplayNamePredicate.kt diff --git a/src/main/kotlin/features/texturepack/predicates/ExtraAttributesPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ExtraAttributesPredicate.kt index 3c8023d..3c8023d 100644 --- a/src/main/kotlin/features/texturepack/predicates/ExtraAttributesPredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ExtraAttributesPredicate.kt diff --git a/src/main/kotlin/features/texturepack/predicates/ItemPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ItemPredicate.kt index 3cb80c7..3cb80c7 100644 --- a/src/main/kotlin/features/texturepack/predicates/ItemPredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/ItemPredicate.kt diff --git a/src/main/kotlin/features/texturepack/predicates/LorePredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/LorePredicate.kt index f0b4737..f0b4737 100644 --- a/src/main/kotlin/features/texturepack/predicates/LorePredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/LorePredicate.kt diff --git a/src/main/kotlin/features/texturepack/predicates/NotPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NotPredicate.kt index 4986ad9..4986ad9 100644 --- a/src/main/kotlin/features/texturepack/predicates/NotPredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NotPredicate.kt diff --git a/src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NumberMatcher.kt index b0d5178..b0d5178 100644 --- a/src/main/kotlin/features/texturepack/predicates/NumberMatcher.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/NumberMatcher.kt diff --git a/src/main/kotlin/features/texturepack/predicates/OrPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/OrPredicate.kt index e3093cd..e3093cd 100644 --- a/src/main/kotlin/features/texturepack/predicates/OrPredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/OrPredicate.kt diff --git a/src/main/kotlin/features/texturepack/predicates/PetPredicate.kt b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PetPredicate.kt index b30b7c9..b30b7c9 100644 --- a/src/main/kotlin/features/texturepack/predicates/PetPredicate.kt +++ b/src/texturePacks/java/moe/nea/firmament/features/texturepack/predicates/PetPredicate.kt diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java new file mode 100644 index 0000000..cf5cf59 --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ApplyHeadModelInItemRenderer.java @@ -0,0 +1,11 @@ + +package moe.nea.firmament.mixins.custommodels; + +import net.minecraft.client.item.ItemModelManager; +import org.spongepowered.asm.mixin.Mixin; + +@Mixin(ItemModelManager.class) +public class ApplyHeadModelInItemRenderer { + // TODO: replace head_model with a condition model (if possible, automatically) + // TODO: ItemAsset.CODEC should upgrade partials +} diff --git a/src/main/java/moe/nea/firmament/mixins/CustomSkullTexturePatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/CustomSkullTexturePatch.java index f3b616a..fede766 100644 --- a/src/main/java/moe/nea/firmament/mixins/CustomSkullTexturePatch.java +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/CustomSkullTexturePatch.java @@ -1,12 +1,13 @@ -package moe.nea.firmament.mixins; +package moe.nea.firmament.mixins.custommodels; import moe.nea.firmament.features.texturepack.CustomSkyBlockTextures; import net.minecraft.block.SkullBlock; import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.block.entity.SkullBlockEntityRenderer; import net.minecraft.component.type.ProfileComponent; +import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -14,8 +15,12 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(SkullBlockEntityRenderer.class) public class CustomSkullTexturePatch { - @Inject(method = "getRenderLayer", at = @At("HEAD"), cancellable = true) - private static void onGetRenderLayer(SkullBlock.SkullType type, ProfileComponent profile, CallbackInfoReturnable<RenderLayer> cir) { + @Inject( + method = "getRenderLayer(Lnet/minecraft/block/SkullBlock$SkullType;Lnet/minecraft/component/type/ProfileComponent;Lnet/minecraft/util/Identifier;)Lnet/minecraft/client/render/RenderLayer;", + at = @At("HEAD"), + cancellable = true + ) + private static void onGetRenderLayer(SkullBlock.SkullType type, ProfileComponent profile, Identifier texture, CallbackInfoReturnable<RenderLayer> cir) { CustomSkyBlockTextures.INSTANCE.modifySkullTexture(type, profile, cir); } } diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java index 4468150..669da63 100644 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchArmorTexture.java @@ -1,29 +1,30 @@ package moe.nea.firmament.mixins.custommodels; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; 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.component.ComponentType; import net.minecraft.component.type.EquippableComponent; +import net.minecraft.entity.EquipmentSlot; import net.minecraft.item.ItemStack; -import net.minecraft.util.Identifier; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; -import java.util.Optional; - @Mixin(ArmorFeatureRenderer.class) public class PatchArmorTexture { - @WrapOperation( + @ModifyExpressionValue( method = "renderArmor", - at = @At(value = "INVOKE", target = "Lnet/minecraft/component/type/EquippableComponent;model()Ljava/util/Optional;")) - private Optional<Identifier> overrideLayers( - EquippableComponent instance, Operation<Optional<Identifier>> original, @Local(argsOnly = true) ItemStack itemStack + at = @At( + value = "INVOKE", + target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;")) + private Object overrideLayers( + Object original, @Local(argsOnly = true) ItemStack itemStack, @Local(argsOnly = true) EquipmentSlot slot ) { - // TODO: check that all armour items are naturally equippable and have the equppable component. otherwise our call here will not be reached. - var overrides = CustomGlobalArmorOverrides.overrideArmor(itemStack); - return overrides.or(() -> original.call(instance)); + var overrides = CustomGlobalArmorOverrides.overrideArmor(itemStack, slot); + return overrides.orElse((EquippableComponent) original); } } diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java new file mode 100644 index 0000000..81ea6cd --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/PatchLegacyArmorLayerSupport.java @@ -0,0 +1,23 @@ +package moe.nea.firmament.mixins.custommodels; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import moe.nea.firmament.features.texturepack.CustomGlobalArmorOverrides; +import net.minecraft.client.render.entity.equipment.EquipmentModel; +import net.minecraft.client.render.entity.equipment.EquipmentModelLoader; +import net.minecraft.client.render.entity.equipment.EquipmentRenderer; +import net.minecraft.item.equipment.EquipmentAsset; +import net.minecraft.registry.RegistryKey; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +// TODO: auto import legacy models, maybe!!! in a later patch tho +@Mixin(EquipmentRenderer.class) +public class PatchLegacyArmorLayerSupport { + @WrapOperation(method = "render(Lnet/minecraft/client/render/entity/equipment/EquipmentModel$LayerType;Lnet/minecraft/registry/RegistryKey;Lnet/minecraft/client/model/Model;Lnet/minecraft/item/ItemStack;Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;ILnet/minecraft/util/Identifier;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/render/entity/equipment/EquipmentModelLoader;get(Lnet/minecraft/registry/RegistryKey;)Lnet/minecraft/client/render/entity/equipment/EquipmentModel;")) + private EquipmentModel patchModelLayers(EquipmentModelLoader instance, RegistryKey<EquipmentAsset> assetKey, Operation<EquipmentModel> original) { + var modelOverride = CustomGlobalArmorOverrides.overrideArmorLayer(assetKey.getValue()); + if (modelOverride != null) return modelOverride; + return original.call(instance, assetKey); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ReferenceCustomModelsPatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReferenceCustomModelsPatch.java index bb9cd10..bbabeb5 100644 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ReferenceCustomModelsPatch.java +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReferenceCustomModelsPatch.java @@ -1,8 +1,10 @@ package moe.nea.firmament.mixins.custommodels; +import com.llamalad7.mixinextras.sugar.Local; import moe.nea.firmament.events.BakeExtraModelsEvent; +import net.minecraft.client.item.ItemAssetsLoader; +import net.minecraft.client.render.model.BakedModelManager; import net.minecraft.client.render.model.BlockStatesLoader; -import net.minecraft.client.render.model.ItemModel; import net.minecraft.client.render.model.ReferencedModelsCollector; import net.minecraft.client.render.model.UnbakedModel; import net.minecraft.client.util.ModelIdentifier; @@ -13,24 +15,17 @@ 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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import java.util.Map; -@Mixin(ReferencedModelsCollector.class) +@Mixin(BakedModelManager.class) public abstract class ReferenceCustomModelsPatch { - @Shadow - protected abstract void addTopLevelModel(ModelIdentifier modelId, UnbakedModel model); - - @Shadow - @Final - private Map<Identifier, UnbakedModel> inputs; - - @Inject(method = "addBlockStates", at = @At("RETURN")) - private void addFirmamentReferencedModels( - BlockStatesLoader.BlockStateDefinition definition, CallbackInfo ci - ) { - BakeExtraModelsEvent.Companion.publish(new BakeExtraModelsEvent( - (modelIdentifier, identifier) -> addTopLevelModel(modelIdentifier, new ItemModel(identifier)))); + @Inject(method = "collect", at = @At("RETURN")) + private static void addFirmamentReferencedModels( + UnbakedModel missingModel, Map<Identifier, UnbakedModel> models, BlockStatesLoader.BlockStateDefinition blockStates, ItemAssetsLoader.Result itemAssets, CallbackInfoReturnable<ReferencedModelsCollector> cir, + @Local ReferencedModelsCollector collector) { + // TODO: Insert fake models based on firmskyblock models for a smoother transition } } diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockBreakSoundPatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockBreakSoundPatch.java index 9401889..9401889 100644 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockBreakSoundPatch.java +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockBreakSoundPatch.java diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockHitSoundPatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockHitSoundPatch.java index f9a1d0d..f9a1d0d 100644 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockHitSoundPatch.java +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockHitSoundPatch.java diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockRenderManagerBlockModel.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockRenderManagerBlockModel.java index 711b2af..711b2af 100644 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockRenderManagerBlockModel.java +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceBlockRenderManagerBlockModel.java diff --git a/src/main/java/moe/nea/firmament/mixins/custommodels/ReplaceFallbackBlockModel.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceFallbackBlockModel.java index 53ab74a..53ab74a 100644 --- a/src/main/java/moe/nea/firmament/mixins/custommodels/ReplaceFallbackBlockModel.java +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceFallbackBlockModel.java diff --git a/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceItemModelPatch.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceItemModelPatch.java new file mode 100644 index 0000000..0863caa --- /dev/null +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceItemModelPatch.java @@ -0,0 +1,24 @@ +package moe.nea.firmament.mixins.custommodels; + + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import moe.nea.firmament.events.CustomItemModelEvent; +import net.minecraft.client.item.ItemModelManager; +import net.minecraft.component.ComponentType; +import net.minecraft.item.ItemStack; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +@Mixin(ItemModelManager.class) +public class ReplaceItemModelPatch { + @WrapOperation( + method = "update(Lnet/minecraft/client/render/item/ItemRenderState;Lnet/minecraft/item/ItemStack;Lnet/minecraft/item/ModelTransformationMode;Lnet/minecraft/world/World;Lnet/minecraft/entity/LivingEntity;I)V", + at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;get(Lnet/minecraft/component/ComponentType;)Ljava/lang/Object;")) + private Object replaceItemModelByIdentifier(ItemStack instance, ComponentType componentType, Operation<Object> original) { + var override = CustomItemModelEvent.getModelIdentifier(instance); + if (override != null) + return override; + return original.call(instance, componentType); + } +} diff --git a/src/main/java/moe/nea/firmament/mixins/ReplaceTextColorInHandledScreen.java b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceTextColorInHandledScreen.java index c9fb073..e4834e9 100644 --- a/src/main/java/moe/nea/firmament/mixins/ReplaceTextColorInHandledScreen.java +++ b/src/texturePacks/java/moe/nea/firmament/mixins/custommodels/ReplaceTextColorInHandledScreen.java @@ -1,4 +1,4 @@ -package moe.nea.firmament.mixins; +package moe.nea.firmament.mixins.custommodels; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; diff --git a/symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt b/symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt index 5c205cc..d7aaf28 100644 --- a/symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt +++ b/symbols/src/main/kotlin/process/SubscribeAnnotationProcessor.kt @@ -44,6 +44,7 @@ class SubscribeAnnotationProcessor( appendLine() appendLine("import moe.nea.firmament.events.subscription.*") appendLine() + appendLine("@Suppress()") appendLine("class $generatedFileName : SubscriptionList {") appendLine(" override fun provideSubscriptions(addSubscription: (Subscription<*>) -> Unit) {") for (subscription in subscriptions) { |