From 5a39fb0c1ceb35a6a146f29257ff2b9c179211b1 Mon Sep 17 00:00:00 2001 From: notevil Date: Thu, 23 Apr 2026 00:42:10 +0200 Subject: [PATCH] Phase 2.8 : V2 player rendering cleanup + QA checklist doc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cut wholesale du pipeline V2 player-anim suite au bascule RIG (pas d'opt-in, pas de rollback — accepté par le mainteneur). - rm MixinPlayerModel : le renderer RIG patched ne passe plus par PlayerModel.setupAnim, donc l'injection @TAIL devenait dead code. Les features dog pose head compensation seront ré-exprimées en StaticAnimation pose_dog.json (V3-REW-07). - Strip tiedup.mixins.json : retiré client/MixinPlayerModel, restent MixinCamera + MixinLivingEntitySleeping. - BondageAnimationManager.init() : retiré les 3 PlayerAnimationFactory registrations (context / item / furniture), le path joueur n'en dépend plus. Factory IDs conservés car les getPlayerLayer*() sont tolérantes au null retour via try/catch existants — et restent utilisées par le cache fallback remote. Les NPCs continuent d'utiliser cette classe via l'accès direct animation stack (IAnimatedPlayer.getAnimationStack().addAnimLayer), inchangé. - TiedUpMod.onClientSetup : suppression de l'appel BondageAnimationManager.init() (la méthode est maintenant un log no-op, conservée pour la signature publique + doc du changement). - AnimationTickHandler.onClientTick : retrait de la boucle mc.level.players() + updatePlayerAnimation + tickFurnitureSafety + cold-cache furniture retry. Les joueurs sont ticked par RigAnimationTickHandler (Phase 2.7). Conservé : le cleanup périodique ClothesClientCache (hygiène mémoire indépendante), le hook onPlayerLogout (cleanup per-UUID des caches NPC restants), et le hook onWorldUnload (caches V2 encore utilisés par NpcAnimationTickHandler). Imports unused strippés. - DogPoseHelper : mis à jour la javadoc pour refléter le retrait du path player (NPCs only désormais). Compile GREEN. 20/20 tests rig GREEN. QA runtime : cf. docs/plans/rig/PHASE2_QA.md (non commit — fichier working doc sous docs/plans/ gitignored par convention repo). Net LOC : -276. --- .../animation/BondageAnimationManager.java | 53 ++-- .../animation/tick/AnimationTickHandler.java | 241 +++--------------- .../client/animation/util/DogPoseHelper.java | 34 +-- .../com/tiedup/remake/core/TiedUpMod.java | 8 +- .../remake/mixin/client/MixinPlayerModel.java | 83 ------ src/main/resources/tiedup.mixins.json | 1 - 6 files changed, 72 insertions(+), 348 deletions(-) delete mode 100644 src/main/java/com/tiedup/remake/mixin/client/MixinPlayerModel.java diff --git a/src/main/java/com/tiedup/remake/client/animation/BondageAnimationManager.java b/src/main/java/com/tiedup/remake/client/animation/BondageAnimationManager.java index bf54669..1646e61 100644 --- a/src/main/java/com/tiedup/remake/client/animation/BondageAnimationManager.java +++ b/src/main/java/com/tiedup/remake/client/animation/BondageAnimationManager.java @@ -90,41 +90,30 @@ public class BondageAnimationManager { /** * Initialize the animation system. - * Must be called during client setup to register the player animation factory. + * + *

Phase 2.8 RIG cleanup — les 3 {@link PlayerAnimationFactory} + * (context / item / furniture) ont été supprimées : le renderer RIG + * patched ne passe plus par le pipeline PlayerAnimator pour le joueur, + * donc les factories devenaient dead code (aucun call site n'atteint + * jamais la map associée côté joueur).

+ * + *

Les NPCs continuent d'être animés via cette classe : le chemin + * {@link #getOrCreateLayer} pour les entités {@code IAnimatedPlayer} + * non-joueur utilise {@code animated.getAnimationStack().addAnimLayer(...)} + * en direct — ça ne dépend d'aucune factory. Voir {@code NpcAnimationTickHandler} + * pour le consumer. Le path player dans {@link #getOrCreateLayer} est + * laissé en place volontairement : il retombe proprement sur null + * (PlayerAnimationAccess throw → catch → null) et laisse le tick RIG + * s'occuper du joueur.

+ * + *

Conservé comme méthode publique pour ne pas casser les call sites + * externes et pour documenter la bascule. Rework V3 (player anim + * natives RIG) : voir V3-REW-01 dans {@code docs/plans/rig/V3_REWORK_BACKLOG.md}.

*/ public static void init() { - LOGGER.info("BondageAnimationManager initializing..."); - - // Context layer: lower priority = evaluated first, overridable by item layer. - // In AnimationStack, layers are sorted ascending by priority and evaluated in order. - // Higher priority layers override lower ones. - PlayerAnimationFactory.ANIMATION_DATA_FACTORY.registerFactory( - CONTEXT_FACTORY_ID, - CONTEXT_LAYER_PRIORITY, - player -> new ModifierLayer<>() - ); - - // Item layer: higher priority = evaluated last, overrides context layer - PlayerAnimationFactory.ANIMATION_DATA_FACTORY.registerFactory( - FACTORY_ID, - ITEM_LAYER_PRIORITY, - player -> new ModifierLayer<>() - ); - - // Furniture layer: highest priority = overrides item layer on blocked bones. - // Non-blocked bones are disabled via FurnitureAnimationContext so items - // can still animate free regions (gag, blindfold, etc.). - PlayerAnimationFactory.ANIMATION_DATA_FACTORY.registerFactory( - FURNITURE_FACTORY_ID, - FURNITURE_LAYER_PRIORITY, - player -> new ModifierLayer<>() - ); - LOGGER.info( - "BondageAnimationManager: Factories registered — context (pri {}), item (pri {}), furniture (pri {})", - CONTEXT_LAYER_PRIORITY, - ITEM_LAYER_PRIORITY, - FURNITURE_LAYER_PRIORITY + "BondageAnimationManager: player-side factories no-op (Phase 2.8 RIG cleanup). " + + "NPC-side animation stack access untouched." ); } diff --git a/src/main/java/com/tiedup/remake/client/animation/tick/AnimationTickHandler.java b/src/main/java/com/tiedup/remake/client/animation/tick/AnimationTickHandler.java index 4160468..332ea42 100644 --- a/src/main/java/com/tiedup/remake/client/animation/tick/AnimationTickHandler.java +++ b/src/main/java/com/tiedup/remake/client/animation/tick/AnimationTickHandler.java @@ -3,29 +3,17 @@ package com.tiedup.remake.client.animation.tick; import com.mojang.logging.LogUtils; import com.tiedup.remake.client.animation.AnimationStateRegistry; import com.tiedup.remake.client.animation.BondageAnimationManager; -import com.tiedup.remake.client.animation.PendingAnimationManager; -import com.tiedup.remake.client.animation.context.AnimationContext; -import com.tiedup.remake.client.animation.context.AnimationContextResolver; -import com.tiedup.remake.client.animation.context.RegionBoneMapper; import com.tiedup.remake.client.events.CellHighlightHandler; import com.tiedup.remake.client.events.LeashProxyClientHandler; import com.tiedup.remake.client.gltf.GltfAnimationApplier; import com.tiedup.remake.client.state.ClothesClientCache; import com.tiedup.remake.client.state.MovementStyleClientState; import com.tiedup.remake.client.state.PetBedClientState; -import com.tiedup.remake.util.HumanChairHelper; import com.tiedup.remake.state.PlayerBindState; -import com.tiedup.remake.v2.BodyRegionV2; -import com.tiedup.remake.v2.bondage.IV2BondageEquipment; -import com.tiedup.remake.v2.bondage.capability.V2EquipmentHelper; -import com.tiedup.remake.v2.bondage.movement.MovementStyle; import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import net.minecraft.client.Minecraft; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.event.TickEvent; @@ -35,16 +23,29 @@ import net.minecraftforge.fml.common.Mod; import org.slf4j.Logger; /** - * Event handler for player animation tick updates. + * Event handler for animation tick updates. * - *

Simplified handler that: + *

Phase 2.8 RIG cleanup : le ticking player V2 (boucle + * {@code mc.level.players()} + {@code updatePlayerAnimation}) est entièrement + * désactivé. Les joueurs sont désormais pilotés par + * {@link com.tiedup.remake.rig.tick.RigAnimationTickHandler} via le pipeline + * RIG (capability {@code LivingEntityPatch} + {@code Animator} natif EF). + * Les features V2 qui dépendaient du tick player sont trackées dans + * {@code docs/plans/rig/V3_REWORK_BACKLOG.md} (V3-REW-01/02/03/07).

+ * + *

Restent actifs ici : *

* - *

Registered on the FORGE event bus (not MOD bus). + *

Le ticking NPC est assuré par {@link NpcAnimationTickHandler}. Ce + * handler ne tick plus les NPCs directement — il ne gère que les hooks + * lifecycle globaux (logout + world unload).

+ * + *

Registered on the FORGE event bus (not MOD bus).

*/ @Mod.EventBusSubscriber( modid = "tiedup", @@ -83,8 +84,20 @@ public class AnimationTickHandler { } /** - * Client tick event - called every tick on the client. - * Updates animations for all players when their bondage state changes. + * Client tick event — called every tick on the client. + * + *

Phase 2.8 : la boucle {@code mc.level.players()} qui appelait + * {@code updatePlayerAnimation}, {@code tickFurnitureSafety} et le + * cold-cache retry furniture a été entièrement supprimée. Les joueurs + * sont désormais ticked par {@link com.tiedup.remake.rig.tick.RigAnimationTickHandler} + * via le pipeline RIG (capability {@code LivingEntityPatch} + + * {@code Animator}). Les régressions visuelles (V2 bondage layer cassé, + * furniture seat pose sur joueur cassée, pet bed pose cassée) sont + * listées dans {@code docs/plans/rig/V3_REWORK_BACKLOG.md}.

+ * + *

Seul le nettoyage périodique de {@link ClothesClientCache} reste + * — c'est de l'hygiène mémoire sur un cache indexé UUID joueur, + * indépendant du pipeline de rendu.

*/ @SubscribeEvent public static void onClientTick(TickEvent.ClientTickEvent event) { @@ -97,193 +110,17 @@ public class AnimationTickHandler { return; } - // Process pending animations first (retry failed animations for remote players) - PendingAnimationManager.processPending(mc.level); - - // Periodic cleanup of stale cache entries (every 60 seconds = 1200 ticks) + // Periodic cleanup of stale clothes cache entries (every 60 seconds = 1200 ticks). + // Indépendant du rendu V2/RIG — c'est juste un cache UUID→ClothesData qui + // doit libérer la mémoire des joueurs déconnectés depuis >5min. if (++cleanupTickCounter >= 1200) { cleanupTickCounter = 0; ClothesClientCache.cleanupStale(); } - // Then update all player animations - for (Player player : mc.level.players()) { - if (player instanceof AbstractClientPlayer clientPlayer) { - updatePlayerAnimation(clientPlayer); - } - // Safety: remove stale furniture animations for players no longer on seats - BondageAnimationManager.tickFurnitureSafety(player); - // Cold-cache retry: if the player is seated on furniture but has no - // active pose (GLB was not yet loaded at mount time, or the GLB cache - // entry was a transient failure), retry until the cache warms. - // FurnitureGltfCache memoizes failures via Optional.empty(), so - // retries after a genuine parse failure return instantly with no - // reparse. Bounded at MAX_FURNITURE_RETRIES so a legacy V1-only - // GLB (no Player_* armature → seatSkeleton==null → no animation - // ever possible) doesn't spam retries at 20 Hz forever. - // Single read of getVehicle() — avoids a re-read where the - // vehicle could change between instanceof and cast. - com.tiedup.remake.v2.furniture.EntityFurniture furniture = - player.getVehicle() instanceof - com.tiedup.remake.v2.furniture.EntityFurniture f ? f : null; - boolean hasAnim = BondageAnimationManager.hasFurnitureAnimation( - player - ); - UUID playerUuid = player.getUUID(); - if (furniture != null && !hasAnim) { - int retries = furnitureRetryCounters.getOrDefault( - playerUuid, - 0 - ); - if (retries < MAX_FURNITURE_RETRIES) { - furnitureRetryCounters.put(playerUuid, retries + 1); - com.tiedup.remake.v2.furniture.client.FurnitureClientAnimator - .start(furniture, player); - if (retries + 1 == MAX_FURNITURE_RETRIES) { - LOGGER.debug( - "[FurnitureAnim] Giving up on furniture animation retry for {} after {} attempts — GLB likely has no Player_* armature.", - player.getName().getString(), - MAX_FURNITURE_RETRIES - ); - } - } - } else { - // Dismounted or successfully applied — drop the counter so a - // later re-mount starts fresh. - furnitureRetryCounters.remove(playerUuid); - } - } - } - - /** - * Update animation for a single player. - */ - private static void updatePlayerAnimation(AbstractClientPlayer player) { - // Safety check: skip for removed/dead players - if (player.isRemoved() || !player.isAlive()) { - return; - } - - PlayerBindState state = PlayerBindState.getInstance(player); - UUID uuid = player.getUUID(); - - // Check if player has ANY V2 bondage item equipped (not just ARMS). - // isTiedUp() only checks ARMS, but items on LEGS, HEAD, etc. also need animation. - boolean isTied = - state != null && - (state.isTiedUp() || V2EquipmentHelper.hasAnyEquipment(player)); - boolean wasTied = - AnimationStateRegistry.getLastTiedState().getOrDefault(uuid, false); - - // Pet bed animations take priority over bondage animations - if (PetBedClientState.get(uuid) != 0) { - // Lock body rotation to bed facing (prevents camera from rotating the model) - float lockedRot = PetBedClientState.getFacing(uuid); - player.yBodyRot = lockedRot; - player.yBodyRotO = lockedRot; - - // Clamp head rotation to ±50° from body (like vehicle) - float headRot = player.getYHeadRot(); - float clamped = - lockedRot + - net.minecraft.util.Mth.clamp( - net.minecraft.util.Mth.wrapDegrees(headRot - lockedRot), - -50f, - 50f - ); - player.setYHeadRot(clamped); - player.yHeadRotO = clamped; - - AnimationStateRegistry.getLastTiedState().put(uuid, isTied); - return; - } - - // Human chair: clamp 1st-person camera only (body lock handled by MixinLivingEntityBodyRot) - // NO return — animation HUMAN_CHAIR must continue playing below - if (isTied && state != null) { - ItemStack chairBind = state.getEquipment(BodyRegionV2.ARMS); - if (HumanChairHelper.isActive(chairBind)) { - // 1st person only: clamp yRot so player can't look behind - // 3rd person: yRot untouched → camera orbits freely 360° - if ( - player == Minecraft.getInstance().player && - Minecraft.getInstance().options.getCameraType() == - net.minecraft.client.CameraType.FIRST_PERSON - ) { - float lockedRot = HumanChairHelper.getFacing(chairBind); - float camClamped = - lockedRot + - net.minecraft.util.Mth.clamp( - net.minecraft.util.Mth.wrapDegrees( - player.getYRot() - lockedRot - ), - -90f, - 90f - ); - player.setYRot(camClamped); - player.yRotO = - lockedRot + - net.minecraft.util.Mth.clamp( - net.minecraft.util.Mth.wrapDegrees( - player.yRotO - lockedRot - ), - -90f, - 90f - ); - } - } - } - - if (isTied) { - // Resolve V2 equipped items - IV2BondageEquipment equipment = V2EquipmentHelper.getEquipment( - player - ); - Map equipped = - equipment != null ? equipment.getAllEquipped() : Map.of(); - - // Resolve ALL V2 items with GLB models and per-item bone ownership - java.util.List v2Items = - RegionBoneMapper.resolveAllV2Items(equipped); - - if (!v2Items.isEmpty()) { - // V2 path: multi-item composite animation - java.util.Set allOwnedParts = - RegionBoneMapper.computeAllOwnedParts(v2Items); - MovementStyle activeStyle = MovementStyleClientState.get( - player.getUUID() - ); - AnimationContext context = AnimationContextResolver.resolve( - player, - state, - activeStyle - ); - GltfAnimationApplier.applyMultiItemV2Animation( - player, - v2Items, - context, - allOwnedParts - ); - } else if (GltfAnimationApplier.hasActiveState(player)) { - // Clear any residual V2 composite animation when the player - // is still isTiedUp() but has no GLB-bearing items — e.g. - // a non-GLB item keeps the tied state, or a GLB item was - // removed while another V2 item remains on a non-animated - // region. Leaving the composite in place locks the arms in - // the pose of an item the player no longer wears. - GltfAnimationApplier.clearV2Animation(player); - } - } else if (wasTied) { - // Was tied, now free - stop all animations - if (GltfAnimationApplier.hasActiveState(player)) { - GltfAnimationApplier.clearV2Animation(player); - } else { - BondageAnimationManager.stopAnimation(player); - } - } - - - AnimationStateRegistry.getLastTiedState().put(uuid, isTied); + // Le tick per-player V2 (updatePlayerAnimation, tickFurnitureSafety, + // cold-cache furniture retry) est délégué à RigAnimationTickHandler + // Phase 2.7+. Rien à faire ici. } /** diff --git a/src/main/java/com/tiedup/remake/client/animation/util/DogPoseHelper.java b/src/main/java/com/tiedup/remake/client/animation/util/DogPoseHelper.java index 9b9e451..38fdc4b 100644 --- a/src/main/java/com/tiedup/remake/client/animation/util/DogPoseHelper.java +++ b/src/main/java/com/tiedup/remake/client/animation/util/DogPoseHelper.java @@ -15,22 +15,14 @@ import net.minecraftforge.api.distmarker.OnlyIn; *
  • Head yaw: convert to zRot (roll) since yRot axis is sideways
  • * * - *

    Architecture: Players vs NPCs

    - *
    - * ┌─────────────────────────────────────────────────────────────────┐
    - * │                        PLAYERS                                  │
    - * ├─────────────────────────────────────────────────────────────────┤
    - * │ 1. PlayerArmHideEventHandler.onRenderPlayerPre()                │
    - * │    - Offset vertical (-6 model units)                           │
    - * │    - Rotation Y lissée (dogPoseState tracking)                  │
    - * │                                                                 │
    - * │ 2. Animation (PlayerAnimator)                                   │
    - * │    - body.pitch = -90° → appliqué au PoseStack automatiquement  │
    - * │                                                                 │
    - * │ 3. MixinPlayerModel.setupAnim() @TAIL                           │
    - * │    - Uses DogPoseHelper.applyHeadCompensationClamped()          │
    - * └─────────────────────────────────────────────────────────────────┘
    + * 

    Architecture — NPCs only (Phase 2.8 RIG cleanup)

    + *

    Le path PLAYER (ex-{@code MixinPlayerModel.setupAnim @TAIL}) a été retiré + * Phase 2.8 : le renderer RIG patched ne passe plus par {@code PlayerModel.setupAnim}, + * donc le mixin devenait dead code. La compensation head dog pose sera ré-exprimée + * nativement en StaticAnimation {@code pose_dog.json} (cf. V3-REW-07 dans + * {@code docs/plans/rig/V3_REWORK_BACKLOG.md}).

    * + *
      * ┌─────────────────────────────────────────────────────────────────┐
      * │                         NPCs                                    │
      * ├─────────────────────────────────────────────────────────────────┤
    @@ -48,25 +40,13 @@ import net.minecraftforge.api.distmarker.OnlyIn;
      * └─────────────────────────────────────────────────────────────────┘
      * 
    * - *

    Key Differences

    - * - * - * - * - * - * - * - *
    AspectPlayersNPCs
    Rotation X applicationAuto by PlayerAnimatorManual in setupRotations()
    Rotation Y smoothingPlayerArmHideEventHandlerEntityDamsel.tick() via RotationSmoother
    Head compensationMixinPlayerModelDamselModel.setupAnim()
    Reset body.xRotNot neededYes (prevents double rotation)
    Vertical offset-6 model units-7 model units
    - * *

    Usage

    *

    Used by: *

      - *
    • MixinPlayerModel - for player head compensation
    • *
    • DamselModel - for NPC head compensation
    • *
    * * @see RotationSmoother for Y rotation smoothing - * @see com.tiedup.remake.mixin.client.MixinPlayerModel * @see com.tiedup.remake.client.model.DamselModel */ @OnlyIn(Dist.CLIENT) diff --git a/src/main/java/com/tiedup/remake/core/TiedUpMod.java b/src/main/java/com/tiedup/remake/core/TiedUpMod.java index 26d2d93..4882a9f 100644 --- a/src/main/java/com/tiedup/remake/core/TiedUpMod.java +++ b/src/main/java/com/tiedup/remake/core/TiedUpMod.java @@ -196,9 +196,11 @@ public class TiedUpMod { // RIG Phase 2 — override client dispatch PLAYER → Local/Client/ServerPlayerPatch com.tiedup.remake.rig.patch.EntityPatchProvider.registerEntityPatchesClient(); - // Initialize unified BondageAnimationManager - com.tiedup.remake.client.animation.BondageAnimationManager.init(); - LOGGER.info("BondageAnimationManager initialized"); + // Phase 2.8 RIG cleanup : BondageAnimationManager.init() (factory + // registrations PlayerAnimator côté joueur) a été supprimé — le RIG + // prend le relai pour les joueurs via RigAnimationTickHandler. + // Les NPCs continuent d'être animés via BondageAnimationManager en + // accès direct animation stack (cf. NpcAnimationTickHandler). // Initialize OBJ model registry for 3D bondage items com.tiedup.remake.client.renderer.obj.ObjModelRegistry.init(); diff --git a/src/main/java/com/tiedup/remake/mixin/client/MixinPlayerModel.java b/src/main/java/com/tiedup/remake/mixin/client/MixinPlayerModel.java deleted file mode 100644 index cc44072..0000000 --- a/src/main/java/com/tiedup/remake/mixin/client/MixinPlayerModel.java +++ /dev/null @@ -1,83 +0,0 @@ -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.PoseType; -import com.tiedup.remake.v2.bondage.PoseTypeHelper; -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()) { - return; - } - - if (PoseTypeHelper.getPoseType(bind) != 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.getUUID() - ); - boolean moving = DogPoseRenderHandler.isDogPoseMoving(player.getUUID()); - - // 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 - ); - } -} diff --git a/src/main/resources/tiedup.mixins.json b/src/main/resources/tiedup.mixins.json index d974c48..d833170 100644 --- a/src/main/resources/tiedup.mixins.json +++ b/src/main/resources/tiedup.mixins.json @@ -9,7 +9,6 @@ "MixinLivingEntityBodyRot" ], "client": [ - "client/MixinPlayerModel", "client/MixinCamera", "client/MixinLivingEntitySleeping" ],