From c4c1be3e2bf652101840a70eff1a91e099a88dc7 Mon Sep 17 00:00:00 2001 From: luisc Date: Tue, 25 Feb 2025 16:13:12 -0600 Subject: [PATCH] Fixed some issues with full model animation rendering. --- .../java/kamkeel/npcs/addon/DBCAddon.java | 5 + .../noppes/npcs/AnimationMixinFunctions.java | 194 ++++++++++++++++++ .../npcs/mixin/CustomNPCsMixinPlugin.java | 2 +- .../noppes/npcs/mixin/MixinModelBase.java | 42 ---- .../noppes/npcs/mixin/MixinModelRenderer.java | 188 +---------------- .../npcs/mixin/MixinRendererLivingEntity.java | 21 ++ 6 files changed, 227 insertions(+), 225 deletions(-) create mode 100644 src/main/java/noppes/npcs/AnimationMixinFunctions.java delete mode 100644 src/main/java/noppes/npcs/mixin/MixinModelBase.java create mode 100644 src/main/java/noppes/npcs/mixin/MixinRendererLivingEntity.java diff --git a/src/main/java/kamkeel/npcs/addon/DBCAddon.java b/src/main/java/kamkeel/npcs/addon/DBCAddon.java index d109d2393..4e4ff5371 100644 --- a/src/main/java/kamkeel/npcs/addon/DBCAddon.java +++ b/src/main/java/kamkeel/npcs/addon/DBCAddon.java @@ -1,5 +1,6 @@ package kamkeel.npcs.addon; +import cpw.mods.fml.common.Loader; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.player.EntityPlayer; @@ -21,6 +22,10 @@ public class DBCAddon { instance = this; } + public static boolean IsAvailable() { + return Loader.isModLoaded("npcdbc"); + } + public void dbcCopyData(EntityLivingBase copied, EntityLivingBase entity){} // AI / STATS diff --git a/src/main/java/noppes/npcs/AnimationMixinFunctions.java b/src/main/java/noppes/npcs/AnimationMixinFunctions.java new file mode 100644 index 000000000..7cc891979 --- /dev/null +++ b/src/main/java/noppes/npcs/AnimationMixinFunctions.java @@ -0,0 +1,194 @@ +package noppes.npcs; + +import kamkeel.npcs.addon.DBCAddon; +import net.minecraft.client.model.ModelBiped; +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import noppes.npcs.client.ClientCacheHandler; +import noppes.npcs.client.ClientEventHandler; +import noppes.npcs.constants.EnumAnimationPart; +import noppes.npcs.controllers.data.AnimationData; +import noppes.npcs.controllers.data.Frame; +import noppes.npcs.controllers.data.FramePart; +import org.lwjgl.opengl.GL11; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import java.lang.reflect.Field; +import java.util.Map; +import java.util.Set; + +public class AnimationMixinFunctions { + + public static boolean applyValues(ModelRenderer modelRenderer) { + if (ClientEventHandler.renderingPlayer == null && ClientEventHandler.renderingNpc == null) { + return false; + } + + if (ClientEventHandler.renderingPlayer != null) { + ClientEventHandler.playerModel = (modelRenderer).baseModel; + if (ClientCacheHandler.playerAnimations.containsKey(ClientEventHandler.renderingPlayer.getUniqueID())) { + AnimationData animData = ClientCacheHandler.playerAnimations.get(ClientEventHandler.renderingPlayer.getUniqueID()); + EnumAnimationPart mainPartType = getPlayerPartType(modelRenderer); + EnumAnimationPart partType = mainPartType != null ? mainPartType : pivotEqualPart(modelRenderer); + if (partType != null && animData != null && animData.animation != null && animData.isActive()) { + if (!ClientEventHandler.originalValues.containsKey(modelRenderer)) { + FramePart part = new FramePart(); + part.pivot = new float[]{modelRenderer.rotationPointX, modelRenderer.rotationPointY, modelRenderer.rotationPointZ}; + part.rotation = new float[]{modelRenderer.rotateAngleX, modelRenderer.rotateAngleY, modelRenderer.rotateAngleZ}; + ClientEventHandler.originalValues.put(modelRenderer, part); + } + FramePart originalPart = ClientEventHandler.originalValues.get(modelRenderer); + Frame frame = (Frame) animData.animation.currentFrame(); + if (frame != null && frame.frameParts.containsKey(partType)) { + FramePart part = frame.frameParts.get(partType); + if (partType == mainPartType) { + part.interpolateAngles(); + part.interpolateOffset(); + modelRenderer.rotationPointX = originalPart.pivot[0] + part.prevPivots[0]; + modelRenderer.rotationPointY = originalPart.pivot[1] + part.prevPivots[1]; + modelRenderer.rotationPointZ = originalPart.pivot[2] + part.prevPivots[2]; + modelRenderer.rotateAngleX = part.prevRotations[0]; + modelRenderer.rotateAngleY = part.prevRotations[1]; + modelRenderer.rotateAngleZ = part.prevRotations[2]; + } else { + modelRenderer.rotateAngleZ += part.prevRotations[2]; + return true; + } + } + } + } + } else if (ClientEventHandler.renderingNpc.display.animationData.isActive()) { + AnimationData animData = ClientEventHandler.renderingNpc.display.animationData; + EnumAnimationPart partType = getPartType(modelRenderer); + if (partType != null && animData != null) { + Frame frame = (Frame) animData.animation.currentFrame(); + if (frame.frameParts.containsKey(partType)) { + FramePart part = frame.frameParts.get(partType); + part.interpolateOffset(); + part.interpolateAngles(); + modelRenderer.rotationPointX += part.prevPivots[0]; + modelRenderer.rotationPointY += part.prevPivots[1]; + modelRenderer.rotationPointZ += part.prevPivots[2]; + modelRenderer.rotateAngleX = part.prevRotations[0]; + modelRenderer.rotateAngleY = part.prevRotations[1]; + modelRenderer.rotateAngleZ = part.prevRotations[2]; + return true; + } + } + } + return false; + } + + private static EnumAnimationPart getPlayerPartType(ModelRenderer renderer) { + if (renderer.baseModel instanceof ModelBiped) { + if (renderer == ((ModelBiped) renderer.baseModel).bipedHead + || renderer == ((ModelBiped) renderer.baseModel).bipedHeadwear) { + return EnumAnimationPart.HEAD; + } + if (renderer == ((ModelBiped) renderer.baseModel).bipedBody) { + return EnumAnimationPart.BODY; + } + if (renderer == ((ModelBiped) renderer.baseModel).bipedRightArm) { + return EnumAnimationPart.RIGHT_ARM; + } + if (renderer == ((ModelBiped) renderer.baseModel).bipedLeftArm) { + return EnumAnimationPart.LEFT_ARM; + } + if (renderer == ((ModelBiped) renderer.baseModel).bipedRightLeg) { + return EnumAnimationPart.RIGHT_LEG; + } + if (renderer == ((ModelBiped) renderer.baseModel).bipedLeftLeg) { + return EnumAnimationPart.LEFT_LEG; + } + } + return getPartType(renderer); + } + + private static EnumAnimationPart pivotEqualPart(ModelRenderer renderer) { + if(renderer.baseModel instanceof ModelBiped){ + ModelRenderer head = ((ModelBiped) renderer.baseModel).bipedHead; + ModelRenderer body = ((ModelBiped) renderer.baseModel).bipedBody; + ModelRenderer larm = ((ModelBiped) renderer.baseModel).bipedLeftArm; + ModelRenderer rarm = ((ModelBiped) renderer.baseModel).bipedRightArm; + ModelRenderer lleg = ((ModelBiped) renderer.baseModel).bipedLeftLeg; + ModelRenderer rleg = ((ModelBiped) renderer.baseModel).bipedRightLeg; + + if (pivotsEqual(renderer,head)) { + return EnumAnimationPart.HEAD; + } + if (pivotsEqual(renderer,body)) { + return EnumAnimationPart.BODY; + } + if (pivotsEqual(renderer,rarm)) { + return EnumAnimationPart.RIGHT_ARM; + } + if (pivotsEqual(renderer,larm)) { + return EnumAnimationPart.LEFT_ARM; + } + if (pivotsEqual(renderer,rleg)) { + return EnumAnimationPart.RIGHT_LEG; + } + if (pivotsEqual(renderer,lleg)) { + return EnumAnimationPart.LEFT_LEG; + } + } + + return null; + } + + private static boolean pivotsEqual(ModelRenderer m1, ModelRenderer m2) { + return m1.rotationPointX == m2.rotationPointX && m1.rotationPointY == m2.rotationPointY && m1.rotationPointZ == m2.rotationPointZ; + } + + private static EnumAnimationPart getPartType(ModelRenderer renderer) { + Class RenderClass = renderer.baseModel.getClass(); + Object model = renderer.baseModel; + + Set> entrySet = ClientEventHandler.partNames.entrySet(); + while (RenderClass != Object.class) { + Field[] declared; + if (ClientEventHandler.declaredFieldCache.containsKey(RenderClass)) { + declared = ClientEventHandler.declaredFieldCache.get(RenderClass); + } else { + declared = RenderClass.getDeclaredFields(); + ClientEventHandler.declaredFieldCache.put(RenderClass,declared); + } + for (Field f : declared) { + f.setAccessible(true); + for (Map.Entry entry : entrySet) { + String[] names = entry.getValue(); + for (String partName : names) { + try { + if (partName.equals(f.getName()) && renderer == f.get(model)) { + return entry.getKey(); + } + } catch (IllegalAccessException ignored) {} + } + } + } + RenderClass = RenderClass.getSuperclass(); + } + + return null; + } + + public static void playerFullModel_head(Entity p_78088_1_, CallbackInfo callbackInfo) { + if (!DBCAddon.IsAvailable() && ClientCacheHandler.playerAnimations.containsKey(p_78088_1_.getUniqueID())) { + AnimationData animData = ClientCacheHandler.playerAnimations.get(p_78088_1_.getUniqueID()); + if (animData != null && animData.isActive()) { + Frame frame = (Frame) animData.animation.currentFrame(); + if (frame.frameParts.containsKey(EnumAnimationPart.FULL_MODEL)) { + FramePart part = frame.frameParts.get(EnumAnimationPart.FULL_MODEL); + part.interpolateOffset(); + part.interpolateAngles(); + float pi = 180 / (float) Math.PI; + GL11.glTranslatef(part.prevPivots[0], part.prevPivots[1], part.prevPivots[2]); + GL11.glRotatef(part.prevRotations[0] * pi, 1, 0, 0); + GL11.glRotatef(part.prevRotations[1] * pi, 0, 1, 0); + GL11.glRotatef(part.prevRotations[2] * pi, 0, 0, 1); + } + } + } + } +} diff --git a/src/main/java/noppes/npcs/mixin/CustomNPCsMixinPlugin.java b/src/main/java/noppes/npcs/mixin/CustomNPCsMixinPlugin.java index 77554d921..e081cee32 100644 --- a/src/main/java/noppes/npcs/mixin/CustomNPCsMixinPlugin.java +++ b/src/main/java/noppes/npcs/mixin/CustomNPCsMixinPlugin.java @@ -49,7 +49,7 @@ public class CustomNPCsMixinPlugin implements IMixinConfigPlugin { } if (ConfigMixin.AnimationMixin) { mixins.add("MixinModelRenderer"); - mixins.add("MixinModelBase"); + mixins.add("MixinRendererLivingEntity"); } if (ConfigMixin.FirstPersonAnimationMixin) { mixins.add("MixinItemRenderer"); diff --git a/src/main/java/noppes/npcs/mixin/MixinModelBase.java b/src/main/java/noppes/npcs/mixin/MixinModelBase.java deleted file mode 100644 index 6d8dda17c..000000000 --- a/src/main/java/noppes/npcs/mixin/MixinModelBase.java +++ /dev/null @@ -1,42 +0,0 @@ -package noppes.npcs.mixin; - -import cpw.mods.fml.relauncher.Side; -import cpw.mods.fml.relauncher.SideOnly; -import net.minecraft.client.model.ModelBase; -import net.minecraft.entity.EntityLivingBase; -import noppes.npcs.client.ClientCacheHandler; -import noppes.npcs.constants.EnumAnimationPart; -import noppes.npcs.controllers.data.AnimationData; -import noppes.npcs.controllers.data.Frame; -import noppes.npcs.controllers.data.FramePart; -import org.lwjgl.opengl.GL11; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(value = ModelBase.class) -public abstract class MixinModelBase { - - @SideOnly(Side.CLIENT) - @Inject(method = "setLivingAnimations", at = @At(value = "TAIL")) - public void setLivingAnimations(EntityLivingBase p_78086_1_, float p_78086_2_, float p_78086_3_, float p_78086_4_, CallbackInfo callbackInfo) - { - if (ClientCacheHandler.playerAnimations.containsKey(p_78086_1_.getUniqueID())) { - AnimationData animData = ClientCacheHandler.playerAnimations.get(p_78086_1_.getUniqueID()); - if (animData != null && animData.isActive()) { - Frame frame = (Frame) animData.animation.currentFrame(); - if (frame.frameParts.containsKey(EnumAnimationPart.FULL_MODEL)) { - FramePart part = frame.frameParts.get(EnumAnimationPart.FULL_MODEL); - part.interpolateOffset(); - part.interpolateAngles(); - float pi = 180 / (float) Math.PI; - GL11.glTranslatef(part.prevPivots[0], part.prevPivots[1], part.prevPivots[2]); - GL11.glRotatef(part.prevRotations[0] * pi, 1, 0, 0); - GL11.glRotatef(part.prevRotations[1] * pi, 0, 1, 0); - GL11.glRotatef(part.prevRotations[2] * pi, 0, 0, 1); - } - } - } - } -} diff --git a/src/main/java/noppes/npcs/mixin/MixinModelRenderer.java b/src/main/java/noppes/npcs/mixin/MixinModelRenderer.java index 60a8ed6fc..d5e8eadbd 100644 --- a/src/main/java/noppes/npcs/mixin/MixinModelRenderer.java +++ b/src/main/java/noppes/npcs/mixin/MixinModelRenderer.java @@ -3,23 +3,16 @@ package noppes.npcs.mixin; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import net.minecraft.client.model.ModelBase; -import net.minecraft.client.model.ModelBiped; import net.minecraft.client.model.ModelRenderer; -import noppes.npcs.client.ClientCacheHandler; +import noppes.npcs.AnimationMixinFunctions; import noppes.npcs.client.ClientEventHandler; import noppes.npcs.constants.EnumAnimationPart; -import noppes.npcs.controllers.data.AnimationData; -import noppes.npcs.controllers.data.Frame; -import noppes.npcs.controllers.data.FramePart; import org.lwjgl.opengl.GL11; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Overwrite; import org.spongepowered.asm.mixin.Shadow; -import java.lang.reflect.Field; import java.util.List; -import java.util.Map; -import java.util.Set; @Mixin(value = ModelRenderer.class) public abstract class MixinModelRenderer { @@ -81,56 +74,10 @@ public abstract class MixinModelRenderer { float prevAngleY = this.rotateAngleY; float prevAngleZ = this.rotateAngleZ; - FramePart currentPart = null; - if (ClientEventHandler.renderingNpc != null && ClientEventHandler.renderingNpc.display.animationData.isActive()) { - AnimationData animData = ClientEventHandler.renderingNpc.display.animationData; - EnumAnimationPart partType = this.getPartType((ModelRenderer) (Object) this); - - if (partType != null && animData != null) { - Frame frame = (Frame) animData.animation.currentFrame(); - if (frame.frameParts.containsKey(partType)) { - currentPart = frame.frameParts.get(partType); - currentPart.interpolateOffset(); - currentPart.interpolateAngles(); - this.rotationPointX += currentPart.prevPivots[0]; - this.rotationPointY += currentPart.prevPivots[1]; - this.rotationPointZ += currentPart.prevPivots[2]; - this.rotateAngleX = currentPart.prevRotations[0]; - this.rotateAngleY = currentPart.prevRotations[1]; - this.rotateAngleZ = currentPart.prevRotations[2]; - } - } - } - - if (ClientEventHandler.renderingPlayer != null) { - ClientEventHandler.playerModel = ((ModelRenderer) (Object) this).baseModel; - } - if (ClientEventHandler.renderingPlayer != null && ClientCacheHandler.playerAnimations.containsKey(ClientEventHandler.renderingPlayer.getUniqueID())) { - ClientEventHandler.playerModel = ((ModelRenderer) (Object) this).baseModel; - AnimationData animData = ClientCacheHandler.playerAnimations.get(ClientEventHandler.renderingPlayer.getUniqueID()); - - EnumAnimationPart mainPartType = this.getPlayerPartType((ModelRenderer) (Object) this); - EnumAnimationPart partType = mainPartType != null ? mainPartType : this.pivotEqualPart((ModelRenderer) (Object) this); - if (partType != null && animData != null && animData.animation != null && animData.isActive()) { - FramePart originalPart = ClientEventHandler.originalValues.get((ModelRenderer) (Object) this); - Frame frame = (Frame) animData.animation.currentFrame(); - if (originalPart != null && frame != null && frame.frameParts.containsKey(partType)) { - FramePart part = frame.frameParts.get(partType); - if (partType == mainPartType) { - part.interpolateAngles(); - part.interpolateOffset(); - this.rotationPointX = originalPart.pivot[0] + part.prevPivots[0]; - this.rotationPointY = originalPart.pivot[1] + part.prevPivots[1]; - this.rotationPointZ = originalPart.pivot[2] + part.prevPivots[2]; - this.rotateAngleX = part.prevRotations[0]; - this.rotateAngleY = part.prevRotations[1]; - this.rotateAngleZ = part.prevRotations[2]; - } else { - currentPart = part; - this.rotateAngleZ += part.prevRotations[2]; - } - } - } + boolean changedAngles = false; + try { + changedAngles = AnimationMixinFunctions.applyValues((ModelRenderer) (Object) this); + } catch (Exception ignored) { } GL11.glTranslatef(this.offsetX, this.offsetY, this.offsetZ); @@ -204,7 +151,7 @@ public abstract class MixinModelRenderer { GL11.glPopMatrix(); } - if (currentPart != null) { + if (changedAngles) { this.rotationPointX = prevPointX; this.rotationPointY = prevPointY; this.rotationPointZ = prevPointZ; @@ -215,127 +162,4 @@ public abstract class MixinModelRenderer { } } } - - public EnumAnimationPart getPlayerPartType(ModelRenderer renderer) { - if (renderer.baseModel instanceof ModelBiped) { - if (renderer == ((ModelBiped) renderer.baseModel).bipedHead - || renderer == ((ModelBiped) renderer.baseModel).bipedHeadwear) { - return EnumAnimationPart.HEAD; - } - if (renderer == ((ModelBiped) renderer.baseModel).bipedBody) { - return EnumAnimationPart.BODY; - } - if (renderer == ((ModelBiped) renderer.baseModel).bipedRightArm) { - return EnumAnimationPart.RIGHT_ARM; - } - if (renderer == ((ModelBiped) renderer.baseModel).bipedLeftArm) { - return EnumAnimationPart.LEFT_ARM; - } - if (renderer == ((ModelBiped) renderer.baseModel).bipedRightLeg) { - return EnumAnimationPart.RIGHT_LEG; - } - if (renderer == ((ModelBiped) renderer.baseModel).bipedLeftLeg) { - return EnumAnimationPart.LEFT_LEG; - } - } - - try { - Class ModelBipedBody = Class.forName("JinRyuu.JRMCore.entity.ModelBipedBody"); - Object model = renderer.baseModel; - if(!(model instanceof ModelBiped)) - return null; - - Field[] declared; - if (ClientEventHandler.declaredFieldCache.containsKey(ModelBipedBody)) { - declared = ClientEventHandler.declaredFieldCache.get(ModelBipedBody); - } else { - declared = ModelBipedBody.getDeclaredFields(); - ClientEventHandler.declaredFieldCache.put(ModelBipedBody,declared); - } - Set> entrySet = ClientEventHandler.partNames.entrySet(); - for (Field f : declared) { - f.setAccessible(true); - for (Map.Entry entry : entrySet) { - String[] names = entry.getValue(); - for (String partName : names) { - try { - if (partName.equals(f.getName()) && renderer == f.get(model)) { - return entry.getKey(); - } - } catch (IllegalAccessException ignored) {} - } - } - } - } catch (ClassNotFoundException ignored) {} - - return null; - } - - public EnumAnimationPart pivotEqualPart(ModelRenderer renderer) { - if(renderer.baseModel instanceof ModelBiped){ - ModelRenderer head = ((ModelBiped) renderer.baseModel).bipedHead; - ModelRenderer body = ((ModelBiped) renderer.baseModel).bipedBody; - ModelRenderer larm = ((ModelBiped) renderer.baseModel).bipedLeftArm; - ModelRenderer rarm = ((ModelBiped) renderer.baseModel).bipedRightArm; - ModelRenderer lleg = ((ModelBiped) renderer.baseModel).bipedLeftLeg; - ModelRenderer rleg = ((ModelBiped) renderer.baseModel).bipedRightLeg; - - if (pivotsEqual(renderer,head)) { - return EnumAnimationPart.HEAD; - } - if (pivotsEqual(renderer,body)) { - return EnumAnimationPart.BODY; - } - if (pivotsEqual(renderer,rarm)) { - return EnumAnimationPart.RIGHT_ARM; - } - if (pivotsEqual(renderer,larm)) { - return EnumAnimationPart.LEFT_ARM; - } - if (pivotsEqual(renderer,rleg)) { - return EnumAnimationPart.RIGHT_LEG; - } - if (pivotsEqual(renderer,lleg)) { - return EnumAnimationPart.LEFT_LEG; - } - } - - return null; - } - - public boolean pivotsEqual(ModelRenderer m1, ModelRenderer m2) { - return m1.rotationPointX == m2.rotationPointX && m1.rotationPointY == m2.rotationPointY && m1.rotationPointZ == m2.rotationPointZ; - } - - public EnumAnimationPart getPartType(ModelRenderer renderer) { - Class RenderClass = renderer.baseModel.getClass(); - Object model = renderer.baseModel; - - Set> entrySet = ClientEventHandler.partNames.entrySet(); - while (RenderClass != Object.class) { - Field[] declared; - if (ClientEventHandler.declaredFieldCache.containsKey(RenderClass)) { - declared = ClientEventHandler.declaredFieldCache.get(RenderClass); - } else { - declared = RenderClass.getDeclaredFields(); - ClientEventHandler.declaredFieldCache.put(RenderClass,declared); - } - for (Field f : declared) { - f.setAccessible(true); - for (Map.Entry entry : entrySet) { - String[] names = entry.getValue(); - for (String partName : names) { - try { - if (partName.equals(f.getName()) && renderer == f.get(model)) { - return entry.getKey(); - } - } catch (IllegalAccessException ignored) {} - } - } - } - RenderClass = RenderClass.getSuperclass(); - } - - return null; - } } diff --git a/src/main/java/noppes/npcs/mixin/MixinRendererLivingEntity.java b/src/main/java/noppes/npcs/mixin/MixinRendererLivingEntity.java new file mode 100644 index 000000000..b06696ff5 --- /dev/null +++ b/src/main/java/noppes/npcs/mixin/MixinRendererLivingEntity.java @@ -0,0 +1,21 @@ +package noppes.npcs.mixin; + +import net.minecraft.client.renderer.entity.RendererLivingEntity; +import net.minecraft.entity.EntityLivingBase; +import noppes.npcs.AnimationMixinFunctions; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(RendererLivingEntity.class) +public class MixinRendererLivingEntity { + + @Inject(method = "doRender(Lnet/minecraft/entity/EntityLivingBase;DDDFF)V", at = @At( + value = "INVOKE", + target = "Lnet/minecraft/client/renderer/entity/RendererLivingEntity;renderModel(Lnet/minecraft/entity/EntityLivingBase;FFFFFF)V", + shift = At.Shift.BEFORE)) + public void render_pre(EntityLivingBase p_76986_1_, double p_76986_2_, double p_76986_4_, double p_76986_6_, float p_76986_8_, float p_76986_9_, CallbackInfo ci) { + AnimationMixinFunctions.playerFullModel_head(p_76986_1_, ci); + } +}