package com.tiedup.remake.mixin.client; import com.tiedup.remake.client.animation.render.DogPoseRenderHandler; import com.tiedup.remake.client.animation.util.DogPoseHelper; import com.tiedup.remake.items.base.ItemBind; import com.tiedup.remake.items.base.PoseType; import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.v2.BodyRegionV2; import net.minecraft.client.model.PlayerModel; import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; 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 for PlayerModel to handle DOG pose head adjustments. * * When in DOG pose (body horizontal): * - Head pitch offset so player looks forward * - Head yaw converted to zRot (roll) since yRot axis is sideways when body is horizontal */ @Mixin(PlayerModel.class) public class MixinPlayerModel { @Inject(method = "setupAnim", at = @At("TAIL")) private void tiedup$adjustDogPose( LivingEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, CallbackInfo ci ) { if (!(entity instanceof AbstractClientPlayer player)) { return; } PlayerBindState state = PlayerBindState.getInstance(player); if (state == null) { return; } ItemStack bind = state.getEquipment(BodyRegionV2.ARMS); if (bind.isEmpty() || !(bind.getItem() instanceof ItemBind itemBind)) { return; } if (itemBind.getPoseType() != PoseType.DOG) { return; } PlayerModel model = (PlayerModel) (Object) this; // === HEAD ROTATION FOR HORIZONTAL BODY === // Body is at -90° pitch (horizontal, face down) // We apply a rotation delta to the poseStack in PlayerArmHideEventHandler // The head needs to compensate for this transformation float rotationDelta = DogPoseRenderHandler.getAppliedRotationDelta( player.getId() ); boolean moving = DogPoseRenderHandler.isDogPoseMoving(player.getId()); // netHeadYaw is head relative to vanilla body (yHeadRot - yBodyRot) // We rotated the model by rotationDelta, so compensate: // effectiveHeadYaw = netHeadYaw + rotationDelta float headYaw = netHeadYaw + rotationDelta; // Clamp based on movement state and apply head compensation float maxYaw = moving ? 60f : 90f; DogPoseHelper.applyHeadCompensationClamped( model.head, model.hat, headPitch, headYaw, maxYaw ); } }