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,