From f80dc68c0ba382dbcbe30c2b87668542debb2c09 Mon Sep 17 00:00:00 2001 From: notevil Date: Thu, 23 Apr 2026 01:10:02 +0200 Subject: [PATCH] Phase 2.8 review fixes : strip player fallback + backlog V3-REW-12-14 + QA edge cases - BondageAnimationManager : strip total du path joueur, tous les call sites 'player' retournent null/false avec WARN once-per-UUID. getOrCreateLayer court-circuite sur Player direct. Retire dead code factory/furniture (FACTORY_ID, FURNITURE_*, npcFurnitureLayers, getPlayerLayer, etc.). Javadoc init() reflete la semantique NPC-only. - DogPoseHelper.applyHeadCompensationClamped : @Deprecated(since=2.8) pointant vers V3-REW-07 (dead apres retrait MixinPlayerModel). - DogPoseRenderHandler.getAppliedRotationDelta + isDogPoseMoving : @Deprecated(since=2.8) meme raison. - Docs (gitignored) : V3_REWORK_BACKLOG.md ajoute V3-REW-12/13/14 (pet bed body-lock, human chair yaw clamp, context layer sit/kneel/sneak), tableau recap 14 -> 17 items. PHASE2_QA.md ajoute sec 2.5 edge cases + corrige le grep pattern 4 -> >=4 lignes. PHASE0_DEGRADATIONS.md ajoute la section Phase 2.8 findings. Compile GREEN. 20/20 tests rig GREEN. Net LOC src : -239 (strip dead code + guards player). Call sites player no-op (attendu par design) : - PacketSyncPetBedState.playAnimation -> V3-REW-12 - PacketPlayTestAnimation.playAnimation (debug) -> V3-REW-14 - FurnitureClientAnimator.playFurniture -> furniture seat rework V3 --- .../animation/BondageAnimationManager.java | 463 +++++------------- .../render/DogPoseRenderHandler.java | 16 +- .../client/animation/util/DogPoseHelper.java | 7 + 3 files changed, 134 insertions(+), 352 deletions(-) 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 1646e61..b70aae1 100644 --- a/src/main/java/com/tiedup/remake/client/animation/BondageAnimationManager.java +++ b/src/main/java/com/tiedup/remake/client/animation/BondageAnimationManager.java @@ -1,13 +1,11 @@ package com.tiedup.remake.client.animation; import com.mojang.logging.LogUtils; -import com.tiedup.remake.v2.furniture.ISeatProvider; import dev.kosmx.playerAnim.api.layered.IAnimation; import dev.kosmx.playerAnim.api.layered.KeyframeAnimationPlayer; import dev.kosmx.playerAnim.api.layered.ModifierLayer; import dev.kosmx.playerAnim.core.data.KeyframeAnimation; import dev.kosmx.playerAnim.impl.IAnimatedPlayer; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationAccess; import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationFactory; import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationRegistry; import java.util.Map; @@ -15,7 +13,6 @@ import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.api.distmarker.Dist; @@ -39,81 +36,42 @@ public class BondageAnimationManager { private static final Logger LOGGER = LogUtils.getLogger(); - /** Cache of ModifierLayers for NPC entities (players use PlayerAnimationAccess) */ + /** Cache of item-layer ModifierLayers for NPC entities. */ private static final Map> npcLayers = new ConcurrentHashMap<>(); - /** Cache of context ModifierLayers for NPC entities */ + /** Cache of context-layer ModifierLayers for NPC entities. */ private static final Map> npcContextLayers = new ConcurrentHashMap<>(); - /** Cache of furniture ModifierLayers for NPC entities */ - private static final Map< - UUID, - ModifierLayer - > npcFurnitureLayers = new ConcurrentHashMap<>(); - - /** Factory ID for PlayerAnimator item layer (players only) */ - private static final ResourceLocation FACTORY_ID = - ResourceLocation.fromNamespaceAndPath("tiedup", "bondage"); - - /** Factory ID for PlayerAnimator context layer (players only) */ - private static final ResourceLocation CONTEXT_FACTORY_ID = - ResourceLocation.fromNamespaceAndPath("tiedup", "bondage_context"); - - /** Factory ID for PlayerAnimator furniture layer (players only) */ - private static final ResourceLocation FURNITURE_FACTORY_ID = - ResourceLocation.fromNamespaceAndPath("tiedup", "bondage_furniture"); - /** Priority for context animation layer (lower = overridable by item layer) */ private static final int CONTEXT_LAYER_PRIORITY = 40; /** Priority for item animation layer (higher = overrides context layer) */ private static final int ITEM_LAYER_PRIORITY = 42; - /** - * Priority for furniture animation layer (highest = overrides item layer on blocked bones). - * Non-blocked bones are disabled so items can still animate them via the item layer. - */ - private static final int FURNITURE_LAYER_PRIORITY = 43; - - /** Number of ticks to wait before removing a stale furniture animation. */ - private static final int FURNITURE_GRACE_TICKS = 3; - - /** - * Tracks ticks since a player with an active furniture animation stopped riding - * an ISeatProvider. After {@link #FURNITURE_GRACE_TICKS}, the animation is removed - * to prevent stuck poses from entity death or network issues. - * - *

Uses ConcurrentHashMap for safe access from both client tick and render thread.

- */ - private static final Map furnitureGraceTicks = - new ConcurrentHashMap<>(); /** * Initialize the animation system. * - *

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).

+ *

Pipeline NPC-only — depuis Phase 2.7, les joueurs sont tickés par + * {@code RigAnimationTickHandler} via le renderer RIG patched. Aucune + * {@link PlayerAnimationFactory} n'est enregistrée pour le joueur et tous + * les chemins joueur dans cette classe sont de short-circuits logués.

* - *

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.

+ *

Cette classe reste active uniquement pour les NPCs + * (entités implémentant {@link IAnimatedPlayer} qui ne sont pas un + * {@link Player}) : {@link #getOrCreateLayer} leur crée un {@link ModifierLayer} + * via accès direct au stack d'animation + * ({@code animated.getAnimationStack().addAnimLayer(...)}) — ce path ne dépend + * d'aucune factory. Consumer principal : {@code NpcAnimationTickHandler}.

* *

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}.

+ * externes. 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: player-side factories no-op (Phase 2.8 RIG cleanup). " + - "NPC-side animation stack access untouched." + "BondageAnimationManager: NPC-only pipeline (Phase 2.8 RIG cleanup). " + + "Players handled by RigAnimationTickHandler; all player call sites no-op." ); } @@ -140,6 +98,11 @@ public class BondageAnimationManager { *

If the animation layer is not available (e.g., remote player not fully * initialized), the animation will be queued for retry via PendingAnimationManager. * + *

Phase 2.8 — les appels sur un {@link Player} sont no-op : le pipeline + * joueur est désormais RIG-native (voir {@link #init} Javadoc). Un WARN est logué + * une fois par UUID pour signaler les call sites stale qui devraient être purgés + * lors du rework V3.

+ * * @param entity The entity to animate * @param animId Full ResourceLocation of the animation * @return true if animation started successfully, false if layer not available @@ -152,6 +115,12 @@ public class BondageAnimationManager { return false; } + // Phase 2.8 : player path is dead. Log once per UUID and no-op. + if (entity instanceof Player player) { + logPlayerCallOnce(player, "playAnimation(" + animId + ")"); + return false; + } + KeyframeAnimation anim = PlayerAnimationRegistry.getAnimation(animId); if (anim == null) { // Try fallback: remove _sneak_ suffix if present @@ -188,7 +157,7 @@ public class BondageAnimationManager { } layer.setAnimation(new KeyframeAnimationPlayer(anim)); - // Remove from pending queue if it was waiting + // Remove from pending queue if it was waiting (legacy, may still hold NPC entries) PendingAnimationManager.remove(entity.getUUID()); LOGGER.debug( @@ -198,23 +167,11 @@ public class BondageAnimationManager { ); return true; } else { - // Layer not available - queue for retry if it's a player - if (entity instanceof AbstractClientPlayer) { - PendingAnimationManager.queueForRetry( - entity.getUUID(), - animId.getPath() - ); - LOGGER.debug( - "Animation layer not ready for {}, queued for retry", - entity.getName().getString() - ); - } else { - LOGGER.warn( - "Animation layer is NULL for NPC: {} (type: {})", - entity.getName().getString(), - entity.getClass().getSimpleName() - ); - } + LOGGER.warn( + "Animation layer is NULL for NPC: {} (type: {})", + entity.getName().getString(), + entity.getClass().getSimpleName() + ); return false; } } @@ -235,6 +192,12 @@ public class BondageAnimationManager { return false; } + // Phase 2.8 : player path is dead. + if (entity instanceof Player player) { + logPlayerCallOnce(player, "playDirect"); + return false; + } + ModifierLayer layer = getOrCreateLayer(entity); if (layer != null) { IAnimation current = layer.getAnimation(); @@ -262,6 +225,11 @@ public class BondageAnimationManager { return; } + // Phase 2.8 : player path is dead — no layer to clear. + if (entity instanceof Player) { + return; + } + ModifierLayer layer = getLayer(entity); if (layer != null) { layer.setAnimation(null); @@ -273,56 +241,36 @@ public class BondageAnimationManager { /** * Get the ModifierLayer for an entity (without creating). + * + *

Phase 2.8 : returns {@code null} directly for any {@link Player} — the + * player animation pipeline is RIG-native, this manager only tracks NPCs.

*/ private static ModifierLayer getLayer(LivingEntity entity) { - // Players: try PlayerAnimationAccess first, then cache - if (entity instanceof AbstractClientPlayer player) { - ModifierLayer factoryLayer = getPlayerLayer(player); - if (factoryLayer != null) { - return factoryLayer; - } - // Check cache (for remote players using fallback) - return npcLayers.get(entity.getUUID()); + if (entity instanceof Player) { + return null; } - - // NPCs: use cache return npcLayers.get(entity.getUUID()); } /** * Get or create the ModifierLayer for an entity. + * + *

Phase 2.8 : returns {@code null} directly for any {@link Player} — the + * player fallback via {@code IAnimatedPlayer.getAnimationStack()} has been + * retired because it was partially alive (FP vanilla render consumed it, + * TP RIG override bypassed it), producing a confusing behavior split. All + * player anim needs are now handled by {@code RigAnimationTickHandler}.

*/ - @SuppressWarnings("unchecked") private static ModifierLayer getOrCreateLayer( LivingEntity entity ) { - UUID uuid = entity.getUUID(); - - // Players: try factory-based access first, fallback to direct stack access - if (entity instanceof AbstractClientPlayer player) { - // Try the registered factory first (works for local player) - ModifierLayer factoryLayer = getPlayerLayer(player); - if (factoryLayer != null) { - return factoryLayer; - } - - // Fallback for remote players: use direct stack access like NPCs - // This handles cases where the factory data isn't available - if (player instanceof IAnimatedPlayer animated) { - return npcLayers.computeIfAbsent(uuid, k -> { - ModifierLayer newLayer = new ModifierLayer<>(); - animated - .getAnimationStack() - .addAnimLayer(ITEM_LAYER_PRIORITY, newLayer); - LOGGER.info( - "Created animation layer for remote player via stack: {}", - player.getName().getString() - ); - return newLayer; - }); - } + // Phase 2.8 : strip player path entirely (no partially-alive fallback). + if (entity instanceof Player) { + return null; } + UUID uuid = entity.getUUID(); + // NPCs implementing IAnimatedPlayer: create/cache layer if (entity instanceof IAnimatedPlayer animated) { return npcLayers.computeIfAbsent(uuid, k -> { @@ -342,87 +290,49 @@ public class BondageAnimationManager { return null; } - /** Per-player dedup set so we log the factory-access failure at most once per UUID. */ - private static final java.util.Set layerFailureLogged = + /** Per-player-UUID dedup so stale call sites log at most once per session. */ + private static final java.util.Set playerCallLogged = java.util.concurrent.ConcurrentHashMap.newKeySet(); /** - * Get the animation layer for a player from PlayerAnimationAccess. - * - *

Throws during the factory-race window for remote players (the factory - * hasn't yet initialized their associated data). This is the expected path - * for the {@link PendingAnimationManager} retry loop, so we log at DEBUG - * and at most once per UUID — a per-tick log would flood during busy - * multiplayer.

+ * Log once per player UUID that a stale call site is invoking this manager. + * Used by the player no-op short-circuits ({@link #playAnimation}, + * {@link #playDirect}) to surface call sites that should be migrated to the + * RIG pipeline (tracked in V3_REWORK_BACKLOG). */ - @SuppressWarnings("unchecked") - private static ModifierLayer getPlayerLayer( - AbstractClientPlayer player - ) { - try { - return (ModifierLayer< - IAnimation - >) PlayerAnimationAccess.getPlayerAssociatedData(player).get( - FACTORY_ID + private static void logPlayerCallOnce(Player player, String op) { + if (playerCallLogged.add(player.getUUID())) { + LOGGER.warn( + "BondageAnimationManager.{} called on player {} — no-op " + + "(RIG owns player anims since Phase 2.7). " + + "Migrate call site to RigAnimationTickHandler (V3 rework).", + op, + player.getName().getString() ); - } catch (Exception e) { - if (layerFailureLogged.add(player.getUUID())) { - LOGGER.debug( - "Animation layer not yet available for player {} (will retry): {}", - player.getName().getString(), - e.toString() - ); - } - return null; } } /** * Safely get the animation layer for a player. - * Returns null if the layer is not yet initialized. * - *

Public method for PendingAnimationManager to access. - * Checks both the factory-based layer and the NPC cache fallback. + *

Phase 2.8 : always returns {@code null}. The player pipeline is + * RIG-native; the {@link PendingAnimationManager} retry loop is no + * longer fed (player calls to {@link #playAnimation} short-circuit + * before queueing), so this getter is maintained only to preserve the + * public signature for external call sites.

* - * @param player The player - * @return The animation layer, or null if not available + * @param player The player (unused) + * @return always null in Phase 2.8+ */ @javax.annotation.Nullable public static ModifierLayer getPlayerLayerSafe( AbstractClientPlayer player ) { - // Try factory first - ModifierLayer factoryLayer = getPlayerLayer(player); - if (factoryLayer != null) { - return factoryLayer; - } - - // Check NPC cache (for remote players using fallback path) - return npcLayers.get(player.getUUID()); + return null; } // CONTEXT LAYER (lower priority, for sit/kneel/sneak) - /** - * Get the context animation layer for a player from PlayerAnimationAccess. - * Returns null if the layer is not yet initialized. - */ - @SuppressWarnings("unchecked") - @javax.annotation.Nullable - private static ModifierLayer getPlayerContextLayer( - AbstractClientPlayer player - ) { - try { - return (ModifierLayer< - IAnimation - >) PlayerAnimationAccess.getPlayerAssociatedData(player).get( - CONTEXT_FACTORY_ID - ); - } catch (Exception e) { - return null; - } - } - /** * Get or create the context animation layer for an NPC entity. * Uses CONTEXT_LAYER_PRIORITY, below the item layer at ITEM_LAYER_PRIORITY. @@ -460,13 +370,14 @@ public class BondageAnimationManager { return false; } - ModifierLayer layer; - if (entity instanceof AbstractClientPlayer player) { - layer = getPlayerContextLayer(player); - } else { - layer = getOrCreateNpcContextLayer(entity); + // Phase 2.8 : player context layer is dead (sit/kneel/sneak visuals + // will be re-expressed as RIG StaticAnimations — cf. V3-REW-14). + if (entity instanceof Player player) { + logPlayerCallOnce(player, "playContext"); + return false; } + ModifierLayer layer = getOrCreateNpcContextLayer(entity); if (layer != null) { layer.setAnimation(new KeyframeAnimationPlayer(anim)); return true; @@ -484,13 +395,12 @@ public class BondageAnimationManager { return; } - ModifierLayer layer; - if (entity instanceof AbstractClientPlayer player) { - layer = getPlayerContextLayer(player); - } else { - layer = npcContextLayers.get(entity.getUUID()); + // Phase 2.8 : player path is dead — no layer to clear. + if (entity instanceof Player) { + return; } + ModifierLayer layer = npcContextLayers.get(entity.getUUID()); if (layer != null) { layer.setAnimation(null); } @@ -522,194 +432,46 @@ public class BondageAnimationManager { return false; } - ModifierLayer layer = getOrCreateFurnitureLayer(player); - if (layer != null) { - layer.setAnimation(new KeyframeAnimationPlayer(animation)); - // Reset grace ticks since we just started/refreshed the animation - furnitureGraceTicks.remove(player.getUUID()); - LOGGER.debug( - "Playing furniture animation on player: {}", - player.getName().getString() - ); - return true; - } - - LOGGER.warn( - "Furniture layer not available for player: {}", - player.getName().getString() - ); + // Phase 2.8 : player furniture seat pose is dead (will be ported to + // RIG StaticAnimations — cf. V3_REWORK_BACKLOG furniture seat entry). + logPlayerCallOnce(player, "playFurniture"); return false; } /** * Stop the furniture layer animation for a player. * + *

Phase 2.8 : no-op — the player furniture layer is dead. Kept for + * signature compatibility with {@code EntityFurniture} cleanup call site.

+ * * @param player the player whose furniture animation should stop */ public static void stopFurniture(Player player) { - if (player == null || !player.level().isClientSide()) { - return; - } - - ModifierLayer layer = getFurnitureLayer(player); - if (layer != null) { - layer.setAnimation(null); - } - furnitureGraceTicks.remove(player.getUUID()); - LOGGER.debug( - "Stopped furniture animation on player: {}", - player.getName().getString() - ); + // Phase 2.8 : dead path. Retained signature for backward-compat. } /** * Check whether a player currently has an active furniture animation. * + *

Phase 2.8 : always returns {@code false} — player furniture layer is dead.

+ * * @param player the player to check - * @return true if the furniture layer has an active animation + * @return always false in Phase 2.8+ */ public static boolean hasFurnitureAnimation(Player player) { - if (player == null || !player.level().isClientSide()) { - return false; - } - - ModifierLayer layer = getFurnitureLayer(player); - return layer != null && layer.getAnimation() != null; + return false; } /** - * Get the furniture ModifierLayer for a player (READ-ONLY). - * Uses PlayerAnimationAccess for local/factory-registered players, - * falls back to NPC cache for remote players. Returns null if no layer - * has been created yet — callers that need to guarantee a layer should use - * {@link #getOrCreateFurnitureLayer}. - */ - @SuppressWarnings("unchecked") - @javax.annotation.Nullable - private static ModifierLayer getFurnitureLayer(Player player) { - if (player instanceof AbstractClientPlayer clientPlayer) { - try { - ModifierLayer layer = (ModifierLayer< - IAnimation - >) PlayerAnimationAccess.getPlayerAssociatedData( - clientPlayer - ).get(FURNITURE_FACTORY_ID); - if (layer != null) { - return layer; - } - } catch (Exception e) { - // Fall through to NPC cache - } - - // Fallback for remote players: check NPC furniture cache - return npcFurnitureLayers.get(player.getUUID()); - } - - // Non-player entities: use NPC cache - return npcFurnitureLayers.get(player.getUUID()); - } - - /** - * Get or create the furniture ModifierLayer for a player. Mirrors - * {@link #getOrCreateLayer} but for the FURNITURE layer priority. + * Safety tick for furniture animations. * - *

For the local player (factory-registered), returns the factory layer. - * For remote players, creates a new layer on first call and caches it in - * {@link #npcFurnitureLayers} — remote players don't own a factory layer, - * so without a fallback they can't receive any furniture seat pose.

- */ - @SuppressWarnings("unchecked") - @javax.annotation.Nullable - private static ModifierLayer getOrCreateFurnitureLayer( - Player player - ) { - if (player instanceof AbstractClientPlayer clientPlayer) { - try { - ModifierLayer layer = (ModifierLayer< - IAnimation - >) PlayerAnimationAccess.getPlayerAssociatedData( - clientPlayer - ).get(FURNITURE_FACTORY_ID); - if (layer != null) { - return layer; - } - } catch (Exception e) { - // Fall through to fallback-create below. - } - - // Remote players: fallback-create via the animation stack. - if (clientPlayer instanceof IAnimatedPlayer animated) { - return npcFurnitureLayers.computeIfAbsent( - clientPlayer.getUUID(), - k -> { - ModifierLayer newLayer = - new ModifierLayer<>(); - animated - .getAnimationStack() - .addAnimLayer(FURNITURE_LAYER_PRIORITY, newLayer); - LOGGER.debug( - "Created furniture animation layer for remote player via stack: {}", - clientPlayer.getName().getString() - ); - return newLayer; - } - ); - } - - return npcFurnitureLayers.get(clientPlayer.getUUID()); - } - - // Non-player entities: use NPC cache (read-only; NPC furniture animation - // is not currently produced by this codebase). - return npcFurnitureLayers.get(player.getUUID()); - } - - /** - * Safety tick for furniture animations. Call once per client tick per player. + *

Phase 2.8 : no-op — the player furniture layer is dead, nothing to + * guard. Kept as an empty stub in case older call sites remain.

* - *

If a player has an active furniture animation but is NOT riding an - * {@link ISeatProvider}, increment a grace counter. After - * {@link #FURNITURE_GRACE_TICKS} consecutive ticks without a seat, the - * animation is removed to prevent stuck poses from entity death, network - * desync, or teleportation.

- * - *

If the player IS riding an ISeatProvider, the counter is reset.

- * - * @param player the player to check + * @param player the player to check (unused) */ public static void tickFurnitureSafety(Player player) { - if (player == null || !player.level().isClientSide()) { - return; - } - - if (!hasFurnitureAnimation(player)) { - // No furniture animation active, nothing to guard - furnitureGraceTicks.remove(player.getUUID()); - return; - } - - UUID uuid = player.getUUID(); - - // Check if the player is riding an ISeatProvider - Entity vehicle = player.getVehicle(); - boolean ridingSeat = vehicle instanceof ISeatProvider; - - if (ridingSeat) { - // Player is properly seated, reset grace counter - furnitureGraceTicks.remove(uuid); - } else { - // Player has furniture anim but no seat -- increment grace - int ticks = furnitureGraceTicks.merge(uuid, 1, Integer::sum); - if (ticks >= FURNITURE_GRACE_TICKS) { - LOGGER.info( - "Removing stale furniture animation for player {} " + - "(not riding ISeatProvider for {} ticks)", - player.getName().getString(), - ticks - ); - stopFurniture(player); - } - } + // Phase 2.8 : dead path. Retained signature for backward-compat. } // FALLBACK ANIMATION HANDLING @@ -778,8 +540,9 @@ public class BondageAnimationManager { * @param entityId UUID of the removed entity */ /** All NPC layer caches, for bulk cleanup operations. */ + @SuppressWarnings({ "unchecked", "rawtypes" }) private static final Map>[] ALL_NPC_CACHES = - new Map[] { npcLayers, npcContextLayers, npcFurnitureLayers }; + new Map[] { npcLayers, npcContextLayers }; public static void cleanup(UUID entityId) { for (Map> cache : ALL_NPC_CACHES) { @@ -788,8 +551,7 @@ public class BondageAnimationManager { layer.setAnimation(null); } } - furnitureGraceTicks.remove(entityId); - layerFailureLogged.remove(entityId); + playerCallLogged.remove(entityId); LOGGER.debug("Cleaned up animation layers for entity: {}", entityId); } @@ -802,8 +564,7 @@ public class BondageAnimationManager { cache.values().forEach(layer -> layer.setAnimation(null)); cache.clear(); } - furnitureGraceTicks.clear(); - layerFailureLogged.clear(); + playerCallLogged.clear(); LOGGER.info("Cleared all NPC animation layers"); } } diff --git a/src/main/java/com/tiedup/remake/client/animation/render/DogPoseRenderHandler.java b/src/main/java/com/tiedup/remake/client/animation/render/DogPoseRenderHandler.java index 424595c..1df33a4 100644 --- a/src/main/java/com/tiedup/remake/client/animation/render/DogPoseRenderHandler.java +++ b/src/main/java/com/tiedup/remake/client/animation/render/DogPoseRenderHandler.java @@ -52,8 +52,15 @@ public class DogPoseRenderHandler { /** * Get the rotation delta applied to a player's render for DOG pose. - * Used by MixinPlayerModel to compensate head rotation. + * + * @deprecated since Phase 2.8 — this getter fed {@code MixinPlayerModel} + * (removed Phase 2.8 RIG cleanup) so head rotation could be compensated + * against the body's -90° pitch. No remaining reader. To be deleted + * when V3-REW-07 re-expresses dog pose head compensation as a RIG + * {@code StaticAnimation pose_dog.json}. See + * {@code docs/plans/rig/V3_REWORK_BACKLOG.md#V3-REW-07}. */ + @Deprecated(since = "2.8") public static float getAppliedRotationDelta(UUID playerUuid) { float[] state = dogPoseState.get(playerUuid); return state != null ? state[IDX_DELTA] : 0f; @@ -61,7 +68,14 @@ public class DogPoseRenderHandler { /** * Check if a player is currently moving in DOG pose. + * + * @deprecated since Phase 2.8 — same cause as {@link #getAppliedRotationDelta} + * (fed {@code MixinPlayerModel}, now removed). To be deleted alongside + * V3-REW-07 when dog pose head compensation is re-expressed as a RIG + * {@code StaticAnimation pose_dog.json}. See + * {@code docs/plans/rig/V3_REWORK_BACKLOG.md#V3-REW-07}. */ + @Deprecated(since = "2.8") public static boolean isDogPoseMoving(UUID playerUuid) { float[] state = dogPoseState.get(playerUuid); return state != null && state[IDX_MOVING] > 0.5f; 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 38fdc4b..53f5e98 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 @@ -110,7 +110,14 @@ public final class DogPoseHelper { * @param headPitch Player's up/down look angle in degrees * @param headYaw Head yaw relative to body in degrees * @param maxYaw Maximum allowed yaw angle in degrees + * @deprecated since Phase 2.8 — player dog pose head compensation was + * previously applied via {@code MixinPlayerModel.setupAnim @TAIL} + * (removed Phase 2.8 RIG cleanup). No remaining call site; retained + * only to preserve the API until V3-REW-07 re-expresses the behavior + * as a RIG {@code StaticAnimation pose_dog.json}. See + * {@code docs/plans/rig/V3_REWORK_BACKLOG.md#V3-REW-07}. */ + @Deprecated(since = "2.8") public static void applyHeadCompensationClamped( ModelPart head, ModelPart hat,