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 dev.kosmx.playerAnim.core.data.KeyframeAnimation;
import java.util.HashSet;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -251,7 +252,40 @@ public final class GltfAnimationApplier {
}
// === 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)) {
activeStateKeys.put(entity.getUUID(), stateKey);
@@ -273,29 +307,13 @@ public final class GltfAnimationApplier {
boolean anyLoaded = false;
for (int i = 0; i < items.size(); i++) {
RegionBoneMapper.V2ItemAnimInfo item = items.get(i);
for (ResolvedItem resolved : resolvedItems) {
RegionBoneMapper.V2ItemAnimInfo item = resolved.info();
GltfData animData = resolved.animData();
String glbAnimName = resolved.glbAnimName();
ResourceLocation animSource =
item.animSource() != null
? item.animSource()
: item.modelLoc();
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
);
GltfData.AnimationClip rawClip;
if (glbAnimName != null) {
rawClip = animData.getRawAnimation(glbAnimName);
@@ -310,9 +328,7 @@ public final class GltfAnimationApplier {
// if the item declares per-animation bone filtering.
Set<String> effectiveParts = item.ownedParts();
if (glbAnimName != null && !item.animationBones().isEmpty()) {
Set<String> override = item
.animationBones()
.get(glbAnimName);
Set<String> override = item.animationBones().get(glbAnimName);
if (override != null) {
Set<String> filtered = new HashSet<>(override);
filtered.retainAll(item.ownedParts());
@@ -323,19 +339,13 @@ public final class GltfAnimationApplier {
}
GltfPoseConverter.addBonesToBuilder(
builder,
animData,
rawClip,
effectiveParts
builder, animData, rawClip, effectiveParts
);
anyLoaded = true;
LOGGER.debug(
"[GltfPipeline] Multi-item: {} -> owned={}, effective={}, anim={}",
animSource,
item.ownedParts(),
effectiveParts,
glbAnimName
animSource, item.ownedParts(), effectiveParts, glbAnimName
);
}