Broad consolidation of the V2 bondage-item, furniture-entity, and
client-side GLTF pipeline.
Parsing and rendering
- Shared GLB parsing helpers consolidated into GlbParserUtils
(accessor reads, weight normalization, joint-index clamping,
coordinate-space conversion, animation parse, primitive loop).
- Grow-on-demand Matrix4f[] scratch pool in GltfSkinningEngine and
GltfLiveBoneReader — removes per-frame joint-matrix allocation
from the render hot path.
- emitVertex helper dedups three parallel loops in GltfMeshRenderer.
- TintColorResolver.resolve has a zero-alloc path when the item
declares no tint channels.
- itemAnimCache bounded to 256 entries (access-order LRU) with
atomic get-or-compute under the map's monitor.
Animation correctness
- First-in-joint-order wins when body and torso both map to the
same PlayerAnimator slot; duplicate writes log a single WARN.
- Multi-item composites honor the FullX / FullHeadX opt-in that
the single-item path already recognized.
- Seat transforms converted to Minecraft model-def space so
asymmetric furniture renders passengers at the correct offset.
- GlbValidator: IBM count / type / presence, JOINTS_0 presence,
animation channel target validation, multi-skin support.
Furniture correctness and anti-exploit
- Seat assignment synced via SynchedEntityData (server is
authoritative; eliminates client-server divergence on multi-seat).
- Force-mount authorization requires same dimension and a free
seat; cross-dimension distance checks rejected.
- Reconnection on login checks for seat takeover before re-mount
and force-loads the target chunk for cross-dimension cases.
- tiedup_furniture_lockpick_ctx carries a session UUID nonce so
stale context can't misroute a body-item lockpick.
- tiedup_locked_furniture survives death without keepInventory
(Forge 1.20.1 does not auto-copy persistent data on respawn).
Lifecycle and memory
- EntityCleanupHandler fans EntityLeaveLevelEvent out to every
per-entity state map on the client.
- DogPoseRenderHandler re-keyed by UUID (stable across dimension
change; entity int ids are recycled).
- PetBedRenderHandler, PlayerArmHideEventHandler, and
HeldItemHideHandler use receiveCanceled + sentinel sets so
Pre-time mutations are restored even when a downstream handler
cancels the render.
Tests
- JUnit harness with 76+ tests across GlbParserUtils, GltfPoseConverter,
FurnitureSeatGeometry, and FurnitureAuthPredicate.
57 lines
2.0 KiB
Java
57 lines
2.0 KiB
Java
package com.tiedup.remake.client.animation;
|
|
|
|
import java.util.Map;
|
|
import java.util.UUID;
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
import net.minecraftforge.api.distmarker.Dist;
|
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
|
|
|
/**
|
|
* Client-side animation state tracking + world-unload cleanup facade.
|
|
*
|
|
* <p>Holds {@link #lastTiedState} (the per-player edge-detector used by
|
|
* {@link com.tiedup.remake.client.animation.tick.AnimationTickHandler} to
|
|
* spot the "just untied" transition) and chains cleanup via
|
|
* {@link #clearAll()} across every animation-related cache on world unload.</p>
|
|
*/
|
|
@OnlyIn(Dist.CLIENT)
|
|
public final class AnimationStateRegistry {
|
|
|
|
/** Track last tied state per player (edge-detect on untie transition). */
|
|
static final Map<UUID, Boolean> lastTiedState = new ConcurrentHashMap<>();
|
|
|
|
private AnimationStateRegistry() {}
|
|
|
|
public static Map<UUID, Boolean> getLastTiedState() {
|
|
return lastTiedState;
|
|
}
|
|
|
|
/**
|
|
* Clear all animation-related state in one call.
|
|
* Called on world unload to prevent memory leaks and stale data.
|
|
*/
|
|
public static void clearAll() {
|
|
// Animation state tracking
|
|
lastTiedState.clear();
|
|
|
|
// Animation managers
|
|
BondageAnimationManager.clearAll();
|
|
PendingAnimationManager.clearAll();
|
|
|
|
// V2 animation context system (clearAll chains to ContextAnimationFactory.clearCache)
|
|
com.tiedup.remake.client.gltf.GltfAnimationApplier.clearAll();
|
|
|
|
// Render state
|
|
com.tiedup.remake.client.animation.render.DogPoseRenderHandler.clearState();
|
|
com.tiedup.remake.client.animation.render.PetBedRenderHandler.clearAll();
|
|
com.tiedup.remake.client.animation.render.HeldItemHideHandler.clearAll();
|
|
com.tiedup.remake.client.animation.render.PlayerArmHideEventHandler.clearAll();
|
|
|
|
// NPC animation state
|
|
com.tiedup.remake.client.animation.tick.NpcAnimationTickHandler.clearAll();
|
|
|
|
// MCA animation cache
|
|
com.tiedup.remake.client.animation.tick.MCAAnimationTickCache.clear();
|
|
}
|
|
}
|