fix(animation): fix variant caching bug in multi-item path — same fix as single-item

This commit is contained in:
NotEvil
2026-04-17 03:15:54 +02:00
parent a3287b7db8
commit 168c0675bb

View File

@@ -7,6 +7,7 @@ import com.tiedup.remake.client.animation.context.GlbAnimationResolver;
import com.tiedup.remake.client.animation.context.RegionBoneMapper; import com.tiedup.remake.client.animation.context.RegionBoneMapper;
import dev.kosmx.playerAnim.core.data.KeyframeAnimation; import dev.kosmx.playerAnim.core.data.KeyframeAnimation;
import java.util.HashSet; import java.util.HashSet;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -251,7 +252,40 @@ public final class GltfAnimationApplier {
} }
// === Layer 2: Composite item animation === // === Layer 2: Composite item animation ===
String compositeCacheKey = "multi#" + stateKey; // Pre-resolve animation data and variant names for all items BEFORE cache lookup.
// This ensures random variant selection happens fresh on each context change,
// and each variant combination gets its own cache entry.
record ResolvedItem(
GltfData animData,
String glbAnimName,
RegionBoneMapper.V2ItemAnimInfo info
) {}
List<ResolvedItem> resolvedItems = new ArrayList<>();
StringBuilder variantKeyBuilder = new StringBuilder("multi#").append(stateKey);
for (RegionBoneMapper.V2ItemAnimInfo item : items) {
ResourceLocation animSource =
item.animSource() != null ? item.animSource() : item.modelLoc();
GltfData animData = GlbAnimationResolver.resolveAnimationData(
item.modelLoc(), item.animSource()
);
if (animData == null) {
LOGGER.warn(
"[GltfPipeline] Failed to load GLB for multi-item: {}",
animSource
);
continue;
}
String glbAnimName = GlbAnimationResolver.resolve(animData, context);
resolvedItems.add(new ResolvedItem(animData, glbAnimName, item));
variantKeyBuilder.append('#')
.append(glbAnimName != null ? glbAnimName : "default");
}
String compositeCacheKey = variantKeyBuilder.toString();
if (failedLoadKeys.contains(compositeCacheKey)) { if (failedLoadKeys.contains(compositeCacheKey)) {
activeStateKeys.put(entity.getUUID(), stateKey); activeStateKeys.put(entity.getUUID(), stateKey);
@@ -273,29 +307,13 @@ public final class GltfAnimationApplier {
boolean anyLoaded = false; boolean anyLoaded = false;
for (int i = 0; i < items.size(); i++) { for (ResolvedItem resolved : resolvedItems) {
RegionBoneMapper.V2ItemAnimInfo item = items.get(i); RegionBoneMapper.V2ItemAnimInfo item = resolved.info();
GltfData animData = resolved.animData();
String glbAnimName = resolved.glbAnimName();
ResourceLocation animSource = ResourceLocation animSource =
item.animSource() != null item.animSource() != null ? item.animSource() : item.modelLoc();
? item.animSource()
: item.modelLoc();
GltfData animData = GlbAnimationResolver.resolveAnimationData(
item.modelLoc(),
item.animSource()
);
if (animData == null) {
LOGGER.warn(
"[GltfPipeline] Failed to load GLB for multi-item: {}",
animSource
);
continue;
}
String glbAnimName = GlbAnimationResolver.resolve(
animData,
context
);
GltfData.AnimationClip rawClip; GltfData.AnimationClip rawClip;
if (glbAnimName != null) { if (glbAnimName != null) {
rawClip = animData.getRawAnimation(glbAnimName); rawClip = animData.getRawAnimation(glbAnimName);
@@ -310,9 +328,7 @@ public final class GltfAnimationApplier {
// if the item declares per-animation bone filtering. // if the item declares per-animation bone filtering.
Set<String> effectiveParts = item.ownedParts(); Set<String> effectiveParts = item.ownedParts();
if (glbAnimName != null && !item.animationBones().isEmpty()) { if (glbAnimName != null && !item.animationBones().isEmpty()) {
Set<String> override = item Set<String> override = item.animationBones().get(glbAnimName);
.animationBones()
.get(glbAnimName);
if (override != null) { if (override != null) {
Set<String> filtered = new HashSet<>(override); Set<String> filtered = new HashSet<>(override);
filtered.retainAll(item.ownedParts()); filtered.retainAll(item.ownedParts());
@@ -323,19 +339,13 @@ public final class GltfAnimationApplier {
} }
GltfPoseConverter.addBonesToBuilder( GltfPoseConverter.addBonesToBuilder(
builder, builder, animData, rawClip, effectiveParts
animData,
rawClip,
effectiveParts
); );
anyLoaded = true; anyLoaded = true;
LOGGER.debug( LOGGER.debug(
"[GltfPipeline] Multi-item: {} -> owned={}, effective={}, anim={}", "[GltfPipeline] Multi-item: {} -> owned={}, effective={}, anim={}",
animSource, animSource, item.ownedParts(), effectiveParts, glbAnimName
item.ownedParts(),
effectiveParts,
glbAnimName
); );
} }