From 1377712a83df6bcb58e504d6db92839bd3710c9f Mon Sep 17 00:00:00 2001 From: Traben Date: Tue, 4 Aug 2026 13:16:08 +1000 Subject: [PATCH 01/20] 26.2 --- build.gradle.kts | 12 +- gradle.properties | 6 +- root.gradle.kts | 5 +- settings.gradle.kts | 3 +- .../entity_model_features/EMFManager.java | 31 ++--- .../config/EMFConfig.java | 12 +- .../MixinBlockEntityRendererFactories.java | 11 +- .../mixin/mixins/MixinParrotEntityModel.java | 3 +- .../mixins/MixinResourceReloadStart.java | 4 +- .../MixinBlockEntityWithoutLevelRenderer.java | 2 + .../MixinEntityRenderDispatcher.java | 1 - .../rendering/MixinEntityRenderers.java | 7 +- .../MixinItemFrameEntityRenderer.java | 4 - .../rendering/MixinLivingEntityRenderer.java | 4 +- .../MixinStuckArrowsFeatureRenderer.java | 2 + .../submits/Mixin_GuiEntityRenderer.java | 2 + .../submits/Mixin_ModelPartRenderer.java | 2 +- .../submits/Mixin_ModelRenderer.java | 106 +++++++++++++++--- .../Mixin_ModelSubmit_AddBackupState.java | 8 +- .../animation/EMFAnimationEntityContext.java | 9 +- .../animation/math/methods/emf/IfBMethod.java | 8 +- .../math/methods/optifine/IfMethod.java | 8 +- .../models/animation/state/EMFSubmitData.java | 8 +- .../models/parts/EMFModelPart.java | 54 +++++++-- .../utils/UEntityTypes.java | 52 +++++++++ .../entity_model_features_15.accesswidener | 42 +++++++ versions/26.2-fabric/gradle.properties | 2 + versions/26.2-neoforge/gradle.properties | 3 + 28 files changed, 327 insertions(+), 84 deletions(-) create mode 100644 src/main/java/traben/entity_model_features/utils/UEntityTypes.java create mode 100644 src/main/resources/entity_model_features_15.accesswidener create mode 100644 versions/26.2-fabric/gradle.properties create mode 100644 versions/26.2-neoforge/gradle.properties diff --git a/build.gradle.kts b/build.gradle.kts index 5a40ee34..fd487926 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -46,6 +46,7 @@ base.archivesName.set("entity_model_features-$modVersion-${project.name}") val manuallyAccessTransform = mcVersion >= 26_00_00 && platform.isNeoForge val accessWidener = "entity_model_features_" + when { + mcVersion >= 26_02_00 -> 15 mcVersion >= 26_01_00 -> 14 mcVersion >= 1_21_11 -> 13 mcVersion >= 1_21_09 -> 12 @@ -97,14 +98,13 @@ dependencies { fun modImpl(modPrefix: String, vararg versions: Pair): Boolean { for ((versionMC, versionMod) in versions) { if (platform.mcVersion >= versionMC) { - if (versionMod != null) { + return if (versionMod != null) { modImplementation("$modPrefix$versionMod") { exclude("net.fabricmc.fabric-api") isTransitive = true } - return true - } - break + true + } else false } } return false @@ -136,7 +136,8 @@ dependencies { "IRIS" setVar ( modImpl("maven.modrinth:iris:", - 26_01_00 to ver("4cGUAiJ6", null, null), + 26_02_00 to ver("3uIIps8q", null, null), + 26_01_00 to ver("MwcLS51S", null, "YEGDGnJM"), //1_21_11 to ver("TSXvi2yD", null, "t3ruzodq"), //"k9tHcfnb"), //todo why does this break 1_21_06 to ver("l77DAK6U", null, "t3ruzodq"), //"xA5cxBvz"), // same here 1_21_05 to ver("U6evbjd0", null, "t3ruzodq"), //"KAopiPos"), @@ -154,6 +155,7 @@ dependencies { if (platform.isFabric) { modImpl( "maven.modrinth:modmenu:", + 26_02_00 to "TLnEHUyx", 26_01_00 to "XIDyVLo7", 1_21_05 to "R7uVB42W", 1_21_02 to "PcJvQYqu", diff --git a/gradle.properties b/gradle.properties index feaa31a4..c9f10e82 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ essential.defaults.loom.mappings=mojmap loom.ignoreDependencyLoomVersionValidation=true archives_base_name=entity_model_features -mod_version=3.2.4 +mod_version=3.2.6 maven_group=traben.entity_model_features -etf_version=7.1 -use_local_etf=false +etf_version=7.1.1 +use_local_etf=true diff --git a/root.gradle.kts b/root.gradle.kts index 9815a52a..9354c83f 100644 --- a/root.gradle.kts +++ b/root.gradle.kts @@ -7,7 +7,7 @@ plugins { // Advanced users may use multiple (potentially independent) multi-version trees in different sub-projects. // This is currently equivalent to applying `com.replaymod.preprocess-root`. kotlin("jvm") version "2.3.0" apply false - id("gg.essential.loom") version "1.15.49" apply false // https://repo.essential.gg/#/public/gg/essential/loom/gg.essential.loom.gradle.plugin + id("gg.essential.loom") version "1.15.50" apply false // https://repo.essential.gg/#/public/gg/essential/loom/gg.essential.loom.gradle.plugin id("gg.essential.multi-version.root") } @@ -56,7 +56,8 @@ preprocess { // next, then remap the main project to this and set the current to old //current.connectToVersion(12109, forge = false, neoforge = false) - null.connectToVersion(26_01_00, forge = false, neoforge = true) + null.connectToVersion(26_02_00, forge = false, neoforge = true) + .connectToVersion(26_01_00, forge = false, neoforge = true) .connectToVersion(1_21_11) .connectToVersion(1_21_09) .connectToVersion(1_21_06) diff --git a/settings.gradle.kts b/settings.gradle.kts index aed174be..8693f571 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -10,7 +10,7 @@ pluginManagement { maven("https://maven.neoforged.net/releases/") } plugins { - val egtVersion = "0.7.0-alpha.5" + val egtVersion = "0.7.2" id("gg.essential.multi-version.root") version egtVersion id("gg.essential.multi-version.api-validation") version egtVersion } @@ -36,6 +36,7 @@ fun MutableList.version(mcVersion: Int, forge: Boolean = true, neoforge: } mutableListOf() + .version(26_02_00, forge = false, neoforge = true) .version(26_01_00, forge = false, neoforge = true) .version(12111) .version(12109) diff --git a/src/main/java/traben/entity_model_features/EMFManager.java b/src/main/java/traben/entity_model_features/EMFManager.java index ad177d30..6d6b421c 100644 --- a/src/main/java/traben/entity_model_features/EMFManager.java +++ b/src/main/java/traben/entity_model_features/EMFManager.java @@ -33,6 +33,7 @@ import traben.entity_model_features.utils.EMFDirectoryHandler; import traben.entity_model_features.utils.EMFResourceCaching; import traben.entity_model_features.utils.EMFUtils; +import traben.entity_model_features.utils.UEntityTypes; import traben.entity_texture_features.ETF; import traben.entity_texture_features.utils.ETFLruCache; @@ -59,14 +60,16 @@ public class EMFManager {//singleton for data holding and resetting needs private static final Map, String> EBETypes = Map.of( - BlockEntityType.BED, "bed", - BlockEntityType.CHEST, "chest", - BlockEntityType.TRAPPED_CHEST, "chest", - BlockEntityType.ENDER_CHEST, "chest", - BlockEntityType.SHULKER_BOX, "shulker_box", - BlockEntityType.BELL, "bell", - BlockEntityType.SIGN, "sign", - BlockEntityType.DECORATED_POT, "decorated_pot"); + //#if MC < 26.2 + UEntityTypes.BED, "bed", + //#endif + UEntityTypes.CHEST, "chest", + UEntityTypes.TRAPPED_CHEST, "chest", + UEntityTypes.ENDER_CHEST, "chest", + UEntityTypes.SHULKER_BOX, "shulker_box", + UEntityTypes.BELL, "bell", + UEntityTypes.SIGN, "sign", + UEntityTypes.DECORATED_POT, "decorated_pot"); public static EMFModelPartRoot lastCreatedRootModelPart = null; private static EMFManager self = null; @@ -735,11 +738,13 @@ public void reloadEnd(){ if (EMF.config().getConfig().showReloadErrorToast && !loadingExceptions.isEmpty()){ try { var toastManager = Minecraft.getInstance() - //#if MC >= 12102 - .getToastManager(); - //#else - //$$ .getToasts(); - //#endif + //#if MC >= 26.2 + //$$ .gui.toastManager(); + //#elseif MC >= 12102 + .getToastManager(); + //#else + //$$.getToasts(); + //#endif SystemToast.add(toastManager, //#if MC > 12002 SystemToast.SystemToastId.PERIODIC_NOTIFICATION diff --git a/src/main/java/traben/entity_model_features/config/EMFConfig.java b/src/main/java/traben/entity_model_features/config/EMFConfig.java index 8d99c281..b858bbf1 100644 --- a/src/main/java/traben/entity_model_features/config/EMFConfig.java +++ b/src/main/java/traben/entity_model_features/config/EMFConfig.java @@ -3,7 +3,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import net.minecraft.client.model.geom.ModelLayers; -//#if MC >= 12102 +//#if MC >= 12102 && MC < 26.2 import net.minecraft.client.renderer.ShapeRenderer; //#else //$$ import net.minecraft.client.renderer.LevelRenderer; @@ -30,6 +30,7 @@ import traben.entity_model_features.utils.IEMFUnmodifiedLayerRootGetter; import traben.entity_texture_features.ETFApi; import traben.entity_texture_features.config.ETFConfig; +import traben.entity_texture_features.utils.UScreen; import traben.tconfig.TConfig; import traben.tconfig.gui.TConfigScreenList; import traben.tconfig.gui.entries.*; @@ -589,7 +590,7 @@ private boolean canRender() { @Override public void render(final GuiGraphics context, final int mouseX, final int mouseY) { if (canRender()) { - Screen screen = Minecraft.getInstance().screen; + Screen screen = UScreen.currentScreen(); if (screen == null) return; @@ -623,6 +624,12 @@ public void render(final GuiGraphics context, final int mouseX, final int mouseY matrixStack.pushPose(); matrixStack.scale(-1.0F, -1.0F, 1.0F); matrixStack.translate(0.0F, -1.501F, 0.0F); + //#if MC >= 26.2 + //$$ //TODO definitely wrong + //$$ var draw = Minecraft.getInstance().gameRenderer.renderBuffers().stagedVertexBuffer().appendDraw( + //$$ RenderTypes.lines().format(), com.mojang.blaze3d.PrimitiveTopology.LINES); + //$$ var buffer = Minecraft.getInstance().gameRenderer.renderBuffers().stagedVertexBuffer().getVertexBuilder(draw); + //#else var buffer = Minecraft.getInstance().renderBuffers().bufferSource().getBuffer( //#if MC >= 12111 //$$ RenderTypes.lines() @@ -630,6 +637,7 @@ public void render(final GuiGraphics context, final int mouseX, final int mouseY RenderType.lines() //#endif ); + //#endif //who knows what mods might do smdh //noinspection ConstantValue if (buffer != null) { diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinBlockEntityRendererFactories.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinBlockEntityRendererFactories.java index 3af706cc..cd0c3c66 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinBlockEntityRendererFactories.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinBlockEntityRendererFactories.java @@ -19,6 +19,7 @@ import traben.entity_model_features.config.EMFConfig; import traben.entity_model_features.EMFManager; import traben.entity_model_features.utils.EMFUtils; +import traben.entity_model_features.utils.UEntityTypes; import java.util.ArrayList; import java.util.List; @@ -50,15 +51,15 @@ public class MixinBlockEntityRendererFactories { EMFManager.getInstance().currentBlockEntityTypeLoading = type; // TODO DONT FORGET TO REPLICATE CHANGES IN SPECIAL RENDERERS - if (BlockEntityType.ENCHANTING_TABLE.equals(type)) + if (UEntityTypes.ENCHANTING_TABLE.equals(type)) EMFManager.getInstance().currentSpecifiedModelLoading = "enchanting_book"; - else if (BlockEntityType.LECTERN.equals(type)) + else if (UEntityTypes.LECTERN.equals(type)) EMFManager.getInstance().currentSpecifiedModelLoading = "lectern_book"; - else if (BlockEntityType.CHEST.equals(type)) + else if (UEntityTypes.CHEST.equals(type)) EMFManager.getInstance().currentSpecifiedModelLoading = "chest"; - else if (BlockEntityType.ENDER_CHEST.equals(type)) + else if (UEntityTypes.ENDER_CHEST.equals(type)) EMFManager.getInstance().currentSpecifiedModelLoading = "ender_chest"; - else if (BlockEntityType.TRAPPED_CHEST.equals(type)) + else if (UEntityTypes.TRAPPED_CHEST.equals(type)) EMFManager.getInstance().currentSpecifiedModelLoading = "trapped_chest"; //#if MC >= 12002 //todo did deprecation start in 1.21.2? diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinParrotEntityModel.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinParrotEntityModel.java index 9367b3c0..1e6d1c68 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinParrotEntityModel.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinParrotEntityModel.java @@ -26,6 +26,7 @@ import net.minecraft.client.Minecraft; import traben.entity_model_features.utils.EMFUtils; import traben.entity_texture_features.features.state.ETFEntityRenderState; +import traben.entity_texture_features.utils.UEntityTypes; @Mixin(ParrotOnShoulderLayer.class) public class MixinParrotEntityModel { @@ -51,7 +52,7 @@ public class MixinParrotEntityModel { @Inject(method = RENDER_METHOD, at = @At("HEAD")) private void emf$parrot1(final CallbackInfo ci) { try{ - var entity = (EMFEntity) EntityType.PARROT.create(Minecraft.getInstance().level, EntitySpawnReason.COMMAND); + var entity = (EMFEntity) UEntityTypes.PARROT.create(Minecraft.getInstance().level, EntitySpawnReason.COMMAND); if (entity != null) { EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) ETFEntityRenderState.forEntity(entity)); EMFSubmitData.AWAITING_backupState = EMFAnimationEntityContext.getEmfState(); diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinResourceReloadStart.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinResourceReloadStart.java index d4652e6d..a751b16b 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinResourceReloadStart.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinResourceReloadStart.java @@ -12,7 +12,9 @@ public abstract class MixinResourceReloadStart { @Inject( - //#if MC >=12100 + //#if MC >= 26.2 + //$$ method = "reloadResourcePacks(ZLnet/minecraft/client/GameLoadCookie;)Ljava/util/concurrent/CompletableFuture;", + //#elseif MC >= 12100 method = "reloadResourcePacks(ZLnet/minecraft/client/Minecraft$GameLoadCookie;)Ljava/util/concurrent/CompletableFuture;", //#elseif MC >= 12002 //$$ method = "reloadResourcePacks(ZLnet/minecraft/client/Minecraft$GameLoadCookie;)Ljava/util/concurrent/CompletableFuture;", diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityWithoutLevelRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityWithoutLevelRenderer.java index 9c9eab2e..7ff25acb 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityWithoutLevelRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityWithoutLevelRenderer.java @@ -2,7 +2,9 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.Minecraft; +//#if MC < 26.2 import net.minecraft.client.renderer.MultiBufferSource; +//#endif import net.minecraft.client.renderer.RenderType; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java index e978d383..3d46b705 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java @@ -2,7 +2,6 @@ import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.world.entity.Entity; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderers.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderers.java index 2b82fd85..d6347d7f 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderers.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderers.java @@ -10,6 +10,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.EMFManager; +import traben.entity_model_features.utils.UEntityTypes; @Mixin(EntityRenderers.class) public class MixinEntityRenderers { @@ -31,9 +32,9 @@ public class MixinEntityRenderers { //$$ EMFManager.getInstance().currentSpecifiedModelLoading = "creaking_transient"; //$$ } else //#endif - if(entityType.equals(EntityType.SPECTRAL_ARROW)) { + if(entityType.equals(UEntityTypes.SPECTRAL_ARROW)) { EMFManager.getInstance().currentSpecifiedModelLoading = "spectral_arrow"; - }else if (entityType.equals(EntityType.BREEZE_WIND_CHARGE)) { + }else if (entityType.equals(UEntityTypes.BREEZE_WIND_CHARGE)) { EMFManager.getInstance().currentSpecifiedModelLoading = "breeze_wind_charge"; }else if (entityType //#if MC >= 26.1 @@ -47,7 +48,7 @@ public class MixinEntityRenderers { .replaceAll("(_boat|_raft|_chest_boat)$",""); } //#if MC >= 12111 - //$$ else if (entityType.equals(EntityType.CAMEL_HUSK)) { + //$$ else if (entityType.equals(UEntityTypes.CAMEL_HUSK)) { //$$ EMFManager.getInstance().currentSpecifiedModelLoading = "camel_husk"; //$$ } //#endif diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinItemFrameEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinItemFrameEntityRenderer.java index 359e8ee9..d78ae15e 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinItemFrameEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinItemFrameEntityRenderer.java @@ -10,10 +10,6 @@ @Mixin(ItemFrameRenderer.class) public class MixinItemFrameEntityRenderer { - //#if MC > 26.1 - //$$ dont forget this - //#endif - //#if MC < 12109 //$$ @Inject(method = //#if MC >=12102 diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java index d5a35d26..f69472b1 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java @@ -8,7 +8,9 @@ import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.model.EntityModel; import net.minecraft.client.model.HumanoidModel; +//#if MC < 26.2 import net.minecraft.client.renderer.MultiBufferSource; +//#endif import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.client.renderer.entity.EntityRendererProvider; @@ -101,7 +103,7 @@ private void falseAnimation(CallbackInfo ci, @Local(argsOnly = true) PoseStack p - //#if MC > 26.1 + //#if MC > 26.2 //$$ dont forget this //#elseif MC < 12109 //$$ @Inject(method = diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinStuckArrowsFeatureRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinStuckArrowsFeatureRenderer.java index 5b46f893..8a7448a6 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinStuckArrowsFeatureRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinStuckArrowsFeatureRenderer.java @@ -5,7 +5,9 @@ import com.mojang.datafixers.util.Pair; import net.minecraft.client.model.PlayerModel; import net.minecraft.client.model.geom.ModelPart; +//#if MC < 26.2 import net.minecraft.client.renderer.MultiBufferSource; +//#endif import net.minecraft.client.renderer.entity.RenderLayerParent; import net.minecraft.client.renderer.entity.layers.RenderLayer; import net.minecraft.client.renderer.entity.layers.StuckInBodyLayer; diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_GuiEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_GuiEntityRenderer.java index 11e578e2..c1900851 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_GuiEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_GuiEntityRenderer.java @@ -25,12 +25,14 @@ public class Mixin_GuiEntityRenderer { // so the entity dispatcher can use this state assertEmfState(guiEntityRenderState); } + //#if MC < 26.2 @Inject(method = "renderToTexture(Lnet/minecraft/client/gui/render/state/pip/GuiEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/feature/FeatureRenderDispatcher;renderAllFeatures()V")) private void emf$initRender2(final CallbackInfo ci, @Local(argsOnly = true) GuiEntityRenderState guiEntityRenderState) { // things get reset by the render dispatcher, re-assert before the actual render assertEmfState(guiEntityRenderState); } + //#endif @Unique private static void assertEmfState(final GuiEntityRenderState guiEntityRenderState) { diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java index 3f2828e4..89c3fdf9 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java @@ -3,7 +3,7 @@ import net.minecraft.client.Minecraft; import org.spongepowered.asm.mixin.Mixin; -//#if MC >= 12109 +//#if MC >= 12109 && MC < 26.2 import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java index 73d0c73a..c3dcc256 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java @@ -1,5 +1,6 @@ package traben.entity_model_features.mixin.mixins.rendering.submits; +import net.minecraft.client.Minecraft; import net.minecraft.client.model.HumanoidModel; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; @@ -10,24 +11,33 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.EMF; +import traben.entity_model_features.EMFManager; import traben.entity_model_features.models.IEMFModel; import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; import traben.entity_model_features.models.animation.state.EMFSubmitData; import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.models.animation.state.EMFSubmitExtension; +import traben.entity_model_features.models.parts.EMFModelPartVanilla; import traben.entity_texture_features.ETF; import traben.entity_texture_features.features.ETFRenderContext; +import traben.entity_texture_features.features.state.ETFEntityRenderState; import traben.entity_texture_features.features.state.HoldsETFRenderState; import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.renderer.SubmitNodeStorage; import net.minecraft.client.renderer.feature.ModelFeatureRenderer; +import traben.entity_texture_features.utils.ETFEntity; @Mixin(ModelFeatureRenderer.class) public class Mixin_ModelRenderer { - @Inject(method = "renderModel", at = @At(value = "HEAD")) - private void emf$initRender(final CallbackInfo ci, @Local(argsOnly = true) SubmitNodeStorage.ModelSubmit modelSubmit) { + @Unique + private void headLogic( + //#if MC >= 26.2 + //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit + //#else + net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit + //#endif + ) { var state = modelSubmit.state(); EMFSubmitData data = EMFSubmitData.from(modelSubmit); @@ -48,6 +58,10 @@ public class Mixin_ModelRenderer { EMFAnimationEntityContext.reset(); } + if (state instanceof net.minecraft.client.renderer.entity.state.ItemFrameRenderState) { + EMFAnimationEntityContext.setInItemFrame = true; + } + // Handle emissive/eyes lighting setup var light = modelSubmit.lightCoords(); if (light == ETF.EMISSIVE_FEATURE_LIGHT_VALUE || light == EMF.EYES_FEATURE_LIGHT_VALUE) { @@ -69,18 +83,54 @@ public class Mixin_ModelRenderer { } } } + + //#if MC >= 26.2 + //$$ // Replaces logic for model part submits that now wrap in simple models + //$$ if (modelSubmit.model().root() instanceof EMFModelPartVanilla partVanilla && partVanilla.getRoot() != partVanilla) { + //$$ EMFManager.getInstance().entityRenderCount++; + //$$ + //$$ if (partVanilla.isPlayerArm) { + //$$ if (Minecraft.getInstance().player != null) + //$$ EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) + //$$ ETFEntityRenderState.forEntity((ETFEntity) Minecraft.getInstance().player)); + //$$ EMFAnimationEntityContext.isFirstPersonHand = true; + //$$ } + //$$ } + //#endif + } - @Inject(method = "renderModel", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/Model;setupAnim(Ljava/lang/Object;)V", + @Inject(method = + //#if MC >= 26.2 + //$$ "prepareModel", + //#else + "renderModel", + //#endif + at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/Model;setupAnim(Ljava/lang/Object;)V", shift = At.Shift.AFTER)) - private void emf$animate(final CallbackInfo ci, @Local(argsOnly = true) SubmitNodeStorage.ModelSubmit modelSubmit) { + private void emf$animate(final CallbackInfo ci, + @Local(argsOnly = true) + //#if MC >= 26.2 + //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit + //#else + net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit + //#endif + + ) { // Apply a simple pose copy to armor if required applyArmorBipedPose(modelSubmit); } @Unique - private void applyArmorBipedPose(SubmitNodeStorage.ModelSubmit modelSubmit) { + private void applyArmorBipedPose( + //#if MC >= 26.2 + //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit + //#else + net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit + //#endif + + ) { EMFSubmitData data = EMFSubmitData.from(modelSubmit); if (data != null @@ -93,7 +143,14 @@ private void applyArmorBipedPose(SubmitNodeStorage.ModelSubmit modelSubmi } @Unique - private boolean setModelVariant(@Nullable EMFSubmitData data, SubmitNodeStorage.ModelSubmit modelSubmit) { + private boolean setModelVariant(@Nullable EMFSubmitData data, + //#if MC >= 26.2 + //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit + //#else + net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit + //#endif + + ) { if (data != null && data.modelVariant != -1 && modelSubmit.model().root() instanceof EMFModelPartRoot root) { root.setVariantStateTo(data.modelVariant); return true; @@ -101,21 +158,40 @@ private boolean setModelVariant(@Nullable EMFSubmitData data, SubmitNodeStor return false; } - @Inject(method = "renderTranslucents", at = @At(value = "TAIL")) - private void emf$endRender(final CallbackInfo ci) { + @Unique + private static void tailLogic() { EMFAnimationEntityContext.reset(); - ETFRenderContext.endSpecialRenderOverlayPhase(); - ETFRenderContext.reset(); EMFAnimationEntityContext.setCurrentEntityOnShoulder(false); + EMFAnimationEntityContext.setInItemFrame = true; + EMFAnimationEntityContext.isFirstPersonHand = false; + } + + //#if MC >= 26.2 + //$$ @Inject(method = "prepareModel", at = @At(value = "HEAD")) + //$$ private void emf$initRender(final CallbackInfo ci, @Local(argsOnly = true) net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit) { + //$$ headLogic(modelSubmit); + //$$ } + //$$ + //$$ @Inject(method = "prepareModel", at = @At(value = "TAIL")) + //$$ private void emf$endRender(final CallbackInfo ci) { + //$$ tailLogic(); + //$$ } + //#else + @Inject(method = "renderModel", at = @At(value = "HEAD")) + private void emf$initRender(final CallbackInfo ci, @Local(argsOnly = true) net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit) { + headLogic(modelSubmit); + } + + @Inject(method = "renderTranslucents", at = @At(value = "TAIL")) + private void emf$endRender(final CallbackInfo ci) { + tailLogic(); } @Inject(method = "renderBatch", at = @At(value = "TAIL")) private void emf$endRender2(final CallbackInfo ci) { - EMFAnimationEntityContext.reset(); - ETFRenderContext.endSpecialRenderOverlayPhase(); - ETFRenderContext.reset(); - EMFAnimationEntityContext.setCurrentEntityOnShoulder(false); + tailLogic(); } + //#endif } //#else diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelSubmit_AddBackupState.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelSubmit_AddBackupState.java index 2ee63b57..e72ae2d2 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelSubmit_AddBackupState.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelSubmit_AddBackupState.java @@ -4,7 +4,6 @@ import org.spongepowered.asm.mixin.Mixin; //#if MC>=12109 -import net.minecraft.client.renderer.SubmitNodeStorage; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -17,8 +16,13 @@ import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.models.animation.state.EMFSubmitExtension; -@Mixin(SubmitNodeStorage.ModelSubmit.class) +//#if MC >= 26.2 +//$$ @Mixin(net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit.class) +//#else +@Mixin(net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit.class) +//#endif public abstract class Mixin_ModelSubmit_AddBackupState implements EMFSubmitExtension { + //TODO to go upstream in ETF refactor @Unique private final EMFSubmitData data = new EMFSubmitData(); diff --git a/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java b/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java index 27561f2b..ab2dc4f6 100644 --- a/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java +++ b/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java @@ -290,7 +290,10 @@ private static int getLODFactorOfEntity() { int factor = distance / EMF.config().getConfig().animationLODDistance; //reduce factor when using zoom mods or lower fov int factorByFOV = (int) (factor * - //#if MC >= 26.1 + + //#if MC >= 26.2 + //$$ Minecraft.getInstance().gameRenderer.gameRenderState().levelRenderState.cameraRenderState.hudFov + //#elseif MC >= 26.1 //$$ Minecraft.getInstance().gameRenderer.getGameRenderState().levelRenderState.cameraRenderState.hudFov //#else lastFOV @@ -336,10 +339,10 @@ public static boolean isLODSkippingThisFrame(String modelId) { //FIXME properly, layers lod flickering, likely related to the layer mixin but not doing that rn var type = emfState.entityType(); - if (type == EntityType.VILLAGER || type == EntityType.HORSE) return false; + if (type == UEntityTypes.VILLAGER || type == UEntityTypes.HORSE) return false; // Just putting this here so that fresh animations counter rotation keep working, plus these tend to render from a distance anyway - if (type == EntityType.BLAZE) return false; + if (type == UEntityTypes.BLAZE) return false; String lodKey = emfState.uuid() + modelId; diff --git a/src/main/java/traben/entity_model_features/models/animation/math/methods/emf/IfBMethod.java b/src/main/java/traben/entity_model_features/models/animation/math/methods/emf/IfBMethod.java index cb412cce..24307324 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/methods/emf/IfBMethod.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/methods/emf/IfBMethod.java @@ -1,7 +1,7 @@ package traben.entity_model_features.models.animation.math.methods.emf; -import net.minecraft.util.Tuple; import org.objectweb.asm.MethodVisitor; +import oshi.util.tuples.Pair; import traben.entity_model_features.models.animation.AnimSetupContext; import traben.entity_model_features.models.animation.math.EMFMathException; import traben.entity_model_features.models.animation.math.expression_tree.MathComponent; @@ -35,7 +35,7 @@ public IfBMethod(final List args, final boolean isNegative, AnimSetupCon , parsedArgs); } else { - List> ifSets = new ArrayList<>(); + List> ifSets = new ArrayList<>(); var lastElse = parsedArgs.get(parsedArgs.size() - 1); for (int i = 0; i < parsedArgs.size() - 1; i += 2) { @@ -44,7 +44,7 @@ public IfBMethod(final List args, final boolean isNegative, AnimSetupCon if (!condition.isConstant()) { MathValue.toBoolean(condition.getResult()); // Validate boolean - ifSets.add(new Tuple<>(condition, result)); + ifSets.add(new Pair<>(condition, result)); } else if (MathValue.toBoolean(condition.getResult())) { lastElse = result; break; @@ -56,7 +56,7 @@ public IfBMethod(final List args, final boolean isNegative, AnimSetupCon final MathComponent finalElse = lastElse; setSupplierAndOptimize(() -> { - for (Tuple ifSet : ifSets) { + for (Pair ifSet : ifSets) { if (MathValue.toBoolean(ifSet.getA().getResult())) { return ifSet.getB().getResult(); } diff --git a/src/main/java/traben/entity_model_features/models/animation/math/methods/optifine/IfMethod.java b/src/main/java/traben/entity_model_features/models/animation/math/methods/optifine/IfMethod.java index 13898ee4..d6e1327d 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/methods/optifine/IfMethod.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/methods/optifine/IfMethod.java @@ -1,6 +1,7 @@ package traben.entity_model_features.models.animation.math.methods.optifine; import org.objectweb.asm.MethodVisitor; +import oshi.util.tuples.Pair; import traben.entity_model_features.models.animation.AnimSetupContext; import traben.entity_model_features.models.animation.math.EMFMathException; import traben.entity_model_features.models.animation.math.expression_tree.MathComponent; @@ -9,7 +10,6 @@ import java.util.ArrayList; import java.util.List; -import net.minecraft.util.Tuple; import traben.entity_model_features.models.animation.math.asm.ASMHelper; import traben.entity_model_features.models.animation.math.asm.ASMVariableHandler; @@ -34,7 +34,7 @@ public IfMethod(final List args, final boolean isNegative, AnimSetupCont , parsedArgs); } else { - List> ifSets = new ArrayList<>(); + List> ifSets = new ArrayList<>(); var lastElse = parsedArgs.get(parsedArgs.size() - 1); for (int i = 0; i < parsedArgs.size() - 1; i += 2) { @@ -43,7 +43,7 @@ public IfMethod(final List args, final boolean isNegative, AnimSetupCont if (!condition.isConstant()) { MathValue.toBoolean(condition.getResult()); // Validate boolean - ifSets.add(new Tuple<>(condition, result)); + ifSets.add(new Pair<>(condition, result)); } else if (MathValue.toBoolean(condition.getResult())) { lastElse = result; break; @@ -55,7 +55,7 @@ public IfMethod(final List args, final boolean isNegative, AnimSetupCont final MathComponent finalElse = lastElse; setSupplierAndOptimize(() -> { - for (Tuple ifSet : ifSets) { + for (Pair ifSet : ifSets) { if (MathValue.toBoolean(ifSet.getA().getResult())) { return ifSet.getB().getResult(); } diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitData.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitData.java index eb668623..f3a1c1a0 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitData.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitData.java @@ -27,7 +27,13 @@ public class EMFSubmitData { //#if MC >= 1.21.9 @Nullable - public static EMFSubmitData from(net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit) { + public static EMFSubmitData from(//TODO whole functionality to be moved upstream to ETF in refactor for proper render states + //#if MC >= 26.2 + //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit + //#else + net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit + //#endif + ) { //noinspection ConstantValue return ((Object) modelSubmit) instanceof EMFSubmitExtension emf ? ((EMFSubmitExtension) (Object) modelSubmit).emf$getData() diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java index b119501a..13a6bebf 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java @@ -1,7 +1,6 @@ package traben.entity_model_features.models.parts; import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.VertexMultiConsumer; import net.minecraft.client.renderer.*; import net.minecraft.util.Mth; import net.minecraft.world.phys.Vec3; @@ -42,6 +41,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; +import traben.entity_texture_features.utils.URenderTypeToVertexConsumer; public abstract class EMFModelPart extends ModelPart { public ResourceLocation textureOverride; @@ -118,8 +118,13 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina //$$ red, green, blue, alpha //#endif ); - case LINES -> - renderBoxes(matrices, Minecraft.getInstance().renderBuffers().bufferSource().getBuffer(lines())); + case LINES ->{ + if (vertices instanceof ETFVertexConsumer etfVertexConsumer) { + URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); + if (provider != null) + renderBoxes(matrices, provider.getBuffer(lines())); + } + } case LINES_AND_TEXTURE -> { renderWithTextureOverride(matrices, vertices, light, overlay, //#if MC >= 12100 @@ -128,7 +133,11 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina //$$ red, green, blue, alpha //#endif ); - renderBoxesNoChildren(matrices, Minecraft.getInstance().renderBuffers().bufferSource().getBuffer(lines()), 1f); + if (vertices instanceof ETFVertexConsumer etfVertexConsumer) { + URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); + if (provider != null) + renderBoxesNoChildren(matrices, provider.getBuffer(lines()), 1f); + } } case LINES_AND_TEXTURE_FLASH -> { renderWithTextureOverride(matrices, vertices, light, overlay, @@ -138,8 +147,13 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina //$$ red, green, blue, alpha //#endif ); - float flash = (Mth.sin(System.currentTimeMillis() / 1000f) + 1) / 2f; - renderBoxesNoChildren(matrices, Minecraft.getInstance().renderBuffers().bufferSource().getBuffer(lines()), flash); + if (vertices instanceof ETFVertexConsumer etfVertexConsumer) { + URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); + if (provider != null) { + float flash = (Mth.sin(System.currentTimeMillis() / 1000f) + 1) / 2f; + renderBoxesNoChildren(matrices, provider.getBuffer(lines()), flash); + } + } } case NONE -> { } @@ -242,7 +256,7 @@ void renderWithTextureOverride(PoseStack matrices, VertexConsumer vertices, int RenderType originalLayer = etfVertexConsumer.etf$getRenderLayer(); if (originalLayer == null) return; - MultiBufferSource provider = etfVertexConsumer.etf$getProvider(); + URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); if (provider == null) return; renderTextureOverrideWithoutReset(provider, matrices, light, overlay, //#if MC >= 12100 @@ -256,7 +270,19 @@ void renderWithTextureOverride(PoseStack matrices, VertexConsumer vertices, int provider.getBuffer(originalLayer); }else{ //could be a sprite originally, if so lets ignore trying to reset the texture at all to its original - MultiBufferSource provider = Minecraft.getInstance().renderBuffers().bufferSource(); + //#if MC >= 26.2 + //$$ URenderTypeToVertexConsumer provider = new URenderTypeToVertexConsumer(null) { + //$$ @Override + //$$ public VertexConsumer getBuffer(RenderType type) { + //$$ //TODO probably wrong investigate further + //$$ var draw = Minecraft.getInstance().gameRenderer.renderBuffers().stagedVertexBuffer().appendDraw( + //$$ type.format(), com.mojang.blaze3d.PrimitiveTopology.QUADS); + //$$ return Minecraft.getInstance().gameRenderer.renderBuffers().stagedVertexBuffer().getVertexBuilder(draw); + //$$ } + //$$ }; + //#else + URenderTypeToVertexConsumer provider = new URenderTypeToVertexConsumer(Minecraft.getInstance().renderBuffers().bufferSource()); + //#endif renderTextureOverrideWithoutReset(provider, matrices, light, overlay, //#if MC >= 12100 k @@ -269,7 +295,7 @@ void renderWithTextureOverride(PoseStack matrices, VertexConsumer vertices, int //else cancel out render } - private void renderTextureOverrideWithoutReset(MultiBufferSource provider, PoseStack matrices, int light, int overlay, + private void renderTextureOverrideWithoutReset(URenderTypeToVertexConsumer provider, PoseStack matrices, int light, int overlay, //#if MC >= 12100 final int k //#else @@ -348,9 +374,13 @@ private VertexConsumer testForBuildingException(VertexConsumer vertices) { testBuilding = (BufferBuilder) vertices; } else if (vertices instanceof SpriteCoordinateExpander sprite && sprite.delegate instanceof BufferBuilder) { testBuilding = (BufferBuilder) sprite.delegate; - }else if (vertices instanceof VertexMultiConsumer.Double dub && dub.second instanceof BufferBuilder) { + }else + //#if MC < 26.2 + if (vertices instanceof com.mojang.blaze3d.vertex.VertexMultiConsumer.Double dub && dub.second instanceof BufferBuilder) { testBuilding = (BufferBuilder) dub.second; - }else{ + } else + //#endif + { //exit early if not a buffer builder return vertices; } @@ -411,7 +441,7 @@ void renderLikeETF(PoseStack matrices, VertexConsumer vertices, int light, int o ETFTexture texture = etfVertexConsumer.etf$getETFTexture(); //is etf texture not null and does it special render? if (texture != null && (texture.isEmissive() || texture.isEnchanted())) { - MultiBufferSource provider = etfVertexConsumer.etf$getProvider(); + URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); //very important this is captured before doing the special renders as they can potentially modify //the same ETFVertexConsumer down stream RenderType layer = etfVertexConsumer.etf$getRenderLayer(); diff --git a/src/main/java/traben/entity_model_features/utils/UEntityTypes.java b/src/main/java/traben/entity_model_features/utils/UEntityTypes.java new file mode 100644 index 00000000..09f10de9 --- /dev/null +++ b/src/main/java/traben/entity_model_features/utils/UEntityTypes.java @@ -0,0 +1,52 @@ +package traben.entity_model_features.utils; + +//#if MC >= 26.2 +//$$ import net.minecraft.world.entity.EntityTypes; +//$$ import net.minecraft.world.level.block.entity.BlockEntityTypes; +//#endif + +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.level.block.entity.BlockEntityType; + +public abstract class UEntityTypes { + //#if MC >= 26.2 + //$$ public static BlockEntityType CHEST = BlockEntityTypes.CHEST; + //$$ public static BlockEntityType TRAPPED_CHEST = BlockEntityTypes.TRAPPED_CHEST; + //$$ public static BlockEntityType ENDER_CHEST = BlockEntityTypes.ENDER_CHEST; + //$$ public static BlockEntityType SHULKER_BOX = BlockEntityTypes.SHULKER_BOX; + //$$ public static BlockEntityType BELL = BlockEntityTypes.BELL; + //$$ public static BlockEntityType SIGN = BlockEntityTypes.SIGN; + //$$ public static BlockEntityType DECORATED_POT = BlockEntityTypes.DECORATED_POT; + //$$ public static BlockEntityType ENCHANTING_TABLE = BlockEntityTypes.ENCHANTING_TABLE; + //$$ public static BlockEntityType LECTERN = BlockEntityTypes.LECTERN; + //$$ + //$$ public static EntityType SPECTRAL_ARROW = EntityTypes.SPECTRAL_ARROW; + //$$ public static EntityType BREEZE_WIND_CHARGE = EntityTypes.BREEZE_WIND_CHARGE; + //$$ public static EntityType VILLAGER = EntityTypes.VILLAGER; + //$$ public static EntityType HORSE = EntityTypes.HORSE; + //$$ public static EntityType BLAZE = EntityTypes.BLAZE; + //$$ public static EntityType CAMEL_HUSK = EntityTypes.CAMEL_HUSK; + //#else + public static BlockEntityType BED = BlockEntityType.BED; + public static BlockEntityType CHEST = BlockEntityType.CHEST; + public static BlockEntityType TRAPPED_CHEST = BlockEntityType.TRAPPED_CHEST; + public static BlockEntityType ENDER_CHEST = BlockEntityType.ENDER_CHEST; + public static BlockEntityType SHULKER_BOX = BlockEntityType.SHULKER_BOX; + public static BlockEntityType BELL = BlockEntityType.BELL; + public static BlockEntityType SIGN = BlockEntityType.SIGN; + public static BlockEntityType DECORATED_POT = BlockEntityType.DECORATED_POT; + public static BlockEntityType ENCHANTING_TABLE = BlockEntityType.ENCHANTING_TABLE; + public static BlockEntityType LECTERN = BlockEntityType.LECTERN; + + public static EntityType SPECTRAL_ARROW = EntityType.SPECTRAL_ARROW; + //#if MC > 1.20.1 + public static EntityType BREEZE_WIND_CHARGE = EntityType.BREEZE_WIND_CHARGE; + //#endif + public static EntityType VILLAGER = EntityType.VILLAGER; + public static EntityType HORSE = EntityType.HORSE; + public static EntityType BLAZE = EntityType.BLAZE; + //#if MC >= 1.21.11 + //$$ public static EntityType CAMEL_HUSK = EntityType.CAMEL_HUSK; + //#endif + //#endif +} diff --git a/src/main/resources/entity_model_features_15.accesswidener b/src/main/resources/entity_model_features_15.accesswidener new file mode 100644 index 00000000..22f28cd3 --- /dev/null +++ b/src/main/resources/entity_model_features_15.accesswidener @@ -0,0 +1,42 @@ +accessWidener v2 official + +accessible method net/minecraft/client/model/geom/ModelPart compile (Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;III)V + +extendable class net/minecraft/client/model/geom/ModelPart + + +accessible class net/minecraft/client/model/geom/ModelPart$Polygon +accessible class net/minecraft/client/model/geom/ModelPart$Vertex + + +extendable method net/minecraft/client/model/geom/ModelPart compile (Lcom/mojang/blaze3d/vertex/PoseStack$Pose;Lcom/mojang/blaze3d/vertex/VertexConsumer;III)V + +accessible field net/minecraft/client/model/geom/ModelPart cubes Ljava/util/List; +accessible field net/minecraft/client/model/geom/ModelPart children Ljava/util/Map; +mutable field net/minecraft/client/model/geom/ModelPart cubes Ljava/util/List; +mutable field net/minecraft/client/model/geom/ModelPart children Ljava/util/Map; + +accessible field net/minecraft/client/model/Model renderType Ljava/util/function/Function; + +accessible field net/minecraft/client/renderer/blockentity/BlockEntityRenderers PROVIDERS Ljava/util/Map; +accessible field net/minecraft/client/model/geom/EntityModelSet roots Ljava/util/Map; + +accessible field net/minecraft/world/level/block/state/BlockBehaviour hasCollision Z + +accessible field com/mojang/blaze3d/vertex/PoseStack poses Ljava/util/List; +accessible method com/mojang/blaze3d/vertex/PoseStack$Pose set (Lcom/mojang/blaze3d/vertex/PoseStack$Pose;)V + +accessible field net/minecraft/world/entity/LivingEntity jumping Z + +accessible field com/mojang/blaze3d/vertex/BufferBuilder building Z + +accessible field net/minecraft/client/renderer/SpriteCoordinateExpander delegate Lcom/mojang/blaze3d/vertex/VertexConsumer; + +extendable class net/minecraft/client/model/geom/ModelPart$Cube +accessible field net/minecraft/client/model/geom/ModelPart$Cube polygons [Lnet/minecraft/client/model/geom/ModelPart$Polygon; + +accessible field net/minecraft/world/entity/Entity yRot F + +accessible method net/minecraft/client/renderer/entity/LivingEntityRenderer isUpsideDownName (Ljava/lang/String;)Z + +accessible method net/minecraft/world/phys/shapes/CubeVoxelShape (Lnet/minecraft/world/phys/shapes/DiscreteVoxelShape;)V \ No newline at end of file diff --git a/versions/26.2-fabric/gradle.properties b/versions/26.2-fabric/gradle.properties new file mode 100644 index 00000000..4abcd5f4 --- /dev/null +++ b/versions/26.2-fabric/gradle.properties @@ -0,0 +1,2 @@ +essential.defaults.loom.minecraft=com.mojang:minecraft:26.2 +essential.defaults.loom.mappings= \ No newline at end of file diff --git a/versions/26.2-neoforge/gradle.properties b/versions/26.2-neoforge/gradle.properties new file mode 100644 index 00000000..e665d32c --- /dev/null +++ b/versions/26.2-neoforge/gradle.properties @@ -0,0 +1,3 @@ +essential.defaults.loom.neoForge=net.neoforged:neoforge:26.2.0.1-beta +essential.defaults.loom.minecraft=com.mojang:minecraft:26.2 +essential.defaults.loom.mappings= \ No newline at end of file From ce4703ccb694c9d4cd234bc36c97290870337908 Mon Sep 17 00:00:00 2001 From: Traben Date: Tue, 4 Aug 2026 13:16:57 +1000 Subject: [PATCH 02/20] fix arms with essential --- CHANGELOG.MD | 1 + .../mixin/mixins/rendering/MixinPlayerEntityRenderer.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index adaefea8..c8a69d28 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,5 +1,6 @@ [?] +- fixed first person arm animations with some other mods hand rendering - added new boolean animation variables `is_player_first_person`, `is_player_third_person`, `is_player_third_person_reversed` [3.2.4] diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java index fb45abf7..9c2a74c8 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java @@ -99,6 +99,8 @@ public abstract class MixinPlayerEntityRenderer Date: Tue, 4 Aug 2026 14:42:57 +1000 Subject: [PATCH 03/20] fixed first person arm sleeves visibility --- CHANGELOG.MD | 1 + .../mixins/rendering/MixinPlayerEntityRenderer.java | 12 ++++++++---- .../rendering/submits/Mixin_ModelPartRenderer.java | 4 +++- .../rendering/submits/Mixin_ModelRenderer.java | 4 +++- .../models/animation/EMFAnimationEntityContext.java | 5 ++++- .../models/parts/EMFModelPartWithState.java | 6 ++++-- 6 files changed, 23 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index c8a69d28..7fd12c2a 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,5 +1,6 @@ [?] +- fixed first person arm rendering with sleeves even when turned off in the settings - fixed first person arm animations with some other mods hand rendering - added new boolean animation variables `is_player_first_person`, `is_player_third_person`, `is_player_third_person_reversed` diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java index 9c2a74c8..f5300f32 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java @@ -90,12 +90,16 @@ public abstract class MixinPlayerEntityRenderer= 12109 - @Inject(method = "renderHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitModelPart(Lnet/minecraft/client/model/geom/ModelPart;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/RenderType;IILnet/minecraft/client/renderer/texture/TextureAtlasSprite;)V")) - private void emf$setHandAnims(CallbackInfo ci, @Local(argsOnly = true) ModelPart modelPart, @Local(argsOnly = true) PoseStack poseStack - ) { - EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) ((HoldsETFRenderState)emf$renderState()).etf$getState()); + @Inject(method = "renderHand", at = @At(value = "HEAD")) + private void emf$setHandAnimState(CallbackInfo ci) { + // Before visibility checks + var state = (EMFEntityRenderState) ((HoldsETFRenderState)emf$renderState()).etf$getState(); + EMFAnimationEntityContext.setCurrentEntityIteration(state); EMFAnimationEntityContext.isFirstPersonHand = true; + } + @Inject(method = "renderHand", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitModelPart(Lnet/minecraft/client/model/geom/ModelPart;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/RenderType;IILnet/minecraft/client/renderer/texture/TextureAtlasSprite;)V")) + private void emf$setHandAnims(CallbackInfo ci, @Local(argsOnly = true) ModelPart modelPart) { // flag this for later submit render if (modelPart instanceof EMFModelPartVanilla vanilla) { vanilla.isPlayerArm = true; diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java index 89c3fdf9..40d9b6ef 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java @@ -34,9 +34,11 @@ public class Mixin_ModelPartRenderer { } if (modelSubmit.modelPart() instanceof EMFModelPartVanilla vanilla && vanilla.isPlayerArm) { - if (Minecraft.getInstance().player != null) + if (Minecraft.getInstance().player != null) { + EMFAnimationEntityContext.modelVariationIgnoresVisibility = true; EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) ETFEntityRenderState.forEntity((ETFEntity) Minecraft.getInstance().player)); + } EMFAnimationEntityContext.isFirstPersonHand = true; } } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java index c3dcc256..a20e75db 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java @@ -90,9 +90,11 @@ private void headLogic( //$$ EMFManager.getInstance().entityRenderCount++; //$$ //$$ if (partVanilla.isPlayerArm) { - //$$ if (Minecraft.getInstance().player != null) + //$$ if (Minecraft.getInstance().player != null) { + //$$ EMFAnimationEntityContext.modelVariationIgnoresVisibility = true; //$$ EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) //$$ ETFEntityRenderState.forEntity((ETFEntity) Minecraft.getInstance().player)); + //$$ } //$$ EMFAnimationEntityContext.isFirstPersonHand = true; //$$ } //$$ } diff --git a/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java b/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java index ab2dc4f6..c14d7db6 100644 --- a/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java +++ b/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java @@ -383,6 +383,8 @@ public static void setCurrentEntityIteration(@Nullable EMFEntityRenderState stat setCurrentEntityIteration(state, false); } + public static boolean modelVariationIgnoresVisibility = false; + public static void setCurrentEntityIteration(@Nullable EMFEntityRenderState state, boolean skipModelVariation) { isFirstPersonHand = false; @@ -413,7 +415,7 @@ public static void setCurrentEntityIteration(@Nullable EMFEntityRenderState stat Set roots = EMFManager.getInstance().rootPartsPerEntityTypeForVariation.get(state.typeString()); if (roots != null) { if (isEntityForcedToVanillaModel()) { - roots.forEach((root) -> root.setVariantStateTo(0)); + roots.forEach(root -> root.setVariantStateTo(0)); } else { roots.forEach(EMFModelPartRoot::doVariantCheck); } @@ -629,6 +631,7 @@ public static void reset() { shadowZ = 0; lodFrameSkipping = null; isLayerPhase = false; + modelVariationIgnoresVisibility = false; //#if MC>=12109 if (ETFRenderContext.getCurrentEntityState() != null) ETFRenderContext.reset(); diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartWithState.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartWithState.java index b99d525f..43b7a921 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartWithState.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartWithState.java @@ -108,8 +108,10 @@ void setFromState(EMFModelState newState) { //$$ zScale = newState.zScale(); //#endif - visible = newState.visible(); - skipDraw = newState.hidden(); + if (!EMFAnimationEntityContext.modelVariationIgnoresVisibility) { + visible = newState.visible(); + skipDraw = newState.hidden(); + } textureOverride = newState.texture(); } From 36848751ea9029a240ea0abb88ffeafc628f8634 Mon Sep 17 00:00:00 2001 From: Traben Date: Tue, 4 Aug 2026 14:47:12 +1000 Subject: [PATCH 04/20] fix neoforge iris --- CHANGELOG.MD | 1 + build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 7fd12c2a..8aadfc66 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,5 +1,6 @@ [?] +- fixed 26.2 neoforge iris compatibility not working causing excess animation during the shadow pass - fixed first person arm rendering with sleeves even when turned off in the settings - fixed first person arm animations with some other mods hand rendering - added new boolean animation variables `is_player_first_person`, `is_player_third_person`, `is_player_third_person_reversed` diff --git a/build.gradle.kts b/build.gradle.kts index fd487926..09c70de7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -136,7 +136,7 @@ dependencies { "IRIS" setVar ( modImpl("maven.modrinth:iris:", - 26_02_00 to ver("3uIIps8q", null, null), + 26_02_00 to ver("3uIIps8q", null, "YL57xq9U"), 26_01_00 to ver("MwcLS51S", null, "YEGDGnJM"), //1_21_11 to ver("TSXvi2yD", null, "t3ruzodq"), //"k9tHcfnb"), //todo why does this break 1_21_06 to ver("l77DAK6U", null, "t3ruzodq"), //"xA5cxBvz"), // same here From 9d13c86d9341e8d13b3b57bee0eb3e432bd58ebc Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 13 Aug 2026 12:38:53 +1000 Subject: [PATCH 05/20] fix export missing parts #1 --- .../models/EMFModelMappings.java | 124 ++++++++++++------ 1 file changed, 85 insertions(+), 39 deletions(-) diff --git a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java index 38964739..51bf5cbd 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java +++ b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -1521,7 +1522,7 @@ private static void exportKnown(final EMFModel_ID mobId, final @Nullable ModelPa EMFUtils.log("Additionally exporting/logging model for " + mobName + " again as though it did not have known OptiFine part names:\nThis might highlight some vanilla, or mod added, parts that are not usually exposed by OptiFine"); try { - exploreProvidedEntityModelAndExportIfNeeded(root, mobId, null, exportOnlyFirstTime, allowsExport); + exploreProvidedEntityModelAndExportIfNeeded(root, mobId, null, false, false); } catch (Exception e) { EMFUtils.logError("Error while exporting model for " + mobName + " again as though it did not have known OptiFine part names:"); //noinspection CallToPrintStackTrace @@ -1566,25 +1567,25 @@ public static Map exploreProvidedEntityModelAndExportIfNeeded(Mo //cache result; UNKNOWN_MODEL_MAP_CACHE.put(id, mobMap); - if (allowsExport) { - StringBuilder mapString = new StringBuilder(); - - String namespace = mobId.namespace; - String fileName = mobId.getfileName(); - - mapString.append(" |-[assets/").append(namespace).append("/optifine/cem/").append(fileName).append(".jem]\n"); - mobMap.forEach((key, entry) -> { - mapString.append(" | |-[").append("root".equals(key) ? "(optional) " : "").append("part=").append(key).append("]\n"); - mapString.append(detailsMap.get(key)); - }); - mapString.append(" \\-\\{{end of model}}"); - - if (known) { - EMFUtils.log("Known model detected, Mapping now...\n" + mapString); - } else { - EMFUtils.log("Unknown (possibly modded) model detected, Mapping now...\n" + mapString); - } + StringBuilder mapString = new StringBuilder(); + + String namespace = mobId.namespace; + String fileName = mobId.getfileName(); + + mapString.append(" |-[assets/").append(namespace).append("/optifine/cem/").append(fileName).append(".jem]\n"); + mobMap.forEach((key, entry) -> { + mapString.append(" | |-[").append("root".equals(key) ? "(optional) " : "").append("part=").append(key).append("]\n"); + mapString.append(detailsMap.get(key)); + }); + mapString.append(" \\-\\{{end of model}}"); + + if (known) { + EMFUtils.log("Known model detected, Mapping now...\n" + mapString); + } else { + EMFUtils.log("Unknown (possibly modded) model detected, Mapping now...\n" + mapString); + } + if (allowsExport) { EMFUtils.log("creating example .jem file for " + fileName); var jemPrinter = new JsonObject(); int[] textureSize = null; @@ -1593,7 +1594,6 @@ public static Map exploreProvidedEntityModelAndExportIfNeeded(Mo mobMap.entrySet()) { JsonObject partPrinter = new JsonObject(); - partPrinter.addProperty("invertAxis", "xy"); partPrinter.addProperty("part", entry.getKey()); partPrinter.addProperty("id", entry.getKey()); partPrinter.addProperty("attach", false); @@ -1601,7 +1601,15 @@ public static Map exploreProvidedEntityModelAndExportIfNeeded(Mo // allow nested child parts named root to be found first otherwise apply the root part as the root PartAndOffsets vanillaModelPart = searchPart == null && "root".equals(entry.getKey()) ? new PartAndOffsets(originalModel, 0,0,0) : searchPart; - textureSize = initPartPrinterAndCaptureTextureSizeIfNeeded(vanillaModelPart, partPrinter, textureSize); + partPrinter(vanillaModelPart, partPrinter, textureSize, mobMap.values(), false, originalModel); + + if (textureSize == null && partPrinter.has("textureSize")) { + var textureSize2 = partPrinter.getAsJsonArray("textureSize"); + if (textureSize2.size() == 2) { + textureSize = new int[]{textureSize2.get(0).getAsInt(), textureSize2.get(1).getAsInt()}; + } + } + models.add(partPrinter); } @@ -1662,17 +1670,25 @@ private static void addArrayProperty(JsonObject obj, String name, JsonObject... } - private static int[] initPartPrinterAndCaptureTextureSizeIfNeeded(PartAndOffsets partAndOffsets, JsonObject partPrinter, int[] textureSize) { - - int[] thisTextureSize = null; + private static JsonObject partPrinter(PartAndOffsets partAndOffsets, JsonObject partPrinter, int[] textureSize, Collection topLevelParts, boolean child) { if (partAndOffsets != null && partAndOffsets.part != null) { var vanillaModelPart = partAndOffsets.part; + partPrinter.addProperty("invertAxis", "xy"); // invert x and y's - var x = -partAndOffsets.x + vanillaModelPart.x; - var y = -24 -partAndOffsets.y + vanillaModelPart.y; - var z = partAndOffsets.z -vanillaModelPart.z; + var x = (child + ? -vanillaModelPart.x - partAndOffsets.x // See self-referential method call at bottom of file + : -partAndOffsets.x + vanillaModelPart.x + ); + var y = (child + ? -vanillaModelPart.y - partAndOffsets.y // See self-referential method call at bottom of file + : -24 -partAndOffsets.y + vanillaModelPart.y + ); + var z = (child + ? vanillaModelPart.z - partAndOffsets.z // See self-referential method call at bottom of file + : partAndOffsets.z - vanillaModelPart.z + ); if (x != 0 || y != 0 || z != 0) addArrayProperty(partPrinter,"translate", x, y, z); float rx = partAndOffsets.part.getInitialPose() @@ -1697,13 +1713,13 @@ private static int[] initPartPrinterAndCaptureTextureSizeIfNeeded(PartAndOffsets //#endif * Mth.RAD_TO_DEG; - if (EMF.config().getConfig().exportRotations && (rx != 0 || ry != 0 || rz != 0)) - addArrayProperty(partPrinter,"rotate", rx, ry, rz); + if (child || EMF.config().getConfig().exportRotations && (rx != 0 || ry != 0 || rz != 0)) + addArrayProperty(partPrinter, "rotate", rx, ry, rz); if (vanillaModelPart.xScale != 1f) partPrinter.addProperty("scale", vanillaModelPart.xScale); // get part size incase empty, though cuboids often have better ideas about this //partPrinter.textureSize = ((IEMFTextureSizeSupplier) vanillaModelPart).emf$getTextureSize(); - thisTextureSize = ((IEMFTextureSizeSupplier) vanillaModelPart).emf$getTextureSize(); + int[] thisTextureSize = ((IEMFTextureSizeSupplier) vanillaModelPart).emf$getTextureSize(); var list =new ArrayList(vanillaModelPart.cubes.size()); @@ -1735,21 +1751,52 @@ private static int[] initPartPrinterAndCaptureTextureSizeIfNeeded(PartAndOffsets } // invert x and y - coordinates[0] = -coordinates[0] - coordinates[3] - x; - coordinates[1] = -coordinates[1] - coordinates[4] - y; - - coordinates[2] = coordinates[2] - z; + if (!child) { + coordinates[0] = -coordinates[0] - coordinates[3] - x; + coordinates[1] = -coordinates[1] - coordinates[4] - y; + + coordinates[2] = coordinates[2] - z; + } else { + // Just flat invert as cem will only flat reinvert it + coordinates[0] = -coordinates[0] - coordinates[3]; + coordinates[1] = -coordinates[1] - coordinates[4]; + } addArrayProperty(boxPrinter, "coordinates", coordinates); list.add(boxPrinter); } - if (textureSize != null && (!Arrays.equals(textureSize, thisTextureSize))) { - addArrayProperty(partPrinter,"textureSize", textureSize[0], textureSize[1]); + if (thisTextureSize != null) { + if (textureSize == null){ + addArrayProperty(partPrinter,"textureSize", thisTextureSize[0], thisTextureSize[1]); + } else if (!Arrays.equals(textureSize, thisTextureSize)) { + addArrayProperty(partPrinter,"textureSize", textureSize[0], textureSize[1]); + } } + if (!list.isEmpty()) addArrayProperty(partPrinter, "boxes", list.toArray(new JsonObject[0])); + + if (!partAndOffsets.part.children.isEmpty()) { + var nonTopLevel = partAndOffsets.part.children.keySet().stream().filter(it -> !topLevelParts.contains(it)).toList(); + if (!nonTopLevel.isEmpty()) { + // There exist child parts that are not in the optifine mappings (e.g. witch hat sub parts & wolf head/tail bullshit) + // we will add them as cem submodels to include their cubes + var childList = new ArrayList(); + for (String name : nonTopLevel) { + var childPart = partAndOffsets.part.getChild(name); + var wrapped = child + // Child calls will use this data class differently as they have simpler setup + ? new PartAndOffsets(childPart, 0, 0, 0) // Further children no longer need weird pivot adjustments + : new PartAndOffsets(childPart, x, y, z); // First child needs to undo these xyz values + var object = new JsonObject(); + object.addProperty("id", name + "_export_copy"); + childList.add(partPrinter(wrapped, object, thisTextureSize, topLevelParts, true)); + } + addArrayProperty(partPrinter, "submodels", childList.toArray(new JsonObject[0])); + } + } } - return textureSize == null ? thisTextureSize : textureSize; + return partPrinter; } private static @Nullable PartAndOffsets getChildByName(String name, @NotNull ModelPart part, float x, float y, float z) { @@ -1852,8 +1899,7 @@ private static class OptifineMapper { return new OptifineMapper(modelNames); } - - private static Set exceptions = Set.of("helmet", "chestplate", "leggings", "boots"); + private static final Set exceptions = Set.of("helmet", "chestplate", "leggings", "boots"); void parts(final Map stringStringMap) { for (String key : modelNames) { From bb46315dbada10566f94cdfc6dc68606213ad77a Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 13 Aug 2026 12:39:13 +1000 Subject: [PATCH 06/20] fix neoforge iris dep value --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 09c70de7..1ecfaa85 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -136,7 +136,7 @@ dependencies { "IRIS" setVar ( modImpl("maven.modrinth:iris:", - 26_02_00 to ver("3uIIps8q", null, "YL57xq9U"), + 26_02_00 to ver("3uIIps8q", null, "1.11.2+26.2-neoforge"), 26_01_00 to ver("MwcLS51S", null, "YEGDGnJM"), //1_21_11 to ver("TSXvi2yD", null, "t3ruzodq"), //"k9tHcfnb"), //todo why does this break 1_21_06 to ver("l77DAK6U", null, "t3ruzodq"), //"xA5cxBvz"), // same here From f7d148b745e611cbd8c3ad5d839169059a5a11fe Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 13 Aug 2026 12:40:36 +1000 Subject: [PATCH 07/20] param fix --- .../traben/entity_model_features/models/EMFModelMappings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java index 51bf5cbd..3ee227ee 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java +++ b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java @@ -1601,7 +1601,7 @@ public static Map exploreProvidedEntityModelAndExportIfNeeded(Mo // allow nested child parts named root to be found first otherwise apply the root part as the root PartAndOffsets vanillaModelPart = searchPart == null && "root".equals(entry.getKey()) ? new PartAndOffsets(originalModel, 0,0,0) : searchPart; - partPrinter(vanillaModelPart, partPrinter, textureSize, mobMap.values(), false, originalModel); + partPrinter(vanillaModelPart, partPrinter, textureSize, mobMap.values(), false); if (textureSize == null && partPrinter.has("textureSize")) { var textureSize2 = partPrinter.getAsJsonArray("textureSize"); From 55f3c8d36013df7c9f14b89cb3b30cae80c8c76b Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 13 Aug 2026 13:38:58 +1000 Subject: [PATCH 08/20] further export fix --- .../entity_model_features/EMFManager.java | 49 ++++++++++++------- .../models/EMFModelMappings.java | 11 +++-- .../models/EMFModel_ID.java | 36 ++++++++++---- 3 files changed, 63 insertions(+), 33 deletions(-) diff --git a/src/main/java/traben/entity_model_features/EMFManager.java b/src/main/java/traben/entity_model_features/EMFManager.java index 6d6b421c..5cb70f8f 100644 --- a/src/main/java/traben/entity_model_features/EMFManager.java +++ b/src/main/java/traben/entity_model_features/EMFManager.java @@ -217,7 +217,8 @@ private static void handleBoats(final String originalLayerName, final EMFModel_I mobNameForFileAndMap.setMapIdAndAddFallbackModel(jem); String type = mobNameForFileAndMap.getfileName().split("/")[1]; - mobNameForFileAndMap.setFileName(type + "_" + jem); + mobNameForFileAndMap.setFileName(type + "_" + jem) + .resetCacheID(); } public boolean wasEBEModified() { @@ -405,7 +406,7 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final //#if MC>=12111 //$$ case "camel" -> { //$$ if (currentSpecifiedModelLoading.equals("camel_husk")) - //$$ mobNameForFileAndMap.pushNewMainModelAddingOldAsFallback("camel_husk"); + //$$ mobNameForFileAndMap.pushNewMainModelAddingOldAsFallback("camel_husk").resetCacheID(); //$$ } //#endif //#if MC>=12109 @@ -432,9 +433,13 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final case "bed_head" -> mobNameForFileAndMap.setBoth("bed_head").addFallbackModel("bed"); case "book" -> { if (currentSpecifiedModelLoading.equals("enchanting_book")) { - mobNameForFileAndMap.setBoth("enchanting_book", "book").addFallbackModel("book"); + mobNameForFileAndMap.setBoth("enchanting_book", "book") + .addFallbackModel("book") + .resetCacheID(); } else {/* if(currentSpecifiedModelLoading.equals("lectern_book"))*/ - mobNameForFileAndMap.setBoth("lectern_book", "book").addFallbackModel("book"); + mobNameForFileAndMap.setBoth("lectern_book", "book") + .addFallbackModel("book") + .resetCacheID(); } } case "salmon_small", "salmon_large" -> mobNameForFileAndMap.addFallbackModel("salmon"); @@ -442,7 +447,8 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final case "creaking_transient" -> mobNameForFileAndMap.setMapIdAndAddFallbackModel("creaking"); case "chest" -> mobNameForFileAndMap.setBoth( currentSpecifiedModelLoading != null && !currentSpecifiedModelLoading.isBlank() - ? currentSpecifiedModelLoading : "chest", "chest"); + ? currentSpecifiedModelLoading : "chest", "chest") + .resetCacheID(); case "conduit_cage" -> mobNameForFileAndMap.setBoth("conduit_cage").addFallbackModel("conduit"); case "conduit_eye" -> mobNameForFileAndMap.setBoth("conduit_eye").addFallbackModel("conduit"); case "conduit_shell" -> @@ -461,9 +467,9 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final case "leash_knot" -> mobNameForFileAndMap.setBoth("lead_knot"); case "llama", "llama_baby" -> traderLlamaHappened = false; case "llama_decor" -> - mobNameForFileAndMap.setBoth(traderLlamaHappened ? "trader_llama_decor" : "llama_decor"); + mobNameForFileAndMap.setBoth(traderLlamaHappened ? "trader_llama_decor" : "llama_decor").resetCacheID(); case "llama_baby_decor" -> - mobNameForFileAndMap.setBoth(traderLlamaHappened ? "trader_llama_baby_decor" : "llama_baby_decor"); + mobNameForFileAndMap.setBoth(traderLlamaHappened ? "trader_llama_baby_decor" : "llama_baby_decor").resetCacheID(); case "chest_minecart", "command_block_minecart", "spawner_minecart", "tnt_minecart", "furnace_minecart", "hopper_minecart" -> mobNameForFileAndMap.setMapIdAndAddFallbackModel("minecart"); @@ -472,15 +478,16 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final case "player_slim" -> mobNameForFileAndMap.addFallbackModel("player"); case "arrow" -> { if (currentSpecifiedModelLoading.equals("spectral_arrow")) { - mobNameForFileAndMap.setBoth("spectral_arrow"); - mobNameForFileAndMap.addFallbackModel("arrow"); + mobNameForFileAndMap.setBoth("spectral_arrow") + .resetCacheID() + .addFallbackModel("arrow"); } } case "boat_water_patch" -> { if (currentSpecifiedModelLoading.startsWith("emf$boat$")) { String type = currentSpecifiedModelLoading.substring(9); - mobNameForFileAndMap.setBoth(type + "_boat_patch", "boat_patch").addFallbackModel("boat_patch"); + mobNameForFileAndMap.setBoth(type + "_boat_patch", "boat_patch").addFallbackModel("boat_patch").resetCacheID(); currentSpecifiedModelLoading = ""; } else { mobNameForFileAndMap.setBoth("boat_patch"); @@ -491,7 +498,7 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final case "pufferfish_small" -> mobNameForFileAndMap.setBoth("puffer_fish_small"); case "shulker" -> { if (currentSpecifiedModelLoading.equals("shulker_box")) { - mobNameForFileAndMap.setBoth("shulker_box"); + mobNameForFileAndMap.setBoth("shulker_box").resetCacheID(); } } case "skeleton_skull" -> mobNameForFileAndMap.setBoth("head_skeleton"); @@ -508,13 +515,13 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final case "undead_horse_armor" -> { if (lastUndeadHorse != null) { mobNameForFileAndMap.pushNewMainModelAndMapIdAddingOldAsFallback( - lastUndeadHorse.replaceAll("_baby", "") + "_armor"); + lastUndeadHorse.replaceAll("_baby", "") + "_armor").resetCacheID(); } } case "undead_horse_baby_armor" -> { if (lastUndeadHorse != null) { mobNameForFileAndMap.pushNewMainModelAndMapIdAddingOldAsFallback( - lastUndeadHorse.replaceAll("_baby", "") + "_baby_armor"); + lastUndeadHorse.replaceAll("_baby", "") + "_baby_armor").resetCacheID(); } } default -> { @@ -533,16 +540,19 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final if (originalLayerName.startsWith("sign/standing/")) { sign += "_sign"; mobNameForFileAndMap.setFileName(sign) - .setMapIdAndAddFallbackModel("sign"); + .setMapIdAndAddFallbackModel("sign") + .resetCacheID(); } else if (originalLayerName.startsWith("sign/wall/")) { sign += "_wall_sign"; mobNameForFileAndMap.setFileName(sign) .setMapIdAndAddFallbackModel("wall_sign") - .setMapIdAndAddFallbackModel("sign"); + .setMapIdAndAddFallbackModel("sign") + .resetCacheID(); } else { sign += "_hanging_sign"; mobNameForFileAndMap.setFileName(sign) - .setMapIdAndAddFallbackModel("hanging_sign"); + .setMapIdAndAddFallbackModel("hanging_sign") + .resetCacheID(); } } default -> { @@ -550,7 +560,8 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final if (EMF.config().getConfig().automaticModelExporting) EMFUtils.log("EMF unknown modifiable block entity model identified during loading: " + currentSpecifiedModelLoading + ".jem"); mobNameForFileAndMap.setFileName(currentSpecifiedModelLoading) - .setMapIdAndAddFallbackModel(currentSpecifiedModelLoading, originalLayerName); + .setMapIdAndAddFallbackModel(currentSpecifiedModelLoading, originalLayerName) + .resetCacheID(); } } } else if (originalLayerName.contains("/") && layer. @@ -585,7 +596,7 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final ///jem name and fallbacks are final and correct from here and there are no blank fallbacks if (mobNameForFileAndMap.getfileName().isBlank()){ if(mobNameForFileAndMap.hasFallbackModels()){ - mobNameForFileAndMap = mobNameForFileAndMap.getNextFallbackModel(); + mobNameForFileAndMap = mobNameForFileAndMap.getNextFallbackModel(0); } else if(!originalLayerName.isBlank()){ mobNameForFileAndMap.setFileName(originalLayerName); } else { @@ -602,7 +613,7 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final //cache the layers for the model // if(!isBaby) { cache_LayersByModelName.put(mobNameForFileAndMap, layer); - mobNameForFileAndMap.forEachFallback((fallBack) -> cache_LayersByModelName.put(fallBack, layer)); + mobNameForFileAndMap.forEachFallback((fallBack) -> cache_LayersByModelName.putIfAbsent(fallBack, layer)); // } diff --git a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java index 3ee227ee..ca374596 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java +++ b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java @@ -1538,7 +1538,7 @@ private static void exportKnown(final EMFModel_ID mobId, final @Nullable ModelPa //this would make a usable mapping of the given model but with no part name changing as it would not be optifine customized public static Map exploreProvidedEntityModelAndExportIfNeeded(ModelPart originalModel, EMFModel_ID mobId, @Nullable Map mobMap, boolean exportOnlyFirstTime, boolean allowsExport) { - String id = mobId.getDisplayFileName(); + String id = mobId.getCacheID(); if (UNKNOWN_MODEL_MAP_CACHE.containsKey(id) && exportOnlyFirstTime) return UNKNOWN_MODEL_MAP_CACHE.get(id); @@ -1561,7 +1561,9 @@ public static Map exploreProvidedEntityModelAndExportIfNeeded(Mo boolean known = mobMap != null; if (!known) { mobMap = new HashMap<>(); - mapThisAndChildren("root", originalModel, mobMap, detailsMap, allowsExport); + mapThisAndChildren("root", originalModel, mobMap, detailsMap, allowsExport); + } else { + mapThisAndChildren("root", originalModel, new HashMap<>(), detailsMap, allowsExport); } //cache result; @@ -1575,7 +1577,8 @@ public static Map exploreProvidedEntityModelAndExportIfNeeded(Mo mapString.append(" |-[assets/").append(namespace).append("/optifine/cem/").append(fileName).append(".jem]\n"); mobMap.forEach((key, entry) -> { mapString.append(" | |-[").append("root".equals(key) ? "(optional) " : "").append("part=").append(key).append("]\n"); - mapString.append(detailsMap.get(key)); + var details = detailsMap.get(entry); + mapString.append(details == null ? "" : details); }); mapString.append(" \\-\\{{end of model}}"); @@ -1624,7 +1627,7 @@ public static Map exploreProvidedEntityModelAndExportIfNeeded(Mo jemPrinter.add("textureSize", textureSize2); printModel(namespace, fileName, jemPrinter); - mobId.forEachFallback((fallback) -> printModel(fallback.namespace, fallback.getfileName(), jemPrinter)); + // Do not print fallbacks } return mobMap; } diff --git a/src/main/java/traben/entity_model_features/models/EMFModel_ID.java b/src/main/java/traben/entity_model_features/models/EMFModel_ID.java index 89c79471..34a1437f 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModel_ID.java +++ b/src/main/java/traben/entity_model_features/models/EMFModel_ID.java @@ -16,6 +16,20 @@ public class EMFModel_ID implements Comparable { private @NotNull String fileName; private @NotNull String mapId; + public EMFModel_ID setCacheID(@NotNull String cacheID) { + this.cacheID = cacheID; + return this; + } + public EMFModel_ID resetCacheID() { + return setCacheID(namespace + ":" + fileName); + } + + public @NotNull String getCacheID() { + return cacheID; + } + + private @NotNull String cacheID; + private final List fallBackModels; private record FallbackModel(String namespace, String fileName){} @@ -23,14 +37,15 @@ private record FallbackModel(String namespace, String fileName){} public EMFModel_ID(String both) { this(both, both); } - public EMFModel_ID(String both, String mapId) { - this(both, mapId, new ArrayList<>()); + public EMFModel_ID(String fileName, String mapId) { + this(fileName, mapId, new ArrayList<>()); } - private EMFModel_ID(@NotNull String both, @NotNull String mapId, List fallBackModels) { - this.fileName = both; + private EMFModel_ID(@NotNull String fileName, @NotNull String mapId, List fallBackModels) { + this.fileName = fileName; this.mapId = mapId; this.fallBackModels = fallBackModels; + this.resetCacheID(); } public EMFModel_ID setFileName(final String fileName) throws EMFException { @@ -51,15 +66,14 @@ public EMFModel_ID setFileName(final String fileName) throws EMFException { @Override public boolean equals(Object o) { - if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; EMFModel_ID that = (EMFModel_ID) o; - return fileName.equals(that.fileName) && Objects.equals(mapId, that.mapId); + return Objects.equals(getCacheID(), that.getCacheID()); } @Override public int hashCode() { - return Objects.hash(fileName, mapId); + return Objects.hashCode(getCacheID()); } @Override @@ -93,21 +107,23 @@ public boolean hasFallbackModels() { public void forEachFallback(Consumer action){ var fallbackModel = this; + int count = 0; while (fallbackModel.hasFallbackModels()) { - fallbackModel = fallbackModel.getNextFallbackModel(); + count++; + fallbackModel = fallbackModel.getNextFallbackModel(count); if (fallbackModel == null) return; action.accept(fallbackModel); } } - public @Nullable EMFModel_ID getNextFallbackModel() { + public @Nullable EMFModel_ID getNextFallbackModel(int count) { if (hasFallbackModels()) { //noinspection SequencedCollectionMethodCanBeUsed var next = fallBackModels.get(0); var second = new EMFModel_ID(next.fileName, mapId, fallBackModels.subList(1, fallBackModels.size())); second.namespace = next.namespace == null ? namespace : next.namespace; - return second; + return second.setCacheID(this.cacheID + "_fallback_" + count); } return null; } From 8f6e93097db4e173b344b0372cd364668697d615 Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 13 Aug 2026 14:02:22 +1000 Subject: [PATCH 09/20] rabbit export fix --- .../entity_model_features/models/EMFModelMappings.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java index ca374596..59b14707 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java +++ b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java @@ -927,8 +927,8 @@ private static void initOptifineMappings() { //$$ partMapping("left_arm", "left_front_leg"), //$$ partMapping("right_arm", "right_front_leg"), //$$ partMapping("head"), - //$$ partMapping("front_legs"), - //$$ partMapping("back_legs"), + //$$ partMapping("frontlegs"), + //$$ partMapping("backlegs"), //$$ partMapping("right_ear"), //$$ partMapping("left_ear"), //$$ partMapping("tail") @@ -943,8 +943,8 @@ private static void initOptifineMappings() { //$$ partMapping("left_arm", "left_front_leg_r1"), //$$ partMapping("right_arm", "right_front_leg_r1"), //$$ partMapping("head"), - //$$ partMapping("front_legs"), - //$$ partMapping("back_legs"), + //$$ partMapping("frontlegs"), + //$$ partMapping("backlegs"), //$$ partMapping("right_ear"), //$$ partMapping("left_ear"), //$$ partMapping("tail", "tail_r1") From f7e5ad75d1f35f4c20be0ab0869af1b5429ce08c Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 13 Aug 2026 14:17:15 +1000 Subject: [PATCH 10/20] axolotl export fix --- .../traben/entity_model_features/models/EMFModelMappings.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java index 59b14707..d6775892 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java +++ b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java @@ -598,7 +598,6 @@ private static void initOptifineMappings() { //$$ partMapping("body"), //$$ partMapping("leg1", "right_hind_leg"), //$$ partMapping("leg2", "left_hind_leg"), - //$$ partMapping("leg2_cube", "right_leg_r1"), // Why? //$$ partMapping("leg3", "right_front_leg"), //$$ partMapping("leg4", "left_front_leg"), //$$ partMapping("right_gills"), From e17dd22807be16e2bf10bf916afcd2b52ce7dec3 Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 13 Aug 2026 14:18:28 +1000 Subject: [PATCH 11/20] changelog --- CHANGELOG.MD | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 8aadfc66..dfae294f 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,5 +1,6 @@ [?] +- fixed several model exporting issues, including missing parts, wrong rotations, and rabbit/axolotl legs on 26.1+ - fixed 26.2 neoforge iris compatibility not working causing excess animation during the shadow pass - fixed first person arm rendering with sleeves even when turned off in the settings - fixed first person arm animations with some other mods hand rendering From 764021cb7a63760e5bad01d18dcda01387f40494 Mon Sep 17 00:00:00 2001 From: Traben Date: Tue, 18 Aug 2026 09:58:46 +1000 Subject: [PATCH 12/20] state refactor --- gradle.properties | 4 +- .../traben/entity_model_features/EMF.java | 51 +- .../EMFAnimationApi.java | 22 +- .../entity_model_features/EMFManager.java | 4 +- .../config/EMFConfig.java | 8 +- .../mixin/mixins/MixinCapeModels.java | 3 +- .../mixin/mixins/MixinEntity.java | 10 +- .../mixin/mixins/MixinGameRenderer.java | 7 +- .../mixin/mixins/MixinModel.java | 7 +- .../mixin/mixins/MixinModelPart.java | 4 +- .../mixin/mixins/MixinParrotEntityModel.java | 20 +- .../accessor/Mixin_GuiEntityTester.java | 11 +- ...inLivingEntityRenderer_ValueCapturing.java | 27 +- .../MixinBlockEntityRenderDispatcher.java | 50 - .../MixinBlockEntityWithoutLevelRenderer.java | 64 +- .../mixins/rendering/MixinDragonRenderer.java | 6 +- .../MixinEntityRenderDispatcher.java | 66 +- .../MixinItemFrameEntityRenderer.java | 6 +- .../rendering/MixinLivingEntityRenderer.java | 31 +- .../rendering/MixinPlayerEntityRenderer.java | 25 +- .../arrows/MixinProjectileEntityRenderer.java | 7 +- .../MixinStuckArrowsFeatureRenderer.java | 8 +- .../feature/MixinEyesFeatureRenderer.java | 24 - .../feature/MixinHeadFeatureRenderer.java | 6 +- .../feature/MixinHeldItemFeatureRenderer.java | 8 +- .../MixinSlimeOverlayFeatureRenderer.java | 5 +- .../MixinWolfCollarFeatureRenderer.java | 1 - .../rendering/model/MixinVillagerModel.java | 5 +- .../Mixin_ChestSpecialRenderer_PassState.java | 46 - .../submits/Mixin_GuiEntityRenderer.java | 66 - ...umanoidArmorLayer_AddBaseModelPoseRef.java | 16 +- .../submits/Mixin_ModelPartRenderer.java | 29 +- .../submits/Mixin_ModelRenderer.java | 140 +- .../Mixin_ModelSubmit_AddBackupState.java | 63 - .../Mixin_BoatRenderer_PassState.java | 39 - .../Mixin_TridentRenderer_PassState.java | 39 - .../models/EMFModelMappings.java | 26 +- .../animation/EMFAnimationEntityContext.java | 1535 +---------------- .../models/animation/math/EMFMath.java | 862 +++++++++ .../math/asm/ASMAnimationHandler.java | 12 +- .../math/asm/ASMVariableHandler.java | 6 +- .../OldEMFAnimationHandler.java | 12 +- .../animation/math/methods/emf/NBTMethod.java | 10 +- .../variables/EMFModelOrRenderVariable.java | 30 +- .../math/variables/VariableRegistry.java | 166 +- .../factories/ModelVariableFactory.java | 6 +- .../models/animation/state/EMFBipedPose.java | 2 + .../animation/state/EMFEntityRenderState.java | 230 +++ .../EMFEntityRenderStateViaReference.java | 73 +- .../models/animation/state/EMFState.java | 266 +++ .../models/animation/state/EMFSubmitData.java | 71 +- .../animation/state/EMFSubmitExtension.java | 6 +- .../models/parts/EMFModelPart.java | 35 +- .../models/parts/EMFModelPartCustom.java | 6 +- .../models/parts/EMFModelPartRoot.java | 29 +- .../models/parts/EMFModelPartWithState.java | 6 +- .../utils/EMFAnimationPauseHandler.java | 103 ++ .../utils/EMFLODHandler.java | 134 ++ .../entity_model_features.mixins.json | 9 +- 59 files changed, 2175 insertions(+), 2388 deletions(-) delete mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityRenderDispatcher.java delete mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinEyesFeatureRenderer.java delete mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ChestSpecialRenderer_PassState.java delete mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_GuiEntityRenderer.java delete mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelSubmit_AddBackupState.java delete mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/adjustments/Mixin_BoatRenderer_PassState.java delete mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/adjustments/Mixin_TridentRenderer_PassState.java create mode 100644 src/main/java/traben/entity_model_features/models/animation/math/EMFMath.java create mode 100644 src/main/java/traben/entity_model_features/models/animation/state/EMFState.java create mode 100644 src/main/java/traben/entity_model_features/utils/EMFAnimationPauseHandler.java create mode 100644 src/main/java/traben/entity_model_features/utils/EMFLODHandler.java diff --git a/gradle.properties b/gradle.properties index c9f10e82..b04e30de 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ essential.defaults.loom.mappings=mojmap loom.ignoreDependencyLoomVersionValidation=true archives_base_name=entity_model_features -mod_version=3.2.6 +mod_version=3.3 maven_group=traben.entity_model_features -etf_version=7.1.1 +etf_version=7.2 use_local_etf=true diff --git a/src/main/java/traben/entity_model_features/EMF.java b/src/main/java/traben/entity_model_features/EMF.java index ba9f446d..6ec0a81b 100644 --- a/src/main/java/traben/entity_model_features/EMF.java +++ b/src/main/java/traben/entity_model_features/EMF.java @@ -7,7 +7,11 @@ import org.apache.logging.log4j.LogManager; import traben.entity_model_features.config.EMFConfig; import traben.entity_model_features.mod_compat.PALCompat; +import traben.entity_model_features.models.animation.state.EMFEntityRenderState; import traben.entity_model_features.models.animation.state.EMFEntityRenderStateViaReference; +import traben.entity_model_features.models.animation.state.EMFState; +import traben.entity_model_features.models.parts.EMFModelPartRoot; +import traben.entity_model_features.models.parts.EMFModelPartVanilla; import traben.entity_model_features.propeties.*; import traben.entity_model_features.utils.EMFEntity; import traben.entity_model_features.utils.EMFUtils; @@ -17,6 +21,9 @@ import traben.entity_texture_features.config.ETFConfigWarnings; import traben.entity_texture_features.features.property_reading.properties.RandomProperties; import traben.entity_texture_features.features.state.ETFEntityRenderState; +import traben.entity_texture_features.features.state.ETFState; +import traben.entity_texture_features.features.state.ETFSubmitData; +import traben.entity_texture_features.utils.ETFEntity; import traben.entity_texture_features.utils.ETFUtils2; import traben.tconfig.TConfigHandler; @@ -24,7 +31,7 @@ public class EMF { - public static final int EYES_FEATURE_LIGHT_VALUE = ETFUtils2.FULL_BRIGHT + 1; + public static final String MOD_ID = "entity_model_features"; public static boolean forgeHadLoadingError = false; public static boolean testedForge = !ETF.isForge(); @@ -110,6 +117,48 @@ public String getSubTitle() { } catch (Exception ignored) {} } //#endif + + //#if MC >= 1.21.9 + ETFSubmitData.DATA_IN.add((data, vanilla)->{ + + var state = EMFState.state(); + if (state != null) { + var pose = state.getBipedPose(); + if (pose != null && pose.applyToSubmit) { + data.data.put("bipedPose", state.getBipedPose()); + } + } + + data.data.put("onShoulder", state != null && state.onShoulder()); + + data.data.put("isMainModelPhase", EMFState.isMainPhase); + data.data.put("isLayerModelPhase", EMFState.isLayerPhase); + + EMFModelPartRoot emfRoot = vanilla.model().root() instanceof EMFModelPartRoot ? (EMFModelPartRoot) vanilla.model().root() : null; + if (emfRoot != null) { + data.data.put("modelVariant", emfRoot.currentModelVariant); + } + }); + + //#if MC >= 26.2 + ETFSubmitData.DATA_OUT.add((data, vanilla)->{ + // Replaces logic for model part submits that now wrap in simple models + if (vanilla.model().root() instanceof EMFModelPartVanilla partVanilla && partVanilla.getRoot() != partVanilla) { + EMFManager.getInstance().entityRenderCount++; + + if (partVanilla.isPlayerArm) { + if (Minecraft.getInstance().player != null) { + EMFState.modelVariationIgnoresVisibility = true; + var state = EMFEntityRenderState.manualPlayerState(); + if (state != null) ETFState.mount(state); + } + EMFState.state().setIsFirstPersonHand(true); + } + } + }); + //#endif + + //#endif } //mod menu config screen factory diff --git a/src/main/java/traben/entity_model_features/EMFAnimationApi.java b/src/main/java/traben/entity_model_features/EMFAnimationApi.java index 5b001ef5..9fd73b0f 100644 --- a/src/main/java/traben/entity_model_features/EMFAnimationApi.java +++ b/src/main/java/traben/entity_model_features/EMFAnimationApi.java @@ -7,13 +7,14 @@ import org.apache.commons.lang3.function.TriFunction; import org.jetbrains.annotations.Nullable; import traben.entity_model_features.models.IEMFModel; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.math.asm.ASMVisitable; import traben.entity_model_features.models.animation.math.methods.MethodRegistry; import traben.entity_model_features.models.animation.math.variables.VariableRegistry; import traben.entity_model_features.models.animation.math.variables.factories.UniqueVariableFactory; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.models.parts.EMFModelPart; import traben.entity_model_features.models.parts.EMFModelPartCustom; +import traben.entity_model_features.utils.EMFAnimationPauseHandler; import traben.entity_model_features.utils.EMFEntity; import traben.entity_model_features.utils.EMFUtils; @@ -54,7 +55,8 @@ static int getApiVersion() { * @return the currently rendered entity */ static @Nullable EMFEntity getCurrentEntity() { - return EMFAnimationEntityContext.getEMFEntity(); + var state = EMFState.state(); + return state != null ? state.emfEntity() : null; } /** @@ -201,7 +203,7 @@ static boolean registerPauseCondition(Function shouldPause) if (shouldPause == null) { throw paramFail("null pause condition"); } - EMFAnimationEntityContext.pauseListeners.add(shouldPause); + EMFAnimationPauseHandler.pauseListeners.add(shouldPause); return true; } @@ -213,7 +215,7 @@ static boolean pauseAllCustomAnimationsForEntity(EMFEntity entityOrBlockEntity) if (entityOrBlockEntity == null || entityOrBlockEntity.etf$getUuid() == null) { return false; } - EMFAnimationEntityContext.entitiesPaused.add(entityOrBlockEntity.etf$getUuid()); + EMFAnimationPauseHandler.entitiesPaused.add(entityOrBlockEntity.etf$getUuid()); return true; } @@ -225,8 +227,8 @@ static boolean resumeAllCustomAnimationsForEntity(EMFEntity entityOrBlockEntity) if (entityOrBlockEntity == null || entityOrBlockEntity.etf$getUuid() == null) { return false; } - EMFAnimationEntityContext.entitiesPaused.remove(entityOrBlockEntity.etf$getUuid()); - EMFAnimationEntityContext.entitiesPausedParts.remove(entityOrBlockEntity.etf$getUuid()); + EMFAnimationPauseHandler.entitiesPaused.remove(entityOrBlockEntity.etf$getUuid()); + EMFAnimationPauseHandler.entitiesPausedParts.remove(entityOrBlockEntity.etf$getUuid()); return true; } @@ -240,7 +242,7 @@ static boolean pauseCustomAnimationsForThesePartsOfEntity(EMFEntity entityOrBloc || parts == null || parts.length == 0) { return false; } - EMFAnimationEntityContext.entitiesPausedParts.put(entityOrBlockEntity.etf$getUuid(), parts); + EMFAnimationPauseHandler.entitiesPausedParts.put(entityOrBlockEntity.etf$getUuid(), parts); return true; } @@ -254,7 +256,7 @@ static boolean registerVanillaModelCondition(Function should if (shouldUseVanillaModel == null) { throw paramFail("null vanilla model condition"); } - EMFAnimationEntityContext.forceVanillaModelListeners.add(shouldUseVanillaModel); + EMFState.forceVanillaModelListeners.add(shouldUseVanillaModel); return true; } @@ -266,7 +268,7 @@ static boolean lockEntityToVanillaModel(EMFEntity entityOrBlockEntity){ if (entityOrBlockEntity == null || entityOrBlockEntity.etf$getUuid() == null) { return false; } - EMFAnimationEntityContext.entitiesToForceVanillaModel.add(entityOrBlockEntity.etf$getUuid()); + EMFState.entitiesToForceVanillaModel.add(entityOrBlockEntity.etf$getUuid()); return true; } @@ -278,7 +280,7 @@ static boolean unlockEntityToVanillaModel(EMFEntity entityOrBlockEntity){ if (entityOrBlockEntity == null || entityOrBlockEntity.etf$getUuid() == null) { return false; } - EMFAnimationEntityContext.entitiesToForceVanillaModel.remove(entityOrBlockEntity.etf$getUuid()); + EMFState.entitiesToForceVanillaModel.remove(entityOrBlockEntity.etf$getUuid()); return true; } diff --git a/src/main/java/traben/entity_model_features/EMFManager.java b/src/main/java/traben/entity_model_features/EMFManager.java index 5cb70f8f..20b68ef3 100644 --- a/src/main/java/traben/entity_model_features/EMFManager.java +++ b/src/main/java/traben/entity_model_features/EMFManager.java @@ -23,10 +23,10 @@ import traben.entity_model_features.models.animation.math.asm.ASMVariableHandler; import traben.entity_model_features.models.animation.math.methods.emf.NBTMethod; import traben.entity_model_features.models.animation.math.variables.factories.GlobalVariableFactory; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.models.parts.EMFModelPart; import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.models.IEMFModelNameContainer; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.math.variables.EMFModelOrRenderVariable; import traben.entity_model_features.models.jem_objects.EMFJemData; import traben.entity_model_features.models.parts.EMFModelPartVanilla; @@ -109,7 +109,6 @@ public void receiveException(Exception exception) { } private EMFManager() { - EMFAnimationEntityContext.globalReset(); IS_PHYSICS_MOD_INSTALLED = ETF.isThisModLoaded("physicsmod"); // IS_IRIS_INSTALLED = EMFVersionDifferenceManager.isThisModLoaded("iris") || EMFVersionDifferenceManager.isThisModLoaded("oculus"); IS_EBE_INSTALLED = ETF.isThisModLoaded("enhancedblockentities"); @@ -137,6 +136,7 @@ public static void resetInstance() { NBTMethod.CACHE.clear(); GlobalVariableFactory.clear(); self = new EMFManager(); + EMFState.clear(); } @Nullable diff --git a/src/main/java/traben/entity_model_features/config/EMFConfig.java b/src/main/java/traben/entity_model_features/config/EMFConfig.java index b858bbf1..1a135052 100644 --- a/src/main/java/traben/entity_model_features/config/EMFConfig.java +++ b/src/main/java/traben/entity_model_features/config/EMFConfig.java @@ -24,6 +24,7 @@ import traben.entity_model_features.models.animation.math.variables.factories.UniqueVariableFactory; import traben.entity_model_features.EMFManager; import traben.entity_model_features.models.EMFModelMappings; +import traben.entity_model_features.models.animation.state.EMFEntityRenderState; import traben.entity_model_features.utils.EMFEntity; import traben.entity_model_features.utils.EMFUtils; import traben.entity_model_features.models.EMFModel_ID; @@ -65,7 +66,12 @@ public class EMFConfig extends TConfig { @Deprecated(forRemoval = true) public ETFConfig.String2EnumNullMap entityPhysicsModPatchOverrides = new ETFConfig.String2EnumNullMap<>(); public ETFConfig.String2EnumNullMap entityVanillaHologramOverrides = new ETFConfig.String2EnumNullMap<>(); - public RenderModeChoice getRenderModeFor(EMFEntity entity) { + public RenderModeChoice getRenderModeFor(@Nullable EMFEntityRenderState state) { + if (state == null) return getRenderModeFor((EMFEntity) null); + return getRenderModeFor(state.emfEntity()); + } + + public RenderModeChoice getRenderModeFor(@Nullable EMFEntity entity) { String typeString = getTypeString(entity); if (typeString == null) return renderModeChoice; return Objects.requireNonNullElseGet(entityRenderModeOverrides.get(typeString), () -> renderModeChoice); diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinCapeModels.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinCapeModels.java index d1907c51..e7ed7338 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinCapeModels.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinCapeModels.java @@ -1,6 +1,7 @@ package traben.entity_model_features.mixin.mixins; import org.spongepowered.asm.mixin.Mixin; +import traben.entity_model_features.models.animation.state.EMFState; //#if MC < 12102 //$$ import net.minecraft.client.model.PlayerModel; @@ -60,7 +61,7 @@ public abstract class MixinCapeModels { //$$ poseStack.popPose(); //$$ poseStack.pushPose(); //$$ -//$$ EMFEntity emfEntity = EMFAnimationEntityContext.getEMFEntity(); +//$$ EMFEntity emfEntity = EMFState.emfEntity(); //$$ if (!(emfEntity instanceof Player)) return; //$$ Player player = (Player) emfEntity; //$$ diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntity.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntity.java index da3e00b6..72203795 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntity.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntity.java @@ -13,7 +13,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import traben.entity_model_features.EMFManager; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.EMFEntity; import java.util.HashMap; @@ -130,10 +130,12 @@ public abstract class MixinEntity implements EMFEntity { //$$ @Inject(method = "getLeashOffset()Lnet/minecraft/world/phys/Vec3;", at = @At("RETURN")) //#endif private void emf$leashwither(CallbackInfoReturnable cir) { + var state = EMFState.state(); + if (state == null) return; //return new Vec3d(0.0, (double)this.getStandingEyeHeight(), (double)(this.getWidth() * 0.4F)); - if (EMFAnimationEntityContext.getLeashX() != 0 || EMFAnimationEntityContext.getLeashY() != 0 || EMFAnimationEntityContext.getLeashZ() != 0) { + if (state.leashX() != 0 || state.leashY() != 0 || state.leashZ() != 0) { Vec3 vec = cir.getReturnValue(); - vec.add(EMFAnimationEntityContext.getLeashX(), EMFAnimationEntityContext.getLeashY(), EMFAnimationEntityContext.getLeashZ()); + vec.add(state.leashX(), state.leashY(), state.leashZ()); } } @@ -282,7 +284,7 @@ public abstract class MixinEntity implements EMFEntity { emf$variableMapGuiCopy = null; } - if (EMFAnimationEntityContext.isInGui()) { + if (EMFState.isInGui) { // Copy the initial variable state but allow the gui to now change these separately if (emf$variableMapGuiCopy == null) emf$variableMapGuiCopy = new HashMap<>(emf$variableMap); return emf$variableMapGuiCopy; diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinGameRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinGameRenderer.java index 39dd30e9..380389ce 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinGameRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinGameRenderer.java @@ -8,7 +8,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import traben.entity_model_features.EMF; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; +import traben.entity_model_features.utils.EMFLODHandler; /** * This mixin is used to get the current FOV value from the game renderer. @@ -28,7 +29,7 @@ public class MixinGameRenderer { //#endif > cir) { if (EMF.config().getConfig().animationLODDistance != 0) { - EMFAnimationEntityContext.lastFOV = (double) cir.getReturnValue(); + EMFLODHandler.lastFOV = (double) cir.getReturnValue(); } } //#endif @@ -36,6 +37,6 @@ public class MixinGameRenderer { @Inject(method = "render", at = @At(value = "HEAD")) private void emf$injectCounter(final CallbackInfo ci) { - EMFAnimationEntityContext.incFrameCount(); + EMFState.incFrameCount(); } } \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinModel.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinModel.java index 418d1521..f438943b 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinModel.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinModel.java @@ -11,9 +11,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import traben.entity_model_features.EMF; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.models.IEMFModel; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.EMFManager; import java.util.function.Function; @@ -60,7 +60,8 @@ public class MixinModel implements IEMFModel { @Inject(method = "renderType", at = @At(value = "HEAD")) private void emf$discoverEMFModel(CallbackInfoReturnable cir) { - //noinspection unchecked,rawtypes - EMFAnimationEntityContext.setLayerFactory(((Model) ((Object) this)).renderType); + var state = EMFState.state(); + if (state == null) return; + state.setLayerFactory(((Model) ((Object) this)).renderType); } } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinModelPart.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinModelPart.java index ed4a84e6..8a890af8 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinModelPart.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinModelPart.java @@ -10,8 +10,8 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.models.IEMFModelNameContainer; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.EMFManager; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.IEMFTextureSizeSupplier; import traben.entity_model_features.models.EMFModel_ID; @@ -40,7 +40,7 @@ public class MixinModelPart implements IEMFModelNameContainer, IEMFTextureSizeSu //$$ float red, float green, float blue, float alpha //#endif , final CallbackInfo ci) { - if (EMFAnimationEntityContext.doAnnounceModels() && emf$modelInfo != null) { + if (EMFState.announceModels && emf$modelInfo != null) { EMFManager.getInstance().modelsAnnounced.add(emf$modelInfo); } } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinParrotEntityModel.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinParrotEntityModel.java index 1e6d1c68..12289f39 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinParrotEntityModel.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinParrotEntityModel.java @@ -14,9 +14,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.EMF; import traben.entity_model_features.EMFManager; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.animation.state.EMFSubmitData; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.EMFEntity; //#if MC >= 12102 @@ -51,21 +50,12 @@ public class MixinParrotEntityModel { @Inject(method = RENDER_METHOD, at = @At("HEAD")) private void emf$parrot1(final CallbackInfo ci) { - try{ - var entity = (EMFEntity) UEntityTypes.PARROT.create(Minecraft.getInstance().level, EntitySpawnReason.COMMAND); - if (entity != null) { - EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) ETFEntityRenderState.forEntity(entity)); - EMFSubmitData.AWAITING_backupState = EMFAnimationEntityContext.getEmfState(); - } - }catch (Exception ignored){ - } - EMFAnimationEntityContext.setCurrentEntityOnShoulder(true); + EMFState.isInShoulderMethod = true; } @Inject(method = RENDER_METHOD, at = @At("TAIL")) private void emf$parrot2(final CallbackInfo ci) { - EMFAnimationEntityContext.setCurrentEntityOnShoulder(false); - EMFSubmitData.AWAITING_backupState = null; + EMFState.isInShoulderMethod = false; } } @@ -74,11 +64,11 @@ public class MixinParrotEntityModel { //$$ public class MixinParrotEntityModel { //$$ @Inject(method = "renderOnShoulder", at = @At("HEAD")) //$$ private void emf$parrot1(PoseStack matrices, VertexConsumer vertexConsumer, int light, int overlay, float limbAngle, float limbDistance, float headYaw, float headPitch, int danceAngle, CallbackInfo ci) { -//$$ EMFAnimationEntityContext.setCurrentEntityOnShoulder(true); +//$$ EMFState.isInShoulderMethod = true; //$$ } //$$ @Inject(method = "renderOnShoulder", at = @At("TAIL")) //$$ private void emf$parrot2(PoseStack matrices, VertexConsumer vertexConsumer, int light, int overlay, float limbAngle, float limbDistance, float headYaw, float headPitch, int danceAngle, CallbackInfo ci) { -//$$ EMFAnimationEntityContext.setCurrentEntityOnShoulder(false); +//$$ EMFState.isInShoulderMethod = false; //$$ } //$$ } //#endif diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/accessor/Mixin_GuiEntityTester.java b/src/main/java/traben/entity_model_features/mixin/mixins/accessor/Mixin_GuiEntityTester.java index 9ebbe29f..aade8fd7 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/accessor/Mixin_GuiEntityTester.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/accessor/Mixin_GuiEntityTester.java @@ -4,22 +4,23 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; //#if MC >= 12106 import net.minecraft.client.gui.render.GuiRenderer; + @Mixin(GuiRenderer.class) public class Mixin_GuiEntityTester { @Inject(method = "render", at = @At("HEAD")) private void etf$beforeRenderToTexture(final CallbackInfo ci) { - EMFAnimationEntityContext.setIsInGui = true; + EMFState.isInGui = true; } @Inject(method = "render", at = @At("TAIL")) private void etf$afterRenderToTexture(final CallbackInfo ci) { - EMFAnimationEntityContext.setIsInGui = false; + EMFState.isInGui = false; } } //#else @@ -32,14 +33,14 @@ public class Mixin_GuiEntityTester { //$$ @ModifyArg(method = "render", //$$ at = @At(value = "INVOKE", target = "Lnet/minecraft/util/profiling/ProfilerFiller;popPush(Ljava/lang/String;)V")) //$$ private String etf$beforeRenderToTexture(String string) { -//$$ if (string.equals("gui")) EMFAnimationEntityContext.setIsInGui = true; +//$$ if (string.equals("gui")) EMFState.isInGui = true; //$$ return string; //$$ } //$$ //$$ @Inject(method = "render", //$$ at = @At("TAIL")) //$$ private void etf$afterRenderToTexture(final CallbackInfo ci) { -//$$ EMFAnimationEntityContext.setIsInGui = false; +//$$ EMFState.isInGui = false; //$$ } //$$ } //#endif diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/optional/MixinLivingEntityRenderer_ValueCapturing.java b/src/main/java/traben/entity_model_features/mixin/mixins/optional/MixinLivingEntityRenderer_ValueCapturing.java index 81b5e8b9..4314a316 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/optional/MixinLivingEntityRenderer_ValueCapturing.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/optional/MixinLivingEntityRenderer_ValueCapturing.java @@ -9,6 +9,7 @@ public abstract class MixinLivingEntityRenderer_ValueCapturing{} //#else //$$ import org.spongepowered.asm.mixin.injection.At; +//$$ import traben.entity_model_features.models.animation.state.EMFState; //$$ import org.spongepowered.asm.mixin.injection.ModifyArg; //$$ import traben.entity_model_features.models.animation.EMFAnimationEntityContext; //$$ import net.minecraft.client.model.EntityModel; @@ -31,7 +32,10 @@ public abstract class MixinLivingEntityRenderer_ValueCapturing{} //$$ index = 1, require = 0 //$$ ) //$$ private float emf$getLimbAngle(float limbAngle) { -//$$ EMFAnimationEntityContext.setLimbAngle(limbAngle); +//$$ var state = EMFState.state(); +//$$ if (state != null) { +//$$ state.setLimbAngle(limbAngle); +//$$ } //$$ return limbAngle; //$$ } //$$ @ModifyArg( @@ -40,7 +44,10 @@ public abstract class MixinLivingEntityRenderer_ValueCapturing{} //$$ index = 2, require = 0 //$$ ) //$$ private float emf$getLimbDistance(float limbDistance) { -//$$ EMFAnimationEntityContext.setLimbDistance(limbDistance); +//$$ var state = EMFState.state(); +//$$ if (state != null) { +//$$ state.setLimbDistance(limbDistance); +//$$ } //$$ return limbDistance; //$$ } //$$ @ModifyArg( @@ -49,10 +56,13 @@ public abstract class MixinLivingEntityRenderer_ValueCapturing{} //$$ index = 4, require = 0 //$$ ) //$$ private float emf$getHeadYaw(float headYaw) { -//$$ if (headYaw >= 180 || headYaw < -180) { -//$$ EMFAnimationEntityContext.setHeadYaw(Mth.wrapDegrees(headYaw)); -//$$ } else { -//$$ EMFAnimationEntityContext.setHeadYaw(headYaw); +//$$ var state = EMFState.state(); +//$$ if (state != null) { +//$$ if (headYaw >= 180 || headYaw < -180) { +//$$ state.setHeadYaw(Mth.wrapDegrees(headYaw)); +//$$ } else { +//$$ state.setHeadYaw(headYaw); +//$$ } //$$ } //$$ return headYaw; //$$ } @@ -62,7 +72,10 @@ public abstract class MixinLivingEntityRenderer_ValueCapturing{} //$$ index = 5, require = 0 //$$ ) //$$ private float emf$getHeadPitch(float headPitch) { -//$$ EMFAnimationEntityContext.setHeadPitch(headPitch); +//$$ var state = EMFState.state(); +//$$ if (state != null) { +//$$ state.setHeadPitch(headPitch); +//$$ } //$$ return headPitch; //$$ } //$$ } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityRenderDispatcher.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityRenderDispatcher.java deleted file mode 100644 index fe95b5df..00000000 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityRenderDispatcher.java +++ /dev/null @@ -1,50 +0,0 @@ -package traben.entity_model_features.mixin.mixins.rendering; - -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.renderer.blockentity.BlockEntityRenderDispatcher; -import net.minecraft.world.level.block.entity.BlockEntity; -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; -import traben.entity_model_features.EMFManager; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; -import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.animation.state.EMFSubmitData; -import traben.entity_texture_features.features.state.ETFEntityRenderState; -import traben.entity_texture_features.features.state.HoldsETFRenderState; -import traben.entity_texture_features.utils.ETFEntity; - -@Mixin(BlockEntityRenderDispatcher.class) -public class MixinBlockEntityRenderDispatcher { - - //#if MC >=12109 - @Inject(method = "submit", at = @At(value = "HEAD")) - private static void emf$grabEntity2(CallbackInfo ci, - @Local(argsOnly = true) T blockEntity) { - var state = (EMFEntityRenderState) ((HoldsETFRenderState) blockEntity).etf$getState(); - EMFAnimationEntityContext.setCurrentEntityIteration(state); - EMFSubmitData.AWAITING_backupState = state; - } - - @Inject(method = "submit", at = @At(value = "TAIL")) - private static void emf$grabEntity2(CallbackInfo ci) { - EMFSubmitData.AWAITING_backupState = null; - } - //#elseif MC >=12104 - //$$ @Inject(method = "setupAndRender", - //$$ at = @At(value = "HEAD")) - //$$ private static void emf$grabEntity2(CallbackInfo ci, @Local(argsOnly = true) T blockEntity) { - //$$ EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) - //$$ ETFEntityRenderState.forEntity((ETFEntity) blockEntity)); - //$$ } - //#else - //$$ - //$$ @Inject(method = "tryRender", - //$$ at = @At(value = "HEAD")) - //$$ private static void emf$grabEntity2(BlockEntity blockEntity, Runnable runnable, CallbackInfo ci) { - //$$ EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) - //$$ ETFEntityRenderState.forEntity((ETFEntity) blockEntity)); - //$$ } - //#endif -} diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityWithoutLevelRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityWithoutLevelRenderer.java index 7ff25acb..cc88f491 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityWithoutLevelRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinBlockEntityWithoutLevelRenderer.java @@ -11,11 +11,11 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.EMFManager; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_texture_features.features.ETFRenderContext; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_texture_features.features.state.ETFEntityRenderState; +import traben.entity_texture_features.features.state.ETFState; import traben.entity_texture_features.utils.ETFEntity; //#if MC >=12104 @@ -44,20 +44,21 @@ public class MixinBlockEntityWithoutLevelRenderer { //$$ private static final String RENDER = "render"; //#endif - @Inject(method = RENDER, - at = @At(value = "INVOKE", - target = - //#if MC >= 26.1 - //$$ "Lnet/minecraft/client/renderer/special/SpecialModelRenderer;submit(Ljava/lang/Object;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;IIZI)V" - //#elseif MC >= 12109 - "Lnet/minecraft/client/renderer/special/SpecialModelRenderer;submit(Ljava/lang/Object;Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;IIZI)V" - //#else - //$$ "Lnet/minecraft/client/renderer/special/SpecialModelRenderer;render(Ljava/lang/Object;Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IIZ)V" - //#endif - , shift = At.Shift.BEFORE)) + //#if MC >= 26.1 + //$$ private static final String TARGET = "Lnet/minecraft/client/renderer/special/SpecialModelRenderer;submit(Ljava/lang/Object;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;IIZI)V"; + //#elseif MC >= 12109 + private static final String TARGET = "Lnet/minecraft/client/renderer/special/SpecialModelRenderer;submit(Ljava/lang/Object;Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;IIZI)V"; + //#else + //$$ private static final String TARGET = "Lnet/minecraft/client/renderer/special/SpecialModelRenderer;render(Ljava/lang/Object;Lnet/minecraft/world/item/ItemDisplayContext;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;IIZ)V"; + //#endif + + @Inject(method = RENDER, at = @At(value = "INVOKE", target = TARGET)) private void emf$setRenderFactory(CallbackInfo ci) { - if (specialRenderer instanceof SkullSpecialRenderer) { - EMFAnimationEntityContext.setLayerFactory( + EMFManager.getInstance().entityRenderCount++; + setPlayerEntity(); + + if (specialRenderer instanceof SkullSpecialRenderer && EMFState.state() != null) { + EMFState.state().setLayerFactory( //#if MC >= 26.1 //$$ RenderTypes::entityCutoutZOffset //#elseif MC>= 12111 @@ -67,15 +68,12 @@ public class MixinBlockEntityWithoutLevelRenderer { //#endif ); } - - EMFManager.getInstance().entityRenderCount++; - setPlayerEntity(); } - @Inject(method = RENDER, at = @At(value = "RETURN")) + @Inject(method = RENDER, at = @At(value = "INVOKE", target = TARGET, shift = At.Shift.AFTER)) private void emf$reset(final CallbackInfo ci) { - EMFAnimationEntityContext.reset(); + unSetPlayerEntity(); } //#else @@ -89,10 +87,15 @@ public class MixinBlockEntityWithoutLevelRenderer { //$$ //$$ @Inject(method = "renderByItem", //$$ at = @At(value = "INVOKE", -//$$ target = "Lnet/minecraft/client/renderer/blockentity/SkullBlockRenderer;renderSkull(Lnet/minecraft/core/Direction;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/model/SkullModelBase;Lnet/minecraft/client/renderer/RenderType;)V", +//$$ target = + //#if MC > 1.21 + //$$ "Lnet/minecraft/client/renderer/blockentity/SkullBlockRenderer;getRenderType(Lnet/minecraft/world/level/block/SkullBlock$Type;Lnet/minecraft/world/item/component/ResolvableProfile;)Lnet/minecraft/client/renderer/RenderType;", + //#else + //$$ "Lnet/minecraft/client/renderer/blockentity/SkullBlockRenderer;getRenderType(Lnet/minecraft/world/level/block/SkullBlock$Type;Lcom/mojang/authlib/GameProfile;)Lnet/minecraft/client/renderer/RenderType;", + //#endif //$$ shift = At.Shift.BEFORE)) //$$ private void emf$setRenderFactory(final ItemStack itemStack, final ItemDisplayContext itemDisplayContext, final PoseStack poseStack, final MultiBufferSource multiBufferSource, final int i, final int j, final CallbackInfo ci) { -//$$ EMFAnimationEntityContext.setLayerFactory(RenderType::entityCutoutNoCullZOffset); +//$$ if (EMFState.state() != null) EMFState.state().setLayerFactory(RenderType::entityCutoutNoCullZOffset); //$$ EMFManager.getInstance().entityRenderCount++; //$$ setPlayerEntity(); //$$ } @@ -116,7 +119,7 @@ public class MixinBlockEntityWithoutLevelRenderer { //$$ //$$ @Inject(method = "renderByItem", at = @At(value = "RETURN")) //$$ private void emf$reset(final CallbackInfo ci) { -//$$ EMFAnimationEntityContext.reset(); +//$$ unSetPlayerEntity(); //$$ } //$$ //$$ @@ -124,10 +127,17 @@ public class MixinBlockEntityWithoutLevelRenderer { @Unique private void setPlayerEntity() { - if (Minecraft.getInstance().player == null) return; - ETFEntityRenderState state = ETFEntityRenderState.forEntity( (ETFEntity) Minecraft.getInstance().player); - // ETFRenderContext.setCurrentEntity(state); // todo was this a mistake? Should this be EMF only? ignoring for now during rewrite - EMFAnimationEntityContext.setCurrentEntityNoIteration((EMFEntityRenderState) state); + var state = EMFEntityRenderState.manualPlayerState(); + ETFState.mount(state); + } + + @Unique + private void unSetPlayerEntity() { + //#if MC < 1.21.4 + //$$ var state = EMFState.state(); + //$$ if (state != null && state.isManualPlayerState()) + //#endif + ETFState.unMount(); } } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinDragonRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinDragonRenderer.java index a1bbe4f4..39a913c5 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinDragonRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinDragonRenderer.java @@ -6,7 +6,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.EMFManager; -import traben.entity_texture_features.features.ETFRenderContext; +import traben.entity_texture_features.features.state.ETFState; @Mixin(EnderDragonRenderer.class) public abstract class MixinDragonRenderer { @@ -52,7 +52,7 @@ public abstract class MixinDragonRenderer { //#endif //$$ )) //$$ private void emf$allowMultiPartRender(final CallbackInfo ci) { -//$$ ETFRenderContext.startSpecialRenderOverlayPhase(); +//$$ ETFState.startSpecialRenderOverlayPhase(); //$$ } //$$ //$$ @Inject(method = @@ -78,7 +78,7 @@ public abstract class MixinDragonRenderer { //#endif //$$ )) //$$ private void emf$allowMultiPartRender2(final CallbackInfo ci) { -//$$ ETFRenderContext.endSpecialRenderOverlayPhase(); +//$$ ETFState.endSpecialRenderOverlayPhase(); //$$ } //$$ //$$ diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java index 3d46b705..babd9e92 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java @@ -10,9 +10,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_texture_features.features.ETFRenderContext; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_texture_features.features.state.ETFEntityRenderState; import traben.entity_texture_features.utils.ETFEntity; import traben.entity_model_features.utils.EMFEntity; @@ -57,26 +57,6 @@ public abstract class MixinEntityRenderDispatcher { //$$ @Shadow public abstract double distanceToSqr(double x, double y, double z); //#endif - //#if MC >= 12103 - //#if MC>= 12105 - @Inject(method = RENDER_ETF, - at = @At(value = "HEAD")) - //#else - //$$ @Inject(method = "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;render(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/renderer/entity/EntityRenderer;)V", - //$$ at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;pushPose()V")) - //#endif - private - void emf$grabContext(final CallbackInfo ci, @SuppressWarnings("LocalMayBeArgsOnly") @Local S state) { - EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) ((HoldsETFRenderState) state).etf$getState()); - } - //#else - //$$ @Inject(method = "render", - //$$ at = @At(value = "HEAD")) - //$$ private void emf$grabContext(CallbackInfo ci, @Local(argsOnly = true) E entity) { - //$$ EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) ETFEntityRenderState.forEntity((ETFEntity) entity)); - //$$ } - //#endif - @Inject(method = RENDER_ETF, at = @At(value = "RETURN")) @@ -89,43 +69,51 @@ public abstract class MixinEntityRenderDispatcher { EMFEntityRenderState emfState = (EMFEntityRenderState) ((HoldsETFRenderState) state).etf$getState(); //#else //$$ ) { - //$$ EMFEntityRenderState emfState = EMFAnimationEntityContext.getEmfState(); + //$$ EMFEntityRenderState emfState = EMFState.state(); //#endif // todo likely extremely broken in 1.21.9 - if (EMFAnimationEntityContext.doAnnounceModels()) { - EMFAnimationEntityContext.anounceModels(emfState); + if (EMFState.announceModels) { + EMFState.anounceModels(emfState); } } //#else //$$ private void emf$endOfRender( CallbackInfo ci, @Local(argsOnly = true) E entity) { - //$$ if (EMFAnimationEntityContext.doAnnounceModels()) { - //$$ EMFAnimationEntityContext.anounceModels((EMFEntityRenderState) ETFEntityRenderState.forEntity((ETFEntity) entity)); + //$$ if (EMFState.announceModels) { + //$$ EMFState.anounceModels((EMFEntityRenderState) ETFEntityRenderState.forEntity((ETFEntity) entity)); //$$ } //$$ } - + //$$ //#endif - @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF, shift = At.Shift.BEFORE)) + @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF)) private void emf$modifyShadowTranslate(final CallbackInfo ci, @Local(argsOnly = true) PoseStack matrices) { - if (EMFAnimationEntityContext.getShadowX() != 0 || EMFAnimationEntityContext.getShadowZ() != 0) { - matrices.translate(EMFAnimationEntityContext.getShadowX(), 0, EMFAnimationEntityContext.getShadowZ()); + var state = EMFState.state(); + if (state == null) return; + if (state.shadowX() != 0 || state.shadowZ() != 0) { + matrices.pushPose(); + matrices.translate(state.shadowX(), 0, state.shadowZ()); } } @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF, shift = At.Shift.AFTER)) private void emf$undoModifyShadowTranslate(final CallbackInfo ci, @Local(argsOnly = true) PoseStack matrices) { - if (EMFAnimationEntityContext.getShadowX() != 0 || EMFAnimationEntityContext.getShadowZ() != 0) { - matrices.translate(-EMFAnimationEntityContext.getShadowX(), 0, -EMFAnimationEntityContext.getShadowZ()); + var state = EMFState.state(); + if (state == null) return; + if (state.shadowX() != 0 || state.shadowZ() != 0) { + matrices.popPose(); +// matrices.translate(-state.shadowX(), 0, -state.shadowZ()); } } //#if MC<12109 //$$ @ModifyArg(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF), index = 3) //$$ private float emf$modifyShadowOpacity(float opacity) { - //$$ if (!Float.isNaN(EMFAnimationEntityContext.getShadowOpacity())) { - //$$ double g = this.distanceToSqr(EMFAnimationEntityContext.getEntityX(), EMFAnimationEntityContext.getEntityY(), EMFAnimationEntityContext.getEntityZ()); - //$$ return (float) ((1.0 - g / 256.0) * EMFAnimationEntityContext.getShadowOpacity()); + //$$ var state = EMFState.state(); + //$$ if (state == null) return opacity; + //$$ if (!Float.isNaN(state.shadowOpacity())) { + //$$ double g = this.distanceToSqr(EMFMath.getEntityX(), EMFMath.getEntityY(), EMFMath.getEntityZ()); + //$$ return (float) ((1.0 - g / 256.0) * state.shadowOpacity()); //$$ } //$$ return opacity; //$$ } @@ -142,8 +130,10 @@ public abstract class MixinEntityRenderDispatcher { //#endif ) private float emf$modifyShadowSize(float size) { - if (!Float.isNaN(EMFAnimationEntityContext.getShadowSize())) { - return Math.min(size * EMFAnimationEntityContext.getShadowSize(), 32.0F); + var state = EMFState.state(); + if (state == null) return size; + if (!Float.isNaN(state.shadowSize())) { + return Math.min(size * state.shadowSize(), 32.0F); } return size; } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinItemFrameEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinItemFrameEntityRenderer.java index d78ae15e..b0a47e26 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinItemFrameEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinItemFrameEntityRenderer.java @@ -5,7 +5,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; @Mixin(ItemFrameRenderer.class) public class MixinItemFrameEntityRenderer { @@ -27,7 +27,7 @@ public class MixinItemFrameEntityRenderer { //$$ shift = At.Shift.AFTER)) //$$ private void emf$setFrame(final CallbackInfo ci) { //$$ //basically "HEAD" - //$$ EMFAnimationEntityContext.setInItemFrame = true; + //$$ EMFState.isInItemFrame = true; //$$ } //$$ //$$ @Inject(method = @@ -38,7 +38,7 @@ public class MixinItemFrameEntityRenderer { //#endif //$$ at = @At(value = "TAIL")) //$$ private void emf$unsetFrame(final CallbackInfo ci) { - //$$ EMFAnimationEntityContext.setInItemFrame = false; + //$$ EMFState.isInItemFrame = false; //$$ } //#endif } \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java index f69472b1..c0b501e7 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java @@ -29,10 +29,9 @@ import traben.entity_model_features.config.EMFConfig; import traben.entity_model_features.models.animation.state.EMFBipedPose; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.animation.state.EMFSubmitData; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.models.IEMFModel; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.EMFManager; import traben.entity_model_features.utils.EMFEntity; @@ -122,7 +121,8 @@ private void falseAnimation(CallbackInfo ci, @Local(argsOnly = true) PoseStack p //$$ //#if MC >= 12102 //$$ private void emf$Animate(final S livingEntityRenderState, final PoseStack matrixStack, final MultiBufferSource vertexConsumerProvider, final int i, final CallbackInfo ci) { - //$$ if(!(EMFAnimationEntityContext.getEMFEntity() instanceof LivingEntity livingEntity)) { + //$$ var emf = EMFState.state(); + //$$ if(!(emf != null && emf.emfEntity() instanceof LivingEntity livingEntity)) { //$$ return; //$$ } //$$ @@ -183,11 +183,9 @@ private void falseAnimation(CallbackInfo ci, @Local(argsOnly = true) PoseStack p @Inject(method = RENDER, at = @At(value = "INVOKE", target = "Ljava/util/List;iterator()Ljava/util/Iterator;")) - private void emf$grabEntity(CallbackInfo ci, @Share("iteration") LocalRef emf$heldIteration) { - emf$heldIteration.set(EMFAnimationEntityContext.getIterationContext()); - EMFSubmitData.AWAITING_isLayerModelPhase = true; - EMFAnimationEntityContext.setLayerPhase(); - EMFSubmitData.AWAITING_isMainModelPhase = false; + private void emf$grabEntity(CallbackInfo ci) { + EMFState.isLayerPhase = true; + EMFState.isMainPhase = false; //#if MC < 1.21.9 //$$ // Set whatever model we used as the main one, handled by submits in 1.21.9+ //$$ if (getModel() instanceof IEMFModel emf && emf.emf$isEMFModel()) { @@ -197,28 +195,23 @@ private void falseAnimation(CallbackInfo ci, @Local(argsOnly = true) PoseStack p } @Inject(method = RENDER, at = @At(value = "INVOKE", target = "Ljava/util/Iterator;next()Ljava/lang/Object;")) - private void emf$eachFeatureLoop(CallbackInfo ci, @Share("iteration") LocalRef emf$heldIteration) { - if (emf$heldIteration.get() != null && EMFManager.getInstance().entityRenderCount != emf$heldIteration.get().entityRenderCount()) { - EMFAnimationEntityContext.setIterationContext(emf$heldIteration.get()); - } + private void emf$eachFeatureLoop(CallbackInfo ci) { //todo needed for stray bogged drowned outer layers in 1.21.2+ //check its needed for 1.21.1 EMFManager.getInstance().entityRenderCount++; - EMFSubmitData.AWAITING_isLayerModelPhase = true; - EMFAnimationEntityContext.setLayerPhase(); + EMFState.isLayerPhase = true; } @Inject(method = RENDER, at = @At("HEAD")) private void emf$preRender(CallbackInfo ci) { - EMFSubmitData.AWAITING_isLayerModelPhase = false; - EMFSubmitData.AWAITING_isMainModelPhase = true; + EMFState.isLayerPhase = false; + EMFState.isMainPhase = true; } @Inject(method = RENDER, at = @At("TAIL")) private void emf$postRender(CallbackInfo ci) { - EMFSubmitData.AWAITING_isLayerModelPhase = false; - EMFSubmitData.AWAITING_isMainModelPhase = false; - EMFAnimationEntityContext.unsetLayerPhase(); + EMFState.isLayerPhase = false; + EMFState.isMainPhase = false; } } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java index f5300f32..9794f98e 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java @@ -12,12 +12,15 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.EMF; +import traben.entity_model_features.EMFManager; import traben.entity_model_features.models.IEMFModel; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.models.parts.EMFModelPartVanilla; import traben.entity_model_features.utils.EMFEntity; import traben.entity_texture_features.features.state.ETFEntityRenderState; +import traben.entity_texture_features.features.state.ETFState; import traben.entity_texture_features.features.state.HoldsETFRenderState; import traben.entity_texture_features.utils.ETFEntity; @@ -81,7 +84,7 @@ public abstract class MixinPlayerEntityRenderer= 12102 - //$$ EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) ((HoldsETFRenderState)emf$renderState()).etf$getState()); + //$$ var state = (EMFEntityRenderState) ((HoldsETFRenderState)emf$renderState()).etf$getState(); //#else - //$$ EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) - //$$ ETFEntityRenderState.forEntity((ETFEntity) Minecraft.getInstance().player)); + //$$ var state = (EMFEntityRenderState) ETFEntityRenderState.forEntity((ETFEntity) Minecraft.getInstance().player); //#endif - //$$ EMFAnimationEntityContext.isFirstPersonHand = true; // moot in 1.21.9+ as despite the method name this is actually a submit + //$$ ETFState.mount(state); + //$$ state.setManualPlayerState(true); + //$$ state.setIsFirstPersonHand(true); + //$$ //EMFAnimationEntityContext.isFirstPersonHand = true; // moot in 1.21.9+ as despite the method name this is actually a submit //$$ } //#endif @Inject(method = "renderHand", at = @At(value = "RETURN")) private void emf$unsetHand(final CallbackInfo ci) { - EMFAnimationEntityContext.reset(); + if (EMFState.state() == null || !EMFState.state().isManualPlayerState()) return; + ETFState.unMount(); } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinProjectileEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinProjectileEntityRenderer.java index c95806fa..94e07121 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinProjectileEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinProjectileEntityRenderer.java @@ -3,10 +3,12 @@ //#if MC >=12102 import org.spongepowered.asm.mixin.Mixin; + @Mixin(traben.entity_texture_features.mixin.CancelTarget.class) public abstract class MixinProjectileEntityRenderer { } //#else //$$ import com.mojang.blaze3d.vertex.PoseStack; +//$$ import traben.entity_model_features.models.animation.state.EMFState; //$$ import com.mojang.blaze3d.vertex.VertexConsumer; //$$ import net.minecraft.client.renderer.MultiBufferSource; //$$ import net.minecraft.client.renderer.RenderType; @@ -36,11 +38,12 @@ public abstract class MixinProjectileEntityRenderer { } //$$ at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/vertex/PoseStack;last()Lcom/mojang/blaze3d/vertex/PoseStack$Pose;", shift = At.Shift.BEFORE), cancellable = true) //$$ private void emf$cancelAndCEMRender(final T entity, final float entityYaw, final float partialTicks, final PoseStack poseStack, final MultiBufferSource buffer, final int packedLight, final CallbackInfo ci) { //$$ if (this instanceof IEMFCustomModelHolder customModelHolder && customModelHolder.emf$hasModel()) { +//$$ var state = EMFState.state(); //$$ //matrixStack.translate(4,0,0); //$$ poseStack.scale(16, -12.8f, -12.8f);//result 0.9, 0.72 0.72 -//$$ EMFAnimationEntityContext.setHeadYaw(entityYaw); +//$$ if (state != null) state.setHeadYaw(entityYaw); //$$ float s = (float) entity.shakeTime - partialTicks; -//$$ EMFAnimationEntityContext.setHeadPitch(-Mth.sin(s * 3.0F) * s);// copy of t +//$$ if (state != null) state.setHeadPitch(-Mth.sin(s * 3.0F) * s);// copy of t //$$ VertexConsumer vertexConsumer = buffer.getBuffer(RenderType.entityTranslucent(this.getTextureLocation(entity))); //$$ customModelHolder.emf$getModel().render(poseStack, vertexConsumer, packedLight, OverlayTexture.NO_OVERLAY //#if MC >= 12100 diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinStuckArrowsFeatureRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinStuckArrowsFeatureRenderer.java index 8a7448a6..d22f8143 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinStuckArrowsFeatureRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/arrows/MixinStuckArrowsFeatureRenderer.java @@ -31,7 +31,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.models.IEMFModel; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; import java.util.ArrayList; import java.util.Collections; @@ -96,7 +96,7 @@ private static float snapToFace(final float f) { //$$ final PoseStack poseStack, final MultiBufferSource buffer, final int packedLight, final T livingEntity, final float limbSwing, final float limbSwingAmount, final float partialTicks, final float ageInTicks, final float netHeadYaw, final float headPitch, final CallbackInfo ci //#endif ) { - EMFAnimationEntityContext.is_in_ground_override = true; + EMFState.isInGroundOverride = true; if(((IEMFModel)this.getParentModel()).emf$isEMFModel()){ ci.cancel(); @@ -122,7 +122,7 @@ private static float snapToFace(final float f) { poseStack.pushPose(); Pair modelPart = emf$bestFromListMutable(new ArrayList<>(root.getAllVanillaPartsEMF()), partRand, poseStack, true); if (modelPart == null) { - EMFAnimationEntityContext.is_in_ground_override = false; + EMFState.isInGroundOverride = false; poseStack.popPose(); return; } @@ -175,7 +175,7 @@ private static float snapToFace(final float f) { @Inject(method = RENDER_METHOD, at = @At(value = "RETURN")) private void emf$end(CallbackInfo ci) { - EMFAnimationEntityContext.is_in_ground_override = false; + EMFState.isInGroundOverride = false; } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinEyesFeatureRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinEyesFeatureRenderer.java deleted file mode 100644 index 993c1bef..00000000 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinEyesFeatureRenderer.java +++ /dev/null @@ -1,24 +0,0 @@ -package traben.entity_model_features.mixin.mixins.rendering.feature; - -import net.minecraft.client.renderer.entity.layers.EyesLayer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.ModifyVariable; - -import static traben.entity_model_features.EMF.EYES_FEATURE_LIGHT_VALUE; - -@Mixin(EyesLayer.class) -public class MixinEyesFeatureRenderer { - @SuppressWarnings("SameReturnValue") - @ModifyVariable(method = - //#if MC >= 12109 - "submit" - //#else - //$$ "render" - //#endif - , at = @At(value = "HEAD"), argsOnly = true, ordinal = 0) - private int emf$markEyeLight(int i) { - return EYES_FEATURE_LIGHT_VALUE; - } - -} diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinHeadFeatureRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinHeadFeatureRenderer.java index 149b7c84..e399f8a6 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinHeadFeatureRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinHeadFeatureRenderer.java @@ -5,7 +5,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; @Mixin(CustomHeadLayer.class) public class MixinHeadFeatureRenderer { @@ -21,12 +21,12 @@ public class MixinHeadFeatureRenderer { @Inject(method = RENDER, at = @At(value = "HEAD")) private void emf$setHand(final CallbackInfo ci) { - EMFAnimationEntityContext.setIsOnHead = true; + EMFState.isOnHead = true; } @Inject(method = RENDER, at = @At(value = "TAIL")) private void emf$unsetHand(final CallbackInfo ci) { - EMFAnimationEntityContext.setIsOnHead = false; + EMFState.isOnHead = false; } } \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinHeldItemFeatureRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinHeldItemFeatureRenderer.java index 2544ef3e..75149093 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinHeldItemFeatureRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinHeldItemFeatureRenderer.java @@ -12,9 +12,9 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.EMFAttachments; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_texture_features.features.state.HoldsETFRenderState; //#if MC>=12109 @@ -59,12 +59,12 @@ @Local(argsOnly = true) S stateIn, //#endif @Local HumanoidArm arm, @Share("armOverride") LocalRef armOverride) { - EMFAnimationEntityContext.setInHand = true; + EMFState.isInHand = true; //#if MC >= 12102 if (stateIn == null) return; var state = (EMFEntityRenderState) ((HoldsETFRenderState) stateIn).etf$getState(); //#else - //$$ var state = EMFAnimationEntityContext.getEmfState(); + //$$ var state = EMFState.state(); //#endif if (state == null) return; @@ -102,7 +102,7 @@ @Inject(method = RENDER_ARM, at = @At(value = "TAIL")) private void emf$unsetHand(final CallbackInfo ci, @Local(argsOnly = true) PoseStack matrices, @Share("needsPop") LocalBooleanRef needsToPop) { - EMFAnimationEntityContext.setInHand = false; + EMFState.isInHand = false; if (needsToPop.get()) matrices.popPose(); } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinSlimeOverlayFeatureRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinSlimeOverlayFeatureRenderer.java index a2cdf9bb..cc342937 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinSlimeOverlayFeatureRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinSlimeOverlayFeatureRenderer.java @@ -7,7 +7,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; //#if MC>= 12111 //$$ import net.minecraft.client.renderer.rendertype.RenderTypes; @@ -30,7 +30,8 @@ public class MixinSlimeOverlayFeatureRenderer { //#endif at = @At(value = "HEAD")) private void emf$setLayerForOverrides(CallbackInfo ci) { - EMFAnimationEntityContext.setLayerFactory( + if (EMFState.state() == null) return; + EMFState.state().setLayerFactory( //#if MC>= 12111 //$$ RenderTypes //#else diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinWolfCollarFeatureRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinWolfCollarFeatureRenderer.java index 16f264c5..75979d17 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinWolfCollarFeatureRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/feature/MixinWolfCollarFeatureRenderer.java @@ -23,7 +23,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.EMF; import traben.entity_model_features.mixin.mixins.accessor.AgeableMobRendererAccessor; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.parts.EMFModelPart; import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.models.IEMFModel; diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/model/MixinVillagerModel.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/model/MixinVillagerModel.java index 46d2aee5..4629af63 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/model/MixinVillagerModel.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/model/MixinVillagerModel.java @@ -6,7 +6,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; @Mixin(VillagerModel.class) public abstract class MixinVillagerModel { @@ -19,7 +19,8 @@ public abstract class MixinVillagerModel { //#endif , at = @At(value = "HEAD")) private void emf$assertLayerFactory(final CallbackInfo ci) { - EMFAnimationEntityContext.setLayerFactory( + if (EMFState.state() != null) + EMFState.state().setLayerFactory( //#if MC>= 12111 //$$ net.minecraft.client.renderer.rendertype.RenderTypes //#else diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ChestSpecialRenderer_PassState.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ChestSpecialRenderer_PassState.java deleted file mode 100644 index 192703fc..00000000 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ChestSpecialRenderer_PassState.java +++ /dev/null @@ -1,46 +0,0 @@ -package traben.entity_model_features.mixin.mixins.rendering.submits; - -//#if MC >=12109 -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.renderer.SubmitNodeCollector; -import net.minecraft.client.renderer.special.ChestSpecialRenderer; -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.ItemDisplayContext; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.entity.ChestBlockEntity; -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; -import traben.entity_model_features.EMFManager; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; -import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.animation.state.EMFSubmitData; -import traben.entity_texture_features.features.state.ETFEntityRenderState; -import traben.entity_texture_features.utils.ETFEntity; - -@Mixin(ChestSpecialRenderer.class) -public class Mixin_ChestSpecialRenderer_PassState { - - @Inject(method = "submit", at = @At(value = "HEAD")) - private static void emf$dummyState(CallbackInfo ci) { - var state = (EMFEntityRenderState) ETFEntityRenderState.forEntity( - // TODO do we really need the actual chest type here? this is just so inventory anims can play - (ETFEntity) new ChestBlockEntity(BlockPos.ZERO, Blocks.CHEST.defaultBlockState())); - EMFAnimationEntityContext.setCurrentEntityIteration(state); - EMFSubmitData.AWAITING_backupState = state; - } - - @Inject(method = "submit", at = @At(value = "TAIL")) - private static void emf$reset(CallbackInfo ci) { - EMFSubmitData.AWAITING_backupState = null; - } - -} -//#else -//$$ import org.spongepowered.asm.mixin.Mixin; -//$$ import traben.entity_texture_features.mixin.CancelTarget; -//$$ -//$$ @Mixin(CancelTarget.class) -//$$ public class Mixin_ChestSpecialRenderer_PassState { } -//#endif \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_GuiEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_GuiEntityRenderer.java deleted file mode 100644 index c1900851..00000000 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_GuiEntityRenderer.java +++ /dev/null @@ -1,66 +0,0 @@ -package traben.entity_model_features.mixin.mixins.rendering.submits; - -import org.spongepowered.asm.mixin.Mixin; - -//#if MC >= 12109 -import net.minecraft.client.gui.render.pip.GuiEntityRenderer; -import net.minecraft.client.gui.render.state.pip.GuiEntityRenderState; -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 traben.entity_model_features.EMF; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; -import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_texture_features.ETF; -import traben.entity_texture_features.features.ETFRenderContext; -import traben.entity_texture_features.features.state.HoldsETFRenderState; -import com.llamalad7.mixinextras.sugar.Local; - -@Mixin(GuiEntityRenderer.class) -public class Mixin_GuiEntityRenderer { - - @Inject(method = "renderToTexture(Lnet/minecraft/client/gui/render/state/pip/GuiEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;)V", at = @At(value = "HEAD")) - private void emf$initRender(final CallbackInfo ci, @Local(argsOnly = true) GuiEntityRenderState guiEntityRenderState) { - // so the entity dispatcher can use this state - assertEmfState(guiEntityRenderState); - } - //#if MC < 26.2 - @Inject(method = "renderToTexture(Lnet/minecraft/client/gui/render/state/pip/GuiEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/feature/FeatureRenderDispatcher;renderAllFeatures()V")) - private void emf$initRender2(final CallbackInfo ci, @Local(argsOnly = true) GuiEntityRenderState guiEntityRenderState) { - // things get reset by the render dispatcher, re-assert before the actual render - assertEmfState(guiEntityRenderState); - } - //#endif - - @Unique - private static void assertEmfState(final GuiEntityRenderState guiEntityRenderState) { - var state = guiEntityRenderState.renderState(); - if (state instanceof HoldsETFRenderState holds && holds.etf$getState() != null) { - var emf = (EMFEntityRenderState) holds.etf$getState(); - EMFAnimationEntityContext.setCurrentEntityIteration(emf); - if (emf != null) EMFAnimationEntityContext.setLayerFactory(emf.layerFactory()); - } else { - EMFAnimationEntityContext.reset(); - } - - var light = state.lightCoords; - if (light == ETF.EMISSIVE_FEATURE_LIGHT_VALUE || light == EMF.EYES_FEATURE_LIGHT_VALUE) { - ETFRenderContext.startSpecialRenderOverlayPhase(); - } else { - ETFRenderContext.endSpecialRenderOverlayPhase(); - } - } - - @Inject(method = "renderToTexture(Lnet/minecraft/client/gui/render/state/pip/GuiEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;)V", at = @At(value = "TAIL")) - private void emf$endRender(final CallbackInfo ci) { - EMFAnimationEntityContext.reset(); - ETFRenderContext.endSpecialRenderOverlayPhase(); - } - -} -//#else -//$$ @Mixin(traben.entity_texture_features.mixin.CancelTarget.class) -//$$ public interface Mixin_GuiEntityRenderer { } -//#endif \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_HumanoidArmorLayer_AddBaseModelPoseRef.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_HumanoidArmorLayer_AddBaseModelPoseRef.java index ef97170c..bc3f24fe 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_HumanoidArmorLayer_AddBaseModelPoseRef.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_HumanoidArmorLayer_AddBaseModelPoseRef.java @@ -7,7 +7,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.animation.state.EMFSubmitData; import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer; import net.minecraft.client.renderer.entity.state.HumanoidRenderState; import com.llamalad7.mixinextras.sugar.Local; @@ -20,14 +19,23 @@ public class Mixin_HumanoidArmorLayer_AddBaseModelPoseRef void headLogic( - //#if MC >= 26.2 - //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit - //#else - net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit - //#endif - ) { - var state = modelSubmit.state(); - EMFSubmitData data = EMFSubmitData.from(modelSubmit); - - // Set up the current entity context for this render - if (state instanceof HoldsETFRenderState holds && holds.etf$getState() != null) { - var state2 = (EMFEntityRenderState) holds.etf$getState(); - EMFAnimationEntityContext.setCurrentEntityIteration(state2, setModelVariant(data, modelSubmit)); - ETFRenderContext.setCurrentEntity(state2); - EMFAnimationEntityContext.setLayerFactory(modelSubmit.model().renderType); - state2.setBipedPose(null); - } else if (data != null && data.backupState != null) { // block entity backup - var state2 = data.backupState; - EMFAnimationEntityContext.setCurrentEntityIteration(state2, setModelVariant(data, modelSubmit)); - EMFAnimationEntityContext.setLayerFactory(modelSubmit.model().renderType); - ETFRenderContext.setCurrentEntity(state2); - state2.setBipedPose(null); - } else { - EMFAnimationEntityContext.reset(); - } - - if (state instanceof net.minecraft.client.renderer.entity.state.ItemFrameRenderState) { - EMFAnimationEntityContext.setInItemFrame = true; - } - - // Handle emissive/eyes lighting setup - var light = modelSubmit.lightCoords(); - if (light == ETF.EMISSIVE_FEATURE_LIGHT_VALUE || light == EMF.EYES_FEATURE_LIGHT_VALUE) { - ETFRenderContext.startSpecialRenderOverlayPhase(); - } else { - ETFRenderContext.endSpecialRenderOverlayPhase(); - } - - if (data != null) { - EMFAnimationEntityContext.setCurrentEntityOnShoulder(data.onShoulder); - - if (modelSubmit.model() instanceof IEMFModel emfModel && emfModel.emf$isEMFModel()) { - if (data.isMainModelPhase) { - emfModel.emf$getEMFRootModel().isMainModel = true; - EMFAnimationEntityContext.unsetLayerPhase(); - } - if (data.isLayerModelPhase) { - EMFAnimationEntityContext.setLayerPhase(); - } - } - } - - //#if MC >= 26.2 - //$$ // Replaces logic for model part submits that now wrap in simple models - //$$ if (modelSubmit.model().root() instanceof EMFModelPartVanilla partVanilla && partVanilla.getRoot() != partVanilla) { - //$$ EMFManager.getInstance().entityRenderCount++; - //$$ - //$$ if (partVanilla.isPlayerArm) { - //$$ if (Minecraft.getInstance().player != null) { - //$$ EMFAnimationEntityContext.modelVariationIgnoresVisibility = true; - //$$ EMFAnimationEntityContext.setCurrentEntityIteration((EMFEntityRenderState) - //$$ ETFEntityRenderState.forEntity((ETFEntity) Minecraft.getInstance().player)); - //$$ } - //$$ EMFAnimationEntityContext.isFirstPersonHand = true; - //$$ } - //$$ } - //#endif - - } @Inject(method = //#if MC >= 26.2 @@ -119,7 +49,6 @@ private void headLogic( //#endif ) { - // Apply a simple pose copy to armor if required applyArmorBipedPose(modelSubmit); } @@ -134,65 +63,26 @@ private void applyArmorBipedPose( ) { - EMFSubmitData data = EMFSubmitData.from(modelSubmit); - if (data != null - && data.bipedPose != null + ETFSubmitData data = ETFSubmitData.from(modelSubmit); + if (data == null) return; + EMFBipedPose pose = (EMFBipedPose) data.data.get("bipedPose"); + if (pose != null && modelSubmit.model() instanceof HumanoidModel humanoidModel && !(modelSubmit.model().root() instanceof EMFModelPartRoot root && root.hasAnimation()) ) { - data.bipedPose.applyTo(humanoidModel); + pose.applyTo(humanoidModel); } } - @Unique - private boolean setModelVariant(@Nullable EMFSubmitData data, - //#if MC >= 26.2 - //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit - //#else - net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit - //#endif - - ) { - if (data != null && data.modelVariant != -1 && modelSubmit.model().root() instanceof EMFModelPartRoot root) { - root.setVariantStateTo(data.modelVariant); - return true; - } - return false; - } - - @Unique - private static void tailLogic() { - EMFAnimationEntityContext.reset(); - EMFAnimationEntityContext.setCurrentEntityOnShoulder(false); - EMFAnimationEntityContext.setInItemFrame = true; - EMFAnimationEntityContext.isFirstPersonHand = false; - } //#if MC >= 26.2 - //$$ @Inject(method = "prepareModel", at = @At(value = "HEAD")) - //$$ private void emf$initRender(final CallbackInfo ci, @Local(argsOnly = true) net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit) { - //$$ headLogic(modelSubmit); - //$$ } - //$$ //$$ @Inject(method = "prepareModel", at = @At(value = "TAIL")) //$$ private void emf$endRender(final CallbackInfo ci) { - //$$ tailLogic(); + //$$ var state = EMFState.state(); + //$$ if (state != null && state.isFirstPersonHand()) { + //$$ ETFState.unMount(); + //$$ } //$$ } - //#else - @Inject(method = "renderModel", at = @At(value = "HEAD")) - private void emf$initRender(final CallbackInfo ci, @Local(argsOnly = true) net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit) { - headLogic(modelSubmit); - } - - @Inject(method = "renderTranslucents", at = @At(value = "TAIL")) - private void emf$endRender(final CallbackInfo ci) { - tailLogic(); - } - - @Inject(method = "renderBatch", at = @At(value = "TAIL")) - private void emf$endRender2(final CallbackInfo ci) { - tailLogic(); - } //#endif } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelSubmit_AddBackupState.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelSubmit_AddBackupState.java deleted file mode 100644 index e72ae2d2..00000000 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelSubmit_AddBackupState.java +++ /dev/null @@ -1,63 +0,0 @@ -package traben.entity_model_features.mixin.mixins.rendering.submits; - -import net.minecraft.client.model.Model; -import org.spongepowered.asm.mixin.Mixin; - -//#if MC>=12109 -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 traben.entity_model_features.EMFManager; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; -import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.animation.state.EMFSubmitData; -import traben.entity_model_features.models.parts.EMFModelPartRoot; -import traben.entity_model_features.models.animation.state.EMFSubmitExtension; - -//#if MC >= 26.2 -//$$ @Mixin(net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit.class) -//#else -@Mixin(net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit.class) -//#endif -public abstract class Mixin_ModelSubmit_AddBackupState implements EMFSubmitExtension { - //TODO to go upstream in ETF refactor - - @Unique private final EMFSubmitData data = new EMFSubmitData(); - - @Override - public EMFSubmitData emf$getData() { - return data; - } - - @Shadow - public abstract Model model(); - - @Inject(method = "", at = @At("TAIL")) - private void emf$init(CallbackInfo ci) { - if (EMFSubmitData.AWAITING_backupState != null) { - // this is for those dumb block entities that don't pass the state through because they only need 1 primitive of state data - data.backupState = EMFSubmitData.AWAITING_backupState; - } - - if (EMFSubmitData.AWAITING_bipedPose != null) { - data.bipedPose = EMFSubmitData.AWAITING_bipedPose; - } - - data.onShoulder = EMFAnimationEntityContext.isOnShoulder(); - - data.isMainModelPhase = EMFSubmitData.AWAITING_isMainModelPhase; - data.isLayerModelPhase = EMFSubmitData.AWAITING_isLayerModelPhase; - - EMFModelPartRoot emfRoot = model().root() instanceof EMFModelPartRoot ? (EMFModelPartRoot) model().root() : null; - if (emfRoot != null) { - data.modelVariant = emfRoot.currentModelVariant; - } - } - -} -//#else -//$$ @Mixin(traben.entity_texture_features.mixin.CancelTarget.class) -//$$ public interface Mixin_ModelSubmit_AddBackupState { } -//#endif diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/adjustments/Mixin_BoatRenderer_PassState.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/adjustments/Mixin_BoatRenderer_PassState.java deleted file mode 100644 index d6e951b5..00000000 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/adjustments/Mixin_BoatRenderer_PassState.java +++ /dev/null @@ -1,39 +0,0 @@ -package traben.entity_model_features.mixin.mixins.rendering.submits.adjustments; - -//#if MC >= 1.21.9 - -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.renderer.entity.BoatRenderer; -import net.minecraft.client.renderer.entity.state.BoatRenderState; -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; -import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.animation.state.EMFSubmitData; - -@Mixin(BoatRenderer.class) -public abstract class Mixin_BoatRenderer_PassState { - - @Inject(method = "submitTypeAdditions", - at = @At(value = "HEAD")) - private void emf$backupState(CallbackInfo ci, @Local(argsOnly = true) BoatRenderState state) { - EMFSubmitData.AWAITING_backupState = EMFEntityRenderState.from(state); - } - - @Inject(method = "submitTypeAdditions", - at = @At(value = "TAIL")) - private void emf$backupStateClear(CallbackInfo ci) { - EMFSubmitData.AWAITING_backupState = null; - } -} -//#else -//$$ import org.spongepowered.asm.mixin.Mixin; -//$$ import traben.entity_texture_features.mixin.CancelTarget; -//$$ -//$$ @Mixin(CancelTarget.class) -//$$ public class Mixin_BoatRenderer_PassState { } -//#endif - - - diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/adjustments/Mixin_TridentRenderer_PassState.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/adjustments/Mixin_TridentRenderer_PassState.java deleted file mode 100644 index 6172e269..00000000 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/adjustments/Mixin_TridentRenderer_PassState.java +++ /dev/null @@ -1,39 +0,0 @@ -package traben.entity_model_features.mixin.mixins.rendering.submits.adjustments; - -//#if MC >= 1.21.9 - -import com.llamalad7.mixinextras.sugar.Local; -import net.minecraft.client.renderer.entity.ThrownTridentRenderer; -import net.minecraft.client.renderer.entity.state.ThrownTridentRenderState; -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; -import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.animation.state.EMFSubmitData; - -@Mixin(ThrownTridentRenderer.class) -public abstract class Mixin_TridentRenderer_PassState { - - @Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/ThrownTridentRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", - at = @At(value = "HEAD")) - private void emf$backupState(CallbackInfo ci, @Local(argsOnly = true) ThrownTridentRenderState state) { - EMFSubmitData.AWAITING_backupState = EMFEntityRenderState.from(state); - } - - @Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/ThrownTridentRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", - at = @At(value = "TAIL")) - private void emf$backupStateClear(CallbackInfo ci) { - EMFSubmitData.AWAITING_backupState = null; - } -} -//#else -//$$ import org.spongepowered.asm.mixin.Mixin; -//$$ import traben.entity_texture_features.mixin.CancelTarget; -//$$ -//$$ @Mixin(CancelTarget.class) -//$$ public class Mixin_TridentRenderer_PassState { } -//#endif - - - diff --git a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java index d6775892..b75dd9d4 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java +++ b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java @@ -1573,18 +1573,20 @@ public static Map exploreProvidedEntityModelAndExportIfNeeded(Mo String namespace = mobId.namespace; String fileName = mobId.getfileName(); - mapString.append(" |-[assets/").append(namespace).append("/optifine/cem/").append(fileName).append(".jem]\n"); - mobMap.forEach((key, entry) -> { - mapString.append(" | |-[").append("root".equals(key) ? "(optional) " : "").append("part=").append(key).append("]\n"); - var details = detailsMap.get(entry); - mapString.append(details == null ? "" : details); - }); - mapString.append(" \\-\\{{end of model}}"); - - if (known) { - EMFUtils.log("Known model detected, Mapping now...\n" + mapString); - } else { - EMFUtils.log("Unknown (possibly modded) model detected, Mapping now...\n" + mapString); + if (allowsExport || EMF.config().getConfig().logModelCreationData) { + mapString.append(" |-[assets/").append(namespace).append("/optifine/cem/").append(fileName).append(".jem]\n"); + mobMap.forEach((key, entry) -> { + mapString.append(" | |-[").append("root".equals(key) ? "(optional) " : "").append("part=").append(key).append("]\n"); + var details = detailsMap.get(entry); + mapString.append(details == null ? "" : details); + }); + mapString.append(" \\-\\{{end of model}}"); + + if (known) { + EMFUtils.log("Known model detected, Mapping now...\n" + mapString); + } else { + EMFUtils.log("Unknown (possibly modded) model detected, Mapping now...\n" + mapString); + } } if (allowsExport) { diff --git a/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java b/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java index c14d7db6..347bd242 100644 --- a/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java +++ b/src/main/java/traben/entity_model_features/models/animation/EMFAnimationEntityContext.java @@ -1,1538 +1,29 @@ package traben.entity_model_features.models.animation; -import net.minecraft.client.Minecraft; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.renderer.RenderType; -import net.minecraft.client.renderer.entity.LivingEntityRenderer; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -//#if MC>=12105 -import net.minecraft.world.entity.animal.wolf.Wolf; -//#else -//$$ import net.minecraft.world.entity.animal.Wolf; -//#endif +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; -import net.minecraft.world.entity.projectile.Arrow; -//#if MC >=12102 -import net.minecraft.client.renderer.entity.state.EntityRenderState; -import net.minecraft.client.renderer.entity.state.LivingEntityRenderState; -import net.minecraft.world.entity.vehicle.AbstractBoat; -//#else -//$$ import net.minecraft.world.entity.vehicle.Boat; -//#endif -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.util.Mth; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.*; -import net.minecraft.world.entity.animal.Cat; -import net.minecraft.world.entity.animal.Fox; -import net.minecraft.world.entity.animal.Parrot; -import net.minecraft.world.entity.animal.camel.Camel; -import net.minecraft.world.entity.monster.*; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.Projectile; -import net.minecraft.world.entity.vehicle.AbstractMinecart; -import net.minecraft.world.level.dimension.BuiltinDimensionTypes; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; -import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.Nullable; -import traben.entity_model_features.EMF; -import traben.entity_model_features.EMFManager; -import traben.entity_model_features.mixin.mixins.accessor.Mixin_GuiEntityTester; -import traben.entity_model_features.mixin.mixins.accessor.MinecraftClientAccessor; -import traben.entity_model_features.mod_compat.IrisShadowPassDetection; -import traben.entity_model_features.mod_compat.PALCompat; -import traben.entity_model_features.models.EMFModelMappings; -import traben.entity_model_features.models.EMFModel_ID; -import traben.entity_model_features.models.animation.state.EMFEntityRenderState; -import traben.entity_model_features.models.parts.EMFModelPartRoot; -import traben.entity_model_features.utils.*; -import traben.entity_texture_features.ETF; -import traben.entity_texture_features.features.ETFRenderContext; +import traben.entity_model_features.models.animation.state.EMFState; +import java.util.UUID; -//#if MC >= 12111 -//$$ import net.minecraft.world.entity.monster.illager.SpellcasterIllager; -//$$ import net.minecraft.world.entity.monster.illager.Vindicator; -//#endif - -import java.lang.reflect.Method; -import java.util.*; -import java.util.function.Function; - -@SuppressWarnings({"SameParameterValue", "unused", "UnnecessaryUnicodeEscape"}) -@Deprecated // todo move most func into EMFRenderState where appropriate +@Deprecated public final class EMFAnimationEntityContext { - private static final Map knownHighestAngerTimeByUUID = new HashMap<>() { - @Override - public Integer get(Object key) { - return super.getOrDefault(key, 0); - } - }; - private static final Map lodEntityTimers = new HashMap<>(); - public static boolean setInHand = false; // todo probably needs a 1.21.9+ solution - public static boolean isFirstPersonHand = false; - public static boolean setInItemFrame = false; - public static boolean setIsOnHead = false; - public static boolean setIsInGui = false; - @Deprecated // 26.1+ - public static double lastFOV = 70; - public static boolean is_in_ground_override = false; - public static Set entitiesToForceVanillaModel = new HashSet<>(); - //private static @Nullable EMFEntity IEMFEntity = null; - private static float shadowSize = Float.NaN; - private static float shadowOpacity = Float.NaN; - private static float leashX = Float.NaN; - private static float leashY = Float.NaN; - private static float leashZ = Float.NaN; - private static float shadowX = Float.NaN; - private static float shadowZ = Float.NaN; - private static float limbAngle = Float.NaN; - private static float limbDistance = Float.NaN; - private static float headYaw = Float.NaN; - private static float headPitch = Float.NaN; - private static boolean onShoulder = false; - private static Function layerFactory = null; - private static Boolean lodFrameSkipping = null; - private static boolean announceModels = false; - private static float frameCounter = 0; - private static boolean isLayerPhase = false; - - private static boolean checkedIfIEmotePlayerExists = false; - private static Class iEmotePlayerEntityType = null; - private static Method isPlayingEmoteMethod = null; - - public static HashMap entitiesPausedParts = new HashMap<>(); - public static Set entitiesPaused = new HashSet<>(); - public static List> pauseListeners = new ArrayList<>(); - public static List> forceVanillaModelListeners = new ArrayList<>(); + @SuppressWarnings("MismatchedQueryAndUpdateOfCollection") + private static final ObjectSet BLANK_SET = new ObjectOpenHashSet<>(); // Note don't modify this, both Essential and EmoteCraft mixin to this method // EmoteCraft is also now intentionally leaving a mixin with a NPE here to effectively just always // crash EMF and is refusing all attempts to rectify, so I'll just wrap this in a catch and use a backup check... // unfortunately I cant fix this on my end without also breaking Essential's mixin // And EmoteCraft has refused my PR to fix - // TODO check up on this with the new pauseListeners and get that in Essential so we can drop this method to just let - // EmoteCraft's mixin fail silently - public static boolean isEntityAnimPaused() { - if (emfState == null) return false; - - // API for other mods to pause animations on specific entities - var entity = emfState.emfEntity(); - if (entity != null) { - if (isPlayerEmoting(entity)) return true; - for (Function pauseListener : pauseListeners) { - try { - if (pauseListener.apply(entity)) return true; - } catch (Exception ignored) {} - } - } - - return entitiesPaused.contains(emfState.uuid()); - } - - // TODO remove eventually Re: NPE in EmoteCraft - public static boolean isEntityAnimPausedWrapped() { - if (emfState == null) return false; - try { - return isEntityAnimPaused(); - } catch (Exception e) { // just in case I guess, already happened once - try { - return isEntityAnimPausedBackupDontMixinToThisOneUseTheNewAPI(); - } catch (Exception ex) { - return false; - } - } - } - - // TODO remove eventually Re: NPE in EmoteCraft - private static boolean isEntityAnimPausedBackupDontMixinToThisOneUseTheNewAPI() { - if (emfState == null) return false; - - // API for other mods to pause animations on specific entities - var entity = emfState.emfEntity(); - if (entity != null) { - if (isPlayerEmoting(entity)) return true; - for (Function pauseListener : pauseListeners) { - try { - if (pauseListener.apply(entity)) return true; - } catch (Exception ignored) {} - } - } - - return entitiesPaused.contains(emfState.uuid()); - } - - private static boolean isPlayerEmoting(EMFEntity entity) { - if (!(entity instanceof Player player)) return false; - - Method emoteMethod = getIsPlayingEmoteMethod(); - if (emoteMethod == null) return false; - - try { - return (boolean) emoteMethod.invoke(player); - } catch (Exception ignored) { - return false; - } - } - - private static @Nullable Class getIEmotePlayerEntityType() { - if (checkedIfIEmotePlayerExists) return iEmotePlayerEntityType; - checkedIfIEmotePlayerExists = true; - - try { - // Tries to get the IEmotePlayerEntity interface in order to access the isPlayingEmote() method - // https://github.com/KosmX/emotes/blob/1.20.1/executor/src/main/java/io/github/kosmx/emotes/executor/emotePlayer/IEmotePlayerEntity.java - // This type should always be found if EmoteCraft mod doesn't change it too much and the mod is actually loaded obv - iEmotePlayerEntityType = Class.forName("io.github.kosmx.emotes.executor.emotePlayer.IEmotePlayerEntity"); - } catch (ClassNotFoundException ignored) { - iEmotePlayerEntityType = null; - } - - return iEmotePlayerEntityType; - } - - private static @Nullable Method getIsPlayingEmoteMethod() { - if (isPlayingEmoteMethod != null) return isPlayingEmoteMethod; - - Class emotePlayerType = getIEmotePlayerEntityType(); - if (emotePlayerType == null) return null; - - try { - isPlayingEmoteMethod = emotePlayerType.getMethod("isPlayingEmote"); - } catch (NoSuchMethodException ignored) { - isPlayingEmoteMethod = null; - } - - return isPlayingEmoteMethod; - } - - - public static @Nullable ModelPart[] getEntityPartsAnimPaused() { - if (emfState == null) return null; - var parts = entitiesPausedParts.get(emfState.uuid()); - return parts == null || parts.length == 0 ? null : parts; - } - - private EMFAnimationEntityContext() { - - } - - public static void incFrameCount(){ - //not 100% certain if the shadow pass passes through this method, I highly doubt it but just in case - if(IrisShadowPassDetection.getInstance().inShadowPass()) return; - - float inc = frameCounter + 1; - //reset counter after exceeding floating point precision cutoff - frameCounter = inc > 27719 ? 0 : inc; - } - - public static float getFrameCounter(){ - return frameCounter; - } - - public static boolean isJumping() { - return emfEntity() instanceof LivingEntity alive && alive.jumping; - } - - - public static void setEntityVariable(String variable, float value) { - //if (variable.equals("var.fly")) System.out.println("setEntityVariable: " + variable + " " + (emfEntity != null ? emfEntity.emf$getVariableMap().getOrDefault(variable, value) : "null")); - if (emfState != null) { - emfState.variableMap().put(variable, value); - } - } - - public static float getEntityVariable(String variable, float defaultValue) { - //if (variable.equals("var.fly")) System.out.println("getEntityVariable: " + variable + " " + (emfEntity != null ? emfEntity.emf$getVariableMap().getOrDefault(variable, defaultValue) : "null")); - if (emfState == null) return defaultValue; - return emfState.variableMap().getOrDefault(variable, defaultValue); - } - - public static void setLayerFactory(Function layerFactory) { - if (emfEntity() instanceof Arrow) { - return; - } - - var state = getEmfState(); - if (state != null && state.layerFactory() == null) { - state.setLayerFactory(layerFactory); - } - - EMFAnimationEntityContext.layerFactory = layerFactory; - } - - private static int distanceOfEntityFrom(BlockPos pos) { - if (emfState == null) return 0; - var blockPos = emfState.blockPos(); - float f = (float) (blockPos.getX() - pos.getX()); - float g = (float) (blockPos.getY() - pos.getY()); - float h = (float) (blockPos.getZ() - pos.getZ()); - return (int) Mth.sqrt(f * f + g * g + h * h); - } - - private static int getLODFactorOfEntity() { - //if (lodFactor != -1) return lodFactor; - - if (EMF.config().getConfig().animationLODDistance == 0) return 0; - - //no factor when using spyglass or player is null - if (Minecraft.getInstance().player == null || Minecraft.getInstance().player.isScoping()) { - return 0; - } - - int distance = distanceOfEntityFrom(Minecraft.getInstance().player.blockPosition()); - if (distance < 1) return 0; - - int factor = distance / EMF.config().getConfig().animationLODDistance; - //reduce factor when using zoom mods or lower fov - int factorByFOV = (int) (factor * - - //#if MC >= 26.2 - //$$ Minecraft.getInstance().gameRenderer.gameRenderState().levelRenderState.cameraRenderState.hudFov - //#elseif MC >= 26.1 - //$$ Minecraft.getInstance().gameRenderer.getGameRenderState().levelRenderState.cameraRenderState.hudFov - //#else - lastFOV - //#endif - / 70); - - int lodFactor; - //factor in low fps detail retention - if (EMF.config().getConfig().retainDetailOnLowFps && Minecraft.getInstance().getFps() < 59) { // count often drops to 59 while capped at 60 :/ - float fpsPercentageOf60 = Minecraft.getInstance().getFps() / 60f; - //reduce factor by the percentage of fps below 60 to recover some level of detail - lodFactor = (int) (factorByFOV * fpsPercentageOf60); - } else { - lodFactor = factorByFOV; - } - - if (EMF.config().getConfig().retainDetailOnLargerMobs && emfEntity() instanceof Entity entity) { - var entitySize = Math.max(entity.getBbWidth(), entity.getBbHeight()); - if (entitySize > 2) { - lodFactor = (int) (lodFactor / (entitySize / 2)); - } - } - - return lodFactor; - } - - public static boolean isLODSkippingThisFrame(String modelId) { - if (isInGui() || isOnShoulder()) return false; - if (lodFrameSkipping != null) return lodFrameSkipping; - - //skip for shadow pass - if(ETF.IRIS_DETECTED - && IrisShadowPassDetection.getInstance().inShadowPass() - && EMF.config().getConfig().animationFrameSkipDuringIrisShadowPass - //not client player in first person - && !(getEMFEntity() instanceof Player player - && player.isLocalPlayer() - && Minecraft.getInstance().options.getCameraType().isFirstPerson())) { - return true; - } - - if (EMF.config().getConfig().animationLODDistance == 0 || emfState == null) return false; - - //FIXME properly, layers lod flickering, likely related to the layer mixin but not doing that rn - var type = emfState.entityType(); - if (type == UEntityTypes.VILLAGER || type == UEntityTypes.HORSE) return false; - - // Just putting this here so that fresh animations counter rotation keep working, plus these tend to render from a distance anyway - if (type == UEntityTypes.BLAZE) return false; - - String lodKey = emfState.uuid() + modelId; - - int lodTimer = lodEntityTimers.getOrDefault(lodKey, 0); - int lodResult; - //check lod - if (lodTimer < 1) { - lodResult = EMFAnimationEntityContext.getLODFactorOfEntity(); - } else { - lodResult = lodTimer - 1; - } - lodEntityTimers.put(lodKey, lodResult); - //intellij requires it for certain versions :/ - //noinspection RedundantCast - lodFrameSkipping = (Boolean) (lodResult > 0); - return lodFrameSkipping; - } - - - public static EMFEntityRenderState getEmfState() { - return emfState; - } - - private static EMFEntityRenderState emfState = null; - - @Deprecated // todo emf render state changes - private static EMFEntity emfEntity() { - return emfState == null ? null : emfState.emfEntity(); - } - - //#if MC >= 12102 - public static EntityRenderState getEntityRenderState() { - return emfState == null ? null : emfState.vanillaState(); - } - //#endif - - public static void setCurrentEntityIteration(@Nullable EMFEntityRenderState state) { - setCurrentEntityIteration(state, false); - } - - public static boolean modelVariationIgnoresVisibility = false; - - public static void setCurrentEntityIteration(@Nullable EMFEntityRenderState state, boolean skipModelVariation) { - - isFirstPersonHand = false; - EMFManager.getInstance().entityRenderCount++; - layerFactory = null; - - shadowSize = Float.NaN; - shadowOpacity = Float.NaN; - leashX = 0; - leashY = 0; - leashZ = 0; - shadowX = 0; - shadowZ = 0; - - newEntity(state); - - if (state != null) { - - //#if MC >= 1.21.9 - // ensure etf is active here, because emf may call on additional texture variation during model rendering - ETFRenderContext.setCurrentEntity(state); - //#endif - - - //perform variant checking for this entity types models - //this is the only way to keep it generic and also before the entity is rendered and affect al its models - if (!skipModelVariation) { - Set roots = EMFManager.getInstance().rootPartsPerEntityTypeForVariation.get(state.typeString()); - if (roots != null) { - if (isEntityForcedToVanillaModel()) { - roots.forEach(root -> root.setVariantStateTo(0)); - } else { - roots.forEach(EMFModelPartRoot::doVariantCheck); - } - - if (state.emfEntity() instanceof Player player && EMF.config().getConfig().resetPlayerModelEachRender_v2) { - roots.forEach(EMFModelPartRoot::resetVanillaPartsToDefaults); - } - } - } - - - - //if this entity requires a debug print do it now after models have variated - if (EMF.config().getConfig().debugOnRightClick - && state.uuid().equals(EMFManager.getInstance().entityForDebugPrint)) { - announceModels = true; - EMFManager.getInstance().entityForDebugPrint = null; - } - } - lodFrameSkipping = null; - } - - public static void anounceModels(EMFEntityRenderState assertEntity) { - String type = assertEntity.typeString(); - Set debugRoots = EMFManager.getInstance().rootPartsPerEntityTypeForDebug.get(type); - EMFUtils.chat("\u00A7e-----------EMF Debug Printout-------------\u00A7r"); - if (debugRoots == null) { - EMFUtils.chat( - "\n\u00A7c\u00A7oThe EMF debug printout did not find any custom models registered to the following entity:\n \u00A73\u00A7l\u00A7u" + type - ); - } else { - String message = "\n\u00A72\u00A7oThe EMF debug printout found the following custom models for the entity:\n \u00A73\u00A7l\u00A7u" + - type + - "\u00A7r\n\u00A72\u00A7oThis first model is usually the primary model for the entity."; - - EMFUtils.chat(message); - - int count = 1; - for (EMFModelPartRoot debugRoot : - debugRoots) { - StringBuilder model = new StringBuilder(); - model.append("\u00A7eModel #").append(count).append("\u00A7r") - .append(entryAndValue("name", debugRoot.modelName.getfileName() + ".jem")); - if (debugRoot.modelName.hasFallbackModels()){ - model.append("\n\u00A7eFallback Models:\u00A7r"); - debugRoot.modelName.forEachFallback((modelId) -> - model.append("\n\u00A76 - \u00A7r").append(modelId.getfileName())); - } - if (debugRoot.directoryContext != null) { - model.append(entryAndValue("directory", - debugRoot.directoryContext - .getRelativeDirectoryLocationNoValidation(debugRoot.modelName.getfileName()))); - } - - if (debugRoot.textureOverride != null) { - model.append(entryAndValue("texture_override", debugRoot.textureOverride.toString())); - } - if (debugRoot.variantTester != null) { - Set set = new HashSet<>(debugRoot.allKnownStateVariants.keySet()); - set.remove(0); - model.append(entryAndValue("model_variants", set.toString())) - .append(entryAndValue("current_variant", String.valueOf(debugRoot.currentModelVariant))); - } - EMFUtils.chat(model + "\n\u00A76 - parts:\u00A7r printed in game log only."); - - EMFUtils.log("\n - parts: " + debugRoot.simplePrintChildren(0)); - - count++; - } - } - - EMFUtils.chat("\n\u00A7e----------------------------------------\u00A7r"); - if (!EMFManager.getInstance().modelsAnnounced.isEmpty()) { - String vanillaMessage = "\n\u00A72\u00A7oThe EMF debug printout found the following non-custom models for the entity:\n \u00A73\u00A7l\u00A7u" + - type + - "\u00A7r\n\u00A72\u00A7oThis first model is usually the primary model for the entity."; - - EMFUtils.chat(vanillaMessage); - int count = 1; - for (EMFModel_ID data : EMFManager.getInstance().modelsAnnounced) { - StringBuilder model = new StringBuilder(); - model.append("\n\u00A7eNon-Custom Model #").append(count).append("\u00A7r") - .append(entryAndValue("possible .jem name", data.getDisplayFileName())); - if (data.hasFallbackModels()){ - model.append("\u00A7eFallback Models:\u00A7r"); - data.forEachFallback((modelId) -> - model.append("\n\u00A76 - \u00A7r").append(modelId.getfileName())); - } - Map map = EMFModelMappings.getMapOf(data, null); - if (!map.isEmpty()) { - EMFUtils.chat(model + "\n\u00A76 - part names:\u00A7r printed in game log only."); - StringBuilder parts = new StringBuilder(); - parts.append("\n - part names: "); - map.forEach((k, v) -> parts.append("\n | - [").append(k).append(']')); - - EMFUtils.log(parts.toString()); - } else { - EMFUtils.chat(model.toString()); - EMFUtils.log(" - part names: could not be found. use the 'printout unknown models' setting instead."); - } - } - EMFUtils.chat("\n\u00A7e----------------------------------------\u00A7r"); - EMFManager.getInstance().modelsAnnounced.clear(); - } - - announceModels = false; - } - - public static boolean doAnnounceModels() { - return announceModels; - } - - private static String entryAndValue(String entry, String value) { - return "\n\u00A76 - " + entry + ":\u00A7r " + value; - } - - public static void setCurrentEntityNoIteration(@Nullable EMFEntityRenderState state) { - newEntity(state); - } - - private static void newEntity(@Nullable EMFEntityRenderState state) { - emfState = state; - - //#if MC >= 12102 - if (getEntityRenderState() instanceof LivingEntityRenderState livingEntityRenderState) { - if (isInGui()) { - // entity isn't actually walking in the gui, zero these out so animations don't jitter - limbAngle = 0; - limbDistance = 0; - } else { - limbAngle = livingEntityRenderState.walkAnimationPos; - limbDistance = livingEntityRenderState.walkAnimationSpeed; - } - headYaw = livingEntityRenderState.yRot; - if (headYaw >= 180 || headYaw < -180) { - headYaw = Mth.wrapDegrees(headYaw); - } - headPitch = livingEntityRenderState.xRot; - } else { //block entity - limbAngle = Float.NaN; - limbDistance = Float.NaN; - headYaw = Float.NaN; - headPitch = Float.NaN; - } - //#else - //$$ limbAngle = Float.NaN; - //$$ limbDistance = Float.NaN; - //$$ headYaw = Float.NaN; - //$$ headPitch = Float.NaN; - //#endif - - if (state != null) { - if (state.entity() instanceof Arrow) { - layerFactory = - //#if MC>= 12111 - //$$ net.minecraft.client.renderer.rendertype.RenderTypes - //#else - RenderType - //#endif - ::entityCutout; - } else if (state.isBlockEntity()) { - layerFactory = - //#if MC>= 12111 - //$$ net.minecraft.client.renderer.rendertype.RenderTypes - //#else - RenderType - //#endif - ::entitySolid; - } - if (state.layerFactory() == null) state.setLayerFactory(layerFactory); - } - - onShoulder = false; - } - -// public static void setAge(final float age) { -// EMFAnimationEntityContext.age = age; -// } - - public static void globalReset(){ - reset(); - frameCounter = 0; - } - - public static boolean isLayerPhase() { - return isLayerPhase; - } - - public static void setLayerPhase() { - isLayerPhase = true; - } - - public static void unsetLayerPhase() { - isLayerPhase = false; - } - - public static void reset() { - isFirstPersonHand = false; - layerFactory = null; - emfState = null; - limbAngle = Float.NaN; - limbDistance = Float.NaN; - headYaw = Float.NaN; - headPitch = Float.NaN; -// age = Float.NaN; - onShoulder = false; - shadowSize = Float.NaN; - shadowOpacity = Float.NaN; - leashX = 0; - leashY = 0; - leashZ = 0; - shadowX = 0; - shadowZ = 0; - lodFrameSkipping = null; - isLayerPhase = false; - modelVariationIgnoresVisibility = false; - - //#if MC>=12109 - if (ETFRenderContext.getCurrentEntityState() != null) ETFRenderContext.reset(); - //#endif - } - - public static RenderType getLayerFromRecentFactoryOrETFOverrideOrTranslucent(ResourceLocation identifier) { - if (layerFactory == null) { - var layer = ETF.config().getConfig().getRenderLayerOverride(); - if (layer == null) { - return - //#if MC>= 12111 - //$$ net.minecraft.client.renderer.rendertype.RenderTypes - //#else - RenderType - //#endif - .entityTranslucent(identifier); - } else { - return switch (layer) { - case TRANSLUCENT -> - //#if MC>= 12111 - //$$ net.minecraft.client.renderer.rendertype.RenderTypes - //#else - RenderType - //#endif - .entityTranslucent(identifier); - case TRANSLUCENT_CULL -> - //#if MC>= 12111 - //$$ net.minecraft.client.renderer.rendertype.RenderTypes.entityTranslucent(identifier); - //#elseif MC >=12102 - RenderType.entityTranslucent(identifier); - //#else - //$$ RenderType.entityTranslucentCull(identifier); - //#endif - case END -> - //#if MC>= 12111 - //$$ net.minecraft.client.renderer.rendertype.RenderTypes - //#else - RenderType - //#endif - .endGateway(); - case OUTLINE -> - //#if MC>= 12111 - //$$ net.minecraft.client.renderer.rendertype.RenderTypes - //#else - RenderType - //#endif - .outline(identifier); - }; - } - } - return layerFactory.apply(identifier); - } - - public static float getRuleIndex() { - if (emfState == null) return 0; - return EMFManager.getInstance().lastModelRuleOfEntity.get(emfState.uuid()); - } - - public static boolean isEntityForcedToVanillaModel(){ - - if (emfState == null) return false; - - if (entitiesToForceVanillaModel.contains(emfState.uuid())) return true; - - try { - - EntityType type = emfState.entity().etf$getType(); - if (type != null && type.toString().contains("customnpc")) { - // CustomNPC has been ported to 1.20.1 by another dev that ask for having access to the source code - // CustomNPC nor UnofficialCustomNPC are not open source (so no source code :x) - //Downloads on https://www.curseforge.com/minecraft/mc-mods/customnpcs-unofficial/files/all?page=1&pageSize=20&version=1.20.1&gameVersionTypeId=1&showAlphaFiles=hide - CompoundTag nbtTags = emfState.entity().etf$getNbt(); - - // If the customNPC is in puppet role - // Or if we want the customNPC to not use EMF animations (like with Fresh Animation RP) we can set his maxhp to 777 to have a full control (usefull for the siting pose for example) - if ((((LivingEntity) emfState.entity()).getMaxHealth() == 777f) || - nbtTags.contains("PuppetStanding") || - nbtTags.contains("PuppetMoving") || - nbtTags.contains("PuppetAttacking") || - nbtTags.contains("PuppetAnimate")) { - return true; - } - } - - for (var check : forceVanillaModelListeners) { - if (check.apply((EMFEntity) emfState.entity())) return true; - } - } catch (Exception ignored) {} - - return EMF.config().getConfig().onlyClientPlayerModel - && EMFAnimationEntityContext.getEMFEntity() instanceof Player player && !player.isLocalPlayer(); - } - - @Deprecated // todo emf render state changes - public static @Nullable EMFEntity getEMFEntity() { - return emfEntity(); - } - - public static float getDimension() { - if (emfState == null || emfState.world() == null) { - return 0; - } else { - var optional = emfState.world().dimensionTypeRegistration().unwrapKey(); - if (optional.isEmpty()) return 0; - ResourceLocation id = optional.get().location(); - //#if MC>= 12111 - //$$ if (id.equals(BuiltinDimensionTypes.NETHER.identifier())) { - //$$ return -1; - //$$ } else if (id.equals(BuiltinDimensionTypes.END.identifier())) { - //#else - if (id.equals(BuiltinDimensionTypes.NETHER_EFFECTS)) { - return -1; - } else if (id.equals(BuiltinDimensionTypes.END_EFFECTS)) { - //#endif - return 1; - } else { - return 0; - } - } - } - - public static float getPlayerX() { - return Minecraft.getInstance().player == null ? 0 : (float) Mth.lerp(getTickDelta(), Minecraft.getInstance().player.xo, Minecraft.getInstance().player.getX()); - } - - public static float getPlayerY() { - return Minecraft.getInstance().player == null ? 0 : (float) Mth.lerp(getTickDelta(), Minecraft.getInstance().player.yo, Minecraft.getInstance().player.getY()); - } - - public static float getPlayerZ() { - return Minecraft.getInstance().player == null ? 0 : (float) Mth.lerp(getTickDelta(), Minecraft.getInstance().player.zo, Minecraft.getInstance().player.getZ()); - } - - public static float getPlayerRX() { - return (Minecraft.getInstance().player == null) ? 0 : - (float) Math.toRadians(Mth.rotLerp(getTickDelta(), Minecraft.getInstance().player.xRotO, Minecraft.getInstance().player.getXRot())); - } - - public static float getPlayerRY() { - return (Minecraft.getInstance().player == null) ? 0 : - (float) Math.toRadians(Mth.rotLerp(getTickDelta(), Minecraft.getInstance().player.yRotO, Minecraft.getInstance().player.getYRot())); - } - - public static float getEntityX() { - return emfState == null ? 0 : (float) Mth.lerp(getTickDelta(), emfState.prevX(), emfState.x()); - } - - public static float getEntityY() { - return emfState == null ? 0 : - //(double) entity.getY(); - (float) Mth.lerp(getTickDelta(), emfState.prevY(), emfState.y()); - } - - public static float getEntityZ() { - return emfState == null ? 0 : (float) Mth.lerp(getTickDelta(), emfState.prevZ(), emfState.z()); - } - - public static float getEntityRX() { - return (emfState == null) ? 0 : - //(double) Math.toRadians(entity.getPitch(tickDelta)); - (float) Math.toRadians(Mth.rotLerp(getTickDelta(), emfState.prevPitch(), emfState.pitch())); - } - - public static float getEntityRY() { - if (emfState == null) return 0; - // yBodyRotO/yBodyRot oscillate between ticks while inventory is open, skip the lerp in gui - if (isInGui()) { - return (emfEntity() instanceof LivingEntity alive) ? - (float) Math.toRadians(alive.yBodyRot) : - emfEntity() instanceof Entity entity ? - (float) Math.toRadians(entity.getYRot()) - : 0; - } - return (emfEntity() instanceof LivingEntity alive) ? - (float) Math.toRadians(Mth.rotLerp(getTickDelta(), alive.yBodyRotO, alive.yBodyRot)) : - emfEntity() instanceof Entity entity ? - (float) Math.toRadians(Mth.rotLerp(getTickDelta(), entity.yRotO, entity.yRot)) - : 0; - } - - public static float getTime() { - if (emfState == null || emfState.world() == null) { - return 0 + getTickDelta(); - } else { - //limit value upper limit to preserve floating point precision - long upTimeInTicks = emfState.world().getGameTime(); // (System.currentTimeMillis() - START_TIME)/50; - return constrainedFloat(upTimeInTicks, 27720) + getTickDelta(); - } - } - - public static float getDayTime() { - if (emfState == null || emfState.world() == null) { - return 0 + getTickDelta(); - } else { - //limit value upper limit to preserve floating point precision - return constrainedFloat(emfState.world() - //#if MC >= 26.1 - //$$ .getOverworldClockTime() - //#else - .getDayTime() - //#endif - , 31415) + getTickDelta(); - } - } - - public static float getDayCount() { - if (emfState == null || emfState.world() == null) { - return 0 + getTickDelta(); - } else { - //limit value upper limit to preserve floating point precision - return (float) (emfState.world() - //#if MC >= 26.1 - //$$ .getOverworldClockTime() - //#else - .getDayTime() - //#endif - / 27720L); - } - } - - - public static float getHealth() { - if (emfState == null) return 0; - return emfEntity() instanceof LivingEntity alive ? alive.getHealth() : 1; - } - - public static float getDeathTime() { - return emfEntity() instanceof LivingEntity alive ? (alive.deathTime > 0 ? alive.deathTime + getTickDelta() : 0) : 0; - } - - public static float getAngerTime() { - if (!(emfEntity() instanceof NeutralMob)) return 0; - - float currentKnownHighest = knownHighestAngerTimeByUUID.getOrDefault(emfState.uuid(), 0); - //#if MC >= 12111 - //$$ int angerTime = (int) (((NeutralMob) emfEntity()).getPersistentAngerEndTime() - emfState.world().getGameTime()); - //#else - int angerTime = ((NeutralMob) emfEntity()).getRemainingPersistentAngerTime(); - //#endif - - //clear anger info if anger is over - if (angerTime <= 0) { - knownHighestAngerTimeByUUID.put(emfState.uuid(), 0); - return 0; - } - - //store this if this is the largest anger time for the entity seen so far - if (angerTime > currentKnownHighest) { - knownHighestAngerTimeByUUID.put(emfState.uuid(), angerTime); - } - return angerTime - getTickDelta(); - } - - public static float getAngerTimeStart() { - //this only makes sense if we are calculating it here from the largest known value of anger time - // i could also reset it when anger time hits 0 - return emfEntity() instanceof NeutralMob ? knownHighestAngerTimeByUUID.getOrDefault(emfState.uuid(), 0) : 0; - - } - public static float getMaxHealth() { - return emfEntity() instanceof LivingEntity alive ? alive.getMaxHealth() : 1; - } - - public static float getId() { - return emfState == null || isOnShoulder() - ? 0 - : Math.abs(emfState.optifineId()) % 27720 ; - } - - public static float getHurtTime() { - return emfEntity() instanceof LivingEntity alive ? (alive.hurtTime > 0 ? alive.hurtTime - getTickDelta() : 0) : 0; - } - - public static float getHeightAboveGround() { - if (!(emfEntity() instanceof Entity)) return 0; - float y = getEntityY(); - BlockPos.MutableBlockPos pos = emfState.blockPos().mutable(); - - int worldBottom = - //#if MC >=12102 - emfState.world().getMinY(); - //#else - //$$ emfState.world().getMinBuildHeight(); - //#endif - - if (emfState.isBlockEntity()) // Don't include self - pos.move(Direction.DOWN); - - //loop down until we hit a block that can be stood on - while (!emfState.world().getBlockState(pos) - .entityCanStandOn(emfState.world(),pos, (Entity) emfEntity()) - && pos.getY() > worldBottom) { - pos.move(Direction.DOWN); - } - return y - pos.getY(); - } - - public static float getFluidDepthDown() { - if (emfState == null - || emfState.world().getFluidState(emfState.blockPos()).isEmpty()) return 0; - - BlockPos pos = emfState.blockPos(); - int worldBottom = - //#if MC >=12102 - emfState.world().getMinY(); - //#else - //$$ emfState.world().getMinBuildHeight(); - //#endif - while (!emfState.world().getFluidState(pos).isEmpty() && pos.getY() > worldBottom) { - pos = pos.below(); - } - return emfState.blockPos().getY() - pos.getY(); - } - - - public static float getFluidDepthUp() { - if (emfState == null - || emfState.world().getFluidState(emfState.blockPos()).isEmpty()) return 0; - - BlockPos pos = emfState.blockPos(); - int worldTop = - //#if MC >=12102 - emfState.world().getMaxY(); - //#else - //$$ emfState.world().getMaxBuildHeight(); - //#endif - while (!emfState.world().getFluidState(pos).isEmpty() && pos.getY() < worldTop) { - pos = pos.above(); - } - return pos.getY() - emfState.blockPos().getY(); - } - - public static float getFluidDepth() { - if (emfState == null - || emfState.world().getFluidState(emfState.blockPos()).isEmpty()) return 0; - return getFluidDepthDown() + getFluidDepthUp() - 1; - } - - public static boolean isInWater() { - return emfState != null && emfState.isTouchingWater(); - } - - public static boolean isBurning() { - return emfState != null && emfState.isOnFire(); - } - - public static boolean isRiding() { - return emfState != null && emfState.hasVehicle(); - } - - public static boolean isChild() { - return emfEntity() instanceof LivingEntity alive && alive.isBaby(); - } - - public static boolean isOnGround() { - return emfState != null && emfState.isOnGround(); - } - - public static boolean isClimbing() { - return emfEntity() instanceof LivingEntity alive && alive.onClimbable(); - } - - public static boolean isAlive() { - if (emfState == null) return false; - return emfState.isAlive(); - } - - public static boolean isUsingItem() { - if (emfState == null) return false; - if (emfEntity() instanceof LivingEntity entity) { - return entity.isUsingItem(); - } - return false; - } - - public static boolean isSwingingArm(boolean right) { - if (emfState == null) return false; - if (getSwingProgress() == 0 && !isUsingItem()) return false; - if (emfEntity() instanceof LivingEntity entity) { - boolean isRightHanded = entity.getMainArm() == HumanoidArm.RIGHT; - boolean usingMainHand = entity.getUsedItemHand() == InteractionHand.MAIN_HAND; - if (right){ - return isRightHanded == usingMainHand; - } else { - return isRightHanded != usingMainHand; - } - - } - return false; - } - - public static boolean isHoldingItem(boolean right) { - if (emfState == null) return false; - if (emfEntity() instanceof LivingEntity entity) { - boolean isRightHanded = entity.getMainArm() == HumanoidArm.RIGHT; - InteractionHand arm; - if (right){ - arm = isRightHanded ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; - } else { - arm = isRightHanded ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; - } - return !entity.getItemInHand(arm).isEmpty(); - } - return false; - } - - - - @SuppressWarnings("IfCanBeSwitch")//only in java 21 - public static boolean isAggressive() { - if (emfState == null) return false; - - if (emfEntity() instanceof final EnderMan enderman) { - return enderman.isCreepy(); - } - if (emfEntity() instanceof final Blaze blaze) { - return blaze.isOnFire(); - } - if (emfEntity() instanceof final Guardian guardian) { - return guardian.getActiveAttackTarget() != null; - } - if (emfEntity() instanceof final Vindicator vindicator) { - return vindicator.isAggressive(); - } - if (emfEntity() instanceof final SpellcasterIllager caster) { - return caster.isCastingSpell(); - } - if (emfEntity() instanceof final Vex vex) { - return vex.isCharging(); - } - - //these ones can fallback just incase the specific method doesn't sync for clients for modded mobs - if (emfEntity() instanceof final NeutralMob angry && angry.isAngry()) { - return true; - } - if (emfEntity() instanceof Targeting targets && targets.getTarget() != null) { - return true; - } - return emfEntity() instanceof Mob mob && mob.isAggressive(); - } - - public static boolean isGlowing() { - return emfState != null && emfState.isGlowing(); - } - - public static boolean isHurt() { - return emfEntity() instanceof LivingEntity alive && alive.hurtTime > 0; - } - - public static boolean isInHand() { - return setInHand; - } - - public static boolean isInItemFrame() { - return setInItemFrame; - } - - public static boolean isInGround() { - return is_in_ground_override || emfEntity() instanceof Projectile proj && proj.isInWall(); - } - - - public static boolean isInGui() { - return setIsInGui; - } - - public static boolean isClientHovered() { - if (emfState == null) return false; - var mc = Minecraft.getInstance(); - - //block entity looked at - if (emfState.isBlockEntity()){ - var player = Minecraft.getInstance().player; - if(player != null - && emfState.distanceTo(player) <= - //#if MC >= 12006 - player.blockInteractionRange() - //#else - //$$ (player.isCreative() ? 5F : 4.5F) - //#endif - + 1) { - Entity entity = mc.getCameraEntity(); - if (entity != null) { - var block = entity.pick(20.0, 0.0F, false); - if (block.getType() == HitResult.Type.BLOCK) { - return ((BlockHitResult) block).getBlockPos().equals(emfState.blockPos()); - } - } - } - return false; - } - - //entity looked at - return mc.crosshairPickEntity != null && mc.crosshairPickEntity.equals(emfEntity()); - } - - public static boolean isInLava() { - return emfState != null && emfState.isInLava(); - } - - public static boolean isInvisible() { - return emfState != null && emfState.isInvisible(); - } - - public static boolean isOnHead() { - return setIsOnHead; - } - - public static boolean isOnShoulder() { - return onShoulder; - } - - public static void setCurrentEntityOnShoulder(boolean onShoulder) { - EMFAnimationEntityContext.onShoulder = onShoulder; - } - - public static boolean isRidden() { - return emfState != null && emfState.hasPassengers(); - } - - public static boolean isSitting() { - if (emfState == null) return false; - return (emfEntity() instanceof TamableAnimal tame && tame.isInSittingPose()) || - (emfEntity() instanceof Fox fox && fox.isSitting()) || - (emfEntity() instanceof Parrot parrot && parrot.isInSittingPose()) || - (emfEntity() instanceof Cat cat && cat.isInSittingPose()) || - (emfEntity() instanceof Wolf wolf && wolf.isInSittingPose()) || - (emfEntity() instanceof Camel camel && camel.isCamelSitting()); - } - - - public static boolean isSneaking() { - return emfState != null && emfState.isSneaking(); - } - - public static boolean isSprinting() { - return emfState != null && emfState.isSprinting(); - } - - public static boolean isTamed() { - return emfEntity() instanceof TamableAnimal tame && tame.isTame(); - } - - public static boolean isWet() { - return emfState != null && emfState.isWet(); - } - - public static float getSwingProgress() { - if (isInGui()) return 0; - return emfEntity() instanceof LivingEntity alive ? alive.getAttackAnim(getTickDelta()) : 0; - } - -// private static float age = Float.NaN; - - public static float getAge() { -// if (!Float.isNaN(age)) return age; - - if (emfState == null) { - return 0 + getTickDelta(); - }else { - return constrainedFloat(emfState.age(), 27720) + getTickDelta(); - } -// return age; - } - - private static float constrainedFloat(float value, int constraint) { - return (value >= constraint ? value % constraint : value); - } - - private static float constrainedFloat(float value) { - return constrainedFloat(value, 27720); - } - - private static float constrainedFloat(long value, int constraint) { - return (value >= constraint ? value % constraint : value); - } - - private static float constrainedFloat(long value) { - return constrainedFloat(value, 27720); - } - - private static float constrainedFloat(int value, int constraint) { - return (value >= constraint ? value % constraint : value); - } - - private static float constrainedFloat(int value) { - return constrainedFloat(value, 27720); - } - - public static float getFrameTime() { - if (Minecraft.getInstance().isPaused()) return 0; - //#if MC > 12002 - if (Minecraft.getInstance().level != null && Minecraft.getInstance().level.tickRateManager().isFrozen()) return 0; - //#endif - - //#if MC >= 12100 - return ((MinecraftClientAccessor)Minecraft.getInstance()) - //#if MC >= 12102 - .getDeltaTracker() - //#else - //$$ .getTimer() - //#endif - .getGameTimeDeltaTicks() / 20; - //#else - //$$ return Minecraft.getInstance().getDeltaFrameTime() / 20; - //#endif - } - - public static float getLimbAngle() {//limb_swing - if (emfState == null) return 0; - if (Float.isNaN(limbAngle)) { - doLimbValues(); - } - return limbAngle; - } - - public static void setLimbAngle(float limbAngle) { - EMFAnimationEntityContext.limbAngle = limbAngle; - } - - public static float getLimbDistance() {//limb_speed - if (emfState == null) return 0; - if (Float.isNaN(limbDistance)) { - doLimbValues(); - } - return limbDistance == Float.MIN_VALUE ? 0 : limbDistance; - } - - public static void setLimbDistance(float limbDistance) { - EMFAnimationEntityContext.limbDistance = limbDistance; - } - - private static void doLimbValues() { - float o = 0; - float n = 0; - assert emfState != null; - if (!emfState.hasVehicle() && emfEntity() instanceof LivingEntity alive) { - o = alive.walkAnimation.position(getTickDelta()); - n = alive.walkAnimation.speed(getTickDelta()); - if (alive.isBaby()) { - o *= 3.0F; - - } - if (n > 1.0F) { - n = 1.0F; - } - } else if (emfEntity() instanceof AbstractMinecart) { - n = 1; - o = -(getEntityX() + getEntityZ()); - } else if (emfEntity() instanceof - //#if MC >= 12102 - AbstractBoat - //#else - //$$ Boat - //#endif - boat) { - n = 1; - //o = boat.interpolatePaddlePhase(0, tickDelta);//1); - o = Math.max(boat.getRowingTime(1, getTickDelta()), boat.getRowingTime(0, getTickDelta())); - } - limbDistance = n; - limbAngle = o; - } - - public static float getHeadYaw() { - if (emfState == null) return 0; - if (Float.isNaN(headYaw)) { - if (isInGui()) return 0; - doHeadValues(); - } - return headYaw; - } - - public static void setHeadYaw(float headYaw) { - EMFAnimationEntityContext.headYaw = headYaw; - } - - public static float getHeadPitch() { - if (emfState == null) return 0; - if (Float.isNaN(headPitch)) { - if (isInGui()) return 0; - doHeadValues(); - } - return headPitch; - } - - public static void setHeadPitch(float headPitch) { - EMFAnimationEntityContext.headPitch = headPitch; - } - - private static void doHeadValues() { - if (emfEntity() instanceof LivingEntity livingEntity) { - float h = Mth.rotLerp(getTickDelta(), livingEntity.yBodyRotO, livingEntity.yBodyRot); - float j = Mth.rotLerp(getTickDelta(), livingEntity.yHeadRotO, livingEntity.yHeadRot); - float k = j - h; - float l; - if (livingEntity.isPassenger() && livingEntity.getVehicle() instanceof LivingEntity livingEntity2) { - h = Mth.rotLerp(getTickDelta(), livingEntity2.yBodyRotO, livingEntity2.yBodyRot); - k = j - h; - l = Mth.wrapDegrees(k); - if (l < -85.0F) { - l = -85.0F; - } - - if (l >= 85.0F) { - l = 85.0F; - } - - h = j - l; - if (l * l > 2500.0F) { - h += l * 0.2F; - } - - k = j - h; - } - - float m = Mth.lerp(getTickDelta(), livingEntity.xRotO, livingEntity.getXRot()); - if ( - //#if MC >= 12109 - // duplicate check of now non-static method - livingEntity.getCustomName() != null && LivingEntityRenderer.isUpsideDownName(livingEntity.getCustomName().getString() ) - //#else - //$$ LivingEntityRenderer.isEntityUpsideDown(livingEntity) - //#endif - ) { - m *= -1.0F; - k *= -1.0F; - } - headPitch = m; - //headYaw = k; - //constrain head yaw amount - if (k >= 180 || k < -180) { - headYaw = Mth.wrapDegrees(k); - } else { - headYaw = k; - } - } else { - headPitch = 0; - headYaw = 0; - } - } - - public static float getTickDelta() { - return - //#if MC >= 12100 - ((MinecraftClientAccessor) Minecraft.getInstance()) - //#if MC >= 12102 - .getDeltaTracker() - //#else - //$$ .getTimer() - //#endif - .getGameTimeDeltaPartialTick(true); - //#else - //$$ Minecraft.getInstance().isPaused() ? ((MinecraftClientAccessor) Minecraft.getInstance()).getPausePartialTick() : Minecraft.getInstance().getFrameTime(); - //#endif - } - - - public static float getMoveForward() { - if (emfState == null || isInGui()) return 0; - double lookDir = Math.toRadians(90 - emfState.yaw()); - //float speed = entity.horizontalSpeed; - Vec3 velocity = emfState.emfVelocity(); - - //consider 2d plane of movement with x y - double x = velocity.x; - double y = velocity.z; - - // compute the new x and y components after rotation - double newX = (x * Math.cos(lookDir)) - (y * Math.sin(lookDir)); - //double newY = (x * Math.sin(lookDir)) + (y * Math.cos(lookDir)); - - - return processMove(newX, x, y); - } - - public static float getMoveStrafe() { - if (emfState == null || isInGui()) return 0; - double lookDir = Math.toRadians(90 - emfState.yaw()); - //float speed = entity.horizontalSpeed; - Vec3 velocity = emfState.emfVelocity(); - - //consider 2d plane of movement with x y - double x = velocity.x; - double y = velocity.z; - - // compute the new x and y components after rotation - //double newX = (x * Math.cos(lookDir)) - (y * Math.sin(lookDir)); - double newY = (x * Math.sin(lookDir)) + (y * Math.cos(lookDir)); - return processMove(newY, x, y); - } - - private static float processMove(double value, double x, double y) { - - double totalMovementVector = Math.sqrt(x * x + y * y); - - if (totalMovementVector == 0) return 0; - - //return percentage that is forward/strafe - return (float) -(value / totalMovementVector); - - } - - public static float getShadowSize() { - return shadowSize; - } - - public static void setShadowSize(float shadowSize) { - EMFAnimationEntityContext.shadowSize = shadowSize; - } - - public static float getShadowOpacity() { - return shadowOpacity; - } - - public static void setShadowOpacity(float shadowOpacity) { - EMFAnimationEntityContext.shadowOpacity = shadowOpacity; - } - - public static float getLeashX() { - return leashX; - } - - public static void setLeashX(float leashX) { - EMFAnimationEntityContext.leashX = leashX; - } - - public static float getLeashY() { - return leashY; - } - - public static void setLeashY(float leashY) { - EMFAnimationEntityContext.leashY = leashY; - } - - public static float getLeashZ() { - return leashZ; - } - - public static void setLeashZ(float leashZ) { - EMFAnimationEntityContext.leashZ = leashZ; - } - - public static float getShadowX() { - return shadowX; - } - - public static void setShadowX(float shadowX) { - EMFAnimationEntityContext.shadowX = shadowX; - } - - public static float getShadowZ() { - return shadowZ; - } - - public static void setShadowZ(float shadowZ) { - EMFAnimationEntityContext.shadowZ = shadowZ; - } - - public static IterationContext getIterationContext() { - return new IterationContext( - EMFManager.getInstance().entityRenderCount, - emfState, - layerFactory, - lodFrameSkipping, - shadowSize, - shadowOpacity, - leashX, - leashY, - leashZ, - shadowX, - shadowZ - ); - } + @SuppressWarnings("DeprecatedIsStillUsed") + @Deprecated // Now exists just to capture Essential's mixin + public static boolean isEntityAnimPaused() { + var state = EMFState.state(); + if (state == null || state.isBlockEntity()) return false; - public static void setIterationContext(IterationContext context) { - EMFManager.getInstance().entityRenderCount = context.entityRenderCount; - emfState = context.emfState; - layerFactory = context.layerFactory; - lodFrameSkipping = context.lodFrameSkipping; - shadowSize = context.shadowSize; - shadowOpacity = context.shadowOpacity; - leashX = context.leashX; - leashY = context.leashY; - leashZ = context.leashZ; - shadowX = context.shadowX; - shadowZ = context.shadowZ; + return BLANK_SET.contains(state.uuid()); // Essential targets this, will only be true due to it } - public record IterationContext( - long entityRenderCount, - @Nullable EMFEntityRenderState emfState, - Function layerFactory, - Boolean lodFrameSkipping, - float shadowSize, - float shadowOpacity, - float leashX, - float leashY, - float leashZ, - float shadowX, - float shadowZ - ) {} } diff --git a/src/main/java/traben/entity_model_features/models/animation/math/EMFMath.java b/src/main/java/traben/entity_model_features/models/animation/math/EMFMath.java new file mode 100644 index 00000000..a6573332 --- /dev/null +++ b/src/main/java/traben/entity_model_features/models/animation/math/EMFMath.java @@ -0,0 +1,862 @@ +package traben.entity_model_features.models.animation.math; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.entity.LivingEntityRenderer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.HumanoidArm; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.NeutralMob; +import net.minecraft.world.entity.TamableAnimal; +import net.minecraft.world.entity.Targeting; +import net.minecraft.world.entity.animal.Cat; +import net.minecraft.world.entity.animal.Fox; +import net.minecraft.world.entity.animal.Parrot; +import net.minecraft.world.entity.animal.camel.Camel; +import net.minecraft.world.entity.animal.wolf.Wolf; +import net.minecraft.world.entity.monster.Blaze; +import net.minecraft.world.entity.monster.EnderMan; +import net.minecraft.world.entity.monster.Guardian; +import net.minecraft.world.entity.monster.SpellcasterIllager; +import net.minecraft.world.entity.monster.Vex; +import net.minecraft.world.entity.monster.Vindicator; +import net.minecraft.world.entity.projectile.Projectile; +import net.minecraft.world.entity.vehicle.AbstractMinecart; +import net.minecraft.world.level.dimension.BuiltinDimensionTypes; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import traben.entity_model_features.EMFManager; +import traben.entity_model_features.mixin.mixins.accessor.MinecraftClientAccessor; +import traben.entity_model_features.models.animation.state.EMFEntityRenderState; +import traben.entity_model_features.models.animation.state.EMFState; +import traben.entity_model_features.utils.EMFEntity; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public abstract class EMFMath { + + //region value wrapping + public static final int WRAP_CONST = 27720; + + @SuppressWarnings("SameParameterValue") + private static float constrainedFloat(float value, int constraint) { + return (value >= constraint ? value % constraint : value); + } + + @SuppressWarnings("unused") + private static float constrainedFloat(float value) { + return constrainedFloat(value, WRAP_CONST); + } + + private static float constrainedFloat(long value, int constraint) { + return (value >= constraint ? value % constraint : value); + } + + @SuppressWarnings("unused") + private static float constrainedFloat(long value) { + return constrainedFloat(value, WRAP_CONST); + } + + @SuppressWarnings("SameParameterValue") + private static float constrainedFloat(int value, int constraint) { + return (value >= constraint ? value % constraint : value); + } + + @SuppressWarnings("unused") + private static float constrainedFloat(int value) { + return constrainedFloat(value, WRAP_CONST); + } + //endregion + + private static final Map knownHighestAngerTimeByUUID = new HashMap<>() { + @Override + public Integer get(Object key) { + return super.getOrDefault(key, 0); + } + }; + + public static void setEntityVariable(String variable, float value) { + var state = emfState(); + if (state != null) { + state.variableMap().put(variable, value); + } + } + + public static float getEntityVariable(String variable, float defaultValue) { + var state = emfState(); + if (state == null) return defaultValue; + return state.variableMap().getOrDefault(variable, defaultValue); + } + + + + + //region player position and rotation + public static float getPlayerX() { + return Minecraft.getInstance().player == null ? 0 : (float) Mth.lerp(getTickDelta(), Minecraft.getInstance().player.xo, Minecraft.getInstance().player.getX()); + } + + public static float getPlayerY() { + return Minecraft.getInstance().player == null ? 0 : (float) Mth.lerp(getTickDelta(), Minecraft.getInstance().player.yo, Minecraft.getInstance().player.getY()); + } + + public static float getPlayerZ() { + return Minecraft.getInstance().player == null ? 0 : (float) Mth.lerp(getTickDelta(), Minecraft.getInstance().player.zo, Minecraft.getInstance().player.getZ()); + } + + public static float getPlayerRX() { + return (Minecraft.getInstance().player == null) ? 0 : + (float) Math.toRadians(Mth.rotLerp(getTickDelta(), Minecraft.getInstance().player.xRotO, Minecraft.getInstance().player.getXRot())); + } + + public static float getPlayerRY() { + return (Minecraft.getInstance().player == null) ? 0 : + (float) Math.toRadians(Mth.rotLerp(getTickDelta(), Minecraft.getInstance().player.yRotO, Minecraft.getInstance().player.getYRot())); + } + //endregion + + //region entity position and rotation + public static float getEntityX() { + var state = emfState(); + return state == null ? 0 : (float) Mth.lerp(getTickDelta(), state.prevX(), state.x()); + } + + public static float getEntityY() { + var state = emfState(); + return state == null ? 0 : + //(double) entity.getY(); + (float) Mth.lerp(getTickDelta(), state.prevY(), state.y()); + } + + public static float getEntityZ() { + var state = emfState(); + return state == null ? 0 : (float) Mth.lerp(getTickDelta(), state.prevZ(), state.z()); + } + + public static float getEntityRX() { + var state = emfState(); + return (state == null) ? 0 : + //(double) Math.toRadians(entity.getPitch(tickDelta)); + (float) Math.toRadians(Mth.rotLerp(getTickDelta(), state.prevPitch(), state.pitch())); + } + + public static float getEntityRY() { + var state = emfState(); + if (state == null) return 0; + var emfEntity = state.entity(); + // yBodyRotO/yBodyRot oscillate between ticks while inventory is open, skip the lerp in gui + if (isInGui()) { + return (emfEntity instanceof LivingEntity alive) ? + (float) Math.toRadians(alive.yBodyRot) : + emfEntity instanceof Entity entity ? + (float) Math.toRadians(entity.getYRot()) + : 0; + } + return (emfEntity instanceof LivingEntity alive) ? + (float) Math.toRadians(Mth.rotLerp(getTickDelta(), alive.yBodyRotO, alive.yBodyRot)) : + emfEntity instanceof Entity entity ? + (float) Math.toRadians(Mth.rotLerp(getTickDelta(), entity.yRotO, entity.yRot)) + : 0; + } + //endregion + + //region move methods + public static float getMoveForward() { + var state = emfState(); + if (state == null || isInGui()) return 0; + double lookDir = Math.toRadians(90 - state.yaw()); + //float speed = entity.horizontalSpeed; + Vec3 velocity = state.emfVelocity(); + + //consider 2d plane of movement with x y + double x = velocity.x; + double y = velocity.z; + + // compute the new x and y components after rotation + double newX = (x * Math.cos(lookDir)) - (y * Math.sin(lookDir)); + //double newY = (x * Math.sin(lookDir)) + (y * Math.cos(lookDir)); + + + return processMove(newX, x, y); + } + + public static float getMoveStrafe() { + var state = emfState(); + if (state == null || isInGui()) return 0; + double lookDir = Math.toRadians(90 - state.yaw()); + //float speed = entity.horizontalSpeed; + Vec3 velocity = state.emfVelocity(); + + //consider 2d plane of movement with x y + double x = velocity.x; + double y = velocity.z; + + // compute the new x and y components after rotation + //double newX = (x * Math.cos(lookDir)) - (y * Math.sin(lookDir)); + double newY = (x * Math.sin(lookDir)) + (y * Math.cos(lookDir)); + return processMove(newY, x, y); + } + + private static float processMove(double value, double x, double y) { + double totalMovementVector = Math.sqrt(x * x + y * y); + if (totalMovementVector == 0) return 0; + //return percentage that is forward/strafe + return (float) -(value / totalMovementVector); + } + //endregion + + //region head methods + public static float getHeadYaw() { + var state = emfState(); + if (state == null) return 0; + if (Float.isNaN(state.headYaw())) { + if (isInGui()) return 0; + doHeadValues(); + } + return state.headYaw(); + } + + public static void setHeadYaw(float headYaw) { + var state = emfState(); + if (state != null) { + state.setHeadYaw(headYaw); + } + } + + public static float getHeadPitch() { + var state = emfState(); + if (state == null) return 0; + if (Float.isNaN(state.headPitch())) { + if (isInGui()) return 0; + doHeadValues(); + } + return state.headPitch(); + } + + public static void setHeadPitch(float headPitch) { + var state = emfState(); + if (state != null) { + state.setHeadPitch(headPitch); + } + } + + private static void doHeadValues() { + var state = emfState(); + if (state instanceof LivingEntity livingEntity) { + float h = Mth.rotLerp(getTickDelta(), livingEntity.yBodyRotO, livingEntity.yBodyRot); + float j = Mth.rotLerp(getTickDelta(), livingEntity.yHeadRotO, livingEntity.yHeadRot); + float k = j - h; + float l; + if (livingEntity.isPassenger() && livingEntity.getVehicle() instanceof LivingEntity livingEntity2) { + h = Mth.rotLerp(getTickDelta(), livingEntity2.yBodyRotO, livingEntity2.yBodyRot); + k = j - h; + l = Mth.wrapDegrees(k); + if (l < -85.0F) { + l = -85.0F; + } + + if (l >= 85.0F) { + l = 85.0F; + } + + h = j - l; + if (l * l > 2500.0F) { + h += l * 0.2F; + } + + k = j - h; + } + + float m = Mth.lerp(getTickDelta(), livingEntity.xRotO, livingEntity.getXRot()); + if ( + //#if MC >= 12109 + // duplicate check of now non-static method + livingEntity.getCustomName() != null && LivingEntityRenderer.isUpsideDownName(livingEntity.getCustomName().getString() ) + //#else + //$$ LivingEntityRenderer.isEntityUpsideDown(livingEntity) + //#endif + ) { + m *= -1.0F; + k *= -1.0F; + } + state.setHeadPitch(m); + //constrain head yaw amount + if (k >= 180 || k < -180) { + state.setHeadYaw(Mth.wrapDegrees(k)); + } else { + state.setHeadYaw(k); + } + } else { + if (state != null) { + state.setHeadPitch(0); + state.setHeadYaw(0); + } + } + } + //endregion + + //region limb methods + public static float getLimbAngle() {//limb_swing + var state = emfState(); + if (state == null) return 0; + if (Float.isNaN(state.limbAngle())) { + doLimbValues(state); + } + return state.limbAngle(); + } + + public static void setLimbAngle(float limbAngle) { + var state = emfState(); + if (state != null) { + state.setLimbAngle(limbAngle); + } + } + + public static float getLimbDistance() {//limb_speed + var state = emfState(); + if (state == null) return 0; + if (Float.isNaN(state.limbDistance())) { + doLimbValues(state); + } + return state.limbDistance() == Float.MIN_VALUE ? 0 : state.limbDistance(); + } + + public static void setLimbDistance(float limbDistance) { + var state = emfState(); + if (state != null) { + state.setLimbDistance(limbDistance); + } + } + + private static void doLimbValues(@NotNull EMFEntityRenderState state) { + float o = 0; + float n = 0; + var entity = state.emfEntity(); + if (!state.hasVehicle() && entity instanceof LivingEntity alive) { + o = alive.walkAnimation.position(getTickDelta()); + n = alive.walkAnimation.speed(getTickDelta()); + if (alive.isBaby()) { + o *= 3.0F; + + } + if (n > 1.0F) { + n = 1.0F; + } + } else if (entity instanceof AbstractMinecart) { + n = 1; + o = -(getEntityX() + getEntityZ()); + } else if (entity instanceof + //#if MC >= 12102 + net.minecraft.world.entity.vehicle.AbstractBoat + //#else + //$$ net.minecraft.world.entity.vehicle.Boat + //#endif + boat) { + n = 1; + //o = boat.interpolatePaddlePhase(0, tickDelta);//1); + o = Math.max(boat.getRowingTime(1, getTickDelta()), boat.getRowingTime(0, getTickDelta())); + } + state.setLimbDistance(n); + state.setLimbAngle(o); + } + //endregion + + //region is_ methods + public static boolean isJumping() { + return emfEntity() instanceof LivingEntity alive && alive.jumping; + } + + public static boolean isInWater() { + var state = emfState(); + return state != null && state.isTouchingWater(); + } + + public static boolean isBurning() { + var state = emfState(); + return state != null && state.isOnFire(); + } + + public static boolean isRiding() { + var state = emfState(); + return state != null && state.hasVehicle(); + } + + public static boolean isChild() { + return emfEntity() instanceof LivingEntity alive && alive.isBaby(); + } + + public static boolean isOnGround() { + var state = emfState(); + return state != null && state.isOnGround(); + } + + public static boolean isClimbing() { + return emfEntity() instanceof LivingEntity alive && alive.onClimbable(); + } + + public static boolean isAlive() { + var state = emfState(); + return state != null && state.isAlive(); + } + + public static boolean isUsingItem() { + var state = emfState(); + if (state == null) return false; + if (state.emfEntity() instanceof LivingEntity entity) { + return entity.isUsingItem(); + } + return false; + } + + public static boolean isSwingingArm(boolean right) { + var state = emfState(); + if (state == null) return false; + if (getSwingProgress() == 0 && !isUsingItem()) return false; + if (state.emfEntity() instanceof LivingEntity entity) { + boolean isRightHanded = entity.getMainArm() == HumanoidArm.RIGHT; + boolean usingMainHand = entity.getUsedItemHand() == InteractionHand.MAIN_HAND; + if (right){ + return isRightHanded == usingMainHand; + } else { + return isRightHanded != usingMainHand; + } + + } + return false; + } + + public static boolean isHoldingItem(boolean right) { + var state = emfState(); + if (state == null) return false; + if (state.emfEntity() instanceof LivingEntity entity) { + boolean isRightHanded = entity.getMainArm() == HumanoidArm.RIGHT; + InteractionHand arm; + if (right){ + arm = isRightHanded ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; + } else { + arm = isRightHanded ? InteractionHand.OFF_HAND : InteractionHand.MAIN_HAND; + } + return !entity.getItemInHand(arm).isEmpty(); + } + return false; + } + + @SuppressWarnings("IfCanBeSwitch")//only in java 21 + public static boolean isAggressive() { + var state = emfState(); + if (state == null) return false; + var emfEntity = state.emfEntity(); + + if (emfEntity instanceof final EnderMan enderman) { + return enderman.isCreepy(); + } + if (emfEntity instanceof final Blaze blaze) { + return blaze.isOnFire(); + } + if (emfEntity instanceof final Guardian guardian) { + return guardian.getActiveAttackTarget() != null; + } + if (emfEntity instanceof final Vindicator vindicator) { + return vindicator.isAggressive(); + } + if (emfEntity instanceof final SpellcasterIllager caster) { + return caster.isCastingSpell(); + } + if (emfEntity instanceof final Vex vex) { + return vex.isCharging(); + } + + // these can fallback just incase the specific method doesn't sync for clients for modded mobs + if (emfEntity instanceof final NeutralMob angry && angry.isAngry()) { + return true; + } + if (emfEntity instanceof Targeting targets && targets.getTarget() != null) { + return true; + } + return emfEntity instanceof Mob mob && mob.isAggressive(); + } + + public static boolean isGlowing() { + var state = emfState(); + return state != null && state.isGlowing(); + } + + public static boolean isHurt() { + var emfEntity = emfEntity(); + return emfEntity instanceof LivingEntity alive && alive.hurtTime > 0; + } + + + public static boolean isInGround() { + return EMFState.isInGroundOverride || emfEntity() instanceof Projectile proj && proj.isInWall(); + } + + + public static boolean isClientHovered() { + var state = emfState(); + if (state == null) return false; + var mc = Minecraft.getInstance(); + + //block entity looked at + if (state.isBlockEntity()){ + var player = Minecraft.getInstance().player; + if(player != null + && state.distanceTo(player) <= + //#if MC >= 12006 + player.blockInteractionRange() + //#else + //$$ (player.isCreative() ? 5F : 4.5F) + //#endif + + 1) { + Entity entity = mc.getCameraEntity(); + if (entity != null) { + var block = entity.pick(20.0, 0.0F, false); + if (block.getType() == HitResult.Type.BLOCK) { + return ((BlockHitResult) block).getBlockPos().equals(state.blockPos()); + } + } + } + return false; + } + + //entity looked at + return mc.crosshairPickEntity != null && mc.crosshairPickEntity.equals(state.emfEntity()); + } + + public static boolean isInLava() { + var state = emfState(); + return state != null && state.isInLava(); + } + + public static boolean isInvisible() { + var state = emfState(); + return state != null && state.isInvisible(); + } + + + public static boolean isOnShoulder() { + var state = emfState(); + return state != null && state.onShoulder(); + } + public static boolean isRidden() { + var state = emfState(); + return state != null && state.hasPassengers(); + } + + public static boolean isSitting() { + var state = emfState(); + if (state == null) return false; + var entity = state.emfEntity(); + return (entity instanceof TamableAnimal tame && tame.isInSittingPose()) || + (entity instanceof Fox fox && fox.isSitting()) || + (entity instanceof Parrot parrot && parrot.isInSittingPose()) || + (entity instanceof Cat cat && cat.isInSittingPose()) || + (entity instanceof Wolf wolf && wolf.isInSittingPose()) || + (entity instanceof Camel camel && camel.isCamelSitting()); + } + + + public static boolean isSneaking() { + var state = emfState(); + return state != null && state.isSneaking(); + } + + public static boolean isSprinting() { + var state = emfState(); + return state != null && state.isSprinting(); + } + + public static boolean isTamed() { + return emfEntity() instanceof TamableAnimal tame && tame.isTame(); + } + + public static boolean isWet() { + var state = emfState(); + return state != null && state.isWet(); + } + //endregion + + //region get_ methods + public static float getRuleIndex() { + var state = emfState(); + if (state == null) return 0; + return EMFManager.getInstance().lastModelRuleOfEntity.get(state.uuid()); + } + + public static float getDimension() { + var state = emfState(); + if (state == null || state.world() == null) { + return 0; + } else { + var optional = state.world().dimensionTypeRegistration().unwrapKey(); + if (optional.isEmpty()) return 0; + ResourceLocation id = optional.get().location(); + //#if MC>= 12111 + //$$ if (id.equals(BuiltinDimensionTypes.NETHER.identifier())) { + //$$ return -1; + //$$ } else if (id.equals(BuiltinDimensionTypes.END.identifier())) { + //#else + if (id.equals(BuiltinDimensionTypes.NETHER_EFFECTS)) { + return -1; + } else if (id.equals(BuiltinDimensionTypes.END_EFFECTS)) { + //#endif + return 1; + } else { + return 0; + } + } + } + + public static float getTickDelta() { + return + //#if MC >= 1.21 + ((MinecraftClientAccessor) Minecraft.getInstance()) + //#if MC >= 1.21.2 + .getDeltaTracker() + //#else + //$$ .getTimer() + //#endif + .getGameTimeDeltaPartialTick(true); + //#else + //$$ Minecraft.getInstance().isPaused() ? ((MinecraftClientAccessor) Minecraft.getInstance()).getPausePartialTick() : Minecraft.getInstance().getFrameTime(); + //#endif + } + + public static float getTime(EMFEntityRenderState state) { + if (state == null || state.world() == null) { + return 0 + getTickDelta(); + } else { + //limit value upper limit to preserve floating point precision + long upTimeInTicks = state.world().getGameTime(); + return constrainedFloat(upTimeInTicks, WRAP_CONST) + getTickDelta(); + } + } + + public static float getDayTime() { + var state = emfState(); + if (state == null || state.world() == null) { + return 0 + getTickDelta(); + } else { + //limit value upper limit to preserve floating point precision + return constrainedFloat(state.world() + //#if MC >= 26.1 + //$$ .getOverworldClockTime() + //#else + .getDayTime() + //#endif + , 24000) + getTickDelta(); + } + } + + public static float getDayCount() { + var state = emfState(); + if (state == null || state.world() == null) { + return 0; + } else { + //limit value upper limit to preserve floating point precision + return (float) (state.world() + //#if MC >= 26.1 + //$$ .getOverworldClockTime() + //#else + .getDayTime() + //#endif + / 24000); + } + } + + + public static float getHealth() { + var state = emfState(); + if (state == null) return 0; + return state.emfEntity() instanceof LivingEntity alive ? alive.getHealth() : 1; + } + + public static float getDeathTime() { + return emfEntity() instanceof LivingEntity alive ? (alive.deathTime > 0 ? alive.deathTime + getTickDelta() : 0) : 0; + } + + public static float getAngerTime() { + var state = emfState(); + if (state == null || !(state.emfEntity() instanceof NeutralMob)) return 0; + + float currentKnownHighest = knownHighestAngerTimeByUUID.getOrDefault(state.uuid(), 0); + //#if MC >= 12111 + //$$ int angerTime = (int) (((NeutralMob) state.emfEntity()).getPersistentAngerEndTime() - state.world().getGameTime()); + //#else + int angerTime = ((NeutralMob) state.emfEntity()).getRemainingPersistentAngerTime(); + //#endif + + //clear anger info if anger is over + if (angerTime <= 0) { + knownHighestAngerTimeByUUID.put(state.uuid(), 0); + return 0; + } + + //store this if this is the largest anger time for the entity seen so far + if (angerTime > currentKnownHighest) { + knownHighestAngerTimeByUUID.put(state.uuid(), angerTime); + } + return angerTime - getTickDelta(); + } + + public static float getAngerTimeStart() { + //this only makes sense if we are calculating it here from the largest known value of anger time + // i could also reset it when anger time hits 0 + var state = emfState(); + return state != null && state.emfEntity() instanceof NeutralMob ? knownHighestAngerTimeByUUID.getOrDefault(state.uuid(), 0) : 0; + + } + + public static float getMaxHealth() { + return emfEntity() instanceof LivingEntity alive ? alive.getMaxHealth() : 1; + } + + public static float getId() { + var state = emfState(); + return state == null || isOnShoulder() + ? 0 + : Math.abs(state.optifineId()) % WRAP_CONST; + } + + public static float getHurtTime() { + return emfEntity() instanceof LivingEntity alive ? (alive.hurtTime > 0 ? alive.hurtTime - getTickDelta() : 0) : 0; + } + + public static float getHeightAboveGround() { + var state = emfState(); + if (state == null || !(state.emfEntity() instanceof Entity)) return 0; + float y = getEntityY(); + BlockPos.MutableBlockPos pos = state.blockPos().mutable(); + + int worldBottom = + //#if MC >=12102 + state.world().getMinY(); + //#else + //$$ state.world().getMinBuildHeight(); + //#endif + + if (state.isBlockEntity()) // Don't include self + pos.move(Direction.DOWN); + + //loop down until we hit a block that can be stood on + while (!state.world().getBlockState(pos) + .entityCanStandOn(state.world(),pos, (Entity) state.emfEntity()) + && pos.getY() > worldBottom) { + pos.move(Direction.DOWN); + } + return y - pos.getY(); + } + + public static float getFluidDepthDown() { + var state = emfState(); + if (state == null + || state.world().getFluidState(state.blockPos()).isEmpty()) return 0; + + BlockPos pos = state.blockPos(); + int worldBottom = + //#if MC >=12102 + state.world().getMinY(); + //#else + //$$ state.world().getMinBuildHeight(); + //#endif + while (!state.world().getFluidState(pos).isEmpty() && pos.getY() > worldBottom) { + pos = pos.below(); + } + return state.blockPos().getY() - pos.getY(); + } + + + public static float getFluidDepthUp() { + var state = emfState(); + if (state == null + || state.world().getFluidState(state.blockPos()).isEmpty()) return 0; + + BlockPos pos = state.blockPos(); + int worldTop = + //#if MC >=12102 + state.world().getMaxY(); + //#else + //$$ state.world().getMaxBuildHeight(); + //#endif + while (!state.world().getFluidState(pos).isEmpty() && pos.getY() < worldTop) { + pos = pos.above(); + } + return pos.getY() - state.blockPos().getY(); + } + + public static float getFluidDepth() { + var state = emfState(); + if (state == null + || state.world().getFluidState(state.blockPos()).isEmpty()) return 0; + return getFluidDepthDown() + getFluidDepthUp() - 1; + } + + public static float getSwingProgress() { + if (isInGui()) return 0; + return emfEntity() instanceof LivingEntity alive ? alive.getAttackAnim(getTickDelta()) : 0; + } + + + public static float getAge() { + var state = emfState(); + if (state == null) { + return 0 + getTickDelta(); + }else { + return constrainedFloat(state.age(), WRAP_CONST) + getTickDelta(); + } + } + + public static float getFrameTime() { + if (Minecraft.getInstance().isPaused()) return 0; + //#if MC > 12002 + if (Minecraft.getInstance().level != null && Minecraft.getInstance().level.tickRateManager().isFrozen()) return 0; + //#endif + + //#if MC >= 12100 + return ((MinecraftClientAccessor)Minecraft.getInstance()) + //#if MC >= 12102 + .getDeltaTracker() + //#else + //$$ .getTimer() + //#endif + .getGameTimeDeltaTicks() / 20; + //#else + //$$ return Minecraft.getInstance().getDeltaFrameTime() / 20; + //#endif + } + //endregion + + + + + //region state passthrough + public static boolean isInGui() { + return EMFState.isInGui; + } + public static boolean isInHand() { + return EMFState.isInHand; + } + public static boolean isInItemFrame() { + return EMFState.isInItemFrame; + } + public static boolean isOnHead() { + return EMFState.isOnHead; + } + + private static @Nullable EMFEntityRenderState emfState() { return EMFState.state(); } + private static @Nullable EMFEntity emfEntity() { + var state = emfState(); + return state == null ? null : state.emfEntity(); + } + //endregion +} diff --git a/src/main/java/traben/entity_model_features/models/animation/math/asm/ASMAnimationHandler.java b/src/main/java/traben/entity_model_features/models/animation/math/asm/ASMAnimationHandler.java index 416bb91d..a456fef0 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/asm/ASMAnimationHandler.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/asm/ASMAnimationHandler.java @@ -5,11 +5,13 @@ import org.jetbrains.annotations.Nullable; import traben.entity_model_features.EMF; import traben.entity_model_features.models.animation.AnimSetupContext; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.EMFAnimationHandler; +import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.animation.math.expression_tree.MathValue; import traben.entity_model_features.models.animation.math.variables.VariableRegistry; import traben.entity_model_features.models.animation.math.variables.factories.GlobalVariableFactory; +import traben.entity_model_features.models.animation.state.EMFState; +import traben.entity_model_features.utils.EMFLODHandler; import traben.entity_model_features.utils.EMFUtils; import traben.entity_texture_features.utils.ETFLruCache; @@ -45,9 +47,9 @@ public ASMAnimationHandler(ASMParser.ASMExecutor compiledAnimationExecutor, ASMV @Override protected void animateInner(ModelPart[] pausedParts) throws Throwable { //noinspection deprecation - var state = EMFAnimationEntityContext.getEmfState(); + var state = EMFState.state(); //noinspection deprecation - if (lod && EMFAnimationEntityContext.isLODSkippingThisFrame(modelName)) { + if (lod && EMFLODHandler.isLODSkippingThisFrame(modelName)) { if (state != null) { AnimVars vars = lastResultsPerEntity.get(state.uuid()); if (vars != null) { @@ -106,7 +108,7 @@ public boolean finishAndValidate() { consumer = (array, doVar) -> { if (doVar) //noinspection deprecation - EMFAnimationEntityContext.setEntityVariable(key, array[index]); + EMFMath.setEntityVariable(key, array[index]); }; } } else if (line.applier != null) { @@ -154,7 +156,7 @@ public boolean finishAndValidate() { consumer = (array, doVar) -> { if (doVar) //noinspection deprecation - EMFAnimationEntityContext.setEntityVariable(key, array[index] ? TRUE : FALSE); + EMFMath.setEntityVariable(key, array[index] ? TRUE : FALSE); }; } } else if (line.applier != null) { diff --git a/src/main/java/traben/entity_model_features/models/animation/math/asm/ASMVariableHandler.java b/src/main/java/traben/entity_model_features/models/animation/math/asm/ASMVariableHandler.java index d8342630..8063cf9d 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/asm/ASMVariableHandler.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/asm/ASMVariableHandler.java @@ -53,13 +53,13 @@ public void scope(boolean isBoolean) { public void verifyEndOfParse() throws EMFMathException { if (!booleanScopeStack.isEmpty()) - throw new EMFMathException("ASMVariableHandler verifyEndOfParse issue: type stack is not empty"); + throw new EMFMathException("ASMVariableHandler verifyEndOfParse issue: type stack is not empty, probably an EMF issue."); if (localVarIndex != 1) - throw new EMFMathException("ASMVariableHandler verifyEndOfParse issue: local variable index is not reset"); + throw new EMFMathException("ASMVariableHandler verifyEndOfParse issue: local variable index is not reset, probably an EMF issue."); if (floatVarList.stream().anyMatch(boolVarList::contains)) - throw new EMFMathException("ASMVariableHandler verifyEndOfParse issue: has variable names that are both in float and bool lists"); + throw new EMFMathException("ASMVariableHandler verifyEndOfParse issue: a variable was used both as a number and a boolean somewhere, this is not allowed."); } public boolean isScopeBool() { diff --git a/src/main/java/traben/entity_model_features/models/animation/math/expression_tree/OldEMFAnimationHandler.java b/src/main/java/traben/entity_model_features/models/animation/math/expression_tree/OldEMFAnimationHandler.java index 5ab9a8e5..846def49 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/expression_tree/OldEMFAnimationHandler.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/expression_tree/OldEMFAnimationHandler.java @@ -2,9 +2,11 @@ import net.minecraft.client.model.geom.ModelPart; import org.jetbrains.annotations.Nullable; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.EMFAnimationHandler; +import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.animation.math.variables.factories.GlobalVariableFactory; +import traben.entity_model_features.models.animation.state.EMFState; +import traben.entity_model_features.utils.EMFLODHandler; import traben.entity_model_features.utils.EMFUtils; import traben.entity_texture_features.utils.ETFLruCache; @@ -41,7 +43,7 @@ public MathValue.ResultSupplier getLastResultGetter(String variableKey) { private Map prevResultsOfEntity() { //noinspection deprecation - var state = EMFAnimationEntityContext.getEmfState(); + var state = EMFState.state(); if (state == null) return null; return lastResultsPerEntity.computeIfAbsent(state.uuid(), u -> new ConcurrentHashMap<>()); @@ -78,10 +80,10 @@ public boolean finishAndValidate() { } else { if (line.isBoolean) { //noinspection deprecation - consumer = value -> EMFAnimationEntityContext.setEntityVariable(key, MathValue.isBoolean(value) ? value : FALSE); + consumer = value -> EMFMath.setEntityVariable(key, MathValue.isBoolean(value) ? value : FALSE); } else { //noinspection deprecation - consumer = value -> EMFAnimationEntityContext.setEntityVariable(key, MathValue.isBoolean(value) ? 0 : value); + consumer = value -> EMFMath.setEntityVariable(key, MathValue.isBoolean(value) ? 0 : value); } } } else if (line.applier != null) { @@ -98,7 +100,7 @@ public boolean finishAndValidate() { protected void animateInner(ModelPart[] pausedParts){ Map prevVals = prevResultsOfEntity(); //noinspection deprecation - boolean skip = prevVals != null && EMFAnimationEntityContext.isLODSkippingThisFrame(modelName); + boolean skip = prevVals != null && EMFLODHandler.isLODSkippingThisFrame(modelName); for (var line : lines()) { if (pausedParts != null) { diff --git a/src/main/java/traben/entity_model_features/models/animation/math/methods/emf/NBTMethod.java b/src/main/java/traben/entity_model_features/models/animation/math/methods/emf/NBTMethod.java index d9d47800..f261bede 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/methods/emf/NBTMethod.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/methods/emf/NBTMethod.java @@ -2,12 +2,12 @@ import org.objectweb.asm.MethodVisitor; import traben.entity_model_features.models.animation.AnimSetupContext; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.math.*; import traben.entity_model_features.models.animation.math.asm.ASMHelper; import traben.entity_model_features.models.animation.math.asm.ASMVariableHandler; import traben.entity_model_features.models.animation.math.expression_tree.MathMethod; import traben.entity_model_features.models.animation.math.expression_tree.MathValue; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.EMFUtils; import traben.entity_texture_features.features.property_reading.properties.optifine_properties.NBTProperty; @@ -36,8 +36,8 @@ public NBTMethod(final List args, final boolean isNegative, AnimSetupCon throw new EMFMathException("nbt() animation function did not parse: nbt("+nbtKey+" "+nbtQuery+"), please check your syntax."); } setSupplierAndOptimize(() -> { - if (EMFAnimationEntityContext.getEMFEntity() == null) return MathValue.FALSE; - return MathValue.fromBoolean(propertyTester.testEntity(EMFAnimationEntityContext.getEmfState(), false)); + if (EMFState.state() == null) return MathValue.FALSE; + return MathValue.fromBoolean(propertyTester.testEntity(EMFState.state(), false)); } ); } @@ -67,9 +67,9 @@ public static boolean nbtMethodStatic(String nbtKey, String nbtQuery) throws EMF return v; }); - if (propertyTester == NULL || EMFAnimationEntityContext.getEMFEntity() == null) return false; + if (propertyTester == NULL || EMFState.state() == null) return false; - var v = propertyTester.testEntity(EMFAnimationEntityContext.getEmfState(), false); + var v = propertyTester.testEntity(EMFState.state(), false); return v; } diff --git a/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java b/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java index f28bc935..6f0dba88 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java @@ -2,8 +2,8 @@ import net.minecraft.client.model.geom.ModelPart; import org.jetbrains.annotations.Nullable; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.models.parts.EMFModelPart; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.math.expression_tree.MathValue; public enum EMFModelOrRenderVariable { @@ -163,12 +163,12 @@ public boolean isBoolean() { RENDER_shadow_size() { @Override public void setValue(EMFModelPart ignored, float value) { - EMFAnimationEntityContext.setShadowSize(value); + if (EMFState.state() != null) EMFState.state().setShadowSize(value); } @Override public float getValue(ModelPart ignored) { - return EMFAnimationEntityContext.getShadowSize(); + return EMFState.state() != null ? EMFState.state().shadowSize() : 0; } @Override @@ -179,12 +179,12 @@ public boolean isRenderVariable() { RENDER_SHADOW_OPACITY() { @Override public void setValue(EMFModelPart ignored, float value) { - EMFAnimationEntityContext.setShadowOpacity(value); + if (EMFState.state() != null) EMFState.state().setShadowOpacity(value); } @Override public float getValue(ModelPart ignored) { - return EMFAnimationEntityContext.getShadowOpacity(); + return EMFState.state() != null ? EMFState.state().shadowOpacity() : 0; } @Override @@ -195,12 +195,12 @@ public boolean isRenderVariable() { RENDER_SHADOW_X() { @Override public void setValue(EMFModelPart ignored, float value) { - EMFAnimationEntityContext.setShadowX(value); + if (EMFState.state() != null) EMFState.state().setShadowX(value); } @Override public float getValue(ModelPart ignored) { - return EMFAnimationEntityContext.getShadowX(); + return EMFState.state() != null ? EMFState.state().shadowX() : 0; } @Override @@ -211,12 +211,12 @@ public boolean isRenderVariable() { RENDER_SHADOW_Z() { @Override public void setValue(EMFModelPart ignored, float value) { - EMFAnimationEntityContext.setShadowZ(value); + if (EMFState.state() != null) EMFState.state().setShadowZ(value); } @Override public float getValue(ModelPart ignored) { - return EMFAnimationEntityContext.getShadowZ(); + return EMFState.state() != null ? EMFState.state().shadowZ() : 0; } @Override @@ -227,12 +227,12 @@ public boolean isRenderVariable() { RENDER_LEASH_X() { @Override public void setValue(EMFModelPart ignored, float value) { - EMFAnimationEntityContext.setLeashX(value); + if (EMFState.state() != null) EMFState.state().setLeashX(value); } @Override public float getValue(ModelPart ignored) { - return EMFAnimationEntityContext.getLeashX(); + return EMFState.state() != null ? EMFState.state().leashX() : 0; } @Override @@ -243,12 +243,12 @@ public boolean isRenderVariable() { RENDER_LEASH_Y() { @Override public void setValue(EMFModelPart ignored, float value) { - EMFAnimationEntityContext.setLeashY(value); + if (EMFState.state() != null) EMFState.state().setLeashY(value); } @Override public float getValue(ModelPart ignored) { - return EMFAnimationEntityContext.getLeashY(); + return EMFState.state() != null ? EMFState.state().leashY() : 0; } @Override @@ -259,12 +259,12 @@ public boolean isRenderVariable() { RENDER_LEASH_Z() { @Override public void setValue(EMFModelPart ignored, float value) { - EMFAnimationEntityContext.setLeashZ(value); + if (EMFState.state() != null) EMFState.state().setLeashZ(value); } @Override public float getValue(ModelPart ignored) { - return EMFAnimationEntityContext.getLeashZ(); + return EMFState.state() != null ? EMFState.state().leashZ() : 0; } @Override diff --git a/src/main/java/traben/entity_model_features/models/animation/math/variables/VariableRegistry.java b/src/main/java/traben/entity_model_features/models/animation/math/variables/VariableRegistry.java index 631007f4..30fb3d42 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/variables/VariableRegistry.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/variables/VariableRegistry.java @@ -5,13 +5,14 @@ import net.minecraft.util.Mth; import traben.entity_model_features.EMF; import traben.entity_model_features.models.animation.AnimSetupContext; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.animation.math.expression_tree.MathComponent; import traben.entity_model_features.models.animation.math.expression_tree.MathConstant; import traben.entity_model_features.models.animation.math.expression_tree.MathValue; import traben.entity_model_features.models.animation.math.expression_tree.MathVariable; import traben.entity_model_features.models.animation.math.variables.factories.*; import traben.entity_model_features.EMFManager; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.EMFUtils; import java.util.ArrayList; @@ -100,107 +101,110 @@ private VariableRegistry() { //simple floats - registerSimpleFloatVariable("limb_swing", EMFAnimationEntityContext::getLimbAngle); - registerSimpleFloatVariable("frame_time", EMFAnimationEntityContext::getFrameTime); - registerSimpleFloatVariable("limb_speed", EMFAnimationEntityContext::getLimbDistance); - registerSimpleFloatVariable("age", EMFAnimationEntityContext::getAge); - registerSimpleFloatVariable("head_pitch", EMFAnimationEntityContext::getHeadPitch); - registerSimpleFloatVariable("head_yaw", EMFAnimationEntityContext::getHeadYaw); - registerSimpleFloatVariable("swing_progress", EMFAnimationEntityContext::getSwingProgress); - registerSimpleFloatVariable("hurt_time", EMFAnimationEntityContext::getHurtTime); - registerSimpleFloatVariable("dimension", EMFAnimationEntityContext::getDimension); - registerSimpleFloatVariable("time", EMFAnimationEntityContext::getTime); - registerSimpleFloatVariable("player_pos_x", emfTranslationKey("player_pos"), EMFAnimationEntityContext::getPlayerX); - registerSimpleFloatVariable("player_pos_y", emfTranslationKey("player_pos"), EMFAnimationEntityContext::getPlayerY); - registerSimpleFloatVariable("player_pos_z", emfTranslationKey("player_pos"), EMFAnimationEntityContext::getPlayerZ); - registerSimpleFloatVariable("pos_x", emfTranslationKey("pos"), EMFAnimationEntityContext::getEntityX); - registerSimpleFloatVariable("pos_y", emfTranslationKey("pos"), EMFAnimationEntityContext::getEntityY); - registerSimpleFloatVariable("pos_z", emfTranslationKey("pos"), EMFAnimationEntityContext::getEntityZ); - registerSimpleFloatVariable("player_rot_x", emfTranslationKey("player_rot"), EMFAnimationEntityContext::getPlayerRX); - registerSimpleFloatVariable("player_rot_y", emfTranslationKey("player_rot"), EMFAnimationEntityContext::getPlayerRY); - registerSimpleFloatVariable("rot_x", emfTranslationKey("rot"), EMFAnimationEntityContext::getEntityRX); - registerSimpleFloatVariable("rot_y", emfTranslationKey("rot"), EMFAnimationEntityContext::getEntityRY); - registerSimpleFloatVariable("health", EMFAnimationEntityContext::getHealth); - registerSimpleFloatVariable("death_time", EMFAnimationEntityContext::getDeathTime); - registerSimpleFloatVariable("anger_time", EMFAnimationEntityContext::getAngerTime); - registerSimpleFloatVariable("max_health", EMFAnimationEntityContext::getMaxHealth); - registerSimpleFloatVariable("id", EMFAnimationEntityContext::getId); - registerSimpleFloatVariable("day_time", EMFAnimationEntityContext::getDayTime); - registerSimpleFloatVariable("day_count", EMFAnimationEntityContext::getDayCount); - registerSimpleFloatVariable("rule_index", EMFAnimationEntityContext::getRuleIndex); - registerSimpleFloatVariable("anger_time_start", EMFAnimationEntityContext::getAngerTimeStart); - registerSimpleFloatVariable("move_forward", EMFAnimationEntityContext::getMoveForward); - registerSimpleFloatVariable("move_strafing", EMFAnimationEntityContext::getMoveStrafe); - registerSimpleFloatVariable("height_above_ground", EMFAnimationEntityContext::getHeightAboveGround); - registerSimpleFloatVariable("fluid_depth", EMFAnimationEntityContext::getFluidDepth); - registerSimpleFloatVariable("fluid_depth_down", EMFAnimationEntityContext::getFluidDepthDown); - registerSimpleFloatVariable("fluid_depth_up", EMFAnimationEntityContext::getFluidDepthUp); + registerSimpleFloatVariable("limb_swing", EMFMath::getLimbAngle); + registerSimpleFloatVariable("frame_time", EMFMath::getFrameTime); + registerSimpleFloatVariable("limb_speed", EMFMath::getLimbDistance); + registerSimpleFloatVariable("age", EMFMath::getAge); + registerSimpleFloatVariable("head_pitch", EMFMath::getHeadPitch); + registerSimpleFloatVariable("head_yaw", EMFMath::getHeadYaw); + registerSimpleFloatVariable("swing_progress", EMFMath::getSwingProgress); + registerSimpleFloatVariable("hurt_time", EMFMath::getHurtTime); + registerSimpleFloatVariable("dimension", EMFMath::getDimension); + registerSimpleFloatVariable("time", ()-> EMFMath.getTime(EMFState.state())); + registerSimpleFloatVariable("player_pos_x", emfTranslationKey("player_pos"), EMFMath::getPlayerX); + registerSimpleFloatVariable("player_pos_y", emfTranslationKey("player_pos"), EMFMath::getPlayerY); + registerSimpleFloatVariable("player_pos_z", emfTranslationKey("player_pos"), EMFMath::getPlayerZ); + registerSimpleFloatVariable("pos_x", emfTranslationKey("pos"), EMFMath::getEntityX); + registerSimpleFloatVariable("pos_y", emfTranslationKey("pos"), EMFMath::getEntityY); + registerSimpleFloatVariable("pos_z", emfTranslationKey("pos"), EMFMath::getEntityZ); + registerSimpleFloatVariable("player_rot_x", emfTranslationKey("player_rot"), EMFMath::getPlayerRX); + registerSimpleFloatVariable("player_rot_y", emfTranslationKey("player_rot"), EMFMath::getPlayerRY); + registerSimpleFloatVariable("rot_x", emfTranslationKey("rot"), EMFMath::getEntityRX); + registerSimpleFloatVariable("rot_y", emfTranslationKey("rot"), EMFMath::getEntityRY); + registerSimpleFloatVariable("health", EMFMath::getHealth); + registerSimpleFloatVariable("death_time", EMFMath::getDeathTime); + registerSimpleFloatVariable("anger_time", EMFMath::getAngerTime); + registerSimpleFloatVariable("max_health", EMFMath::getMaxHealth); + registerSimpleFloatVariable("id", EMFMath::getId); + registerSimpleFloatVariable("day_time", EMFMath::getDayTime); + registerSimpleFloatVariable("day_count", EMFMath::getDayCount); + registerSimpleFloatVariable("rule_index", EMFMath::getRuleIndex); + registerSimpleFloatVariable("anger_time_start", EMFMath::getAngerTimeStart); + registerSimpleFloatVariable("move_forward", EMFMath::getMoveForward); + registerSimpleFloatVariable("move_strafing", EMFMath::getMoveStrafe); + registerSimpleFloatVariable("height_above_ground", EMFMath::getHeightAboveGround); + registerSimpleFloatVariable("fluid_depth", EMFMath::getFluidDepth); + registerSimpleFloatVariable("fluid_depth_down", EMFMath::getFluidDepthDown); + registerSimpleFloatVariable("fluid_depth_up", EMFMath::getFluidDepthUp); registerSimpleFloatVariable("nan", () -> EMFManager.getInstance().isAnimationValidationPhase ? 0 : Float.NaN); registerSimpleFloatVariable("distance", () -> { - if (EMFAnimationEntityContext.getEMFEntity() == null) return 0; - return EMFAnimationEntityContext.getEMFEntity().etf$distanceTo(Minecraft.getInstance().player); + if (EMFState.emfEntity() == null) return 0; + return EMFState.emfEntity().etf$distanceTo(Minecraft.getInstance().player); }); - registerSimpleFloatVariable("frame_counter", EMFAnimationEntityContext::getFrameCounter); + registerSimpleFloatVariable("frame_counter", EMFState::getFrameCounter); //simple booleans - registerSimpleBoolVariable("is_hovered", EMFAnimationEntityContext::isClientHovered); + registerSimpleBoolVariable("is_hovered", EMFMath::isClientHovered); registerSimpleBoolVariable("is_paused", () -> Minecraft.getInstance().isPaused()); - registerSimpleBoolVariable("is_first_person_hand", () -> EMFAnimationEntityContext.isFirstPersonHand); + registerSimpleBoolVariable("is_first_person_hand", () -> { + var state = EMFState.state(); + return state != null && state.isFirstPersonHand(); + }); registerSimpleBoolVariable("is_right_handed", () -> { - if (EMFAnimationEntityContext.getEMFEntity() == null) return false; - return EMFAnimationEntityContext.getEMFEntity() instanceof LivingEntity entity && entity.getMainArm() == HumanoidArm.RIGHT; + if (EMFState.emfEntity() == null) return false; + return EMFState.emfEntity() instanceof LivingEntity entity && entity.getMainArm() == HumanoidArm.RIGHT; }); - registerSimpleBoolVariable("is_swinging_right_arm", () -> EMFAnimationEntityContext.isSwingingArm(true)); - registerSimpleBoolVariable("is_swinging_left_arm", () -> EMFAnimationEntityContext.isSwingingArm(false)); - registerSimpleBoolVariable("is_holding_item_right", () -> EMFAnimationEntityContext.isHoldingItem(true)); - registerSimpleBoolVariable("is_holding_item_left", () -> EMFAnimationEntityContext.isHoldingItem(false)); - registerSimpleBoolVariable("is_using_item", EMFAnimationEntityContext::isUsingItem); + registerSimpleBoolVariable("is_swinging_right_arm", () -> EMFMath.isSwingingArm(true)); + registerSimpleBoolVariable("is_swinging_left_arm", () -> EMFMath.isSwingingArm(false)); + registerSimpleBoolVariable("is_holding_item_right", () -> EMFMath.isHoldingItem(true)); + registerSimpleBoolVariable("is_holding_item_left", () -> EMFMath.isHoldingItem(false)); + registerSimpleBoolVariable("is_using_item", EMFMath::isUsingItem); registerSimpleBoolVariable("is_swimming", () -> { - if (EMFAnimationEntityContext.getEMFEntity() == null) return false; - return EMFAnimationEntityContext.getEMFEntity() instanceof Entity entity && entity.isSwimming(); + if (EMFState.emfEntity() == null) return false; + return EMFState.emfEntity() instanceof Entity entity && entity.isSwimming(); }); registerSimpleBoolVariable("is_gliding", () -> { - if (EMFAnimationEntityContext.getEMFEntity() == null) return false; - return EMFAnimationEntityContext.getEMFEntity() instanceof LivingEntity entity && entity.isFallFlying(); + if (EMFState.emfEntity() == null) return false; + return EMFState.emfEntity() instanceof LivingEntity entity && entity.isFallFlying(); }); registerSimpleBoolVariable("is_blocking", () -> { - if (EMFAnimationEntityContext.getEMFEntity() == null) return false; - return EMFAnimationEntityContext.getEMFEntity() instanceof LivingEntity livingEntity && livingEntity.isBlocking(); + if (EMFState.emfEntity() == null) return false; + return EMFState.emfEntity() instanceof LivingEntity livingEntity && livingEntity.isBlocking(); }); registerSimpleBoolVariable("is_crawling", () -> { - if (EMFAnimationEntityContext.getEMFEntity() == null) return false; - return EMFAnimationEntityContext.getEMFEntity() instanceof Entity entity && entity.isVisuallyCrawling(); + if (EMFState.emfEntity() == null) return false; + return EMFState.emfEntity() instanceof Entity entity && entity.isVisuallyCrawling(); }); - registerSimpleBoolVariable("is_climbing", EMFAnimationEntityContext::isClimbing); - registerSimpleBoolVariable("is_child", EMFAnimationEntityContext::isChild); - registerSimpleBoolVariable("is_in_water", EMFAnimationEntityContext::isInWater); - registerSimpleBoolVariable("is_riding", EMFAnimationEntityContext::isRiding); - registerSimpleBoolVariable("is_on_ground", EMFAnimationEntityContext::isOnGround); - registerSimpleBoolVariable("is_burning", EMFAnimationEntityContext::isBurning); - registerSimpleBoolVariable("is_alive", EMFAnimationEntityContext::isAlive); - registerSimpleBoolVariable("is_glowing", EMFAnimationEntityContext::isGlowing); - registerSimpleBoolVariable("is_aggressive", EMFAnimationEntityContext::isAggressive); - registerSimpleBoolVariable("is_hurt", EMFAnimationEntityContext::isHurt); - registerSimpleBoolVariable("is_in_hand", EMFAnimationEntityContext::isInHand); - registerSimpleBoolVariable("is_in_item_frame", EMFAnimationEntityContext::isInItemFrame); - registerSimpleBoolVariable("is_in_ground", EMFAnimationEntityContext::isInGround); - registerSimpleBoolVariable("is_in_gui", EMFAnimationEntityContext::isInGui); - registerSimpleBoolVariable("is_in_lava", EMFAnimationEntityContext::isInLava); - registerSimpleBoolVariable("is_invisible", EMFAnimationEntityContext::isInvisible); - registerSimpleBoolVariable("is_on_head", EMFAnimationEntityContext::isOnHead); - registerSimpleBoolVariable("is_on_shoulder", EMFAnimationEntityContext::isOnShoulder); - registerSimpleBoolVariable("is_ridden", EMFAnimationEntityContext::isRidden); - registerSimpleBoolVariable("is_sitting", EMFAnimationEntityContext::isSitting); - registerSimpleBoolVariable("is_sneaking", EMFAnimationEntityContext::isSneaking); - registerSimpleBoolVariable("is_sprinting", EMFAnimationEntityContext::isSprinting); - registerSimpleBoolVariable("is_tamed", EMFAnimationEntityContext::isTamed); - registerSimpleBoolVariable("is_wet", EMFAnimationEntityContext::isWet); - registerSimpleBoolVariable("is_jumping", EMFAnimationEntityContext::isJumping); + registerSimpleBoolVariable("is_climbing", EMFMath::isClimbing); + registerSimpleBoolVariable("is_child", EMFMath::isChild); + registerSimpleBoolVariable("is_in_water", EMFMath::isInWater); + registerSimpleBoolVariable("is_riding", EMFMath::isRiding); + registerSimpleBoolVariable("is_on_ground", EMFMath::isOnGround); + registerSimpleBoolVariable("is_burning", EMFMath::isBurning); + registerSimpleBoolVariable("is_alive", EMFMath::isAlive); + registerSimpleBoolVariable("is_glowing", EMFMath::isGlowing); + registerSimpleBoolVariable("is_aggressive", EMFMath::isAggressive); + registerSimpleBoolVariable("is_hurt", EMFMath::isHurt); + registerSimpleBoolVariable("is_in_hand", EMFMath::isInHand); + registerSimpleBoolVariable("is_in_item_frame", EMFMath::isInItemFrame); + registerSimpleBoolVariable("is_in_ground", EMFMath::isInGround); + registerSimpleBoolVariable("is_in_gui", EMFMath::isInGui); + registerSimpleBoolVariable("is_in_lava", EMFMath::isInLava); + registerSimpleBoolVariable("is_invisible", EMFMath::isInvisible); + registerSimpleBoolVariable("is_on_head", EMFMath::isOnHead); + registerSimpleBoolVariable("is_on_shoulder", EMFMath::isOnShoulder); + registerSimpleBoolVariable("is_ridden", EMFMath::isRidden); + registerSimpleBoolVariable("is_sitting", EMFMath::isSitting); + registerSimpleBoolVariable("is_sneaking", EMFMath::isSneaking); + registerSimpleBoolVariable("is_sprinting", EMFMath::isSprinting); + registerSimpleBoolVariable("is_tamed", EMFMath::isTamed); + registerSimpleBoolVariable("is_wet", EMFMath::isWet); + registerSimpleBoolVariable("is_jumping", EMFMath::isJumping); registerSimpleBoolVariable("is_player_first_person", ()-> Minecraft.getInstance().options.getCameraType() == CameraType.FIRST_PERSON); registerSimpleBoolVariable("is_player_third_person", ()-> Minecraft.getInstance().options.getCameraType() == CameraType.THIRD_PERSON_BACK); registerSimpleBoolVariable("is_player_third_person_reversed", ()-> Minecraft.getInstance().options.getCameraType() == CameraType.THIRD_PERSON_FRONT); diff --git a/src/main/java/traben/entity_model_features/models/animation/math/variables/factories/ModelVariableFactory.java b/src/main/java/traben/entity_model_features/models/animation/math/variables/factories/ModelVariableFactory.java index 4e1076b9..9bb4fe07 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/variables/factories/ModelVariableFactory.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/variables/factories/ModelVariableFactory.java @@ -2,7 +2,7 @@ import org.jetbrains.annotations.Nullable; import traben.entity_model_features.models.animation.AnimSetupContext; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.animation.math.expression_tree.MathValue; import java.util.function.BooleanSupplier; @@ -13,9 +13,9 @@ public class ModelVariableFactory extends UniqueVariableFactory { @Override public MathValue.ResultSupplier getSupplierOrNull(final String variableKey, AnimSetupContext context) { if (variableKey.startsWith("varb")) { - return () -> EMFAnimationEntityContext.getEntityVariable(variableKey, FALSE); + return () -> EMFMath.getEntityVariable(variableKey, FALSE); } else { - return () -> EMFAnimationEntityContext.getEntityVariable(variableKey, 0); + return () -> EMFMath.getEntityVariable(variableKey, 0); } } diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFBipedPose.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFBipedPose.java index 7833e3f9..8bf3a227 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFBipedPose.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFBipedPose.java @@ -13,6 +13,8 @@ public class EMFBipedPose { private final PosePart rightLeg; public final PosePart root; + public boolean applyToSubmit = false; + public EMFBipedPose(HumanoidModel model) { this.head = new PosePart(model.head); this.body = new PosePart(model.body); diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java index d08f4d00..4ab7885e 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java @@ -1,17 +1,33 @@ package traben.entity_model_features.models.animation.state; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.Arrow; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; +import traben.entity_model_features.EMF; +import traben.entity_model_features.EMFManager; +import traben.entity_model_features.models.IEMFModel; import traben.entity_model_features.models.animation.EMFAttachments; +import traben.entity_model_features.models.animation.math.EMFMath; +import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.utils.EMFEntity; +import traben.entity_model_features.utils.EMFLODHandler; import traben.entity_texture_features.features.state.ETFEntityRenderState; +import traben.entity_texture_features.features.state.ETFSubmitData; import traben.entity_texture_features.features.state.HoldsETFRenderState; import java.util.Map; +import java.util.Set; import java.util.function.Function; +import traben.entity_texture_features.utils.ETFEntity; + public interface EMFEntityRenderState extends ETFEntityRenderState { /** @@ -20,6 +36,31 @@ public interface EMFEntityRenderState extends ETFEntityRenderState { @Deprecated EMFEntity emfEntity(); + boolean isManualPlayerState(); + void setManualPlayerState(boolean manualPlayerState); + static @Nullable EMFEntityRenderState manualPlayerState() { + if (Minecraft.getInstance().player == null) return null; + + //#if MC >= 1.21.2 + // Attempt to capture the full render state + EMFEntityRenderState state = null; + try { + EntityRenderer renderer = + (EntityRenderer) + Minecraft.getInstance().getEntityRenderDispatcher().getRenderer(Minecraft.getInstance().player); + var vanilla = renderer.createRenderState(); + renderer.extractRenderState(Minecraft.getInstance().player, vanilla, EMFMath.getTickDelta()); + state = EMFEntityRenderState.from(vanilla); + } catch (Exception ignored) {} + if (state == null) state = (EMFEntityRenderState) ETFEntityRenderState.forEntity((ETFEntity) Minecraft.getInstance().player); + //#else + //$$ var state = (EMFEntityRenderState) ETFEntityRenderState.forEntity((ETFEntity) Minecraft.getInstance().player); + //#endif + + state.setManualPlayerState(true); + return state; + } + double prevX(); double x(); double prevY(); @@ -65,6 +106,195 @@ public interface EMFEntityRenderState extends ETFEntityRenderState { /** Returns the biped pose if it was animated. */ @Nullable EMFBipedPose getBipedPose(); + + boolean isFirstPersonHand(); + void setIsFirstPersonHand(boolean isFirst); + + float shadowSize(); + void setShadowSize(float shadowSize); + + float shadowOpacity(); + void setShadowOpacity(float shadowOpacity); + + float leashX(); + void setLeashX(float leashX); + + float leashY(); + void setLeashY(float leashY); + + float leashZ(); + void setLeashZ(float leashZ); + + float shadowX(); + void setShadowX(float shadowX); + + float shadowZ(); + void setShadowZ(float shadowZ); + + float limbAngle(); + void setLimbAngle(float limbAngle); + + float limbDistance(); + void setLimbDistance(float limbDistance); + + float headYaw(); + void setHeadYaw(float headYaw); + + float headPitch(); + void setHeadPitch(float headPitch); + + boolean onShoulder(); + void setOnShoulder(boolean onShoulder); + + + + + boolean skipModelVariate(); + void setSkipModelVariate(boolean value); + + //#if MC >= 1.21.9 + @Override + default void preSubmitActivate(ETFSubmitData submitData, + //#if MC >= 26.2 + //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit vanillaSubmit + //#else + net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit vanillaSubmit + //#endif + ) { + ETFEntityRenderState.super.preSubmitActivate(submitData, vanillaSubmit); + + if (submitData == null) { + setSkipModelVariate(false); + } else { + Integer variant = (Integer) submitData.data.get("modelVariant"); + if (variant != null && vanillaSubmit.model().root() instanceof EMFModelPartRoot root) { + root.setVariantStateTo(variant); + setSkipModelVariate(true); + } else { + setSkipModelVariate(false); + } + } + + setLayerFactory(vanillaSubmit.model().renderType); + + if (vanillaSubmit.state() instanceof net.minecraft.client.renderer.entity.state.ItemFrameRenderState) { + EMFState.isInItemFrame = true; + } + + if (submitData != null) { + setOnShoulder(submitData.data.get("onShoulder") == Boolean.TRUE); + + if (vanillaSubmit.model() instanceof IEMFModel emfModel && emfModel.emf$isEMFModel()) { + if (submitData.data.get("isMainModelPhase") == Boolean.TRUE) { + emfModel.emf$getEMFRootModel().isMainModel = true; + EMFState.isLayerPhase = false; + } + if (submitData.data.get("isLayerModelPhase") == Boolean.TRUE) { + EMFState.isLayerPhase = true; + } + } + } + + + } + //#endif + + @Override + default void activate(boolean inMount) { + ETFEntityRenderState.super.activate(inMount); + + if (inMount) { + EMFManager.getInstance().entityRenderCount++; + + if (EMFState.isInShoulderMethod) setOnShoulder(true); + + //#if MC >= 12102 + if (vanillaState() instanceof net.minecraft.client.renderer.entity.state.LivingEntityRenderState livingEntityRenderState) { + if (EMFState.isInGui) { + // entity isn't actually walking in the gui, zero these out so animations don't jitter + setLimbAngle(0); + setLimbDistance(0); + } else { + setLimbAngle(livingEntityRenderState.walkAnimationPos); + setLimbDistance(livingEntityRenderState.walkAnimationSpeed); + } + setHeadYaw(livingEntityRenderState.yRot); + if (headYaw() >= 180 || headYaw() < -180) { + setHeadYaw(Mth.wrapDegrees(headYaw())); + } + setHeadPitch(livingEntityRenderState.xRot); + } else { //block entity + setLimbAngle(Float.NaN); + setLimbDistance(Float.NaN); + setHeadYaw(Float.NaN); + setHeadPitch(Float.NaN); + } + //#else + //$$ setLimbAngle(Float.NaN); + //$$ setLimbDistance(Float.NaN); + //$$ setHeadYaw(Float.NaN); + //$$ setHeadPitch(Float.NaN); + //#endif + + if (entity() instanceof Arrow) { + setLayerFactory( + //#if MC>= 12111 + //$$ net.minecraft.client.renderer.rendertype.RenderTypes + //#else + RenderType + //#endif + ::entityCutout); + } else if (isBlockEntity()) { + setLayerFactory( + //#if MC>= 12111 + //$$ net.minecraft.client.renderer.rendertype.RenderTypes + //#else + RenderType + //#endif + ::entitySolid); + } + + setOnShoulder(false); + + //perform variant checking for this entity types models + //this is the only way to keep it generic and also before the entity is rendered and affect al its models + if (!skipModelVariate()) { + Set roots = EMFManager.getInstance().rootPartsPerEntityTypeForVariation.get(typeString()); + if (roots != null) { + if (EMFState.isEntityForcedToVanillaModel(this)) { + roots.forEach(root -> root.setVariantStateTo(0)); + } else { + roots.forEach(root -> root.doVariantCheck(this)); + } + + if (emfEntity() instanceof Player && EMF.config().getConfig().resetPlayerModelEachRender_v2) { + roots.forEach(EMFModelPartRoot::resetVanillaPartsToDefaults); + } + } + } + + //if this entity requires a debug print do it now after models have variated + if (EMF.config().getConfig().debugOnRightClick + && uuid().equals(EMFManager.getInstance().entityForDebugPrint)) { + EMFState.announceModels = true; + EMFManager.getInstance().entityForDebugPrint = null; + } + } + EMFLODHandler.setNullLodFrameSkipping(); + } + + @Override + default void deactivate(boolean inMount) { + ETFEntityRenderState.super.deactivate(inMount); + EMFState.isLayerPhase = false; + EMFState.modelVariationIgnoresVisibility = false; + EMFState.isInItemFrame = false; + + if (!inMount) { + setSkipModelVariate(false); + } + } + //#if MC >= 1.21.2 @Nullable static EMFEntityRenderState from(net.minecraft.client.renderer.entity.state.EntityRenderState state) { diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java index 9558fdc3..5e6acc16 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java @@ -2,6 +2,7 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.projectile.Arrow; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import traben.entity_model_features.models.animation.EMFAttachments; @@ -22,6 +23,11 @@ public EMFEntityRenderStateViaReference(EMFEntity emfEntity) { @Override @Deprecated public EMFEntity emfEntity() { return emfEntity; } + boolean isManualPlayerState = false; + @Override public boolean isManualPlayerState() { return isManualPlayerState; } + @Override public void setManualPlayerState(boolean manualPlayerState) { isManualPlayerState = manualPlayerState; } + + //region emfEntity passthrough @Override public double prevX() { return emfEntity.emf$prevX(); } @Override public double x() { return emfEntity.emf$getX(); } @Override public double prevY() { return emfEntity.emf$prevY(); } @@ -55,7 +61,7 @@ public EMFEntityRenderStateViaReference(EMFEntity emfEntity) { @Override public Map variableMap() { return emfEntity.emf$getVariableMap(); } - + //endregion private Function layerFactory = null; @Override @@ -64,6 +70,9 @@ public Function layerFactory() { } @Override public void setLayerFactory(final Function layerFactory) { + if (emfEntity instanceof Arrow) { + return; + } this.layerFactory = layerFactory; } @@ -78,4 +87,66 @@ public void setLayerFactory(final Function layerFa EMFBipedPose bipedPose = null; @Override public void setBipedPose(EMFBipedPose pose) { bipedPose = pose; } @Override public EMFBipedPose getBipedPose() { return bipedPose; } + + boolean isFirstPersonHand = false; + @Override public boolean isFirstPersonHand() { return isFirstPersonHand; } + @Override public void setIsFirstPersonHand(boolean isFirst) { this.isFirstPersonHand = isFirst; } + + boolean onShoulder = false; + @Override public boolean onShoulder() { return onShoulder; } + @Override public void setOnShoulder(boolean onShoulder) { this.onShoulder = onShoulder; } + + boolean skipModelVariate = false; + @Override public boolean skipModelVariate() { return skipModelVariate; } + @Override public void setSkipModelVariate(boolean value) { skipModelVariate = value; } + + float shadowSize = Float.NaN; + @Override public float shadowSize() { return shadowSize; } + @Override public void setShadowSize(float shadowSize) { this.shadowSize = shadowSize; } + + float shadowOpacity = Float.NaN; + @Override public float shadowOpacity() { return shadowOpacity; } + @Override public void setShadowOpacity(float shadowOpacity) { this.shadowOpacity = shadowOpacity; } + + float leashX = Float.NaN; + @Override public float leashX() { return leashX; } + @Override public void setLeashX(float leashX) { this.leashX = leashX; } + + float leashY = Float.NaN; + @Override public float leashY() { return leashY; } + @Override public void setLeashY(float leashY) { this.leashY = leashY; } + + float leashZ = Float.NaN; + @Override public float leashZ() { return leashZ; } + @Override public void setLeashZ(float leashZ) { this.leashZ = leashZ; } + + float shadowX = Float.NaN; + @Override public float shadowX() { return shadowX; } + @Override public void setShadowX(float shadowX) { this.shadowX = shadowX; } + + float shadowZ = Float.NaN; + @Override public float shadowZ() { return shadowZ; } + @Override public void setShadowZ(float shadowZ) { this.shadowZ = shadowZ; } + + float limbAngle = Float.NaN; + @Override public float limbAngle() { return limbAngle; } + @Override public void setLimbAngle(float limbAngle) { this.limbAngle = limbAngle; } + + float limbDistance = Float.NaN; + @Override public float limbDistance() { return limbDistance; } + @Override public void setLimbDistance(float limbDistance) { this.limbDistance = limbDistance; } + + float headYaw = Float.NaN; + @Override public float headYaw() { return headYaw; } + @Override public void setHeadYaw(float headYaw) { this.headYaw = headYaw; } + + float headPitch = Float.NaN; + @Override public float headPitch() { return headPitch; } + @Override public void setHeadPitch(float headPitch) { this.headPitch = headPitch; } + + + @Override + public String toString() { + return "EMFState-" + this.typeString(); + } } \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFState.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFState.java new file mode 100644 index 00000000..f8f7e5ce --- /dev/null +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFState.java @@ -0,0 +1,266 @@ +package traben.entity_model_features.models.animation.state; + +import net.minecraft.client.renderer.RenderType; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.NotNull; +import traben.entity_model_features.EMF; +import traben.entity_model_features.EMFManager; +import traben.entity_model_features.mod_compat.IrisShadowPassDetection; +import traben.entity_model_features.models.EMFModelMappings; +import traben.entity_model_features.models.EMFModel_ID; +import traben.entity_model_features.models.parts.EMFModelPartRoot; +import traben.entity_model_features.utils.EMFEntity; +import traben.entity_model_features.utils.EMFUtils; +import traben.entity_texture_features.ETF; +import traben.entity_texture_features.features.state.ETFState; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; +import java.util.function.Function; + +import static traben.entity_model_features.models.animation.math.EMFMath.WRAP_CONST; + +public abstract class EMFState { + + public static EMFEntityRenderState state() { + return (EMFEntityRenderState) ETFState.state(); + } + + @Deprecated // Don't rely on this its just a stop gap to simplify state refactor + public static EMFEntity emfEntity() { + var state = state(); + return state != null ? state.emfEntity() : null; + } + + + public static void clear() { + frameCounter = 0; + ETFState.clear(); + isLayerPhase = false; + isMainPhase = false; + isInShoulderMethod = false; + isInGui = false; + modelVariationIgnoresVisibility = false; + isInGroundOverride = false; + isOnHead = false; + isInHand = false; + isInItemFrame = false; + } + + public static float frameCounter = 0; + public static boolean isLayerPhase = false; + public static boolean isMainPhase = false; + public static boolean isInShoulderMethod = false; + public static boolean isInGui = false; + public static boolean isInGroundOverride = false; + public static boolean isOnHead = false; + public static boolean isInHand = false; + public static boolean isInItemFrame = false; + public static boolean modelVariationIgnoresVisibility = false; + + + public static void incFrameCount(){ + //not 100% certain if the shadow pass passes through this method, I highly doubt it but just in case + if(IrisShadowPassDetection.getInstance().inShadowPass()) return; + + float inc = frameCounter + 1; + //reset counter after exceeding floating point precision cutoff + frameCounter = inc >= WRAP_CONST ? 0 : inc; + } + + public static float getFrameCounter(){ + return frameCounter; + } + + + //region debug chat anouncement + + public static boolean announceModels = false; + + public static void anounceModels(EMFEntityRenderState assertEntity) { + String type = assertEntity.typeString(); + Set debugRoots = EMFManager.getInstance().rootPartsPerEntityTypeForDebug.get(type); + EMFUtils.chat("§e-----------EMF Debug Printout-------------§r"); + if (debugRoots == null) { + EMFUtils.chat( + "\n§c§oThe EMF debug printout did not find any custom models registered to the following entity:\n §3§l§u" + type + ); + } else { + String message = "\n§2§oThe EMF debug printout found the following custom models for the entity:\n §3§l§u" + + type + + "§r\n§2§oThis first model is usually the primary model for the entity."; + + EMFUtils.chat(message); + + int count = 1; + for (EMFModelPartRoot debugRoot : + debugRoots) { + StringBuilder model = new StringBuilder(); + model.append("§eModel #").append(count).append("§r") + .append(entryAndValue("name", debugRoot.modelName.getfileName() + ".jem")); + if (debugRoot.modelName.hasFallbackModels()){ + model.append("\n§eFallback Models:§r"); + debugRoot.modelName.forEachFallback((modelId) -> + model.append("\n§6 - §r").append(modelId.getfileName())); + } + if (debugRoot.directoryContext != null) { + model.append(entryAndValue("directory", + debugRoot.directoryContext + .getRelativeDirectoryLocationNoValidation(debugRoot.modelName.getfileName()))); + } + + if (debugRoot.textureOverride != null) { + model.append(entryAndValue("texture_override", debugRoot.textureOverride.toString())); + } + if (debugRoot.variantTester != null) { + Set set = new HashSet<>(debugRoot.allKnownStateVariants.keySet()); + set.remove(0); + model.append(entryAndValue("model_variants", set.toString())) + .append(entryAndValue("current_variant", String.valueOf(debugRoot.currentModelVariant))); + } + EMFUtils.chat(model + "\n§6 - parts:§r printed in game log only."); + + EMFUtils.log("\n - parts: " + debugRoot.simplePrintChildren(0)); + + count++; + } + } + + EMFUtils.chat("\n§e----------------------------------------§r"); + if (!EMFManager.getInstance().modelsAnnounced.isEmpty()) { + String vanillaMessage = "\n§2§oThe EMF debug printout found the following non-custom models for the entity:\n §3§l§u" + + type + + "§r\n§2§oThis first model is usually the primary model for the entity."; + + EMFUtils.chat(vanillaMessage); + int count = 1; + for (EMFModel_ID data : EMFManager.getInstance().modelsAnnounced) { + StringBuilder model = new StringBuilder(); + model.append("\n§eNon-Custom Model #").append(count).append("§r") + .append(entryAndValue("possible .jem name", data.getDisplayFileName())); + if (data.hasFallbackModels()){ + model.append("§eFallback Models:§r"); + data.forEachFallback((modelId) -> + model.append("\n§6 - §r").append(modelId.getfileName())); + } + Map map = EMFModelMappings.getMapOf(data, null); + if (!map.isEmpty()) { + EMFUtils.chat(model + "\n§6 - part names:§r printed in game log only."); + StringBuilder parts = new StringBuilder(); + parts.append("\n - part names: "); + map.forEach((k, v) -> parts.append("\n | - [").append(k).append(']')); + + EMFUtils.log(parts.toString()); + } else { + EMFUtils.chat(model.toString()); + EMFUtils.log(" - part names: could not be found. use the 'printout unknown models' setting instead."); + } + } + EMFUtils.chat("\n§e----------------------------------------§r"); + EMFManager.getInstance().modelsAnnounced.clear(); + } + + announceModels = false; + } + + private static String entryAndValue(String entry, String value) { + return "\n§6 - " + entry + ":§r " + value; + } + //endregion + + //region model variation disabling + public static Set entitiesToForceVanillaModel = new HashSet<>(); + + public static List> forceVanillaModelListeners = new ArrayList<>(); + + public static boolean isEntityForcedToVanillaModel(@NotNull EMFEntityRenderState state) { + if (entitiesToForceVanillaModel.contains(state.uuid())) return true; + + try { + + EntityType type = state.entityType(); + if (type != null && type.toString().contains("customnpc")) { + // CustomNPC has been ported to 1.20.1 by another dev that ask for having access to the source code + // CustomNPC nor UnofficialCustomNPC are not open source (so no source code :x) + // Downloads on https://www.curseforge.com/minecraft/mc-mods/customnpcs-unofficial/files/all?page=1&pageSize=20&version=1.20.1&gameVersionTypeId=1&showAlphaFiles=hide + CompoundTag nbtTags = state.nbt(); + + // If the customNPC is in puppet role + // Or if we want the customNPC to not use EMF animations (like with Fresh Animation RP) we can set his maxhp to 777 to have a full control (usefull for the siting pose for example) + if ((((LivingEntity) state.entity()).getMaxHealth() == 777f) || + nbtTags.contains("PuppetStanding") || + nbtTags.contains("PuppetMoving") || + nbtTags.contains("PuppetAttacking") || + nbtTags.contains("PuppetAnimate")) { + return true; + } + } + + for (var check : forceVanillaModelListeners) { + if (check.apply(state.emfEntity())) return true; + } + } catch (Exception ignored) {} + + return EMF.config().getConfig().onlyClientPlayerModel + && state.emfEntity() instanceof Player player && !player.isLocalPlayer(); + } + //endregion + + public static RenderType getLayerFromRecentFactoryOrETFOverrideOrTranslucent(ResourceLocation identifier) { + var state = state(); + if (state == null || state.layerFactory() == null) { + var layer = ETF.config().getConfig().getRenderLayerOverride(); + if (layer == null) { + return + //#if MC>= 12111 + //$$ net.minecraft.client.renderer.rendertype.RenderTypes + //#else + RenderType + //#endif + .entityTranslucent(identifier); + } else { + return switch (layer) { + case TRANSLUCENT -> + //#if MC>= 12111 + //$$ net.minecraft.client.renderer.rendertype.RenderTypes + //#else + RenderType + //#endif + .entityTranslucent(identifier); + case TRANSLUCENT_CULL -> + //#if MC>= 12111 + //$$ net.minecraft.client.renderer.rendertype.RenderTypes.entityTranslucent(identifier); + //#elseif MC >=12102 + RenderType.entityTranslucent(identifier); + //#else + //$$ RenderType.entityTranslucentCull(identifier); + //#endif + case END -> + //#if MC>= 12111 + //$$ net.minecraft.client.renderer.rendertype.RenderTypes + //#else + RenderType + //#endif + .endGateway(); + case OUTLINE -> + //#if MC>= 12111 + //$$ net.minecraft.client.renderer.rendertype.RenderTypes + //#else + RenderType + //#endif + .outline(identifier); + }; + } + } + return state.layerFactory().apply(identifier); + } + +} diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitData.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitData.java index f3a1c1a0..1163defe 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitData.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitData.java @@ -2,43 +2,34 @@ import org.jetbrains.annotations.Nullable; -public class EMFSubmitData { - - public EMFEntityRenderState backupState = null; - - public int modelVariant = -1; - - public EMFBipedPose bipedPose = null; - - public boolean onShoulder = false; - public boolean isMainModelPhase = false; - public boolean isLayerModelPhase = false; - - - /** - * These fields are used as a sort of "thread local" for passing data easily into new submit instances - */ - public static EMFEntityRenderState AWAITING_backupState = null; - public static EMFBipedPose AWAITING_bipedPose = null; - - public static boolean AWAITING_isMainModelPhase = false; - public static boolean AWAITING_isLayerModelPhase = false; - - - //#if MC >= 1.21.9 - @Nullable - public static EMFSubmitData from(//TODO whole functionality to be moved upstream to ETF in refactor for proper render states - //#if MC >= 26.2 - //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit - //#else - net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit - //#endif - ) { - //noinspection ConstantValue - return ((Object) modelSubmit) instanceof EMFSubmitExtension emf - ? ((EMFSubmitExtension) (Object) modelSubmit).emf$getData() - : null; - } - //#endif - -} +//public class EMFSubmitData { +// +////// public EMFEntityRenderState backupState = null; +//// +//// public int modelVariant = -1; +//// +//// public EMFBipedPose bipedPose = null; +//// +//// +//// +//// public static EMFBipedPose AWAITING_bipedPose = null; +//// +//// +//// +//// //#if MC >= 1.21.9 +//// @Nullable +//// public static EMFSubmitData from(//TODO whole functionality to be moved upstream to ETF in refactor for proper render states +//// //#if MC >= 26.2 +//// //$$ net.minecraft.client.renderer.feature.ModelFeatureRenderer.Submit modelSubmit +//// //#else +//// net.minecraft.client.renderer.SubmitNodeStorage.ModelSubmit modelSubmit +//// //#endif +//// ) { +//// //noinspection ConstantValue +//// return ((Object) modelSubmit) instanceof EMFSubmitExtension emf +//// ? ((EMFSubmitExtension) (Object) modelSubmit).emf$getData() +//// : null; +//// } +//// //#endif +// +//} diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitExtension.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitExtension.java index cb5a59de..7cbd0459 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitExtension.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFSubmitExtension.java @@ -1,5 +1,5 @@ package traben.entity_model_features.models.animation.state; -public interface EMFSubmitExtension { - EMFSubmitData emf$getData(); -} +//public interface EMFSubmitExtension { +// EMFSubmitData emf$getData(); +//} diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java index 13a6bebf..7c9c6688 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java @@ -10,11 +10,12 @@ import traben.entity_model_features.EMF; import traben.entity_model_features.config.EMFConfig; import traben.entity_model_features.mod_compat.IrisShadowPassDetection; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.EMFManager; +import traben.entity_model_features.models.animation.math.EMFMath; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.EMFUtils; import traben.entity_texture_features.ETF; -import traben.entity_texture_features.features.ETFRenderContext; +import traben.entity_texture_features.features.state.ETFState; import traben.entity_texture_features.features.texture_handlers.ETFTexture; import traben.entity_texture_features.utils.ETFUtils2; import traben.entity_texture_features.utils.ETFVertexConsumer; @@ -37,7 +38,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.phys.AABB; -import static traben.entity_model_features.EMF.EYES_FEATURE_LIGHT_VALUE; +import static traben.entity_texture_features.ETF.EYES_FEATURE_LIGHT_VALUE; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; @@ -82,7 +83,7 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina //#endif ) { try { - var choice = EMF.config().getConfig().getRenderModeFor(EMFAnimationEntityContext.getEMFEntity()); + var choice = EMF.config().getConfig().getRenderModeFor(EMFState.state()); //normal render if (choice == EMFConfig.RenderModeChoice.NORMAL) { renderWithTextureOverride(matrices, vertices, light, overlay, @@ -97,7 +98,7 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina //debug choice chosen //check if only render debug when hovered - if (EMF.config().getConfig().onlyDebugRenderOnHover && !EMFAnimationEntityContext.isClientHovered()) { + if (EMF.config().getConfig().onlyDebugRenderOnHover && !EMFMath.isClientHovered()) { renderWithTextureOverride(matrices, vertices, light, overlay, //#if MC >= 12100 k @@ -207,7 +208,7 @@ void renderWithTextureOverride(PoseStack matrices, VertexConsumer vertices, int //$$ float red, float green, float blue, float alpha //#endif ) { - if (textureOverride == null || (EMFAnimationEntityContext.isLayerPhase() && getRoot().isMainModel)) { + if (textureOverride == null || (EMFState.isLayerPhase && getRoot().isMainModel)) { // || lastTextureOverride == EMFManager.getInstance().entityRenderCount // prevents texture overrides carrying over into feature renderers that reuse the base model //normal vertex consumer renderLikeETF(matrices, vertices, light, overlay, @@ -218,7 +219,7 @@ void renderWithTextureOverride(PoseStack matrices, VertexConsumer vertices, int //#endif ); } else if (light != EYES_FEATURE_LIGHT_VALUE // this is only the case for EyesFeatureRenderer - && !ETFRenderContext.isIsInSpecialRenderOverlayPhase() //do not allow new etf emissive rendering here + && !ETFState.isIsInSpecialRenderOverlayPhase() //do not allow new etf emissive rendering here //&& vertices instanceof ETFVertexConsumer etfVertexConsumer ) { //can restore to previous render layer @@ -226,7 +227,8 @@ void renderWithTextureOverride(PoseStack matrices, VertexConsumer vertices, int // fixed weird bug with certain texture overrides rendering in first person as though from the sun's POV // downside is incorrect shadows for some model parts :/ //todo triple check it is only block entities, I so far cannot recreate the bug for regular mobs - if ((EMFAnimationEntityContext.getEMFEntity() != null && EMFAnimationEntityContext.getEMFEntity().etf$isBlockEntity()) + var state = EMFState.state(); + if ((state != null && state.isBlockEntity()) && ETF.IRIS_DETECTED && IrisShadowPassDetection.getInstance().inShadowPass()) { //skip texture override renderLikeETF(matrices, vertices, light, overlay, @@ -304,7 +306,7 @@ private void renderTextureOverrideWithoutReset(URenderTypeToVertexConsumer provi ){ // lastTextureOverride = EMFManager.getInstance().entityRenderCount; - RenderType layerModified = EMFAnimationEntityContext.getLayerFromRecentFactoryOrETFOverrideOrTranslucent(textureOverride); + RenderType layerModified = EMFState.getLayerFromRecentFactoryOrETFOverrideOrTranslucent(textureOverride); VertexConsumer newConsumer = provider.getBuffer(layerModified); renderLikeVanilla(matrices, newConsumer, light, overlay, @@ -390,12 +392,11 @@ private VertexConsumer testForBuildingException(VertexConsumer vertices) { if (testBuilding instanceof ETFVertexConsumer etf && etf.etf$getRenderLayer() != null && etf.etf$getProvider() != null){ - boolean allowed = ETFRenderContext.isAllowedToRenderLayerTextureModify(); - ETFRenderContext.preventRenderLayerTextureModify(); + ETFState.pushRenderLayerModifyState(false); vertices = etf.etf$getProvider().getBuffer(etf.etf$getRenderLayer()); - if (allowed) ETFRenderContext.allowRenderLayerTextureModify(); + ETFState.popRenderLayerModifyState(); }else { return null; } @@ -421,7 +422,7 @@ void renderLikeETF(PoseStack matrices, VertexConsumer vertices, int light, int o //#endif //etf ModelPartMixin copy - ETFRenderContext.incrementCurrentModelPartDepth(); + ETFState.currentModelPartDepth++; renderLikeVanilla(matrices, vertices, light, overlay, //#if MC >= 12100 @@ -432,11 +433,11 @@ void renderLikeETF(PoseStack matrices, VertexConsumer vertices, int light, int o ); //etf ModelPartMixin copy - if (ETFRenderContext.getCurrentModelPartDepth() != 1) { - ETFRenderContext.decrementCurrentModelPartDepth(); + if (ETFState.currentModelPartDepth != 1) { + ETFState.currentModelPartDepth--; } else { //top level model so try special rendering - if (ETFRenderContext.isCurrentlyRenderingEntity() + if (ETFState.isStateActive() && vertices instanceof ETFVertexConsumer etfVertexConsumer) { ETFTexture texture = etfVertexConsumer.etf$getETFTexture(); //is etf texture not null and does it special render? @@ -466,7 +467,7 @@ void renderLikeETF(PoseStack matrices, VertexConsumer vertices, int light, int o } } //ensure model count is reset - ETFRenderContext.resetCurrentModelPartDepth(); + ETFState.currentModelPartDepth = 0; } } diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartCustom.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartCustom.java index bc620b1b..715da32b 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartCustom.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartCustom.java @@ -9,8 +9,8 @@ import traben.entity_model_features.EMF; import traben.entity_model_features.mixin.mixins.accessor.CuboidAccessor; import traben.entity_model_features.mod_compat.IrisShadowPassDetection; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.EMFAttachments; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.models.jem_objects.EMFBoxData; import traben.entity_model_features.models.jem_objects.EMFPartData; import traben.entity_model_features.EMFManager; @@ -142,7 +142,7 @@ public void processArmItemOverrides(PoseStack matrices) { attachment.setAttachment(matrices); matrices.popPose(); - var state = EMFAnimationEntityContext.getEmfState(); + var state = EMFState.state(); if (state != null) { if (attachment.right) state.setRightArmOverride(attachment); else state.setLeftArmOverride(attachment); @@ -188,7 +188,7 @@ void renderWithTextureOverride(final PoseStack matrices, final VertexConsumer ve //$$ float red, float green, float blue, float alpha //#endif ) { - if (textureOverride != null && (EMFAnimationEntityContext.isLayerPhase() && getRoot().isMainModel)){ + if (textureOverride != null && (EMFState.isLayerPhase && getRoot().isMainModel)){ //do not render if this is a custom part with a texture override and are rendering a feature overlay //custom parts with texture overrides are explicitly stating they will not be used in feature layers return; diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java index 460c85a0..529792b3 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java @@ -8,10 +8,13 @@ import org.jetbrains.annotations.Nullable; import traben.entity_model_features.EMF; import traben.entity_model_features.config.EMFConfig; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; import traben.entity_model_features.models.animation.EMFAnimationHandler; +import traben.entity_model_features.models.animation.math.EMFMath; +import traben.entity_model_features.models.animation.state.EMFEntityRenderState; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.models.jem_objects.EMFJemData; import traben.entity_model_features.models.jem_objects.EMFPartData; +import traben.entity_model_features.utils.EMFAnimationPauseHandler; import traben.entity_model_features.utils.EMFDirectoryHandler; import traben.entity_model_features.EMFManager; import traben.entity_model_features.utils.EMFResourceCaching; @@ -91,7 +94,7 @@ public void oneTimeRunnable() { private void registerModelRunnableWithEntityTypeContext() { //noinspection deprecation - var entity = EMFAnimationEntityContext.getEmfState(); + var entity = EMFState.state(); if (entity != null) { // await a valid entity String type = entity.typeString(); @@ -119,10 +122,8 @@ private void registerModelRunnableWithEntityTypeContext() { } - public void doVariantCheck() { - //noinspection deprecation - var emfState = EMFAnimationEntityContext.getEmfState(); - if(this.variantTester == null || emfState == null) { + public void doVariantCheck(@NotNull EMFEntityRenderState emfState) { + if(this.variantTester == null) { this.setVariantStateTo(1); return; } @@ -131,7 +132,7 @@ public void doVariantCheck() { int finalSuffix = entitySuffixMap.get(id); if (finalSuffix != -1) { - checkIfShouldExpireEntity(id); + checkIfShouldExpireEntity(emfState, id); } else { finalSuffix = Math.max(1, variantTester.getSuffixForETFEntity(emfState)); entitySuffixMap.put(id, finalSuffix); @@ -140,15 +141,14 @@ public void doVariantCheck() { setVariantStateTo(finalSuffix); } - public void checkIfShouldExpireEntity(UUID id) { + public void checkIfShouldExpireEntity(@NotNull EMFEntityRenderState emfState, UUID id) { if (this.variantTester.entityCanUpdate(id)) { switch (EMF.config().getConfig().modelUpdateFrequency) { case Never -> {} case Instant -> this.entitySuffixMap.remove(id); default -> { int delay = EMF.config().getConfig().modelUpdateFrequency.getDelay(); - //noinspection deprecation - int time = (int) (EMFAnimationEntityContext.getTime() % delay); + int time = (int) (EMFMath.getTime(emfState) % delay); if (time == Math.abs(id.hashCode()) % delay) { this.entitySuffixMap.remove(id); } @@ -292,7 +292,7 @@ public void tryRenderVanillaRootNormally(PoseStack matrixStack, VertexConsumer v if (vanillaRoot != null) { matrixStack.pushPose(); //noinspection deprecation - if (EMF.config().getConfig().getVanillaHologramModeFor(EMFAnimationEntityContext.getEMFEntity()) == EMFConfig.VanillaModelRenderMode.OFFSET) { + if (EMF.config().getConfig().getVanillaHologramModeFor(EMFState.state().emfEntity()) == EMFConfig.VanillaModelRenderMode.OFFSET) { matrixStack.translate(1, 0, 0); } vanillaRoot.render(matrixStack, vertexConsumer, light, overlay @@ -346,7 +346,7 @@ public void setVariantStateTo(int newVariant) { } public void animate() { - if (animation != null && !EMFAnimationEntityContext.isEntityAnimPausedWrapped()) { + if (animation != null && !EMFAnimationPauseHandler.shouldAnimationsPause(EMFState.state())) { animation.run(); } } @@ -358,12 +358,13 @@ public void receiveAnimationHandler(int variant, final EMFAnimationHandler anima lastMobCountAnimatedOn = EMFManager.getInstance().entityRenderCount; //noinspection deprecation - if (EMFAnimationEntityContext.isFirstPersonHand && EMF.config().getConfig().preventFirstPersonHandAnimating) + var state = EMFState.state(); + if (state != null && state.isFirstPersonHand() && EMF.config().getConfig().preventFirstPersonHandAnimating) return; try { //noinspection deprecation - animationHandler.animate(EMFAnimationEntityContext.getEntityPartsAnimPaused()); + animationHandler.animate(EMFAnimationPauseHandler.getEntityPartsAnimPaused()); } catch (Throwable e) { EMFUtils.logError("Error in animation for model [" + modelName.getfileName() + "]."); //noinspection CallToPrintStackTrace diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartWithState.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartWithState.java index 43b7a921..03cca34f 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartWithState.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartWithState.java @@ -3,7 +3,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import org.jetbrains.annotations.NotNull; -import traben.entity_model_features.models.animation.EMFAnimationEntityContext; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.EMFUtils; import java.util.ArrayList; @@ -21,7 +21,7 @@ public abstract class EMFModelPartWithState extends EMFModelPart { public EMFModelState get(Object k) { var val = super.get(k); if (val == null) { - EMFUtils.logWarn("EMFModelState variant with key " + k + " does not exist in part [" + toStringShort() + "], returning copy of 0"); + EMFUtils.logWarn("EMFModelState variant with key " + k + " does not exist in part [" + toStringShort() + "], returning copy of 0. State is :" + EMFState.state()); val = get(0).copy(); put((Integer) k, val); } @@ -108,7 +108,7 @@ void setFromState(EMFModelState newState) { //$$ zScale = newState.zScale(); //#endif - if (!EMFAnimationEntityContext.modelVariationIgnoresVisibility) { + if (!EMFState.modelVariationIgnoresVisibility) { visible = newState.visible(); skipDraw = newState.hidden(); } diff --git a/src/main/java/traben/entity_model_features/utils/EMFAnimationPauseHandler.java b/src/main/java/traben/entity_model_features/utils/EMFAnimationPauseHandler.java new file mode 100644 index 00000000..5a42ef79 --- /dev/null +++ b/src/main/java/traben/entity_model_features/utils/EMFAnimationPauseHandler.java @@ -0,0 +1,103 @@ +package traben.entity_model_features.utils; + +import net.minecraft.client.model.geom.ModelPart; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.Nullable; +import traben.entity_model_features.models.animation.state.EMFEntityRenderState; +import traben.entity_model_features.models.animation.state.EMFState; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.function.Function; + +public abstract class EMFAnimationPauseHandler { + + private static boolean checkedIfIEmotePlayerExists = false; + private static Class iEmotePlayerEntityType = null; + private static Method isPlayingEmoteMethod = null; + + public static HashMap entitiesPausedParts = new HashMap<>(); + public static Set entitiesPaused = new HashSet<>(); + public static List> pauseListeners = new ArrayList<>(); + + public static boolean shouldAnimationsPause(EMFEntityRenderState state) { + if (state == null) return false; + + // API for other mods to pause animations on specific entities + var entity = state.emfEntity(); + if (entity != null) { + if (isPlayerEmoting_KosmX_mod(entity)) return true; + + //noinspection deprecation + if (traben.entity_model_features.models.animation.EMFAnimationEntityContext.isEntityAnimPaused()) return true; + + for (Function pauseListener : pauseListeners) { + try { + if (pauseListener.apply(entity)) return true; + } catch (Exception ignored) {} + } + } + + return entitiesPaused.contains(state.uuid()); + } + + //region KosmX emote mod compat + private static boolean isPlayerEmoting_KosmX_mod(EMFEntity entity) { + if (!(entity instanceof Player player)) return false; + + Method emoteMethod = getIsPlayingEmoteMethod(); + if (emoteMethod == null) return false; + + try { + return (boolean) emoteMethod.invoke(player); + } catch (Exception ignored) { + return false; + } + } + + private static @Nullable Class getIEmotePlayerEntityType() { + if (checkedIfIEmotePlayerExists) return iEmotePlayerEntityType; + checkedIfIEmotePlayerExists = true; + + try { + // Tries to get the IEmotePlayerEntity interface in order to access the isPlayingEmote() method + // https://github.com/KosmX/emotes/blob/1.20.1/executor/src/main/java/io/github/kosmx/emotes/executor/emotePlayer/IEmotePlayerEntity.java + // This type should always be found if EmoteCraft mod doesn't change it too much and the mod is actually loaded obv + iEmotePlayerEntityType = Class.forName("io.github.kosmx.emotes.executor.emotePlayer.IEmotePlayerEntity"); + } catch (ClassNotFoundException ignored) { + iEmotePlayerEntityType = null; + } + + return iEmotePlayerEntityType; + } + + private static @Nullable Method getIsPlayingEmoteMethod() { + if (isPlayingEmoteMethod != null) return isPlayingEmoteMethod; + + Class emotePlayerType = getIEmotePlayerEntityType(); + if (emotePlayerType == null) return null; + + try { + isPlayingEmoteMethod = emotePlayerType.getMethod("isPlayingEmote"); + } catch (NoSuchMethodException ignored) { + isPlayingEmoteMethod = null; + } + + return isPlayingEmoteMethod; + } + //endregion + + + public static @Nullable ModelPart[] getEntityPartsAnimPaused() { + var state = EMFState.state(); + if (state == null) return null; + var parts = entitiesPausedParts.get(state.uuid()); + return parts == null || parts.length == 0 ? null : parts; + } + +} diff --git a/src/main/java/traben/entity_model_features/utils/EMFLODHandler.java b/src/main/java/traben/entity_model_features/utils/EMFLODHandler.java new file mode 100644 index 00000000..c35dfd22 --- /dev/null +++ b/src/main/java/traben/entity_model_features/utils/EMFLODHandler.java @@ -0,0 +1,134 @@ +package traben.entity_model_features.utils; + +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import traben.entity_model_features.EMF; +import traben.entity_model_features.mod_compat.IrisShadowPassDetection; +import traben.entity_model_features.models.animation.state.EMFEntityRenderState; +import traben.entity_model_features.models.animation.state.EMFState; +import traben.entity_texture_features.ETF; + +import java.util.HashMap; +import java.util.Map; + +public abstract class EMFLODHandler { + + private static final Map lodEntityTimers = new HashMap<>(); + + private static Boolean lodFrameSkipping = null; + public static void setNullLodFrameSkipping() { + lodFrameSkipping = null; + } + + @Deprecated // In 26.1+ + public static double lastFOV = 70; + + + private static int getLODFactorOfEntity(@NotNull EMFEntityRenderState state) { + //if (lodFactor != -1) return lodFactor; + + if (EMF.config().getConfig().animationLODDistance == 0) return 0; + + //no factor when using spyglass or player is null + if (Minecraft.getInstance().player == null || Minecraft.getInstance().player.isScoping()) { + return 0; + } + + int distance = distanceOfEntityFrom(Minecraft.getInstance().player.blockPosition(), state); + if (distance < 1) return 0; + + int factor = distance / EMF.config().getConfig().animationLODDistance; + //reduce factor when using zoom mods or lower fov + int factorByFOV = (int) (factor * + + //#if MC >= 26.2 + //$$ Minecraft.getInstance().gameRenderer.gameRenderState().levelRenderState.cameraRenderState.hudFov + //#elseif MC >= 26.1 + //$$ Minecraft.getInstance().gameRenderer.getGameRenderState().levelRenderState.cameraRenderState.hudFov + //#else + lastFOV + //#endif + / 70); + + int lodFactor; + //factor in low fps detail retention + if (EMF.config().getConfig().retainDetailOnLowFps && Minecraft.getInstance().getFps() < 59) { // count often drops to 59 while capped at 60 :/ + float fpsPercentageOf60 = Minecraft.getInstance().getFps() / 60f; + //reduce factor by the percentage of fps below 60 to recover some level of detail + lodFactor = (int) (factorByFOV * fpsPercentageOf60); + } else { + lodFactor = factorByFOV; + } + + if (EMF.config().getConfig().retainDetailOnLargerMobs && state.emfEntity() instanceof Entity entity) { + var entitySize = Math.max(entity.getBbWidth(), entity.getBbHeight()); + if (entitySize > 2) { + lodFactor = (int) (lodFactor / (entitySize / 2)); + } + } + + return lodFactor; + } + + public static boolean isLODSkippingThisFrame(String modelId) { + if (EMFState.isInGui || EMFState.isInShoulderMethod) return false; + if (lodFrameSkipping != null) return lodFrameSkipping; + + //skip for shadow pass + if(ETF.IRIS_DETECTED + && IrisShadowPassDetection.getInstance().inShadowPass() + && EMF.config().getConfig().animationFrameSkipDuringIrisShadowPass + //not client player in first person + && !(emfEntity() instanceof Player player + && player.isLocalPlayer() + && Minecraft.getInstance().options.getCameraType().isFirstPerson())) { + return true; + } + + var state = emfState(); + if (EMF.config().getConfig().animationLODDistance == 0 || state == null) return false; + + + var type = state.entityType(); + if (type == UEntityTypes.VILLAGER || type == UEntityTypes.HORSE) return false; + + // Just putting this here so that fresh animations counter rotation keep working, plus these tend to render from a distance anyway + if (type == UEntityTypes.BLAZE) return false; + + String lodKey = state.uuid() + modelId; + + int lodTimer = lodEntityTimers.getOrDefault(lodKey, 0); + int lodResult; + //check lod + if (lodTimer < 1) { + lodResult = getLODFactorOfEntity(state); + } else { + lodResult = lodTimer - 1; + } + lodEntityTimers.put(lodKey, lodResult); + //intellij requires it for certain versions :/ + //noinspection RedundantCast + lodFrameSkipping = (Boolean) (lodResult > 0); + return lodFrameSkipping; + } + + private static int distanceOfEntityFrom(BlockPos pos, @NotNull EMFEntityRenderState state) { + var blockPos = state.blockPos(); + float f = (float) (blockPos.getX() - pos.getX()); + float g = (float) (blockPos.getY() - pos.getY()); + float h = (float) (blockPos.getZ() - pos.getZ()); + return (int) Mth.sqrt(f * f + g * g + h * h); + } + + private static @Nullable EMFEntityRenderState emfState() { return EMFState.state(); } + private static @Nullable EMFEntity emfEntity() { + var state = emfState(); + return state == null ? null : state.emfEntity(); + } + +} diff --git a/src/main/resources/entity_model_features.mixins.json b/src/main/resources/entity_model_features.mixins.json index 7b74e758..7bd25c03 100644 --- a/src/main/resources/entity_model_features.mixins.json +++ b/src/main/resources/entity_model_features.mixins.json @@ -28,7 +28,6 @@ "exporting.MixinMeshTransformer", "rendering.Mixin_SpecialModelRenderers_SetCurrentSpecifiedModel", "rendering.MixinBannerRenderer", - "rendering.MixinBlockEntityRenderDispatcher", "rendering.MixinBlockEntityWithoutLevelRenderer", "rendering.MixinDragonRenderer", "rendering.MixinEntityRenderDispatcher", @@ -41,7 +40,6 @@ "rendering.arrows.MixinSpectralArrowRenderer", "rendering.arrows.MixinStuckArrowsFeatureRenderer", "rendering.feature.MixinCreeperChargeFeatureRenderer", - "rendering.feature.MixinEyesFeatureRenderer", "rendering.feature.MixinHeadFeatureRenderer", "rendering.feature.MixinHeldItemFeatureRenderer", "rendering.feature.MixinHumanoidArmorLayer", @@ -55,14 +53,9 @@ "rendering.model.MixinDragonModel", "rendering.model.MixinVillagerModel", "rendering.model.MixinWolfEntityModel", - "rendering.submits.Mixin_ChestSpecialRenderer_PassState", - "rendering.submits.Mixin_GuiEntityRenderer", "rendering.submits.Mixin_HumanoidArmorLayer_AddBaseModelPoseRef", "rendering.submits.Mixin_ModelPartRenderer", - "rendering.submits.Mixin_ModelRenderer", - "rendering.submits.Mixin_ModelSubmit_AddBackupState", - "rendering.submits.adjustments.Mixin_BoatRenderer_PassState", - "rendering.submits.adjustments.Mixin_TridentRenderer_PassState" + "rendering.submits.Mixin_ModelRenderer" ], "mixins": [ ], From 7d7fe743efb8c917f7320d46a2812a13cc9a61ce Mon Sep 17 00:00:00 2001 From: Traben Date: Wed, 19 Aug 2026 16:17:18 +1000 Subject: [PATCH 13/20] several fixes --- CHANGELOG.MD | 4 + .../traben/entity_model_features/EMF.java | 11 +- .../entity_model_features/EMFManager.java | 28 ++-- .../config/EMFConfig.java | 14 +- .../mixin/mixins/MixinModel.java | 5 +- .../rendering/MixinLivingEntityRenderer.java | 24 +--- .../rendering/MixinPlayerEntityRenderer.java | 5 +- .../feature/MixinHeldItemFeatureRenderer.java | 63 +++------ .../submits/Mixin_ModelPartRenderer.java | 10 +- .../submits/Mixin_ModelRenderer.java | 11 -- .../models/EMFModelMappings.java | 4 +- .../models/animation/EMFAttachments.java | 11 +- .../models/animation/state/EMFBipedPose.java | 2 +- .../animation/state/EMFEntityRenderState.java | 33 +++-- .../EMFEntityRenderStateViaReference.java | 8 -- .../models/animation/state/EMFState.java | 7 + .../models/jem_objects/EMFJemData.java | 3 +- .../models/jem_objects/EMFPartData.java | 5 +- .../models/parts/EMFModelPart.java | 130 ++++++++++-------- .../models/parts/EMFModelPartCustom.java | 26 ++-- .../models/parts/EMFModelPartRoot.java | 31 +++-- .../models/parts/EMFModelPartVanilla.java | 47 +++++-- 22 files changed, 239 insertions(+), 243 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index dfae294f..3297b876 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,9 +1,13 @@ [?] - fixed several model exporting issues, including missing parts, wrong rotations, and rabbit/axolotl legs on 26.1+ +- fixed vex items not matching animated arm positions +- improved item attachment handling +- fixed debug outline rendering not outlining everything - fixed 26.2 neoforge iris compatibility not working causing excess animation during the shadow pass - fixed first person arm rendering with sleeves even when turned off in the settings - fixed first person arm animations with some other mods hand rendering +- fixed several issues relating to layered or held models desyncing with or breaking the base model e.g. held tridents possibly breaking the player model - added new boolean animation variables `is_player_first_person`, `is_player_third_person`, `is_player_third_person_reversed` [3.2.4] diff --git a/src/main/java/traben/entity_model_features/EMF.java b/src/main/java/traben/entity_model_features/EMF.java index 6ec0a81b..4a9643af 100644 --- a/src/main/java/traben/entity_model_features/EMF.java +++ b/src/main/java/traben/entity_model_features/EMF.java @@ -144,16 +144,7 @@ public String getSubTitle() { ETFSubmitData.DATA_OUT.add((data, vanilla)->{ // Replaces logic for model part submits that now wrap in simple models if (vanilla.model().root() instanceof EMFModelPartVanilla partVanilla && partVanilla.getRoot() != partVanilla) { - EMFManager.getInstance().entityRenderCount++; - - if (partVanilla.isPlayerArm) { - if (Minecraft.getInstance().player != null) { - EMFState.modelVariationIgnoresVisibility = true; - var state = EMFEntityRenderState.manualPlayerState(); - if (state != null) ETFState.mount(state); - } - EMFState.state().setIsFirstPersonHand(true); - } + EMFManager.getInstance().entityRenderCount++; // TODO still needed? } }); //#endif diff --git a/src/main/java/traben/entity_model_features/EMFManager.java b/src/main/java/traben/entity_model_features/EMFManager.java index 20b68ef3..83771629 100644 --- a/src/main/java/traben/entity_model_features/EMFManager.java +++ b/src/main/java/traben/entity_model_features/EMFManager.java @@ -52,7 +52,6 @@ import net.minecraft.world.level.block.entity.BlockEntityType; import static traben.entity_model_features.models.animation.math.expression_tree.MathExpressionParser.NULL_EXPRESSION; -import static traben.entity_model_features.models.animation.math.expression_tree.MathValue.FALSE; public class EMFManager {//singleton for data holding and resetting needs @@ -279,7 +278,6 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final || currentSpecifiedModelLoading.startsWith("emf$") //key to not override ? originalLayerName : currentSpecifiedModelLoading); - try { EMFManager.lastCreatedRootModelPart = null; boolean printing = (EMF.config().getConfig().logModelCreationData); @@ -297,7 +295,7 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final //#else //$$ getLayer() //#endif - ); + ); originalLayerName = originalLayerName + "_" + layer. //#if MC >= 12102 layer() @@ -390,6 +388,8 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final lastUndeadHorse = filename; } + mobNameForFileAndMap.resetCacheID(); + if (!skipSwitch) { //vanilla model switch (originalLayerName) { @@ -411,9 +411,9 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final //#endif //#if MC>=12109 case "villager_no_hat" -> mobNameForFileAndMap.setMapIdAndAddFallbackModel("villager"); - case "villager_no_hat_baby" -> mobNameForFileAndMap.setMapIdAndAddFallbackModel("villager_baby").addFallbackModel("villager"); + case "villager_baby_no_hat" -> mobNameForFileAndMap.setMapIdAndAddFallbackModel("villager_baby").addFallbackModel("villager"); case "zombie_villager_no_hat" -> mobNameForFileAndMap.setMapIdAndAddFallbackModel("zombie_villager"); - case "zombie_villager_no_hat_baby" -> mobNameForFileAndMap.setMapIdAndAddFallbackModel("zombie_villager_baby").addFallbackModel("zombie_villager"); + case "zombie_villager_baby_no_hat" -> mobNameForFileAndMap.setMapIdAndAddFallbackModel("zombie_villager_baby").addFallbackModel("zombie_villager"); //#endif //#if MC >= 12105 case "cow" -> mobNameForFileAndMap.pushNewMainModelAddingOldAsFallback("temperate_cow"); @@ -429,8 +429,8 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final case "evoker" -> mobNameForFileAndMap.addFallbackModel("evocation_illager"); case "evoker_fangs" -> mobNameForFileAndMap.addFallbackModel("evocation_fangs"); case "vindicator" -> mobNameForFileAndMap.addFallbackModel("vindication_illager"); - case "bed_foot" -> mobNameForFileAndMap.setBoth("bed_foot").addFallbackModel("bed"); - case "bed_head" -> mobNameForFileAndMap.setBoth("bed_head").addFallbackModel("bed"); + case "bed_foot" -> mobNameForFileAndMap.setBoth("bed_foot").addFallbackModel("bed").resetCacheID(); + case "bed_head" -> mobNameForFileAndMap.setBoth("bed_head").addFallbackModel("bed").resetCacheID(); case "book" -> { if (currentSpecifiedModelLoading.equals("enchanting_book")) { mobNameForFileAndMap.setBoth("enchanting_book", "book") @@ -611,12 +611,8 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final } //cache the layers for the model -// if(!isBaby) { - cache_LayersByModelName.put(mobNameForFileAndMap, layer); - mobNameForFileAndMap.forEachFallback((fallBack) -> cache_LayersByModelName.putIfAbsent(fallBack, layer)); -// } - - + cache_LayersByModelName.put(mobNameForFileAndMap, layer); + mobNameForFileAndMap.forEachFallback((fallBack) -> cache_LayersByModelName.putIfAbsent(fallBack, layer)); @@ -682,8 +678,7 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final EMFModelPartRoot emfRoot = new EMFModelPartRoot(finalMapData, Objects.requireNonNullElseGet(directoryContextBaseAndVariant.getLeft(), directoryContextBaseAndVariant::getRight), root, optifinePartNames, new HashMap<>()); if (jemData != null) { - emfRoot.addVariantOfJem(jemData, 1); - emfRoot.setVariantStateTo(1); + emfRoot.addAndSetVariantOfJem(jemData, 1); setupAnimationsFromJemToModel(jemData, emfRoot, 1); emfRoot.containsCustomModel = true; if (hasVariants) { @@ -828,7 +823,8 @@ private void getDoubleChest(ModelPart root, EMFModel_ID mobNameForFileAndMap, bo root.children = newChildren; // mutable } mobNameForFileAndMap.addFallbackModel(mobNameForFileAndMap.namespace, mobNameForFileAndMap.getfileName()); - mobNameForFileAndMap.setFileName(currentSpecifiedModelLoading + "_" + thisSide); + mobNameForFileAndMap.setFileName(currentSpecifiedModelLoading + "_" + thisSide) + .resetCacheID(); } public void setupAnimationsFromJemToModel(EMFJemData jemData, EMFModelPartRoot emfRootPart, int variantNum) { diff --git a/src/main/java/traben/entity_model_features/config/EMFConfig.java b/src/main/java/traben/entity_model_features/config/EMFConfig.java index 1a135052..c8e1fc57 100644 --- a/src/main/java/traben/entity_model_features/config/EMFConfig.java +++ b/src/main/java/traben/entity_model_features/config/EMFConfig.java @@ -67,26 +67,28 @@ public class EMFConfig extends TConfig { public ETFConfig.String2EnumNullMap entityVanillaHologramOverrides = new ETFConfig.String2EnumNullMap<>(); public RenderModeChoice getRenderModeFor(@Nullable EMFEntityRenderState state) { - if (state == null) return getRenderModeFor((EMFEntity) null); + if (state == null || entityRenderModeOverrides.isEmpty()) return renderModeChoice; return getRenderModeFor(state.emfEntity()); } public RenderModeChoice getRenderModeFor(@Nullable EMFEntity entity) { String typeString = getTypeString(entity); if (typeString == null) return renderModeChoice; - return Objects.requireNonNullElseGet(entityRenderModeOverrides.get(typeString), () -> renderModeChoice); + return Objects.requireNonNullElse(entityRenderModeOverrides.get(typeString), renderModeChoice); } @Deprecated(forRemoval = true) public PhysicsModCompatChoice getPhysicsModModeFor(EMFEntity entity) { + if (entityPhysicsModPatchOverrides.isEmpty()) return attemptPhysicsModPatch_2; String typeString = getTypeString(entity); if (typeString == null) return attemptPhysicsModPatch_2; - return Objects.requireNonNullElseGet(entityPhysicsModPatchOverrides.get(typeString), () -> attemptPhysicsModPatch_2); + return Objects.requireNonNullElse(entityPhysicsModPatchOverrides.get(typeString), attemptPhysicsModPatch_2); } public VanillaModelRenderMode getVanillaHologramModeFor(EMFEntity entity) { + if (entityVanillaHologramOverrides.isEmpty()) return vanillaModelHologramRenderMode_2; String typeString = getTypeString(entity); if (typeString == null) return vanillaModelHologramRenderMode_2; - return Objects.requireNonNullElseGet(entityVanillaHologramOverrides.get(typeString), () -> vanillaModelHologramRenderMode_2); + return Objects.requireNonNullElse(entityVanillaHologramOverrides.get(typeString), vanillaModelHologramRenderMode_2); } private static @Nullable String getTypeString(final EMFEntity entity) { @@ -567,6 +569,10 @@ public enum RenderModeChoice { public String toString() { return Component.translatable(text).getString(); } + + public boolean allowsRegularDraw() { + return this == NORMAL || this == LINES_AND_TEXTURE || this == LINES_AND_TEXTURE_FLASH; + } } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinModel.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinModel.java index f438943b..36f8a173 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinModel.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinModel.java @@ -12,6 +12,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import traben.entity_model_features.EMF; import traben.entity_model_features.models.animation.state.EMFState; +import traben.entity_model_features.models.parts.EMFModelPart; import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.models.IEMFModel; import traben.entity_model_features.EMFManager; @@ -30,8 +31,10 @@ public class MixinModel implements IEMFModel { at = @At(value = "TAIL")) private void emf$discoverEMFModel(final ModelPart modelPart, final Function function, final CallbackInfo ci) { if (EMF.testForForgeLoadingError()) return; - if(modelPart instanceof EMFModelPartRoot root) { + if (modelPart instanceof EMFModelPartRoot root) { emf$thisEMFModelRoot = root; + } else if (modelPart instanceof EMFModelPart nonRoot) { + emf$thisEMFModelRoot = nonRoot.getRoot(); // See vex model having a non-root root part } EMFManager.lastCreatedRootModelPart = null; } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java index c0b501e7..b8944df1 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java @@ -63,13 +63,15 @@ protected MixinLivingEntityRenderer(EntityRendererProvider.Context ctx) { super(ctx); } - //#if MC >= 12109 + //#if MC > 26.2 + //$$ todo check that they still use this.model and not the getter + //#elseif MC >= 12109 @Inject(method = "submit(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/EntityModel;setupAnim(Ljava/lang/Object;)V", shift = At.Shift.AFTER)) private void falseAnimation(CallbackInfo ci, @Local(argsOnly = true) PoseStack pose, @Local(argsOnly = true) S renderState) { // animate so that dependant layers can read the positions (only applies if they set their matrix prior to submission) - IEMFModel model = (IEMFModel) getModel(); + IEMFModel model = (IEMFModel) this.model; if (model.emf$isEMFModel() && model.emf$getEMFRootModel().hasAnimation()) { model.emf$getEMFRootModel().triggerManualAnimation(pose); // Store the biped pose in the render state for use by layers that need it. @@ -80,24 +82,6 @@ private void falseAnimation(CallbackInfo ci, @Local(argsOnly = true) PoseStack p } } - //#else - //#if MC >= 1.21.2 - //$$ @ModifyExpressionValue(method = "render(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", - //$$ at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;shouldRenderLayers(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;)Z")) - //$$ private boolean armOverrides(boolean original, @Local PoseStack pose) { - //$$ if (original) { - //#else - //$$ @ModifyExpressionValue(method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", - //$$ at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/LivingEntity;isSpectator()Z")) - //$$ private boolean armOverrides(boolean original, @Local PoseStack pose) { - //$$ if (!original) { - //#endif - //$$ // check arm overrides - //$$ IEMFModel model = (IEMFModel) getModel(); - //$$ if (model.emf$isEMFModel()) model.emf$getEMFRootModel().checkArmOverrides(pose); - //$$ } - //$$ return original; - //$$ } //#endif diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java index 9794f98e..8c58c9da 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinPlayerEntityRenderer.java @@ -96,10 +96,9 @@ public abstract class MixinPlayerEntityRenderer= 12109 + private static final String TRANSLATE = "Lnet/minecraft/client/model/ArmedModel;translateToHand(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/world/entity/HumanoidArm;Lcom/mojang/blaze3d/vertex/PoseStack;)V"; + //#else + //$$ private static final String TRANSLATE = "Lnet/minecraft/client/model/ArmedModel;translateToHand(Lnet/minecraft/world/entity/HumanoidArm;Lcom/mojang/blaze3d/vertex/PoseStack;)V"; + //#endif + @Inject(method = RENDER_ARM, at = @At(value = "HEAD")) - private void emf$setHand(final CallbackInfo ci, - //#if MC >= 12102 - @Local(argsOnly = true) S stateIn, - //#endif - @Local HumanoidArm arm, @Share("armOverride") LocalRef armOverride) { + private void emf$setHand(final CallbackInfo ci, @Local HumanoidArm arm) { EMFState.isInHand = true; - //#if MC >= 12102 - if (stateIn == null) return; - var state = (EMFEntityRenderState) ((HoldsETFRenderState) stateIn).etf$getState(); - //#else - //$$ var state = EMFState.state(); - //#endif - if (state == null) return; - - armOverride.set(arm == HumanoidArm.RIGHT ? state.rightArmOverride() : state.leftArmOverride()); + EMFState.isInLeftHand = arm == HumanoidArm.LEFT; } - @Inject( - method = RENDER_ARM, - at = @At(value = "INVOKE", target = - //#if MC >= 12109 - "Lnet/minecraft/client/model/ArmedModel;translateToHand(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/world/entity/HumanoidArm;Lcom/mojang/blaze3d/vertex/PoseStack;)V", - //#else - //$$ "Lnet/minecraft/client/model/ArmedModel;translateToHand(Lnet/minecraft/world/entity/HumanoidArm;Lcom/mojang/blaze3d/vertex/PoseStack;)V", - //#endif - shift = At.Shift.AFTER) - ) - private void emf$transforms(final CallbackInfo ci, @Local(argsOnly = true) PoseStack matrices, - @Share("armOverride") LocalRef armOverride, - @Share("needsPop") LocalBooleanRef needsToPop) { - if (armOverride.get() != null) { - var entry = armOverride.get().pose; - if (entry != null) { - needsToPop.set(true); + @Inject(method = RENDER_ARM, at = @At(value = "INVOKE", target = TRANSLATE)) + private void emf$transform(final CallbackInfo ci) { + EMFState.isInHandItemLayerTransform = true; + EMFState.hasDoneArmOverride = null; + } - //#if MC>=12105 - matrices.pushPose(); - matrices.last().set(entry); - //#else - //$$ matrices.poseStack.addLast(entry); - //#endif - } - } + @Inject(method = RENDER_ARM, at = @At(value = "INVOKE", target =TRANSLATE, shift = At.Shift.AFTER)) + private void emf$transform2(final CallbackInfo ci) { + EMFState.isInHandItemLayerTransform = false; } - @Inject(method = RENDER_ARM, - at = @At(value = "TAIL")) - private void emf$unsetHand(final CallbackInfo ci, @Local(argsOnly = true) PoseStack matrices, @Share("needsPop") LocalBooleanRef needsToPop) { + @Inject(method = RENDER_ARM, at = @At(value = "TAIL")) + private void emf$unsetHand(final CallbackInfo ci) { EMFState.isInHand = false; - if (needsToPop.get()) matrices.popPose(); + EMFState.isInLeftHand = null; } } \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java index 6e409e62..a48fbc00 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelPartRenderer.java @@ -28,9 +28,15 @@ public class Mixin_ModelPartRenderer { if (Minecraft.getInstance().player != null) { EMFState.modelVariationIgnoresVisibility = true; var state = EMFEntityRenderState.manualPlayerState(); - if (state != null) ETFState.mount(state); + if (state != null) { + state.setIsFirstPersonHand(true); + ETFState.mount(state); + } + } else { + var state = EMFState.state(); + if (state != null) state.setIsFirstPersonHand(true); } - if (EMFState.state() != null) EMFState.state().setIsFirstPersonHand(true); + } } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java index 88993b1c..53b2864e 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/Mixin_ModelRenderer.java @@ -74,17 +74,6 @@ private void applyArmorBipedPose( } } - - //#if MC >= 26.2 - //$$ @Inject(method = "prepareModel", at = @At(value = "TAIL")) - //$$ private void emf$endRender(final CallbackInfo ci) { - //$$ var state = EMFState.state(); - //$$ if (state != null && state.isFirstPersonHand()) { - //$$ ETFState.unMount(); - //$$ } - //$$ } - //#endif - } //#else //$$ @Mixin(traben.entity_texture_features.mixin.CancelTarget.class) diff --git a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java index b75dd9d4..e0dca2a3 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java +++ b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java @@ -939,8 +939,8 @@ private static void initOptifineMappings() { //$$ partMapping("right_foot", "right_haunch"), //$$ partMapping("left_thigh", "left_hind_leg"), //$$ partMapping("right_thigh", "right_hind_leg"), - //$$ partMapping("left_arm", "left_front_leg_r1"), - //$$ partMapping("right_arm", "right_front_leg_r1"), + //$$ partMapping("left_arm", "left_front_leg"), + //$$ partMapping("right_arm", "right_front_leg"), //$$ partMapping("head"), //$$ partMapping("frontlegs"), //$$ partMapping("backlegs"), diff --git a/src/main/java/traben/entity_model_features/models/animation/EMFAttachments.java b/src/main/java/traben/entity_model_features/models/animation/EMFAttachments.java index 78f4bd8f..977c2872 100644 --- a/src/main/java/traben/entity_model_features/models/animation/EMFAttachments.java +++ b/src/main/java/traben/entity_model_features/models/animation/EMFAttachments.java @@ -21,16 +21,7 @@ public EMFAttachments(float x, float y, float z, boolean right) { this.right = right; } - public void setAttachment(PoseStack entry) { - entry.pushPose(); + public void translate(PoseStack entry) { entry.translate(x / 16, y / 16, z / 16); - var copyOnly = entry.last(); - //#if MC>=12105 - this.pose = copyOnly.copy(); - //#else - //$$ this.pose = new PoseStack.Pose(new Matrix4f(copyOnly.pose()), new Matrix3f(copyOnly.normal())); - //#endif - - entry.popPose(); } } diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFBipedPose.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFBipedPose.java index 8bf3a227..3193ae3a 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFBipedPose.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFBipedPose.java @@ -11,7 +11,7 @@ public class EMFBipedPose { private final PosePart rightArm; private final PosePart leftLeg; private final PosePart rightLeg; - public final PosePart root; + private final PosePart root; public boolean applyToSubmit = false; diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java index 4ab7885e..0b502ce5 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java @@ -96,12 +96,6 @@ public interface EMFEntityRenderState extends ETFEntityRenderState { Function layerFactory(); void setLayerFactory(Function layerFactory); - @Nullable EMFAttachments leftArmOverride(); - void setLeftArmOverride(EMFAttachments override); - @Nullable EMFAttachments rightArmOverride(); - void setRightArmOverride(EMFAttachments override); - - void setBipedPose(EMFBipedPose pose); /** Returns the biped pose if it was animated. */ @Nullable EMFBipedPose getBipedPose(); @@ -163,8 +157,12 @@ default void preSubmitActivate(ETFSubmitData submitData, ) { ETFEntityRenderState.super.preSubmitActivate(submitData, vanillaSubmit); + // The specific submit might have more precise changes that multiple submits using the same state might need to + // be different, consider that here + if (submitData == null) { setSkipModelVariate(false); + setBipedPose(null); } else { Integer variant = (Integer) submitData.data.get("modelVariant"); if (variant != null && vanillaSubmit.model().root() instanceof EMFModelPartRoot root) { @@ -173,6 +171,9 @@ default void preSubmitActivate(ETFSubmitData submitData, } else { setSkipModelVariate(false); } + + // Submit data now controls if the state keeps this during the submit consumption phase, setting it null if we didn't want it this submit + if (!isFirstPersonHand()) setBipedPose((EMFBipedPose) submitData.data.get("bipedPose")); } setLayerFactory(vanillaSubmit.model().renderType); @@ -181,6 +182,7 @@ default void preSubmitActivate(ETFSubmitData submitData, EMFState.isInItemFrame = true; } + EMFState.isLayerPhase = false; if (submitData != null) { setOnShoulder(submitData.data.get("onShoulder") == Boolean.TRUE); @@ -258,16 +260,22 @@ default void activate(boolean inMount) { //perform variant checking for this entity types models //this is the only way to keep it generic and also before the entity is rendered and affect al its models - if (!skipModelVariate()) { + boolean playerNeedsReset = emfEntity() instanceof Player + && EMF.config().getConfig().resetPlayerModelEachRender_v2 + && !isFirstPersonHand(); + + if (!skipModelVariate() || playerNeedsReset) { Set roots = EMFManager.getInstance().rootPartsPerEntityTypeForVariation.get(typeString()); if (roots != null) { - if (EMFState.isEntityForcedToVanillaModel(this)) { - roots.forEach(root -> root.setVariantStateTo(0)); - } else { - roots.forEach(root -> root.doVariantCheck(this)); + if (!skipModelVariate()) { + if (EMFState.isEntityForcedToVanillaModel(this)) { + roots.forEach(root -> root.setVariantStateTo(0)); + } else { + roots.forEach(root -> root.doVariantCheck(this)); + } } - if (emfEntity() instanceof Player && EMF.config().getConfig().resetPlayerModelEachRender_v2) { + if (playerNeedsReset) { roots.forEach(EMFModelPartRoot::resetVanillaPartsToDefaults); } } @@ -286,7 +294,6 @@ && uuid().equals(EMFManager.getInstance().entityForDebugPrint)) { @Override default void deactivate(boolean inMount) { ETFEntityRenderState.super.deactivate(inMount); - EMFState.isLayerPhase = false; EMFState.modelVariationIgnoresVisibility = false; EMFState.isInItemFrame = false; diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java index 5e6acc16..3f986ed9 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java @@ -76,14 +76,6 @@ public void setLayerFactory(final Function layerFa this.layerFactory = layerFactory; } - private EMFAttachments leftArmOverride = null; - @Override public @Nullable EMFAttachments leftArmOverride() { return leftArmOverride; } - @Override public void setLeftArmOverride(EMFAttachments override) { leftArmOverride = override; } - - private EMFAttachments rightArmOverride = null; - @Override public @Nullable EMFAttachments rightArmOverride() { return rightArmOverride; } - @Override public void setRightArmOverride(EMFAttachments override) { rightArmOverride = override; } - EMFBipedPose bipedPose = null; @Override public void setBipedPose(EMFBipedPose pose) { bipedPose = pose; } @Override public EMFBipedPose getBipedPose() { return bipedPose; } diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFState.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFState.java index f8f7e5ce..dc8ec35c 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFState.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFState.java @@ -7,6 +7,7 @@ import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import traben.entity_model_features.EMF; import traben.entity_model_features.EMFManager; import traben.entity_model_features.mod_compat.IrisShadowPassDetection; @@ -52,7 +53,10 @@ public static void clear() { isInGroundOverride = false; isOnHead = false; isInHand = false; + isInLeftHand = null; isInItemFrame = false; + isInHandItemLayerTransform = false; + hasDoneArmOverride = null; } public static float frameCounter = 0; @@ -63,6 +67,9 @@ public static void clear() { public static boolean isInGroundOverride = false; public static boolean isOnHead = false; public static boolean isInHand = false; + public static @Nullable Boolean isInLeftHand = null; + public static boolean isInHandItemLayerTransform = false; + public static @Nullable Boolean hasDoneArmOverride = null; public static boolean isInItemFrame = false; public static boolean modelVariationIgnoresVisibility = false; diff --git a/src/main/java/traben/entity_model_features/models/jem_objects/EMFJemData.java b/src/main/java/traben/entity_model_features/models/jem_objects/EMFJemData.java index 6aa88b70..8d0ac090 100644 --- a/src/main/java/traben/entity_model_features/models/jem_objects/EMFJemData.java +++ b/src/main/java/traben/entity_model_features/models/jem_objects/EMFJemData.java @@ -28,7 +28,8 @@ public class EMFJemData { public transient EMFDirectoryHandler directoryContext = null; private transient EMFModel_ID mobModelIDInfo = null; private transient ResourceLocation customTexture = null; - public transient boolean hasAttachments = false; + public transient boolean hasAttachmentsLeft = false; + public transient boolean hasAttachmentsRight = false; public LinkedHashMap>> getAllTopLevelAnimationsByVanillaPartName() { return allTopLevelAnimationsByVanillaPartName; diff --git a/src/main/java/traben/entity_model_features/models/jem_objects/EMFPartData.java b/src/main/java/traben/entity_model_features/models/jem_objects/EMFPartData.java index 6d6f3232..cc040206 100644 --- a/src/main/java/traben/entity_model_features/models/jem_objects/EMFPartData.java +++ b/src/main/java/traben/entity_model_features/models/jem_objects/EMFPartData.java @@ -141,8 +141,9 @@ public void prepare(int[] textureSize, EMFJemData jem){ } } - if (!attachments.isEmpty() && (attachments.containsKey("left_handheld_item") || attachments.containsKey("right_handheld_item"))) { - jem.hasAttachments = true; + if (!attachments.isEmpty()) { + if (attachments.containsKey("left_handheld_item")) jem.hasAttachmentsLeft = true; + if (attachments.containsKey("right_handheld_item")) jem.hasAttachmentsRight = true; } if (translate == null) translate = new float[]{0, 0, 0}; diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java index 7c9c6688..35c5b709 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java @@ -6,6 +6,7 @@ import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape; import net.minecraft.world.phys.shapes.CubeVoxelShape; +import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; import traben.entity_model_features.EMF; import traben.entity_model_features.config.EMFConfig; @@ -14,6 +15,7 @@ import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.EMFUtils; +import traben.entity_model_features.utils.IEMFCuboidDataSupplier; import traben.entity_texture_features.ETF; import traben.entity_texture_features.features.state.ETFState; import traben.entity_texture_features.features.texture_handlers.ETFTexture; @@ -32,6 +34,7 @@ //#endif import java.util.*; +import java.util.function.Consumer; import net.minecraft.client.Minecraft; import net.minecraft.client.model.geom.ModelPart; @@ -67,11 +70,20 @@ public EMFModelPart(List cuboids, Map children, EMFMode this.root = root; } - public void processArmItemOverrides(PoseStack matrices) { - matrices.pushPose(); - translateAndRotate(matrices); - children.values().forEach(v -> ((EMFModelPart) v).processArmItemOverrides(matrices)); - matrices.popPose(); + protected @Nullable Consumer getArmPositioner(boolean left) { + for (ModelPart p : children.values()) { + if (p instanceof EMFModelPart part) { + var subConsumer = part.getArmPositioner(left); // Only a part with the correct attachment will end this deep search + if (subConsumer != null) { + return (stack) -> { + // Add this 'parent' to the cumulative stack transformation started by the child, and send it up the chain + this.translateAndRotate(stack); + subConsumer.accept(stack); + }; + } + } + } + return null; } @Override @@ -83,8 +95,22 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina //#endif ) { try { + if (ETFState.currentModelPartDepth != 1) { + renderWithTextureOverride(matrices, vertices, light, overlay, + //#if MC >= 12100 + k + //#else + //$$ red, green, blue, alpha + //#endif + ); + return; + } + + // This is the top level render + var choice = EMF.config().getConfig().getRenderModeFor(EMFState.state()); - //normal render + + // Normal render if (choice == EMFConfig.RenderModeChoice.NORMAL) { renderWithTextureOverride(matrices, vertices, light, overlay, //#if MC >= 12100 @@ -92,12 +118,13 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina //#else //$$ red, green, blue, alpha //#endif - ); + ); return; } - //debug choice chosen - //check if only render debug when hovered + // We want debug rendering but can we? + + // Check if only render debug when hovered if (EMF.config().getConfig().onlyDebugRenderOnHover && !EMFMath.isClientHovered()) { renderWithTextureOverride(matrices, vertices, light, overlay, //#if MC >= 12100 @@ -109,7 +136,18 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina return; } - //else render debug + // Now lets debug render + + if (choice.allowsRegularDraw()) { + renderWithTextureOverride(matrices, vertices, light, overlay, + //#if MC >= 12100 + k + //#else + //$$ red, green, blue, alpha + //#endif + ); + } + switch (choice) { case GREEN -> renderDebugTinted(matrices, vertices, light, overlay, @@ -123,36 +161,22 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina if (vertices instanceof ETFVertexConsumer etfVertexConsumer) { URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); if (provider != null) - renderBoxes(matrices, provider.getBuffer(lines())); + renderBoxes(matrices, provider.getBuffer(lines()), 1f); } } case LINES_AND_TEXTURE -> { - renderWithTextureOverride(matrices, vertices, light, overlay, - //#if MC >= 12100 - k - //#else - //$$ red, green, blue, alpha - //#endif - ); if (vertices instanceof ETFVertexConsumer etfVertexConsumer) { URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); if (provider != null) - renderBoxesNoChildren(matrices, provider.getBuffer(lines()), 1f); + renderBoxes(matrices, provider.getBuffer(lines()), 1f); } } case LINES_AND_TEXTURE_FLASH -> { - renderWithTextureOverride(matrices, vertices, light, overlay, - //#if MC >= 12100 - k - //#else - //$$ red, green, blue, alpha - //#endif - ); if (vertices instanceof ETFVertexConsumer etfVertexConsumer) { URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); if (provider != null) { float flash = (Mth.sin(System.currentTimeMillis() / 1000f) + 1) / 2f; - renderBoxesNoChildren(matrices, provider.getBuffer(lines()), flash); + renderBoxes(matrices, provider.getBuffer(lines()), flash); } } } @@ -471,7 +495,7 @@ void renderLikeETF(PoseStack matrices, VertexConsumer vertices, int light, int o } } - public void renderBoxes(PoseStack matrices, VertexConsumer vertices) { + public void renderBoxes(PoseStack matrices, VertexConsumer vertices, float alpha) { if (this.visible) { if (!cubes.isEmpty() || !children.isEmpty()) { matrices.pushPose(); @@ -479,21 +503,30 @@ public void renderBoxes(PoseStack matrices, VertexConsumer vertices) { if (!this.skipDraw) { for (Cube cuboid : cubes) { AABB box = new AABB(cuboid.minX / 16, cuboid.minY / 16, cuboid.minZ / 16, cuboid.maxX / 16, cuboid.maxY / 16, cuboid.maxZ / 16); + + var adds = ((IEMFCuboidDataSupplier) cuboid).emf$getSizeAdd(); + if (adds != null) { + if (adds[0] != 0 || adds[1] != 0 || adds[2] != 0) { + box = box.inflate(adds[0] / 16, adds[1] / 16, adds[2] / 16); + } + } + box = box.inflate(0.0001); + var col = debugBoxColor(); - //#if MC >=12111 - //$$ EMFUtils.renderLineBox(matrices.last(), vertices, box.inflate(0.0001), col[0], col[1], col[2], 1.0F); - //#elseif MC >=12109 - ShapeRenderer.renderLineBox(matrices.last(), vertices, box.inflate(0.0001), col[0], col[1], col[2], 1.0F); - //#elseif MC >=12102 - //$$ ShapeRenderer.renderLineBox(matrices, vertices, box.inflate(0.0001), col[0], col[1], col[2], 1.0F); + //#if MC >= 12111 + //$$ EMFUtils.renderLineBox(matrices.last(), vertices, box, col[0], col[1], col[2], alpha); + //#elseif MC >= 12109 + ShapeRenderer.renderLineBox(matrices.last(), vertices, box, col[0], col[1], col[2], alpha); + //#elseif MC >= 12102 + //$$ ShapeRenderer.renderLineBox(matrices, vertices, box, col[0], col[1], col[2], alpha); //#else - //$$ LevelRenderer.renderLineBox(matrices, vertices, box.inflate(0.0001), col[0], col[1], col[2], 1.0F); + //$$ LevelRenderer.renderLineBox(matrices, vertices, box, col[0], col[1], col[2], alpha); //#endif } } for (ModelPart modelPart : children.values()) { if (modelPart instanceof EMFModelPart emf) - emf.renderBoxes(matrices, vertices); + emf.renderBoxes(matrices, vertices, alpha); } matrices.popPose(); } @@ -502,31 +535,6 @@ public void renderBoxes(PoseStack matrices, VertexConsumer vertices) { protected abstract float[] debugBoxColor(); - public void renderBoxesNoChildren(PoseStack matrices, VertexConsumer vertices, float alpha) { - if (this.visible) { - if (!cubes.isEmpty() || !children.isEmpty()) { - matrices.pushPose(); - this.translateAndRotate(matrices); - if (!this.skipDraw) { - for (Cube cuboid : cubes) { - AABB box = new AABB(cuboid.minX / 16, cuboid.minY / 16, cuboid.minZ / 16, cuboid.maxX / 16, cuboid.maxY / 16, cuboid.maxZ / 16); - var col = debugBoxColor(); - //#if MC >=12111 - //$$ EMFUtils.renderLineBox(matrices.last(), vertices, box.inflate(0.0001), col[0], col[1], col[2], alpha); - //#elseif MC >=12109 - ShapeRenderer.renderLineBox(matrices.last(), vertices, box.inflate(0.0001), col[0], col[1], col[2], alpha); - //#elseif MC >=12102 - //$$ ShapeRenderer.renderLineBox(matrices, vertices, box.inflate(0.0001), col[0], col[1], col[2], alpha); - //#else - //$$ LevelRenderer.renderLineBox(matrices, vertices, box.inflate(0.0001), col[0], col[1], col[2], alpha); - //#endif - } - } - matrices.popPose(); - } - } - } - //required for sodium pre 0.5.4 // overrides to circumvent sodium optimizations that mess with custom uv quad creation and swapping out cuboids @Override diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartCustom.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartCustom.java index 715da32b..3440f6b8 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartCustom.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartCustom.java @@ -19,6 +19,7 @@ import com.mojang.blaze3d.vertex.VertexConsumer; import java.util.*; +import java.util.function.Consumer; //#if MC < 12002 //$$ import org.joml.Matrix3f; @@ -134,23 +135,19 @@ public String toStringShort() { } @Override - public void processArmItemOverrides(PoseStack matrices) { + protected @Nullable Consumer getArmPositioner(boolean left) { if (attachments != null) { for (EMFAttachments attachment : attachments) { - matrices.pushPose(); - this.translateAndRotate(matrices); - attachment.setAttachment(matrices); - matrices.popPose(); - - var state = EMFState.state(); - if (state != null) { - if (attachment.right) state.setRightArmOverride(attachment); - else state.setLeftArmOverride(attachment); + if (attachment.right != left) { + // End deep search here + return poseStack -> { + translateAndRotate(poseStack); + attachment.translate(poseStack); + }; } } - } else { - super.processArmItemOverrides(matrices); } + return super.getArmPositioner(left); } @Override @@ -161,9 +158,6 @@ public void render(PoseStack matrices, VertexConsumer vertices, int light, int o //$$ float red, float green, float blue, float alpha //#endif ) { - //#if MC < 12109 - //$$ processArmItemOverrides(matrices); - //#endif super.render(matrices, vertices, light, overlay, //#if MC >= 12100 @@ -176,7 +170,7 @@ public void render(PoseStack matrices, VertexConsumer vertices, int light, int o @Override protected float[] debugBoxColor() { - return new float[]{1f, 1f, 1f}; + return EMFState.isLayerPhase ? new float[]{0f, 0f, 1f} : new float[]{1f, 1f, 1f}; } diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java index 529792b3..2b8b4a65 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java @@ -24,6 +24,7 @@ import traben.entity_texture_features.features.property_reading.PropertiesRandomProvider; import java.util.*; +import java.util.function.Consumer; import static traben.entity_model_features.EMFManager.getJemDataWithDirectory; @@ -45,11 +46,15 @@ public class EMFModelPartRoot extends EMFModelPartVanilla { public boolean containsCustomAnims = false; private long lastMobCountAnimatedOn = 0; private boolean hasRemovedTopLevelJemTextureFromChildren = false; - private boolean hasArmItemOverrides = false; + + protected final Set hasRightArmItemOverrides = new HashSet<>(); + protected final Set hasLeftArmItemOverrides = new HashSet<>(); + protected final Map> leftArmPositioners = new HashMap<>(); + protected final Map> rightArmPositioners = new HashMap<>(); public boolean isMainModel = false; - private Set registeredSet = new HashSet<>(); + private final Set registeredSet = new HashSet<>(); private final HashMap animations = new HashMap<>(); @Nullable @@ -158,11 +163,10 @@ public void checkIfShouldExpireEntity(@NotNull EMFEntityRenderState emfState, UU } //root only - public void addVariantOfJem(EMFJemData jemData, int variant) { + public void addAndSetVariantOfJem(EMFJemData jemData, int variant) { if (EMF.config().getConfig().logModelCreationData) EMFUtils.log(" > " + jemData.getMobModelIDInfo().getfileName() + ", constructing variant #" + variant); - if (jemData.hasAttachments) this.hasArmItemOverrides = true; Map newEmfParts = new HashMap<>(); for (EMFPartData part : jemData.models) { @@ -201,6 +205,17 @@ public void addVariantOfJem(EMFJemData jemData, int variant) { } allKnownStateVariants.putIfAbsent(variant, allKnownStateVariants.get(0).copy()); + + setVariantStateTo(variant); + + if (jemData.hasAttachmentsLeft) { + this.hasLeftArmItemOverrides.add(variant); + this.leftArmPositioners.put(variant, getArmPositioner(true)); + } + if (jemData.hasAttachmentsRight) { + this.hasRightArmItemOverrides.add(variant); + this.rightArmPositioners.put(variant, getArmPositioner(false)); + } } public void discoverAndInitVariants(String fallbackPropertiesName) { @@ -257,8 +272,7 @@ public void discoverAndInitVariants(String fallbackPropertiesName) { EMFJemData jemDataVariant = canUseVariant ? getJemDataWithDirectory(variantDirectoryContext, modelName) : null; if (jemDataVariant != null) { - addVariantOfJem(jemDataVariant, variant); - setVariantStateTo(variant); + addAndSetVariantOfJem(jemDataVariant, variant); EMFManager.getInstance().setupAnimationsFromJemToModel(jemDataVariant, this, variant); containsCustomModel = true; } else { @@ -324,11 +338,6 @@ public boolean hasAnimation(){ public void triggerManualAnimation(PoseStack pose) { if (animation != null) animation.run(); - checkArmOverrides(pose); - } - - public void checkArmOverrides(PoseStack pose) { - if (hasArmItemOverrides) processArmItemOverrides(pose); } public ModelPart getVanillaFormatRoot() { diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartVanilla.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartVanilla.java index 7ab8662d..b276b6df 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartVanilla.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartVanilla.java @@ -3,10 +3,12 @@ import net.minecraft.client.model.geom.ModelPart; import traben.entity_model_features.EMF; +import traben.entity_model_features.models.animation.state.EMFState; import traben.entity_model_features.utils.EMFUtils; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import java.util.*; +import java.util.function.Consumer; public class EMFModelPartVanilla extends EMFModelPartWithState { @@ -53,6 +55,43 @@ public ModelPart[] getAllEMFCustomChildren() { .toArray(ModelPart[]::new); } + @Override + public void translateAndRotate(PoseStack poseStack) { + if (EMFState.isInHandItemLayerTransform && EMFState.isInLeftHand != null) { + // Held item rendering runs this to translate for hand positioning, but we might have attachment points set in any arbitrary part at any depth + // To account for this on the first call to this method during that layer call we will run that stack through + // the root's positioner + var root = getRoot(); + boolean leftArm = EMFState.isInLeftHand == Boolean.TRUE; + if ((leftArm && root.hasLeftArmItemOverrides.contains(currentModelVariant)) + || (!leftArm && root.hasRightArmItemOverrides.contains(currentModelVariant))) { + // Already done the once only transform + if (EMFState.hasDoneArmOverride == Boolean.TRUE) return; + // Already failed the once only transform + if (EMFState.hasDoneArmOverride == Boolean.FALSE) { + super.translateAndRotate(poseStack); + return; + } + + Consumer positioner = leftArm + ? root.leftArmPositioners.get(currentModelVariant) + : root.rightArmPositioners.get(currentModelVariant); + + if (positioner != null) { + EMFState.isInHandItemLayerTransform = false; // Very likely to recurse into this method + positioner.accept(poseStack); + EMFState.isInHandItemLayerTransform = true; + EMFState.hasDoneArmOverride = Boolean.TRUE; + } else { + EMFState.hasDoneArmOverride = Boolean.FALSE; + } + return; + } + } + + // Normal or aborted call + super.translateAndRotate(poseStack); + } @Override protected float[] debugBoxColor() { @@ -69,7 +108,6 @@ public void render(PoseStack matrices, VertexConsumer vertices, int light, int o ) { //ignore non optifine specified parts when not vanilla variant if (!hideInTheseStates.contains(currentModelVariant)){ -// if (legacyScaler == null) { super.render(matrices, vertices, light, overlay, //#if MC >= 12100 k @@ -77,13 +115,6 @@ public void render(PoseStack matrices, VertexConsumer vertices, int light, int o //$$ red, green, blue, alpha //#endif ); -// }else{ -// matrices.pushPose(); -// legacyScaler.accept(matrices); -// super.render(matrices, vertices, light, overlay, #if MC >= MC_21 k #else red, green, blue, alpha #endif); -// matrices.popPose(); -// } - } } From 4d35c385480d77ea27d98360e6c8f12ee4662013 Mon Sep 17 00:00:00 2001 From: Traben Date: Wed, 19 Aug 2026 19:57:14 +1000 Subject: [PATCH 14/20] export uv mirroring --- CHANGELOG.MD | 4 ++-- .../mixin/mixins/MixinModelPart$Cuboid.java | 9 +++++++++ .../models/EMFModelMappings.java | 12 +++++++++--- .../utils/IEMFCuboidDataSupplier.java | 2 ++ 4 files changed, 22 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 3297b876..d66762f3 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,7 +1,7 @@ [?] -- fixed several model exporting issues, including missing parts, wrong rotations, and rabbit/axolotl legs on 26.1+ -- fixed vex items not matching animated arm positions +- fixed several model exporting issues, including missing parts, wrong rotations, missing mirrored uvs, and rabbit/axolotl legs on 26.1+ +- fixed vex & allay items not matching animated arm positions - improved item attachment handling - fixed debug outline rendering not outlining everything - fixed 26.2 neoforge iris compatibility not working causing excess animation during the shadow pass diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinModelPart$Cuboid.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinModelPart$Cuboid.java index 89fbe561..d4ce7543 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinModelPart$Cuboid.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinModelPart$Cuboid.java @@ -24,12 +24,16 @@ public class MixinModelPart$Cuboid implements IEMFCuboidDataSupplier { @Unique private int[] emf$textureXY = null; + @Unique + private boolean emf$mirror = false; + @Inject(method = "", at = @At(value = "TAIL")) private void emf$injectAnnouncerCube(final int u, final int v, final float x, final float y, final float z, final float sizeX, final float sizeY, final float sizeZ, final float extraX, final float extraY, final float extraZ, final boolean mirror, final float textureWidth, final float textureHeight, final Set set, final CallbackInfo ci) { emf$textureUV = new int[]{u, v}; emf$sizeAdd = new float[]{extraX, extraY, extraZ}; emf$textureXY = new int[]{(int) textureWidth, (int) textureHeight}; + emf$mirror = mirror; } @Override @@ -46,4 +50,9 @@ public class MixinModelPart$Cuboid implements IEMFCuboidDataSupplier { public float[] emf$getSizeAdd() { return emf$sizeAdd; } + + @Override + public boolean emf$getMirror() { + return emf$mirror; + } } \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java index e0dca2a3..79f0dc96 100644 --- a/src/main/java/traben/entity_model_features/models/EMFModelMappings.java +++ b/src/main/java/traben/entity_model_features/models/EMFModelMappings.java @@ -1738,12 +1738,14 @@ private static JsonObject partPrinter(PartAndOffsets partAndOffsets, JsonObject cube.maxY - cube.minY, cube.maxZ - cube.minZ}; // can be different from part - thisTextureSize = thisTextureSize == null ? ((IEMFCuboidDataSupplier) cube).emf$getTextureXY() : thisTextureSize; - var uv = ((IEMFCuboidDataSupplier) cube).emf$getTextureUV(); + IEMFCuboidDataSupplier cubeData = (IEMFCuboidDataSupplier) cube; + thisTextureSize = thisTextureSize == null ? cubeData.emf$getTextureXY() : thisTextureSize; + + var uv = cubeData.emf$getTextureUV(); addArrayProperty(boxPrinter, "textureOffset", uv[0], uv[1]); - var adds = ((IEMFCuboidDataSupplier) cube).emf$getSizeAdd(); + var adds = cubeData.emf$getSizeAdd(); if (adds != null) { if (adds[0] == adds[1] && adds[0] == adds[2]) { if (adds[0] != 0) boxPrinter.addProperty("sizeAdd", adds[0]); @@ -1754,6 +1756,10 @@ private static JsonObject partPrinter(PartAndOffsets partAndOffsets, JsonObject } } + if (cubeData.emf$getMirror()) { + partPrinter.addProperty("mirrorTexture", "u"); + } + // invert x and y if (!child) { coordinates[0] = -coordinates[0] - coordinates[3] - x; diff --git a/src/main/java/traben/entity_model_features/utils/IEMFCuboidDataSupplier.java b/src/main/java/traben/entity_model_features/utils/IEMFCuboidDataSupplier.java index 6d474188..e808d052 100644 --- a/src/main/java/traben/entity_model_features/utils/IEMFCuboidDataSupplier.java +++ b/src/main/java/traben/entity_model_features/utils/IEMFCuboidDataSupplier.java @@ -8,4 +8,6 @@ public interface IEMFCuboidDataSupplier { int[] emf$getTextureXY(); float[] emf$getSizeAdd(); + + boolean emf$getMirror(); } From 8ac855f58a2289509aee3ef06c13eb435fa5e84a Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 20 Aug 2026 10:19:36 +1000 Subject: [PATCH 15/20] fix block entities --- .../entity_model_features/EMFManager.java | 11 +++++----- .../config/EMFConfig.java | 1 - .../MixinBlockEntityRendererFactories.java | 20 ++++++++--------- .../rendering/MixinEntityRenderers.java | 14 ++++++------ ...delRenderers_SetCurrentSpecifiedModel.java | 22 +++++++++---------- .../models/parts/EMFModelPart.java | 10 +-------- 6 files changed, 35 insertions(+), 43 deletions(-) diff --git a/src/main/java/traben/entity_model_features/EMFManager.java b/src/main/java/traben/entity_model_features/EMFManager.java index 83771629..aed30f7e 100644 --- a/src/main/java/traben/entity_model_features/EMFManager.java +++ b/src/main/java/traben/entity_model_features/EMFManager.java @@ -91,7 +91,7 @@ public class EMFManager {//singleton for data holding and resetting needs public UUID entityForDebugPrint = null; public long entityRenderCount = 0; public boolean isAnimationValidationPhase = false; - public String currentSpecifiedModelLoading = ""; + public final ThreadLocal currentSpecifiedModelLoading = ThreadLocal.withInitial(() -> ""); public BlockEntityType currentBlockEntityTypeLoading = null; private boolean traderLlamaHappened = false; @@ -109,7 +109,6 @@ public void receiveException(Exception exception) { private EMFManager() { IS_PHYSICS_MOD_INSTALLED = ETF.isThisModLoaded("physicsmod"); -// IS_IRIS_INSTALLED = EMFVersionDifferenceManager.isThisModLoaded("iris") || EMFVersionDifferenceManager.isThisModLoaded("oculus"); IS_EBE_INSTALLED = ETF.isThisModLoaded("enhancedblockentities"); lastModelRuleOfEntity = new ETFLruCache.UUIDInteger(); lastModelRuleOfEntity.defaultReturnValue(0); @@ -249,6 +248,8 @@ public void modifyEBEIfRequired() { } public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final ModelPart root) { + final String currentSpecifiedModelLoading = this.currentSpecifiedModelLoading.get(); + var allowedCEM = EMF.config().getConfig().allowedCEM; if (!allowedCEM.isOn()) return root; @@ -488,7 +489,7 @@ public ModelPart injectIntoModelRootGetter(final ModelLayerLocation layer, final if (currentSpecifiedModelLoading.startsWith("emf$boat$")) { String type = currentSpecifiedModelLoading.substring(9); mobNameForFileAndMap.setBoth(type + "_boat_patch", "boat_patch").addFallbackModel("boat_patch").resetCacheID(); - currentSpecifiedModelLoading = ""; + this.currentSpecifiedModelLoading.set(""); } else { mobNameForFileAndMap.setBoth("boat_patch"); } @@ -812,7 +813,7 @@ private void getDoubleChest(ModelPart root, EMFModel_ID mobNameForFileAndMap, bo String thisSide = isRight ? "right" : "left"; String otherSide = isRight ? "left" : "right"; - mobNameForFileAndMap.setBoth(currentSpecifiedModelLoading + "_large", "double_chest_" + thisSide); + mobNameForFileAndMap.setBoth(currentSpecifiedModelLoading.get() + "_large", "double_chest_" + thisSide); if (EMF.config().getConfig().doubleChestAnimFix) { if (printing) EMFUtils.log("injecting empty " + otherSide + " side parts into 'double chest' for animation purposes"); @@ -823,7 +824,7 @@ private void getDoubleChest(ModelPart root, EMFModel_ID mobNameForFileAndMap, bo root.children = newChildren; // mutable } mobNameForFileAndMap.addFallbackModel(mobNameForFileAndMap.namespace, mobNameForFileAndMap.getfileName()); - mobNameForFileAndMap.setFileName(currentSpecifiedModelLoading + "_" + thisSide) + mobNameForFileAndMap.setFileName(currentSpecifiedModelLoading.get() + "_" + thisSide) .resetCacheID(); } diff --git a/src/main/java/traben/entity_model_features/config/EMFConfig.java b/src/main/java/traben/entity_model_features/config/EMFConfig.java index c8e1fc57..2aa2eb33 100644 --- a/src/main/java/traben/entity_model_features/config/EMFConfig.java +++ b/src/main/java/traben/entity_model_features/config/EMFConfig.java @@ -552,7 +552,6 @@ public String toString() { public enum RenderModeChoice { NORMAL("entity_model_features.config.render.normal"), - GREEN("entity_model_features.config.render.green"), LINES_AND_TEXTURE("entity_model_features.config.render.lines_texture"), LINES_AND_TEXTURE_FLASH("entity_model_features.config.render.lines_texture_flash"), LINES("entity_model_features.config.render.lines"), diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinBlockEntityRendererFactories.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinBlockEntityRendererFactories.java index cd0c3c66..6daab041 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinBlockEntityRendererFactories.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinBlockEntityRendererFactories.java @@ -35,7 +35,7 @@ public class MixinBlockEntityRendererFactories { @Inject(method = "createEntityRenderers", at = @At(value = "RETURN")) private static void emf$clearMarker(final BlockEntityRendererProvider.Context args, final CallbackInfoReturnable, BlockEntityRenderer>> cir) { if (EMF.testForForgeLoadingError()) return; - EMFManager.getInstance().currentSpecifiedModelLoading = ""; + EMFManager.getInstance().currentSpecifiedModelLoading.set(""); EMFManager.getInstance().currentBlockEntityTypeLoading = null; if (EMF.config().getConfig().logModelCreationData || EMF.config().getConfig().automaticModelExporting) EMFUtils.log("Identified block entity renderers: " + emf$renderers); @@ -52,15 +52,15 @@ public class MixinBlockEntityRendererFactories { // TODO DONT FORGET TO REPLICATE CHANGES IN SPECIAL RENDERERS if (UEntityTypes.ENCHANTING_TABLE.equals(type)) - EMFManager.getInstance().currentSpecifiedModelLoading = "enchanting_book"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("enchanting_book"); else if (UEntityTypes.LECTERN.equals(type)) - EMFManager.getInstance().currentSpecifiedModelLoading = "lectern_book"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("lectern_book"); else if (UEntityTypes.CHEST.equals(type)) - EMFManager.getInstance().currentSpecifiedModelLoading = "chest"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("chest"); else if (UEntityTypes.ENDER_CHEST.equals(type)) - EMFManager.getInstance().currentSpecifiedModelLoading = "ender_chest"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("ender_chest"); else if (UEntityTypes.TRAPPED_CHEST.equals(type)) - EMFManager.getInstance().currentSpecifiedModelLoading = "trapped_chest"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("trapped_chest"); //#if MC >= 12002 //todo did deprecation start in 1.21.2? else if (type.builtInRegistryHolder() != null && type.builtInRegistryHolder().unwrapKey().isPresent()) { @@ -70,14 +70,14 @@ else if (type.builtInRegistryHolder() != null && type.builtInRegistryHolder().un //$$ ResourceLocation id = BuiltInRegistries.BLOCK_ENTITY_TYPE.getResourceKey(type).get().location(); //#endif if (id.getNamespace().equals("minecraft")) { - EMFManager.getInstance().currentSpecifiedModelLoading = id.getPath(); + EMFManager.getInstance().currentSpecifiedModelLoading.set(id.getPath()); } else { - EMFManager.getInstance().currentSpecifiedModelLoading = id.getNamespace() + ":" + id.getPath(); + EMFManager.getInstance().currentSpecifiedModelLoading.set(id.getNamespace() + ":" + id.getPath()); } } - emf$renderers.add(EMFManager.getInstance().currentSpecifiedModelLoading); + emf$renderers.add(EMFManager.getInstance().currentSpecifiedModelLoading.get()); if (EMF.config().getConfig().logModelCreationData) - EMFUtils.log("Seeing block entity renderer init for: " + EMFManager.getInstance().currentSpecifiedModelLoading); + EMFUtils.log("Seeing block entity renderer init for: " + EMFManager.getInstance().currentSpecifiedModelLoading.get()); // og code action.accept(type, idk); diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderers.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderers.java index d6347d7f..1523cb3c 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderers.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderers.java @@ -29,33 +29,33 @@ public class MixinEntityRenderers { private static void emf$locateTransient(final ImmutableMap.Builder builder, final EntityRendererProvider.Context context, final EntityType entityType, final EntityRendererProvider entityRendererProvider, final CallbackInfo ci) { //#if MC == 12103 //$$ if (entityType.equals(EntityType.CREAKING_TRANSIENT)) { - //$$ EMFManager.getInstance().currentSpecifiedModelLoading = "creaking_transient"; + //$$ EMFManager.getInstance().currentSpecifiedModelLoading.set("creaking_transient"); //$$ } else //#endif if(entityType.equals(UEntityTypes.SPECTRAL_ARROW)) { - EMFManager.getInstance().currentSpecifiedModelLoading = "spectral_arrow"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("spectral_arrow"); }else if (entityType.equals(UEntityTypes.BREEZE_WIND_CHARGE)) { - EMFManager.getInstance().currentSpecifiedModelLoading = "breeze_wind_charge"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("breeze_wind_charge"); }else if (entityType //#if MC >= 26.1 //$$ .builtInRegistryHolder() //#endif .is(EntityTypeTags.BOAT)) { //entity.minecraft.dark_oak_boat - EMFManager.getInstance().currentSpecifiedModelLoading = "emf$boat$" //key to not override + EMFManager.getInstance().currentSpecifiedModelLoading.set("emf$boat$" //key to not override + entityType.getDescriptionId() .replaceAll("entity.minecraft.","") - .replaceAll("(_boat|_raft|_chest_boat)$",""); + .replaceAll("(_boat|_raft|_chest_boat)$","")); } //#if MC >= 12111 //$$ else if (entityType.equals(UEntityTypes.CAMEL_HUSK)) { - //$$ EMFManager.getInstance().currentSpecifiedModelLoading = "camel_husk"; + //$$ EMFManager.getInstance().currentSpecifiedModelLoading.set("camel_husk"); //$$ } //#endif } @Inject(method = method, at = @At(value = "TAIL")) private static void emf$reset(final ImmutableMap.Builder builder, final EntityRendererProvider.Context context, final EntityType entityType, final EntityRendererProvider entityRendererProvider, final CallbackInfo ci) { - EMFManager.getInstance().currentSpecifiedModelLoading = ""; + EMFManager.getInstance().currentSpecifiedModelLoading.set(""); } //#endif } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/Mixin_SpecialModelRenderers_SetCurrentSpecifiedModel.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/Mixin_SpecialModelRenderers_SetCurrentSpecifiedModel.java index 61fd1fb8..dedb2f24 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/Mixin_SpecialModelRenderers_SetCurrentSpecifiedModel.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/Mixin_SpecialModelRenderers_SetCurrentSpecifiedModel.java @@ -47,7 +47,7 @@ public class Mixin_SpecialModelRenderers_SetCurrentSpecifiedModel { , at = @At(value = "RETURN")) private static void emf$clearMarker(CallbackInfoReturnable>> cir) { if (EMF.testForForgeLoadingError()) return; - EMFManager.getInstance().currentSpecifiedModelLoading = ""; + EMFManager.getInstance().currentSpecifiedModelLoading.set(""); EMFManager.getInstance().currentBlockEntityTypeLoading = null; if (EMF.config().getConfig().logModelCreationData || EMF.config().getConfig().automaticModelExporting) EMFUtils.log("Identified SPECIAL block entity renderers: " + emf$renderers); @@ -80,31 +80,31 @@ private static void setModel(BlockState state) { // TODO DONT FORGET TO REPLICATE CHANGES IN REGULAR RENDERERS if (state.is(Blocks.ENCHANTING_TABLE)) - EMFManager.getInstance().currentSpecifiedModelLoading = "enchanting_book"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("enchanting_book"); else if (state.is(Blocks.LECTERN)) - EMFManager.getInstance().currentSpecifiedModelLoading = "lectern_book"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("lectern_book"); else if (state.is(Blocks.CHEST)) - EMFManager.getInstance().currentSpecifiedModelLoading = "chest"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("chest"); else if (state.is(Blocks.ENDER_CHEST)) - EMFManager.getInstance().currentSpecifiedModelLoading = "ender_chest"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("ender_chest"); else if (state.is(Blocks.TRAPPED_CHEST)) - EMFManager.getInstance().currentSpecifiedModelLoading = "trapped_chest"; + EMFManager.getInstance().currentSpecifiedModelLoading.set("trapped_chest"); else { try { ResourceLocation id = BuiltInRegistries.BLOCK.wrapAsHolder(state.getBlock()).unwrapKey().get().location(); if (id.getNamespace().equals("minecraft")) { - EMFManager.getInstance().currentSpecifiedModelLoading = id.getPath(); + EMFManager.getInstance().currentSpecifiedModelLoading.set(id.getPath()); } else { - EMFManager.getInstance().currentSpecifiedModelLoading = id.getNamespace() + ":" + id.getPath(); + EMFManager.getInstance().currentSpecifiedModelLoading.set(id.getNamespace() + ":" + id.getPath()); } } catch (Exception e) { - EMFManager.getInstance().currentSpecifiedModelLoading = state.toString(); + EMFManager.getInstance().currentSpecifiedModelLoading.set(state.toString()); } } - emf$renderers.add(EMFManager.getInstance().currentSpecifiedModelLoading); + emf$renderers.add(EMFManager.getInstance().currentSpecifiedModelLoading.get()); if (EMF.config().getConfig().logModelCreationData) - EMFUtils.log("Seeing SPECIAL block entity renderer init for: " + EMFManager.getInstance().currentSpecifiedModelLoading); + EMFUtils.log("Seeing SPECIAL block entity renderer init for: " + EMFManager.getInstance().currentSpecifiedModelLoading.get()); } } diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java index 35c5b709..ff3a177a 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPart.java @@ -95,7 +95,7 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina //#endif ) { try { - if (ETFState.currentModelPartDepth != 1) { + if (ETFState.currentModelPartDepth != 0) { renderWithTextureOverride(matrices, vertices, light, overlay, //#if MC >= 12100 k @@ -149,14 +149,6 @@ public void render(final PoseStack matrices, final VertexConsumer vertices, fina } switch (choice) { - case GREEN -> - renderDebugTinted(matrices, vertices, light, overlay, - //#if MC >= 12100 - k - //#else - //$$ red, green, blue, alpha - //#endif - ); case LINES ->{ if (vertices instanceof ETFVertexConsumer etfVertexConsumer) { URenderTypeToVertexConsumer provider = etfVertexConsumer.etf$getProvider(); From 0c6375086cd1cf391921607308f6cf73c840806f Mon Sep 17 00:00:00 2001 From: Traben Date: Thu, 20 Aug 2026 10:42:13 +1000 Subject: [PATCH 16/20] clear deprecated configs --- CHANGELOG.MD | 1 + .../config/EMFConfig.java | 72 ++++--------------- .../rendering/MixinLivingEntityRenderer.java | 50 ------------- .../models/parts/EMFModelPartRoot.java | 38 ---------- .../entity_model_features/lang/en_us.json | 8 --- 5 files changed, 15 insertions(+), 154 deletions(-) diff --git a/CHANGELOG.MD b/CHANGELOG.MD index d66762f3..82e803a2 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -1,6 +1,7 @@ [?] - fixed several model exporting issues, including missing parts, wrong rotations, missing mirrored uvs, and rabbit/axolotl legs on 26.1+ +- fixed block entity models breaking in the latest versions - fixed vex & allay items not matching animated arm positions - improved item attachment handling - fixed debug outline rendering not outlining everything diff --git a/src/main/java/traben/entity_model_features/config/EMFConfig.java b/src/main/java/traben/entity_model_features/config/EMFConfig.java index 2aa2eb33..077ed8ea 100644 --- a/src/main/java/traben/entity_model_features/config/EMFConfig.java +++ b/src/main/java/traben/entity_model_features/config/EMFConfig.java @@ -57,14 +57,14 @@ public class EMFConfig extends TConfig { public boolean logModelCreationData = false; public boolean debugOnRightClick = false; public RenderModeChoice renderModeChoice = RenderModeChoice.NORMAL; - public VanillaModelRenderMode vanillaModelHologramRenderMode_2 = VanillaModelRenderMode.OFF; + @Deprecated(forRemoval = true) public VanillaModelRenderMode vanillaModelHologramRenderMode_2 = VanillaModelRenderMode.OFF; @Deprecated(forRemoval = true) public ModelPrintMode modelExportMode = ModelPrintMode.NONE; public boolean automaticModelExporting = false; @Deprecated(forRemoval = true) public PhysicsModCompatChoice attemptPhysicsModPatch_2 = PhysicsModCompatChoice.CUSTOM; public ETFConfig.UpdateFrequency modelUpdateFrequency = ETFConfig.UpdateFrequency.Average; public ETFConfig.String2EnumNullMap entityRenderModeOverrides = new ETFConfig.String2EnumNullMap<>(); @Deprecated(forRemoval = true) public ETFConfig.String2EnumNullMap entityPhysicsModPatchOverrides = new ETFConfig.String2EnumNullMap<>(); - public ETFConfig.String2EnumNullMap entityVanillaHologramOverrides = new ETFConfig.String2EnumNullMap<>(); + @Deprecated(forRemoval = true) public ETFConfig.String2EnumNullMap entityVanillaHologramOverrides = new ETFConfig.String2EnumNullMap<>(); public RenderModeChoice getRenderModeFor(@Nullable EMFEntityRenderState state) { if (state == null || entityRenderModeOverrides.isEmpty()) return renderModeChoice; @@ -84,11 +84,9 @@ public RenderModeChoice getRenderModeFor(@Nullable EMFEntity entity) { return Objects.requireNonNullElse(entityPhysicsModPatchOverrides.get(typeString), attemptPhysicsModPatch_2); } - public VanillaModelRenderMode getVanillaHologramModeFor(EMFEntity entity) { - if (entityVanillaHologramOverrides.isEmpty()) return vanillaModelHologramRenderMode_2; - String typeString = getTypeString(entity); - if (typeString == null) return vanillaModelHologramRenderMode_2; - return Objects.requireNonNullElse(entityVanillaHologramOverrides.get(typeString), vanillaModelHologramRenderMode_2); + @Deprecated(forRemoval = true) + public VanillaModelRenderMode getVanillaHologramModeFor(EMFEntity ignored) { + return VanillaModelRenderMode.OFF; } private static @Nullable String getTypeString(final EMFEntity entity) { @@ -141,10 +139,6 @@ public TConfigEntryCategory getGUIOptions() { new TConfigEntryCategory("entity_model_features.config.options", "entity_model_features.config.options.tooltip").add( new TConfigEntryEnumButton<>("entity_model_features.config.allowed_cem", "entity_model_features.config.allowed_cem.tooltip", () -> allowedCEM, (it) -> allowedCEM = it, CustomEntityModelSupportMode.ALL), -// new TConfigEntryBoolean("entity_model_features.config.force_models", "entity_model_features.config.force_models.tooltip", -// () -> attemptRevertingEntityModelsAlteredByAnotherMod, value -> attemptRevertingEntityModelsAlteredByAnotherMod = value, true), -// new TConfigEntryEnumButton<>("entity_model_features.config.physics", "entity_model_features.config.physics.tooltip", -// () -> attemptPhysicsModPatch_2, value -> attemptPhysicsModPatch_2 = value, PhysicsModCompatChoice.CUSTOM), new TConfigEntryBoolean("entity_model_features.config.ebe_config_modify", "entity_model_features.config.ebe_config_modify.tooltip", () -> allowEBEModConfigModify, value -> allowEBEModConfigModify = value, true), new TConfigEntryBoolean("entity_model_features.config.double_chest_fix", "entity_model_features.config.double_chest_fix.tooltip", @@ -173,8 +167,6 @@ public TConfigEntryCategory getGUIOptions() { ), new TConfigEntryCategory("entity_model_features.config.tools", "entity_model_features.config.tools.tooltip").add( - new TConfigEntryEnumSlider<>("entity_model_features.config.vanilla_render", "entity_model_features.config.vanilla_render.tooltip", - () -> vanillaModelHologramRenderMode_2, value -> vanillaModelHologramRenderMode_2 = value, VanillaModelRenderMode.OFF), new TConfigEntryBoolean("entity_model_features.config.print_mode", "entity_model_features.config.print_mode.tooltip", () -> automaticModelExporting, value -> automaticModelExporting = value, false) ), @@ -206,7 +198,7 @@ public TConfigEntryCategory getGUIOptions() { () -> logASM, value -> logASM = value, false) ), getModelSettings() , getMathInfo() - )//, new TConfigEntryCategory("config.entity_features.general_settings.title") + ) , getEntitySettings(), new TConfigEntryCategory("config.entity_features.optifine_settings","config.entity_texture_features.optifine.desc").add( new TConfigEntryBoolean("entity_model_features.config.variation_base", "entity_model_features.config.variation_base.tooltip", @@ -328,10 +320,6 @@ private TConfigEntryCategory getModelSettings() { } } }); -// category.addAll(TConfigEntryText.fromLongOrMultilineTranslation( -// "entity_model_features.config.models.arrows", 200, TConfigEntryText.TextAlignment.LEFT)); -// category.addAll(TConfigEntryText.fromLongOrMultilineTranslation( -// "entity_model_features.config.models.cape", 200, TConfigEntryText.TextAlignment.LEFT)); return category; } @@ -340,8 +328,6 @@ private TConfigEntry getExport(final EMFModel_ID key, ModelLayerLocation layer) TConfigEntry export; try { Objects.requireNonNull(key.getMapId()); -// Objects.requireNonNull(((IEMFUnmodifiedLayerRootGetter)Minecraft.getInstance().getEntityModels()) -// .emf$getUnmodifiedRoots().get(layer)); export = new TConfigEntryCustomButton("entity_model_features.config.models.export", "entity_model_features.config.models.export.tooltip", (button) -> { try { EMFModelMappings.getMapOf(key, @@ -426,15 +412,7 @@ private void addEntityConfigs(TConfigEntryCategory entityCategory, String transl new TConfigEntryEnumSlider<>("entity_model_features.config.render", "entity_model_features.config.render.tooltip", () -> this.entityRenderModeOverrides.get(translationKey), (layer) -> this.entityRenderModeOverrides.putNullable(translationKey, layer), - null, RenderModeChoice.class), - new TConfigEntryEnumButton<>("entity_model_features.config.vanilla_render", "entity_model_features.config.vanilla_render.tooltip", - () -> this.entityVanillaHologramOverrides.get(translationKey), - (layer) -> this.entityVanillaHologramOverrides.putNullable(translationKey, layer), - null, VanillaModelRenderMode.class)//, -// new TConfigEntryEnumButton<>("entity_model_features.config.physics", "entity_model_features.config.physics.tooltip", -// () -> this.entityPhysicsModPatchOverrides.getNullable(translationKey), -// (layer) -> this.entityPhysicsModPatchOverrides.putNullable(translationKey, layer), -// null, PhysicsModCompatChoice.class) + null, RenderModeChoice.class) ); } @@ -479,22 +457,11 @@ public String toString() { } } + @Deprecated(forRemoval = true) public enum VanillaModelRenderMode { - OFF("options.off"), - @SuppressWarnings("unused") - NORMAL("entity_model_features.config.vanilla_render.normal"), - OFFSET("entity_model_features.config.vanilla_render.offset"); - - private final String text; - - VanillaModelRenderMode(String text) { - this.text = text; - } - - @Override - public String toString() { - return Component.translatable(text).getString(); - } + OFF, + NORMAL, + OFFSET } public enum CustomEntityModelSupportMode { @@ -534,20 +501,9 @@ public boolean allowsAll() { //todo remove fully @Deprecated(forRemoval = true) public enum PhysicsModCompatChoice { - OFF("options.off"), - VANILLA("entity_model_features.config.physics.1"), - CUSTOM("entity_model_features.config.physics.2"); - - private final String text; - - PhysicsModCompatChoice(String text) { - this.text = text; - } - - @Override - public String toString() { - return Component.translatable(text).getString(); - } + OFF, + VANILLA, + CUSTOM } public enum RenderModeChoice { diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java index b8944df1..4f01f7ee 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLivingEntityRenderer.java @@ -85,56 +85,6 @@ private void falseAnimation(CallbackInfo ci, @Local(argsOnly = true) PoseStack p //#endif - - //#if MC > 26.2 - //$$ dont forget this - //#elseif MC < 12109 - //$$ @Inject(method = - //#if MC >= 12102 - //$$ "render(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", - //#else - //$$ "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", - //#endif - //$$ at = @At(value = "INVOKE", - //#if MC >= 12100 - //$$ target = "Lnet/minecraft/client/model/EntityModel;renderToBuffer(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;III)V" - //#else - //$$ target = "Lnet/minecraft/client/model/EntityModel;renderToBuffer(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;IIFFFF)V" - //#endif - //$$ , shift = At.Shift.BEFORE)) - //$$ - //#if MC >= 12102 - //$$ private void emf$Animate(final S livingEntityRenderState, final PoseStack matrixStack, final MultiBufferSource vertexConsumerProvider, final int i, final CallbackInfo ci) { - //$$ var emf = EMFState.state(); - //$$ if(!(emf != null && emf.emfEntity() instanceof LivingEntity livingEntity)) { - //$$ return; - //$$ } - //$$ - //#else - //$$ private void emf$Animate(T livingEntity, float f, float g, PoseStack matrixStack, MultiBufferSource vertexConsumerProvider, int i, CallbackInfo ci) { - //#endif - //$$ - //$$ //EMFManager.getInstance().preRenderEMFActions(emf$ModelId,livingEntity, vertexConsumerProvider, o, n, l, k, m); - //$$ if (((IEMFModel) model).emf$isEMFModel()) { - //$$ - //$$ EMFModelPartRoot root = ((IEMFModel) model).emf$getEMFRootModel(); - //$$ if (root != null) { - //$$ if (EMF.config().getConfig().getVanillaHologramModeFor((EMFEntity) livingEntity) != EMFConfig.VanillaModelRenderMode.OFF) { - //$$ root.tryRenderVanillaRootNormally(matrixStack, vertexConsumerProvider.getBuffer( - //$$ RenderType.entityTranslucent(getTextureLocation( - //#if MC >= 12102 - //$$ livingEntityRenderState - //#else - //$$ livingEntity - //#endif - //$$ ))), i, OverlayTexture.NO_OVERLAY); - //$$ } - //$$ } - //$$ } - //$$ } - //#endif - - @ModifyExpressionValue(method = "getRenderType", at = @At(value = "INVOKE", //#if MC >= 12102 target = "Lnet/minecraft/client/renderer/entity/LivingEntityRenderer;getTextureLocation(Lnet/minecraft/client/renderer/entity/state/LivingEntityRenderState;)Lnet/minecraft/resources/ResourceLocation;" diff --git a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java index 2b8b4a65..0ad5107a 100644 --- a/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java +++ b/src/main/java/traben/entity_model_features/models/parts/EMFModelPartRoot.java @@ -302,36 +302,6 @@ public void setVariant1ToVanilla0() { } - public void tryRenderVanillaRootNormally(PoseStack matrixStack, VertexConsumer vertexConsumer, int light, int overlay) { - if (vanillaRoot != null) { - matrixStack.pushPose(); - //noinspection deprecation - if (EMF.config().getConfig().getVanillaHologramModeFor(EMFState.state().emfEntity()) == EMFConfig.VanillaModelRenderMode.OFFSET) { - matrixStack.translate(1, 0, 0); - } - vanillaRoot.render(matrixStack, vertexConsumer, light, overlay - //#if MC >= 12100 - //#else - //$$ , 1f, 1f, 1f, 1f - //#endif - ); - matrixStack.popPose(); - } - } - -// public void tryRenderVanillaFormatRoot(PoseStack matrixStack, VertexConsumer vertexConsumer, int light, int overlay) { -// if (EMF.config().getConfig().getPhysicsModModeFor(EMFAnimationEntityContext.getEMFEntity()) == EMFConfig.PhysicsModCompatChoice.VANILLA) { -// if (vanillaRoot != null) { -// vanillaRoot.render(matrixStack, vertexConsumer, light, overlay #if MC >= MC_21 #else , 1f, 1f, 1f, 1f #endif); -// } -// } else { -// ModelPart vanillaFormat = getVanillaFormatRoot(); -// if (vanillaFormat != null) { -// vanillaFormat.render(matrixStack, vertexConsumer, light, overlay #if MC >= MC_21 #else , 1f, 1f, 1f, 1f #endif); -// } -// } -// } - public boolean hasAnimation(){ return animation != null; } @@ -340,14 +310,6 @@ public void triggerManualAnimation(PoseStack pose) { if (animation != null) animation.run(); } - public ModelPart getVanillaFormatRoot() { - if (!vanillaFormatModelPartOfEachState.containsKey(currentModelVariant)) { - vanillaFormatModelPartOfEachState.put(currentModelVariant, getVanillaModelPartsOfCurrentState()); - } - return vanillaFormatModelPartOfEachState.get(currentModelVariant); - } - - @Override public void setVariantStateTo(int newVariant) { super.setVariantStateTo(newVariant); diff --git a/src/main/resources/assets/entity_model_features/lang/en_us.json b/src/main/resources/assets/entity_model_features/lang/en_us.json index e0126cfd..966c68f0 100644 --- a/src/main/resources/assets/entity_model_features/lang/en_us.json +++ b/src/main/resources/assets/entity_model_features/lang/en_us.json @@ -131,10 +131,6 @@ "entity_model_features.config.options": "Options & fixes", "entity_model_features.config.options.tooltip": "Various options for fundamental features or mod compatibility fixes", "entity_model_features.config.performance": "Performance settings", - "entity_model_features.config.physics": "Physics mod patch", - "entity_model_features.config.physics.1": "Use vanilla model", - "entity_model_features.config.physics.2": "Use EMF (CEM) model", - "entity_model_features.config.physics.tooltip": "Will only render the original vanilla model parts on death if physics mod is enabled\n this partially works but is not a perfect solution", "entity_model_features.config.print_mode": "Model exporting", "entity_model_features.config.print_mode.all_log": "All models - Log only", "entity_model_features.config.print_mode.all_log_jem": "All models - Log & .jem", @@ -162,10 +158,6 @@ "entity_model_features.config.tools.tooltip": "Optional tools to help with model making or distinguishing custom models", "entity_model_features.config.update": "Model update rate", "entity_model_features.config.update.tooltip": "Sets how often a mobs model will\nupdate for changes like health & age\nNever = never update\nSlow = 3-5 seconds\nAverage = about 1 second\nFast = less than a second\nInstant = instant (possible lag with hundred of mobs)", - "entity_model_features.config.vanilla_render": "Vanilla model display mode", - "entity_model_features.config.vanilla_render.normal": "normal", - "entity_model_features.config.vanilla_render.offset": "offset", - "entity_model_features.config.vanilla_render.tooltip": "This setting will render the vanilla model alongside the custom one for comparison\nIt will not animate and thus might be positioned a bit weird", "entity_model_features.config.variable_explanation.age": "Age in ticks", "entity_model_features.config.variable_explanation.is_swinging_right_arm": "True if the entity is swinging its right arm. Note false does not mean the other arm is swinging", "entity_model_features.config.variable_explanation.is_swinging_left_arm": "True if the entity is swinging its left arm. Note false does not mean the other arm is swinging", From 6be8550c992a323ad6c3a1782b11a8d7ce82acda Mon Sep 17 00:00:00 2001 From: Traben Date: Fri, 21 Aug 2026 11:48:48 +1000 Subject: [PATCH 17/20] clear deprecated configs --- CHANGELOG.MD | 1 + build.gradle.kts | 2 +- .../mixin/mixins/MixinEntityRenderer.java | 39 +++ .../MixinEntityRenderDispatcher.java | 223 ++++++++++++------ .../animation/state/EMFEntityRenderState.java | 7 +- .../entity_model_features.mixins.json | 1 + .../entity_model_features_12.accesswidener | 6 +- .../entity_model_features_13.accesswidener | 6 +- .../entity_model_features_14.accesswidener | 6 +- .../entity_model_features_15.accesswidener | 6 +- 10 files changed, 223 insertions(+), 74 deletions(-) create mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/MixinEntityRenderer.java diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 82e803a2..ff08919d 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -3,6 +3,7 @@ - fixed several model exporting issues, including missing parts, wrong rotations, missing mirrored uvs, and rabbit/axolotl legs on 26.1+ - fixed block entity models breaking in the latest versions - fixed vex & allay items not matching animated arm positions +- fixed custom shadow position, size, and opacity for models & animations not working - improved item attachment handling - fixed debug outline rendering not outlining everything - fixed 26.2 neoforge iris compatibility not working causing excess animation during the shadow pass diff --git a/build.gradle.kts b/build.gradle.kts index 1ecfaa85..b2c47e52 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -316,7 +316,7 @@ private fun changelog(): String? { } } - if (sb.isEmpty()) null + if (sb.isEmpty()) return null return sb.toString() } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntityRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntityRenderer.java new file mode 100644 index 00000000..ed1b9033 --- /dev/null +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntityRenderer.java @@ -0,0 +1,39 @@ +package traben.entity_model_features.mixin.mixins; + +//#if MC < 1.21.9 +//$$ import net.minecraft.client.renderer.entity.EntityRenderer; +//$$ import org.spongepowered.asm.mixin.Mixin; +//$$ import traben.entity_texture_features.mixin.CancelTarget; +//$$ +//$$ @Mixin(CancelTarget.class) +//$$ public abstract class MixinEntityRenderer { } +//#else +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import net.minecraft.client.renderer.entity.EntityRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import traben.entity_model_features.models.animation.state.EMFState; + +@Mixin(EntityRenderer.class) +public abstract class MixinEntityRenderer { + + @ModifyExpressionValue(method = "extractShadow", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;getShadowRadius(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;)F")) + private float radius(float original) { + var state = EMFState.state(); + if (state != null && !Float.isNaN(state.shadowSize())) { + return state.shadowSize(); + } + return original; + } + + @ModifyExpressionValue(method = "extractShadow", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;getShadowStrength(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;)F")) + private float strength(float original) { + var state = EMFState.state(); + if (state != null && !Float.isNaN(state.shadowOpacity())) { + return state.shadowOpacity(); + } + return original; + } + +} +//#endif \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java index babd9e92..be81b842 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java @@ -1,27 +1,25 @@ package traben.entity_model_features.mixin.mixins.rendering; +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.sugar.Local; import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; +import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.world.entity.Entity; +import org.objectweb.asm.Opcodes; 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.ModifyArg; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.animation.state.EMFEntityRenderState; import traben.entity_model_features.models.animation.state.EMFState; -import traben.entity_texture_features.features.state.ETFEntityRenderState; -import traben.entity_texture_features.utils.ETFEntity; -import traben.entity_model_features.utils.EMFEntity; -//#if MC >=12102 -import net.minecraft.client.renderer.entity.EntityRenderer; -import net.minecraft.client.renderer.entity.state.EntityRenderState; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; -import traben.entity_texture_features.features.state.HoldsETFRenderState; +import traben.entity_texture_features.features.state.ETFState; + +//#if MC < 12102 +//$$ import net.minecraft.world.entity.Entity; +//$$ import traben.entity_texture_features.features.state.ETFEntityRenderState; +//$$ import traben.entity_texture_features.utils.ETFEntity; //#endif @Mixin(EntityRenderDispatcher.class) @@ -29,11 +27,11 @@ public abstract class MixinEntityRenderDispatcher { private static final String SHADOW_RENDER_ETF = - //#if MC>=12109 + //#if MC >= 12109 "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitShadow(Lcom/mojang/blaze3d/vertex/PoseStack;FLjava/util/List;)V" - //#elseif MC>=12105 + //#elseif MC >= 12105 //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/renderer/entity/state/EntityRenderState;FLnet/minecraft/world/level/LevelReader;F)V" - //#elseif MC >=12102 + //#elseif MC >= 12102 //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/renderer/entity/state/EntityRenderState;FFLnet/minecraft/world/level/LevelReader;F)V" //#else //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/world/entity/Entity;FFLnet/minecraft/world/level/LevelReader;F)V" @@ -41,32 +39,26 @@ public abstract class MixinEntityRenderDispatcher { ; private static final String RENDER_ETF = - //#if MC>=12109 + //#if MC >= 12109 "submit" - //#elseif MC>=12105 + //#elseif MC >= 12105 //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;render(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;DDDLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/renderer/entity/EntityRenderer;)V" - //#elseif MC >=12102 + //#elseif MC >= 12102 //$$ "render(Lnet/minecraft/world/entity/Entity;DDDFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;ILnet/minecraft/client/renderer/entity/EntityRenderer;)V" //#else //$$ "render" //#endif ; - //#if MC>=12109 - //#else - //$$ @Shadow public abstract double distanceToSqr(double x, double y, double z); - //#endif - - @Inject(method = RENDER_ETF, at = @At(value = "RETURN")) - //#if MC >=12102 + //#if MC >= 12102 private void emf$endOfRender( final CallbackInfo ci - //#if MC>= 12105 + //#if MC >= 12105 , @Local(argsOnly = true) S state ) { - EMFEntityRenderState emfState = (EMFEntityRenderState) ((HoldsETFRenderState) state).etf$getState(); + EMFEntityRenderState emfState = EMFEntityRenderState.from(state); //#else //$$ ) { //$$ EMFEntityRenderState emfState = EMFState.state(); @@ -79,62 +71,157 @@ public abstract class MixinEntityRenderDispatcher { //#else //$$ private void emf$endOfRender( CallbackInfo ci, @Local(argsOnly = true) E entity) { //$$ if (EMFState.announceModels) { - //$$ EMFState.anounceModels((EMFEntityRenderState) ETFEntityRenderState.forEntity((ETFEntity) entity)); + //$$ EMFState.anounceModels(EMFState.state()); //$$ } //$$ } //$$ //#endif - @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF)) - private void emf$modifyShadowTranslate(final CallbackInfo ci, @Local(argsOnly = true) PoseStack matrices) { - var state = EMFState.state(); + //#if MC >= 1.21.9 + @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;submit(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", + shift = At.Shift.AFTER)) + private void + postSubmitTweaks(CallbackInfo ci, @Local EntityRenderer entityRenderer, @Local(argsOnly = true) S ogState) { + + var state = EMFEntityRenderState.from(ogState); if (state == null) return; - if (state.shadowX() != 0 || state.shadowZ() != 0) { - matrices.pushPose(); - matrices.translate(state.shadowX(), 0, state.shadowZ()); + + ETFState.stackVerify(state); + + if (state.needsToModifyShadow()) { + var x = ogState.x; + var z = ogState.z; + boolean useShadowX = !Float.isNaN(state.shadowX()); + boolean useShadowZ = !Float.isNaN(state.shadowZ()); + if (useShadowX) ogState.x += state.shadowX(); + if (useShadowZ) ogState.z += state.shadowZ(); + // Size and opacity are set from MixinEntityRenderer + + // Recalculate shadow that has been modified, this now needs to run before the actual shadow call so that its + // surrounding condition check can pass or fail based on the state values + //noinspection unchecked + entityRenderer.extractShadow(ogState, Minecraft.getInstance(), EMFState.state().world()); + + if (useShadowX) ogState.x = x; + if (useShadowZ) ogState.z = z; } } - @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF, shift = At.Shift.AFTER)) - private void emf$undoModifyShadowTranslate(final CallbackInfo ci, @Local(argsOnly = true) PoseStack matrices) { - var state = EMFState.state(); - if (state == null) return; - if (state.shadowX() != 0 || state.shadowZ() != 0) { - matrices.popPose(); -// matrices.translate(-state.shadowX(), 0, -state.shadowZ()); - } + @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF)) + private + void preShadow(CallbackInfo ci, @Local PoseStack poseStack, @Local(argsOnly = true) S ogState) { + var state = EMFEntityRenderState.from(ogState); + if (state == null || (Float.isNaN(state.shadowX()) && Float.isNaN(state.shadowZ()))) return; + + poseStack.translate(Float.isNaN(state.shadowX()) ? 0 : state.shadowX(), 0, Float.isNaN(state.shadowZ()) ? 0 : state.shadowZ()); } - //#if MC<12109 - //$$ @ModifyArg(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF), index = 3) - //$$ private float emf$modifyShadowOpacity(float opacity) { + @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF, shift = At.Shift.AFTER)) + private + void postShadow(CallbackInfo ci, @Local PoseStack poseStack, @Local(argsOnly = true) S ogState) { + var state = EMFEntityRenderState.from(ogState); + if (state == null || (Float.isNaN(state.shadowX()) && Float.isNaN(state.shadowZ()))) return; + + poseStack.translate(Float.isNaN(state.shadowX()) ? 0 : -state.shadowX(), 0, Float.isNaN(state.shadowZ()) ? 0 : -state.shadowZ()); + } + //#elseif MC >= 1.21.2 + //$$ + //$$ + //$$ @ModifyExpressionValue(method = RENDER_ETF, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;getShadowRadius(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;)F")) + //$$ private float radius(float original) { + //$$ var state = EMFState.state(); + //$$ if (state != null && !Float.isNaN(state.shadowSize())) { + //$$ return state.shadowSize(); + //$$ } + //$$ return original; + //$$ } + //$$ + //$$ @ModifyExpressionValue(method = RENDER_ETF, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;getShadowStrength(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;)F")) + //$$ private float strength(float original) { + //$$ var state = EMFState.state(); + //$$ if (state != null && !Float.isNaN(state.shadowOpacity())) { + //$$ return state.shadowOpacity(); + //$$ } + //$$ return original; + //$$ } + //$$ + //$$ @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF)) + //$$ private + //$$ void preShadow(CallbackInfo ci, @Local PoseStack poseStack, @Local(argsOnly = true) S ogState) { + //$$ var state = EMFEntityRenderState.from(ogState); + //$$ if (state == null || !state.needsToModifyShadow()) return; + //$$ + //$$ ETFState.stackVerify(state); + //$$ + //$$ if (!Float.isNaN(state.shadowX())) ogState.x += state.shadowX(); + //$$ if (!Float.isNaN(state.shadowZ())) ogState.z += state.shadowZ(); + //$$ + //$$ poseStack.translate(Float.isNaN(state.shadowX()) ? 0 : state.shadowX(), 0, Float.isNaN(state.shadowZ()) ? 0 : state.shadowZ()); + //$$ } + //$$ + //$$ @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF, shift = At.Shift.AFTER)) + //$$ private + //$$ void postShadow(CallbackInfo ci, @Local PoseStack poseStack, @Local(argsOnly = true) S ogState) { + //$$ var state = EMFEntityRenderState.from(ogState); + //$$ if (state == null || !state.needsToModifyShadow()) return; + //$$ + //$$ if (!Float.isNaN(state.shadowX())) ogState.x -= state.shadowX(); + //$$ if (!Float.isNaN(state.shadowZ())) ogState.z -= state.shadowZ(); + //$$ + //$$ poseStack.translate(Float.isNaN(state.shadowX()) ? 0 : -state.shadowX(), 0, Float.isNaN(state.shadowZ()) ? 0 : -state.shadowZ()); + //$$ } + //#else + //$$ + //#if MC >= 1.21 + //$$ @ModifyExpressionValue(method = RENDER_ETF, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;getShadowRadius(Lnet/minecraft/world/entity/Entity;)F")) + //#else + //$$ @ModifyExpressionValue(method = RENDER_ETF, at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;shadowRadius:F", opcode = Opcodes.GETFIELD)) + //#endif + //$$ private float radius(float original) { //$$ var state = EMFState.state(); - //$$ if (state == null) return opacity; - //$$ if (!Float.isNaN(state.shadowOpacity())) { - //$$ double g = this.distanceToSqr(EMFMath.getEntityX(), EMFMath.getEntityY(), EMFMath.getEntityZ()); - //$$ return (float) ((1.0 - g / 256.0) * state.shadowOpacity()); + //$$ if (state != null && !Float.isNaN(state.shadowSize())) { + //$$ return state.shadowSize(); //$$ } - //$$ return opacity; + //$$ return original; + //$$ } + //$$ + //$$ @ModifyExpressionValue(method = RENDER_ETF, at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;shadowStrength:F", opcode = Opcodes.GETFIELD)) + //$$ private float strength(float original) { + //$$ var state = EMFState.state(); + //$$ if (state != null && !Float.isNaN(state.shadowOpacity())) { + //$$ return state.shadowOpacity(); + //$$ } + //$$ return original; + //$$ } + //$$ + //$$ @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF)) + //$$ private void preShadow(CallbackInfo ci, @Local PoseStack poseStack, @Local(argsOnly = true) Entity entity) { + //$$ var state = EMFState.state(); + //$$ if (state == null || !state.needsToModifyShadow()) return; + //$$ + //$$ entity.setPos( + //$$ entity.position().x + (Float.isNaN(state.shadowX()) ? 0 : state.shadowX()), + //$$ entity.position().y, + //$$ entity.position().z + (Float.isNaN(state.shadowZ()) ? 0 : state.shadowZ()) + //$$ ); + //$$ + //$$ poseStack.translate(Float.isNaN(state.shadowX()) ? 0 : state.shadowX(), 0, Float.isNaN(state.shadowZ()) ? 0 : state.shadowZ()); + //$$ } + //$$ + //$$ @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF, shift = At.Shift.AFTER)) + //$$ private void postShadow(CallbackInfo ci, @Local PoseStack poseStack, @Local(argsOnly = true) Entity entity) { + //$$ var state =EMFState.state(); + //$$ if (state == null || !state.needsToModifyShadow()) return; + //$$ + //$$ entity.setPos( + //$$ entity.position().x + (Float.isNaN(state.shadowX()) ? 0 : -state.shadowX()), + //$$ entity.position().y, + //$$ entity.position().z + (Float.isNaN(state.shadowZ()) ? 0 : -state.shadowZ()) + //$$ ); + //$$ + //$$ poseStack.translate(Float.isNaN(state.shadowX()) ? 0 : -state.shadowX(), 0, Float.isNaN(state.shadowZ()) ? 0 : -state.shadowZ()); //$$ } //#endif - @ModifyArg(method = RENDER_ETF, at = @At(value = "INVOKE", target = SHADOW_RENDER_ETF), - index = - //#if MC>=12109 - 1 - //#elseif MC>=12105 - //$$ 5 - //#else - //$$ 6 - //#endif - ) - private float emf$modifyShadowSize(float size) { - var state = EMFState.state(); - if (state == null) return size; - if (!Float.isNaN(state.shadowSize())) { - return Math.min(size * state.shadowSize(), 32.0F); - } - return size; - } } diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java index 0b502ce5..853cd18c 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java @@ -140,7 +140,12 @@ public interface EMFEntityRenderState extends ETFEntityRenderState { boolean onShoulder(); void setOnShoulder(boolean onShoulder); - + default boolean needsToModifyShadow() { + return !Float.isNaN(shadowSize()) + || !Float.isNaN(shadowOpacity()) + || !Float.isNaN(shadowX()) + || !Float.isNaN(shadowZ()); + } boolean skipModelVariate(); diff --git a/src/main/resources/entity_model_features.mixins.json b/src/main/resources/entity_model_features.mixins.json index 7bd25c03..7dfa8713 100644 --- a/src/main/resources/entity_model_features.mixins.json +++ b/src/main/resources/entity_model_features.mixins.json @@ -10,6 +10,7 @@ "MixinCapeModels", "MixinEntity", "MixinEntityModelLoader", + "MixinEntityRenderer", "MixinGameRenderer", "MixinModel", "MixinModelPart", diff --git a/src/main/resources/entity_model_features_12.accesswidener b/src/main/resources/entity_model_features_12.accesswidener index 173169e6..7235a74e 100644 --- a/src/main/resources/entity_model_features_12.accesswidener +++ b/src/main/resources/entity_model_features_12.accesswidener @@ -39,4 +39,8 @@ accessible field net/minecraft/client/model/geom/ModelPart$Cube polygons [Lnet/m accessible field net/minecraft/world/entity/Entity yRot F -accessible method net/minecraft/client/renderer/entity/LivingEntityRenderer isUpsideDownName (Ljava/lang/String;)Z \ No newline at end of file +accessible method net/minecraft/client/renderer/entity/LivingEntityRenderer isUpsideDownName (Ljava/lang/String;)Z + +accessible method net/minecraft/client/renderer/entity/EntityRenderer extractShadow (Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/Minecraft;Lnet/minecraft/world/level/Level;)V +accessible field net/minecraft/client/renderer/entity/EntityRenderer shadowRadius F +accessible field net/minecraft/client/renderer/entity/EntityRenderer shadowStrength F \ No newline at end of file diff --git a/src/main/resources/entity_model_features_13.accesswidener b/src/main/resources/entity_model_features_13.accesswidener index dcbce92d..bfbf337e 100644 --- a/src/main/resources/entity_model_features_13.accesswidener +++ b/src/main/resources/entity_model_features_13.accesswidener @@ -41,4 +41,8 @@ accessible field net/minecraft/world/entity/Entity yRot F accessible method net/minecraft/client/renderer/entity/LivingEntityRenderer isUpsideDownName (Ljava/lang/String;)Z -accessible method net/minecraft/world/phys/shapes/CubeVoxelShape (Lnet/minecraft/world/phys/shapes/DiscreteVoxelShape;)V \ No newline at end of file +accessible method net/minecraft/world/phys/shapes/CubeVoxelShape (Lnet/minecraft/world/phys/shapes/DiscreteVoxelShape;)V + +accessible method net/minecraft/client/renderer/entity/EntityRenderer extractShadow (Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/Minecraft;Lnet/minecraft/world/level/Level;)V +accessible field net/minecraft/client/renderer/entity/EntityRenderer shadowRadius F +accessible field net/minecraft/client/renderer/entity/EntityRenderer shadowStrength F \ No newline at end of file diff --git a/src/main/resources/entity_model_features_14.accesswidener b/src/main/resources/entity_model_features_14.accesswidener index 547d7b0a..a10955e5 100644 --- a/src/main/resources/entity_model_features_14.accesswidener +++ b/src/main/resources/entity_model_features_14.accesswidener @@ -41,4 +41,8 @@ accessible field net/minecraft/world/entity/Entity yRot F accessible method net/minecraft/client/renderer/entity/LivingEntityRenderer isUpsideDownName (Ljava/lang/String;)Z -accessible method net/minecraft/world/phys/shapes/CubeVoxelShape (Lnet/minecraft/world/phys/shapes/DiscreteVoxelShape;)V \ No newline at end of file +accessible method net/minecraft/world/phys/shapes/CubeVoxelShape (Lnet/minecraft/world/phys/shapes/DiscreteVoxelShape;)V + +accessible method net/minecraft/client/renderer/entity/EntityRenderer extractShadow (Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/Minecraft;Lnet/minecraft/world/level/Level;)V +accessible field net/minecraft/client/renderer/entity/EntityRenderer shadowRadius F +accessible field net/minecraft/client/renderer/entity/EntityRenderer shadowStrength F \ No newline at end of file diff --git a/src/main/resources/entity_model_features_15.accesswidener b/src/main/resources/entity_model_features_15.accesswidener index 22f28cd3..f17dffca 100644 --- a/src/main/resources/entity_model_features_15.accesswidener +++ b/src/main/resources/entity_model_features_15.accesswidener @@ -39,4 +39,8 @@ accessible field net/minecraft/world/entity/Entity yRot F accessible method net/minecraft/client/renderer/entity/LivingEntityRenderer isUpsideDownName (Ljava/lang/String;)Z -accessible method net/minecraft/world/phys/shapes/CubeVoxelShape (Lnet/minecraft/world/phys/shapes/DiscreteVoxelShape;)V \ No newline at end of file +accessible method net/minecraft/world/phys/shapes/CubeVoxelShape (Lnet/minecraft/world/phys/shapes/DiscreteVoxelShape;)V + +accessible method net/minecraft/client/renderer/entity/EntityRenderer extractShadow (Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lnet/minecraft/client/Minecraft;Lnet/minecraft/world/level/Level;)V +accessible field net/minecraft/client/renderer/entity/EntityRenderer shadowRadius F +accessible field net/minecraft/client/renderer/entity/EntityRenderer shadowStrength F \ No newline at end of file From fab1dc80a7ba9074d5b79cbe175b44971dbeabb3 Mon Sep 17 00:00:00 2001 From: Traben Date: Fri, 21 Aug 2026 12:36:45 +1000 Subject: [PATCH 18/20] added fire animation variables --- CHANGELOG.MD | 2 + .../MixinEntityRenderDispatcher.java | 91 ++++++++++++++++--- .../submits/MixinFlameFeatureRenderer.java | 64 +++++++++++++ .../variables/EMFModelOrRenderVariable.java | 77 ++++++++++++++++ .../animation/state/EMFEntityRenderState.java | 21 ++++- .../EMFEntityRenderStateViaReference.java | 18 ++++ .../entity_model_features.mixins.json | 3 +- 7 files changed, 261 insertions(+), 15 deletions(-) create mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/MixinFlameFeatureRenderer.java diff --git a/CHANGELOG.MD b/CHANGELOG.MD index ff08919d..5474865b 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -4,6 +4,8 @@ - fixed block entity models breaking in the latest versions - fixed vex & allay items not matching animated arm positions - fixed custom shadow position, size, and opacity for models & animations not working +- added `render.fire_x`, `render.fire_y`, `render.fire_z` animation variables for controlling the fire rendering position on entities +- added `render.fire_scale`, `render.fire_height` animation variables for controlling the fire rendering scale and height on entities - improved item attachment handling - fixed debug outline rendering not outlining everything - fixed 26.2 neoforge iris compatibility not working causing excess animation during the shadow pass diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java index be81b842..ba9c0f9e 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinEntityRenderDispatcher.java @@ -20,24 +20,13 @@ //$$ import net.minecraft.world.entity.Entity; //$$ import traben.entity_texture_features.features.state.ETFEntityRenderState; //$$ import traben.entity_texture_features.utils.ETFEntity; +//#else +import net.minecraft.client.renderer.entity.state.EntityRenderState; //#endif @Mixin(EntityRenderDispatcher.class) public abstract class MixinEntityRenderDispatcher { - - private static final String SHADOW_RENDER_ETF = - //#if MC >= 12109 - "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitShadow(Lcom/mojang/blaze3d/vertex/PoseStack;FLjava/util/List;)V" - //#elseif MC >= 12105 - //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/renderer/entity/state/EntityRenderState;FLnet/minecraft/world/level/LevelReader;F)V" - //#elseif MC >= 12102 - //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/renderer/entity/state/EntityRenderState;FFLnet/minecraft/world/level/LevelReader;F)V" - //#else - //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/world/entity/Entity;FFLnet/minecraft/world/level/LevelReader;F)V" - //#endif - ; - private static final String RENDER_ETF = //#if MC >= 12109 "submit" @@ -77,6 +66,19 @@ public abstract class MixinEntityRenderDispatcher { //$$ //#endif + //region shadow modification + + private static final String SHADOW_RENDER_ETF = + //#if MC >= 12109 + "Lnet/minecraft/client/renderer/SubmitNodeCollector;submitShadow(Lcom/mojang/blaze3d/vertex/PoseStack;FLjava/util/List;)V" + //#elseif MC >= 12105 + //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/renderer/entity/state/EntityRenderState;FLnet/minecraft/world/level/LevelReader;F)V" + //#elseif MC >= 12102 + //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/client/renderer/entity/state/EntityRenderState;FFLnet/minecraft/world/level/LevelReader;F)V" + //#else + //$$ "Lnet/minecraft/client/renderer/entity/EntityRenderDispatcher;renderShadow(Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;Lnet/minecraft/world/entity/Entity;FFLnet/minecraft/world/level/LevelReader;F)V" + //#endif + ; //#if MC >= 1.21.9 @Inject(method = RENDER_ETF, at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/entity/EntityRenderer;submit(Lnet/minecraft/client/renderer/entity/state/EntityRenderState;Lcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/SubmitNodeCollector;Lnet/minecraft/client/renderer/state/CameraRenderState;)V", @@ -224,4 +226,67 @@ void postShadow(CallbackInfo ci, @Local PoseStack poseStack, @Local(argsOnly = t //$$ } //#endif + //endregion + + //region flame modification + + //#if MC >= 1.21.2 && MC < 1.21.9 + //$$ @ModifyExpressionValue(method = "renderFlame", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/state/EntityRenderState;boundingBoxWidth:F", opcode = Opcodes.GETFIELD)) + //$$ private float width(float original, @Local EntityRenderState vanilla, @Local PoseStack pose) { + //$$ var state = EMFEntityRenderState.from(vanilla); + //$$ if (state == null) return original; + //$$ + //$$ if (state.needsToModifyFire()) { + //$$ pose.translate( + //$$ Float.isNaN(state.fireX()) ? 0 : state.fireX(), + //$$ Float.isNaN(state.fireY()) ? 0 : state.fireY(), + //$$ Float.isNaN(state.fireZ()) ? 0 : state.fireZ() + //$$ ); + //$$ + //$$ if (!Float.isNaN(state.fireScale())) { + //$$ return state.fireScale(); + //$$ } + //$$ } + //$$ return original; + //$$ } + //$$ + //$$ @ModifyExpressionValue(method = "renderFlame", at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/state/EntityRenderState;boundingBoxHeight:F", opcode = Opcodes.GETFIELD)) + //$$ private float height(float original, @Local EntityRenderState vanilla) { + //$$ var state = EMFEntityRenderState.from(vanilla); + //$$ if (state != null && !Float.isNaN(state.fireHeight())) { + //$$ return state.fireHeight(); + //$$ } + //$$ return original; + //$$ } + //#elseif MC < 1.21.2 + //$$ @ModifyExpressionValue(method = "renderFlame", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getBbWidth()F")) + //$$ private float width(float original, @Local PoseStack pose) { + //$$ var state = EMFState.state(); + //$$ if (state == null) return original; + //$$ + //$$ if (state.needsToModifyFire()) { + //$$ pose.translate( + //$$ Float.isNaN(state.fireX()) ? 0 : state.fireX(), + //$$ Float.isNaN(state.fireY()) ? 0 : state.fireY(), + //$$ Float.isNaN(state.fireZ()) ? 0 : state.fireZ() + //$$ ); + //$$ + //$$ if (!Float.isNaN(state.fireScale())) { + //$$ return state.fireScale(); + //$$ } + //$$ } + //$$ return original; + //$$ } + //$$ + //$$ @ModifyExpressionValue(method = "renderFlame", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getBbHeight()F")) + //$$ private float height(float original) { + //$$ var state = EMFState.state(); + //$$ if (state != null && !Float.isNaN(state.fireHeight())) { + //$$ return state.fireHeight(); + //$$ } + //$$ return original; + //$$ } + //#endif + + //endregion } diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/MixinFlameFeatureRenderer.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/MixinFlameFeatureRenderer.java new file mode 100644 index 00000000..1a3632ed --- /dev/null +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/submits/MixinFlameFeatureRenderer.java @@ -0,0 +1,64 @@ +package traben.entity_model_features.mixin.mixins.rendering.submits; + +//#if MC < 1.21.9 +//$$ import net.minecraft.client.renderer.entity.EntityRenderer; +//$$ import org.spongepowered.asm.mixin.Mixin; +//$$ import traben.entity_texture_features.mixin.CancelTarget; +//$$ +//$$ @Mixin(CancelTarget.class) +//$$ public abstract class MixinFlameFeatureRenderer { } +//#else +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.sugar.Local; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.renderer.entity.state.EntityRenderState; +import net.minecraft.client.renderer.feature.FlameFeatureRenderer; +import org.objectweb.asm.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import traben.entity_model_features.models.animation.state.EMFEntityRenderState; + +@Mixin(FlameFeatureRenderer.class) +public abstract class MixinFlameFeatureRenderer { + + //#if MC >= 26.2 + //$$ private static final String METHOD = "prepare"; + //#else + private static final String METHOD = "renderFlame"; + //#endif + + + @ModifyExpressionValue(method = METHOD, at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/state/EntityRenderState;boundingBoxWidth:F", opcode = Opcodes.GETFIELD)) + private float width(float original, @Local EntityRenderState vanilla, @Local PoseStack.Pose pose) { + var state = EMFEntityRenderState.from(vanilla); + if (state == null) return original; + + if (state.needsToModifyFire()) { + pose.translate( + Float.isNaN(state.fireX()) ? 0 : state.fireX(), + Float.isNaN(state.fireY()) ? 0 : state.fireY(), + Float.isNaN(state.fireZ()) ? 0 : state.fireZ() + ); + + if (!Float.isNaN(state.fireScale())) { + return state.fireScale(); + } + } + + + return original; + } + + @ModifyExpressionValue(method = METHOD, at = @At(value = "FIELD", target = "Lnet/minecraft/client/renderer/entity/state/EntityRenderState;boundingBoxHeight:F", opcode = Opcodes.GETFIELD)) + private float height(float original, @Local EntityRenderState vanilla) { + var state = EMFEntityRenderState.from(vanilla); + if (state != null && !Float.isNaN(state.fireHeight())) { + return state.fireHeight(); + } + return original; + } + + + +} +//#endif \ No newline at end of file diff --git a/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java b/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java index 6f0dba88..1990ee57 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java @@ -272,6 +272,78 @@ public boolean isRenderVariable() { return true; } }, + RENDER_FIRE_X() { + @Override + public void setValue(EMFModelPart ignored, float value) { + if (EMFState.state() != null) EMFState.state().setFireX(value); + } + + @Override + public float getValue(ModelPart ignored) { + return EMFState.state() != null ? EMFState.state().fireX() : 0; + } + + @Override + public boolean isRenderVariable() { + return true; + } + }, + RENDER_FIRE_Y() { + @Override + public void setValue(EMFModelPart ignored, float value) { + if (EMFState.state() != null) EMFState.state().setFireY(value); + } + @Override + public float getValue(ModelPart ignored) { + return EMFState.state() != null ? EMFState.state().fireY() : 0; + } + @Override + public boolean isRenderVariable() { + return true; + } + }, + RENDER_FIRE_Z() { + @Override + public void setValue(EMFModelPart ignored, float value) { + if (EMFState.state() != null) EMFState.state().setFireZ(value); + } + @Override + public float getValue(ModelPart ignored) { + return EMFState.state() != null ? EMFState.state().fireZ() : 0; + } + @Override + public boolean isRenderVariable() { + return true; + } + }, + RENDER_FIRE_SCALE() { + @Override + public void setValue(EMFModelPart ignored, float value) { + if (EMFState.state() != null) EMFState.state().setFireScale(value); + } + @Override + public float getValue(ModelPart ignored) { + return EMFState.state() != null ? EMFState.state().fireScale() : 0; + } + @Override + public boolean isRenderVariable() { + return true; + } + }, + RENDER_FIRE_HEIGHT() { + @Override + public void setValue(EMFModelPart ignored, float value) { + if (EMFState.state() != null) EMFState.state().setFireHeight(value); + } + @Override + public float getValue(ModelPart ignored) { + return EMFState.state() != null ? EMFState.state().fireHeight() : 0; + } + @Override + public boolean isRenderVariable() { + return true; + } + } ; @@ -286,6 +358,11 @@ public static EMFModelOrRenderVariable getRenderVariable(String id) { case "render.leash_offset_x" -> RENDER_LEASH_X; case "render.leash_offset_y" -> RENDER_LEASH_Y; case "render.leash_offset_z" -> RENDER_LEASH_Z; + case "render.fire_x" -> RENDER_FIRE_X; + case "render.fire_y" -> RENDER_FIRE_Y; + case "render.fire_z" -> RENDER_FIRE_Z; + case "render.fire_scale" -> RENDER_FIRE_SCALE; + case "render.fire_height" -> RENDER_FIRE_HEIGHT; default -> null; }; } diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java index 853cd18c..661e7a6e 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java @@ -13,7 +13,6 @@ import traben.entity_model_features.EMF; import traben.entity_model_features.EMFManager; import traben.entity_model_features.models.IEMFModel; -import traben.entity_model_features.models.animation.EMFAttachments; import traben.entity_model_features.models.animation.math.EMFMath; import traben.entity_model_features.models.parts.EMFModelPartRoot; import traben.entity_model_features.utils.EMFEntity; @@ -147,6 +146,26 @@ default boolean needsToModifyShadow() { || !Float.isNaN(shadowZ()); } + float fireX(); + void setFireX(float fireX); + float fireY(); + void setFireY(float fireY); + float fireZ(); + void setFireZ(float fireZ); + + float fireHeight(); + void setFireHeight(float fireHeightScale); + float fireScale(); + void setFireScale(float fireWidthScale); + + default boolean needsToModifyFire() { + return !Float.isNaN(fireScale()) + || !Float.isNaN(fireHeight()) + || !Float.isNaN(fireX()) + || !Float.isNaN(fireY()) + || !Float.isNaN(fireZ()); + } + boolean skipModelVariate(); void setSkipModelVariate(boolean value); diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java index 3f986ed9..3bacee44 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java @@ -136,6 +136,24 @@ public void setLayerFactory(final Function layerFa @Override public float headPitch() { return headPitch; } @Override public void setHeadPitch(float headPitch) { this.headPitch = headPitch; } + float fireX = Float.NaN; + @Override public float fireX() { return fireX; } + @Override public void setFireX(float fireX) { this.fireX = fireX; } + float fireY = Float.NaN; + @Override public float fireY() { return fireY; } + @Override public void setFireY(float fireY) { this.fireY = fireY; } + float fireZ = Float.NaN; + @Override public float fireZ() { return fireZ; } + @Override public void setFireZ(float fireZ) { this.fireZ = fireZ; } + float fireWidth = Float.NaN; + @Override public float fireScale() { return fireWidth; } + @Override public void setFireScale(float fireWidth) { this.fireWidth = fireWidth; } + float fireHeight = Float.NaN; + @Override public float fireHeight() { return fireHeight; } + @Override public void setFireHeight(float fireHeight) { this.fireHeight = fireHeight; } + + + @Override public String toString() { diff --git a/src/main/resources/entity_model_features.mixins.json b/src/main/resources/entity_model_features.mixins.json index 7dfa8713..555c82bd 100644 --- a/src/main/resources/entity_model_features.mixins.json +++ b/src/main/resources/entity_model_features.mixins.json @@ -56,7 +56,8 @@ "rendering.model.MixinWolfEntityModel", "rendering.submits.Mixin_HumanoidArmorLayer_AddBaseModelPoseRef", "rendering.submits.Mixin_ModelPartRenderer", - "rendering.submits.Mixin_ModelRenderer" + "rendering.submits.Mixin_ModelRenderer", + "rendering.submits.MixinFlameFeatureRenderer" ], "mixins": [ ], From 83f55097286828f9509317833d4ac7374341826a Mon Sep 17 00:00:00 2001 From: Traben Date: Fri, 21 Aug 2026 16:24:54 +1000 Subject: [PATCH 19/20] leash fix --- .github/emf_animation.txt | 9 + CHANGELOG.MD | 9 +- .../mixin/mixins/MixinEntity.java | 28 +- .../mixins/rendering/MixinLeashOffsets.java | 113 ++++++++ .../variables/EMFModelOrRenderVariable.java | 274 ++++++++++++++---- .../animation/state/EMFEntityRenderState.java | 9 - .../EMFEntityRenderStateViaReference.java | 12 - .../entity_model_features.mixins.json | 1 + 8 files changed, 362 insertions(+), 93 deletions(-) create mode 100644 src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLeashOffsets.java diff --git a/.github/emf_animation.txt b/.github/emf_animation.txt index 320af38c..1aa257be 100644 --- a/.github/emf_animation.txt +++ b/.github/emf_animation.txt @@ -71,6 +71,12 @@ # render.shadow_opacity - How transparent the shadow is # render.shadow_offset_x, render.shadow_offset_z - The location of the shadow # render.leash_offset_x, render.leash_offset_y, render.leash_offset_z - The position of the point the leash attaches to +@ render.leash_holder_offset_x, render.leash_holder_offset_y, +@ render.leash_holder_offset_z - The position of the point the leash attaches to for the holding entity +@ render._1, render._2, +@ render._3 , render._4 - The 4 corner positions of leashes when on happy ghast and boats (fallback to the leash_offset_x/y/zif not present) +@ render.fire_x, render.fire_y, render.fire_z - The position of the fire effect +@ render.fire_scale, render.fire_height - The scale and height of the fire effect # # Expressions # @@ -163,6 +169,9 @@ @ is_holding_item_left - If an item is held in the entities left hand slot @ is_paused - If the game is paused @ is_hovered - If the entity is being looked at and within normal reach of the player +@ is_player_first_person - If the player is in first person view +@ is_player_third_person - If the player is in third person view +@ is_player_third_person_reversed - If the player is in reversed third person view # # Operators # +, -, *, /, % diff --git a/CHANGELOG.MD b/CHANGELOG.MD index 5474865b..746ca056 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -3,10 +3,15 @@ - fixed several model exporting issues, including missing parts, wrong rotations, missing mirrored uvs, and rabbit/axolotl legs on 26.1+ - fixed block entity models breaking in the latest versions - fixed vex & allay items not matching animated arm positions -- fixed custom shadow position, size, and opacity for models & animations not working +- fixed `render.shadow_size`, `render.shadow_opacity`, `render.shadow_offset_x`, `render.shadow_offset_z` - added `render.fire_x`, `render.fire_y`, `render.fire_z` animation variables for controlling the fire rendering position on entities - added `render.fire_scale`, `render.fire_height` animation variables for controlling the fire rendering scale and height on entities -- improved item attachment handling +- fixed `render.leash_offset_x`, `render.leash_offset_y`, `render.leash_offset_z` +- added `render.leash_holder_offset_x`, `render.leash_holder_offset_y`, `render.leash_holder_offset_z` which do the same as above but affect the holding entity instead of the leashed entity +- added `render._1`, `render._2`, `render._3` , `render._4` + - these can apply to any of the x,y,z or holder and normal leash offset values and allows you to modify the quad leash offsets used by ghasts and boats, and any other entity that uses a quad leash connection + - Note: if the _1 .. _4 variants aren't used then the regular x,y,z offset can be used instead applied to all 4 positions +- improved and fixed item attachment handling - fixed debug outline rendering not outlining everything - fixed 26.2 neoforge iris compatibility not working causing excess animation during the shadow pass - fixed first person arm rendering with sleeves even when turned off in the settings diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntity.java b/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntity.java index 72203795..b5e9a356 100644 --- a/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntity.java +++ b/src/main/java/traben/entity_model_features/mixin/mixins/MixinEntity.java @@ -1,6 +1,7 @@ package traben.entity_model_features.mixin.mixins; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; import net.minecraft.client.Minecraft; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; @@ -10,7 +11,6 @@ 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.CallbackInfoReturnable; import traben.entity_model_features.EMFManager; import traben.entity_model_features.models.animation.state.EMFState; @@ -124,20 +124,20 @@ public abstract class MixinEntity implements EMFEntity { @Shadow public abstract boolean isInWaterOrRain(); - //#if MC >= 12106 - @Inject(method = "getRopeHoldPosition", at = @At("RETURN")) - //#else - //$$ @Inject(method = "getLeashOffset()Lnet/minecraft/world/phys/Vec3;", at = @At("RETURN")) + //#if MC < 1.21 + //$$ @ModifyReturnValue(method = "getLeashOffset()Lnet/minecraft/world/phys/Vec3;", at = @At("RETURN")) + //$$ private Vec3 emf$leash(Vec3 vec) { + //$$ var map = emf$getVariableMap(); + //$$ var x = map.getOrDefault("render.leash_offset_x", 0.0f); + //$$ var y = map.getOrDefault("render.leash_offset_y", 0.0f); + //$$ var z = map.getOrDefault("render.leash_offset_z", 0.0f); + //$$ + //$$ if (x != 0 || y != 0 || z != 0) { + //$$ return vec.add(x, y, z); + //$$ } + //$$ return vec; + //$$ } //#endif - private void emf$leashwither(CallbackInfoReturnable cir) { - var state = EMFState.state(); - if (state == null) return; - //return new Vec3d(0.0, (double)this.getStandingEyeHeight(), (double)(this.getWidth() * 0.4F)); - if (state.leashX() != 0 || state.leashY() != 0 || state.leashZ() != 0) { - Vec3 vec = cir.getReturnValue(); - vec.add(state.leashX(), state.leashY(), state.leashZ()); - } - } @Override public double emf$prevX() { diff --git a/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLeashOffsets.java b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLeashOffsets.java new file mode 100644 index 00000000..4911cbab --- /dev/null +++ b/src/main/java/traben/entity_model_features/mixin/mixins/rendering/MixinLeashOffsets.java @@ -0,0 +1,113 @@ +package traben.entity_model_features.mixin.mixins.rendering; +//#if MC < 1.21 +//$$ import net.minecraft.client.renderer.entity.EntityRenderer; +//$$ import org.spongepowered.asm.mixin.Mixin; +//$$ import traben.entity_texture_features.mixin.CancelTarget; +//$$ +//$$ @Mixin(CancelTarget.class) +//$$ public abstract class MixinLeashOffsets { } +//#else +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.llamalad7.mixinextras.sugar.Local; +import com.llamalad7.mixinextras.sugar.Share; +import com.llamalad7.mixinextras.sugar.ref.LocalRef; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import traben.entity_model_features.utils.EMFEntity; + +import java.util.Map; + + +@Mixin(EntityRenderer.class) +public class MixinLeashOffsets { + + //#if MC >= 1.21.2 + private static final String METHOD = "extractRenderState"; + //#else + //$$ private static final String METHOD = "renderLeash"; + //#endif + + //#if MC >= 1.21.2 + @ModifyExpressionValue(method = METHOD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;getLeashHolder()Lnet/minecraft/world/entity/Entity;")) + private Entity getLeashHolder(Entity original, @Share("holder") LocalRef roper) { + roper.set(original); + return original; + } + //#endif + + //#if MC >= 12106 + @ModifyExpressionValue(method = METHOD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;getLeashOffset(F)Lnet/minecraft/world/phys/Vec3;")) + private Vec3 emf$leash(Vec3 original, @Local net.minecraft.world.entity.Leashable leashable) { + //#else + //$$ @ModifyExpressionValue(method = METHOD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getLeashOffset(F)Lnet/minecraft/world/phys/Vec3;")) + //$$ private Vec3 emf$leash(Vec3 original, @Local(ordinal = 0, argsOnly = true) Entity leashable) { + //#endif + return leashModify(original, "", ((EMFEntity) leashable).emf$getVariableMap(), false); + } + + @ModifyExpressionValue(method = METHOD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getRopeHoldPosition(F)Lnet/minecraft/world/phys/Vec3;")) + //#if MC >= 1.21.2 + private Vec3 emf$leashHold(Vec3 original, @Share("holder") LocalRef roper) { + return leashModify(original, "", ((EMFEntity) roper.get()).emf$getVariableMap(), true); + } + //#else + //$$ private Vec3 emf$leashHold(Vec3 original, @Local(ordinal = 1, argsOnly = true) Entity roper) { + //$$ return leashModify(original, "", ((EMFEntity) roper).emf$getVariableMap(), true); + //$$ } + //#endif + + @Unique + private Vec3 leashModify(Vec3 original, String variant, Map variable, boolean holder) { + String type = holder ? "_holder" : ""; + var modifiedX = variable.getOrDefault("render.leash" + type + "_offset_x" + variant, 0f); + var modifiedY = variable.getOrDefault("render.leash" + type + "_offset_y" + variant, 0f); + var modifiedZ = variable.getOrDefault("render.leash" + type + "_offset_z" + variant, 0f); + if (modifiedX != 0 || modifiedY != 0 || modifiedZ != 0) { + foundQuadLeashHolderOffsets = true; + return original.add(modifiedX, modifiedY, modifiedZ); + } + return original; + } + + @Unique private boolean foundQuadLeashHolderOffsets = false; + + //#if MC >= 12106 + @ModifyExpressionValue(method = METHOD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Leashable;getQuadLeashOffsets()[Lnet/minecraft/world/phys/Vec3;")) + private Vec3[] emf$leashQuad(Vec3[] original, @Local net.minecraft.world.entity.Leashable leashable) { + return quad(original, (EMFEntity) leashable, false); + } + + @ModifyExpressionValue(method = METHOD, at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;getQuadLeashHolderOffsets()[Lnet/minecraft/world/phys/Vec3;")) + private Vec3[] emf$leashQuadHolder(Vec3[] original, @Share("holder") LocalRef roper) { + return quad(original, (EMFEntity) roper.get(), true); + } + + @Unique + private Vec3 @NotNull [] quad(Vec3[] original, EMFEntity leashable, boolean holder) { + foundQuadLeashHolderOffsets = false; + var map = leashable.emf$getVariableMap(); + original[0] = leashModify(original[0], "_1", map, holder); + original[1] = leashModify(original[1], "_2", map, holder); + original[2] = leashModify(original[2], "_3", map, holder); + original[3] = leashModify(original[3], "_4", map, holder); + if (!foundQuadLeashHolderOffsets) { + var og = original[0]; + original[0] = leashModify(og, "", map, holder); + if (!og.equals(original[0])) { + original[1] = leashModify(original[1], "", map, holder); + original[2] = leashModify(original[2], "", map, holder); + original[3] = leashModify(original[3], "", map, holder); + } + } + return original; + } + //#endif +} +//#endif diff --git a/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java b/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java index 1990ee57..bfa99ce6 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/variables/EMFModelOrRenderVariable.java @@ -163,12 +163,14 @@ public boolean isBoolean() { RENDER_shadow_size() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setShadowSize(value); + var state = EMFState.state(); + if (state != null) state.setShadowSize(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().shadowSize() : 0; + var state = EMFState.state(); + return state != null ? state.shadowSize() : 0; } @Override @@ -179,12 +181,14 @@ public boolean isRenderVariable() { RENDER_SHADOW_OPACITY() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setShadowOpacity(value); + var state = EMFState.state(); + if (state != null) state.setShadowOpacity(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().shadowOpacity() : 0; + var state = EMFState.state(); + return state != null ? state.shadowOpacity() : 0; } @Override @@ -195,12 +199,14 @@ public boolean isRenderVariable() { RENDER_SHADOW_X() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setShadowX(value); + var state = EMFState.state(); + if (state != null) state.setShadowX(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().shadowX() : 0; + var state = EMFState.state(); + return state != null ? state.shadowX() : 0; } @Override @@ -211,12 +217,14 @@ public boolean isRenderVariable() { RENDER_SHADOW_Z() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setShadowZ(value); + var state = EMFState.state(); + if (state != null) state.setShadowZ(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().shadowZ() : 0; + var state = EMFState.state(); + return state != null ? state.shadowZ() : 0; } @Override @@ -224,63 +232,178 @@ public boolean isRenderVariable() { return true; } }, + RENDER_LEASH_X() { - @Override - public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setLeashX(value); - } + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_x", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_x", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Y() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_y", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_y", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Z() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_z", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_z", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, - @Override - public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().leashX() : 0; - } + RENDER_LEASH_X_1() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_x_1", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_x_1", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Y_1() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_y_1", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_y_1", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Z_1() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_z_1", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_z_1", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, - @Override - public boolean isRenderVariable() { - return true; - } + RENDER_LEASH_X_2() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_x_2", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_x_2", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Y_2() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_y_2", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_y_2", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Z_2() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_z_2", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_z_2", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} }, - RENDER_LEASH_Y() { - @Override - public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setLeashY(value); - } - @Override - public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().leashY() : 0; - } + RENDER_LEASH_X_3() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_x_3", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_x_3", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Y_3() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_y_3", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_y_3", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Z_3() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_z_3", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_z_3", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, - @Override - public boolean isRenderVariable() { - return true; - } + RENDER_LEASH_X_4() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_x_4", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_x_4", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Y_4() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_y_4", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_y_4", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_LEASH_Z_4() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_offset_z_4", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_offset_z_4", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} }, - RENDER_LEASH_Z() { - @Override - public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setLeashZ(value); - } - @Override - public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().leashZ() : 0; - } + RENDER_HOLDER_LEASH_X() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_x", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_x", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Y() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_y", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_y", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Z() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_z", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_z", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, - @Override - public boolean isRenderVariable() { - return true; - } + RENDER_HOLDER_LEASH_X_1() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_x_1", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_x_1", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} }, + RENDER_HOLDER_LEASH_Y_1() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_y_1", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_y_1", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Z_1() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_z_1", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_z_1", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + + RENDER_HOLDER_LEASH_X_2() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_x_2", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_x_2", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Y_2() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_y_2", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_y_2", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Z_2() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_z_2", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_z_2", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + + RENDER_HOLDER_LEASH_X_3() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_x_3", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_x_3", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Y_3() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_y_3", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_y_3", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Z_3() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_z_3", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_z_3", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + + RENDER_HOLDER_LEASH_X_4() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_x_4", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_x_4", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Y_4() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_y_4", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_y_4", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_HOLDER_LEASH_Z_4() { + @Override public void setValue(EMFModelPart ignored, float value) {var state = EMFState.state();if (state != null) state.variableMap().put("render.leash_holder_offset_z_4", value);} + @Override public float getValue(ModelPart ignored) {var state = EMFState.state();return state != null ? state.variableMap().getOrDefault("render.leash_holder_offset_z_4", 0f) : 0;} + @Override public boolean isRenderVariable() {return true;} + }, + RENDER_FIRE_X() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setFireX(value); + var state = EMFState.state(); + if (state != null) state.setFireX(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().fireX() : 0; + var state = EMFState.state(); + return state != null ? state.fireX() : 0; } @Override @@ -291,11 +414,13 @@ public boolean isRenderVariable() { RENDER_FIRE_Y() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setFireY(value); + var state = EMFState.state(); + if (state != null) state.setFireY(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().fireY() : 0; + var state = EMFState.state(); + return state != null ? state.fireY() : 0; } @Override public boolean isRenderVariable() { @@ -305,11 +430,13 @@ public boolean isRenderVariable() { RENDER_FIRE_Z() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setFireZ(value); + var state = EMFState.state(); + if (state != null) state.setFireZ(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().fireZ() : 0; + var state = EMFState.state(); + return state != null ? state.fireZ() : 0; } @Override public boolean isRenderVariable() { @@ -319,11 +446,13 @@ public boolean isRenderVariable() { RENDER_FIRE_SCALE() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setFireScale(value); + var state = EMFState.state(); + if (state != null) state.setFireScale(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().fireScale() : 0; + var state = EMFState.state(); + return state != null ? state.fireScale() : 0; } @Override public boolean isRenderVariable() { @@ -333,11 +462,13 @@ public boolean isRenderVariable() { RENDER_FIRE_HEIGHT() { @Override public void setValue(EMFModelPart ignored, float value) { - if (EMFState.state() != null) EMFState.state().setFireHeight(value); + var state = EMFState.state(); + if (state != null) state.setFireHeight(value); } @Override public float getValue(ModelPart ignored) { - return EMFState.state() != null ? EMFState.state().fireHeight() : 0; + var state = EMFState.state(); + return state != null ? state.fireHeight() : 0; } @Override public boolean isRenderVariable() { @@ -355,9 +486,40 @@ public static EMFModelOrRenderVariable getRenderVariable(String id) { case "render.shadow_opacity" -> RENDER_SHADOW_OPACITY; case "render.shadow_offset_x" -> RENDER_SHADOW_X; case "render.shadow_offset_z" -> RENDER_SHADOW_Z; + case "render.leash_offset_x" -> RENDER_LEASH_X; case "render.leash_offset_y" -> RENDER_LEASH_Y; case "render.leash_offset_z" -> RENDER_LEASH_Z; + case "render.leash_offset_x_1" -> RENDER_LEASH_X_1; + case "render.leash_offset_y_1" -> RENDER_LEASH_Y_1; + case "render.leash_offset_z_1" -> RENDER_LEASH_Z_1; + case "render.leash_offset_x_2" -> RENDER_LEASH_X_2; + case "render.leash_offset_y_2" -> RENDER_LEASH_Y_2; + case "render.leash_offset_z_2" -> RENDER_LEASH_Z_2; + case "render.leash_offset_x_3" -> RENDER_LEASH_X_3; + case "render.leash_offset_y_3" -> RENDER_LEASH_Y_3; + case "render.leash_offset_z_3" -> RENDER_LEASH_Z_3; + case "render.leash_offset_x_4" -> RENDER_LEASH_X_4; + case "render.leash_offset_y_4" -> RENDER_LEASH_Y_4; + case "render.leash_offset_z_4" -> RENDER_LEASH_Z_4; + + + case "render.leash_holder_offset_x" -> RENDER_HOLDER_LEASH_X; + case "render.leash_holder_offset_y" -> RENDER_HOLDER_LEASH_Y; + case "render.leash_holder_offset_z" -> RENDER_HOLDER_LEASH_Z; + case "render.leash_holder_offset_x_1" -> RENDER_HOLDER_LEASH_X_1; + case "render.leash_holder_offset_y_1" -> RENDER_HOLDER_LEASH_Y_1; + case "render.leash_holder_offset_z_1" -> RENDER_HOLDER_LEASH_Z_1; + case "render.leash_holder_offset_x_2" -> RENDER_HOLDER_LEASH_X_2; + case "render.leash_holder_offset_y_2" -> RENDER_HOLDER_LEASH_Y_2; + case "render.leash_holder_offset_z_2" -> RENDER_HOLDER_LEASH_Z_2; + case "render.leash_holder_offset_x_3" -> RENDER_HOLDER_LEASH_X_3; + case "render.leash_holder_offset_y_3" -> RENDER_HOLDER_LEASH_Y_3; + case "render.leash_holder_offset_z_3" -> RENDER_HOLDER_LEASH_Z_3; + case "render.leash_holder_offset_x_4" -> RENDER_HOLDER_LEASH_X_4; + case "render.leash_holder_offset_y_4" -> RENDER_HOLDER_LEASH_Y_4; + case "render.leash_holder_offset_z_4" -> RENDER_HOLDER_LEASH_Z_4; + case "render.fire_x" -> RENDER_FIRE_X; case "render.fire_y" -> RENDER_FIRE_Y; case "render.fire_z" -> RENDER_FIRE_Z; diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java index 661e7a6e..850ec345 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderState.java @@ -109,15 +109,6 @@ public interface EMFEntityRenderState extends ETFEntityRenderState { float shadowOpacity(); void setShadowOpacity(float shadowOpacity); - float leashX(); - void setLeashX(float leashX); - - float leashY(); - void setLeashY(float leashY); - - float leashZ(); - void setLeashZ(float leashZ); - float shadowX(); void setShadowX(float shadowX); diff --git a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java index 3bacee44..866297c1 100644 --- a/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java +++ b/src/main/java/traben/entity_model_features/models/animation/state/EMFEntityRenderStateViaReference.java @@ -100,18 +100,6 @@ public void setLayerFactory(final Function layerFa @Override public float shadowOpacity() { return shadowOpacity; } @Override public void setShadowOpacity(float shadowOpacity) { this.shadowOpacity = shadowOpacity; } - float leashX = Float.NaN; - @Override public float leashX() { return leashX; } - @Override public void setLeashX(float leashX) { this.leashX = leashX; } - - float leashY = Float.NaN; - @Override public float leashY() { return leashY; } - @Override public void setLeashY(float leashY) { this.leashY = leashY; } - - float leashZ = Float.NaN; - @Override public float leashZ() { return leashZ; } - @Override public void setLeashZ(float leashZ) { this.leashZ = leashZ; } - float shadowX = Float.NaN; @Override public float shadowX() { return shadowX; } @Override public void setShadowX(float shadowX) { this.shadowX = shadowX; } diff --git a/src/main/resources/entity_model_features.mixins.json b/src/main/resources/entity_model_features.mixins.json index 555c82bd..eda62a63 100644 --- a/src/main/resources/entity_model_features.mixins.json +++ b/src/main/resources/entity_model_features.mixins.json @@ -34,6 +34,7 @@ "rendering.MixinEntityRenderDispatcher", "rendering.MixinEntityRenderers", "rendering.MixinItemFrameEntityRenderer", + "rendering.MixinLeashOffsets", "rendering.MixinLivingEntityRenderer", "rendering.MixinPlayerEntityRenderer", "rendering.arrows.MixinArrowRenderer", From 384e8d02b6f52ae0a371c2867fc3aa9313c47550 Mon Sep 17 00:00:00 2001 From: Traben Date: Fri, 21 Aug 2026 16:49:53 +1000 Subject: [PATCH 20/20] fix esf --- .../math/expression_tree/MathMethod.java | 8 +++++++- .../animation/math/methods/SimpleMethod.java | 15 +++++++++++++-- .../math/variables/VariableRegistry.java | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/main/java/traben/entity_model_features/models/animation/math/expression_tree/MathMethod.java b/src/main/java/traben/entity_model_features/models/animation/math/expression_tree/MathMethod.java index 7a0d783f..1367b452 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/expression_tree/MathMethod.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/expression_tree/MathMethod.java @@ -40,14 +40,20 @@ public abstract class MathMethod extends MathValue implements MathComponent { protected @Nullable ResultSupplier supplier = null; protected final @NotNull List rawArgs; protected final @NotNull List parsedArgs; + protected final @NotNull List stringArgs; protected MathMethod(boolean isNegative, AnimSetupContext context, @NotNull List args) throws EMFMathException { this(isNegative, context, args, -1); } protected MathMethod(boolean isNegative, AnimSetupContext context, @NotNull List args, int customArgCount) throws EMFMathException { + this(isNegative, context, args, customArgCount, List.of()); + } + + protected MathMethod(boolean isNegative, AnimSetupContext context, @NotNull List args, int customArgCount, List stringArgs) throws EMFMathException { super(isNegative); rawArgs = args; + this.stringArgs = stringArgs; boolean correctArgCount = customArgCount != -1 ? customArgCount == args.size() : hasCorrectArgCount(args.size()); @@ -207,7 +213,7 @@ public final void asmVisit(MethodVisitor mv, ASMVariableHandler vars) throws EMF public abstract void asmVisitInner(MethodVisitor mv, ASMVariableHandler varNames) throws EMFMathException; protected boolean isRawStringArg(int index) { - return false; + return stringArgs.contains(index); } protected abstract boolean hasCorrectArgCount(int argCount); diff --git a/src/main/java/traben/entity_model_features/models/animation/math/methods/SimpleMethod.java b/src/main/java/traben/entity_model_features/models/animation/math/methods/SimpleMethod.java index a11cb190..e55eb983 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/methods/SimpleMethod.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/methods/SimpleMethod.java @@ -12,6 +12,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -27,7 +28,7 @@ protected SimpleMethod( Method staticMethod, @Nullable ASMVisitable asmCompiler ) throws EMFMathException { - super(isNegative, context, args, getParameterCount(staticMethod)); + super(isNegative, context, args, getParameterCount(staticMethod), getStringArgs(staticMethod)); this.staticMethod = staticMethod; boolean isBoolean = staticMethod.getReturnType().equals(boolean.class) || staticMethod.getReturnType().equals(Boolean.class); this.asmCompiler = asmCompiler; @@ -83,7 +84,7 @@ public void asmVisitInner(MethodVisitor mv, ASMVariableHandler vars) throws EMFM for (int i = 0; i < parsedArgs.size(); i++) { var arg = parsedArgs.get(i); if (arg == null) { - mv.visitLdcInsn(rawArgs.get(i)); // String + mv.visitLdcInsn((String) rawArgs.get(i)); // String } else { if (params[i] == boolean.class) { vars.scopeBool(); @@ -107,6 +108,16 @@ private static int getParameterCount(Method method) { return method.getParameterCount(); } + private static List getStringArgs(Method method) { + var list = new ArrayList(); + for (int i = 0; i < method.getParameterTypes().length; i++) { + if (method.getParameterTypes()[i] == String.class) { + list.add(i); + } + } + return list; + } + @Override protected boolean hasCorrectArgCount(final int argCount) { return true; diff --git a/src/main/java/traben/entity_model_features/models/animation/math/variables/VariableRegistry.java b/src/main/java/traben/entity_model_features/models/animation/math/variables/VariableRegistry.java index 30fb3d42..0c517335 100644 --- a/src/main/java/traben/entity_model_features/models/animation/math/variables/VariableRegistry.java +++ b/src/main/java/traben/entity_model_features/models/animation/math/variables/VariableRegistry.java @@ -333,7 +333,8 @@ public MathComponent getVariable(String variableName, boolean isNegative, AnimSe } catch (Exception e) { if (printing()) EMFUtils.logError("Error finding variable: [" + variableName + "] in animation [" + context.animKey + "] of model [" + context.modelName + "]. EMF will treat the variable as zero."); } - return variableName.startsWith("is_") ? MathConstant.FALSE_CONST : MathConstant.ZERO_CONST; + return new MathVariable(variableName, isNegative, + variableName.startsWith("is_") ? MathConstant.FALSE_CONST.getResultSupplier() : MathConstant.ZERO_CONST.getResultSupplier()); } private boolean printing() {