diff --git a/LightlessSync/PlayerData/Pairs/PairHandlerAdapter.cs b/LightlessSync/PlayerData/Pairs/PairHandlerAdapter.cs index fc469db..e11f290 100644 --- a/LightlessSync/PlayerData/Pairs/PairHandlerAdapter.cs +++ b/LightlessSync/PlayerData/Pairs/PairHandlerAdapter.cs @@ -2357,7 +2357,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa } private static bool IsPapCompatible( - IReadOnlyDictionary> localBoneSets, + IReadOnlyDictionary> targetBoneSets, IReadOnlyDictionary> papBoneIndices, out string reason) { @@ -2378,56 +2378,60 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa return false; } - var relevant = groups.Where(g => localBoneSets.ContainsKey(g.Key)).ToList(); + var papKeys = string.Join(", ", groups.Select(g => g.Key).Distinct(StringComparer.OrdinalIgnoreCase)); + var targetKeys = string.Join(", ", targetBoneSets.Keys); - if (relevant.Count == 0) + foreach (var g in groups) { - var papKeys = string.Join(", ", groups.Select(g => g.Key).Distinct(StringComparer.OrdinalIgnoreCase)); - var localKeys = string.Join(", ", localBoneSets.Keys); - reason = $"No matching skeleton bucket between PAP [{papKeys}] and local [{localKeys}]."; - return false; - } + var candidates = targetBoneSets + .Where(kvp => string.Equals(kvp.Key, g.Key, StringComparison.OrdinalIgnoreCase)) + .ToList(); - foreach (var g in relevant) - { - var available = localBoneSets[g.Key]; - - bool anyVariantOk = false; - foreach (var variant in g) + if (candidates.Count == 0) { - bool ok = true; - foreach (var idx in variant.Indices) + if (targetBoneSets.Count == 1) { - if (!ContainsIndexCompat(available, idx)) - { - ok = false; - break; - } + candidates = targetBoneSets.ToList(); } - - if (ok) + else { - anyVariantOk = true; - break; + reason = $"No matching skeleton bucket between PAP [{papKeys}] and target [{targetKeys}]."; + return false; } } - if (!anyVariantOk) + bool groupOk = false; + string? lastFail = null; + + foreach (var (targetKey, available) in candidates) { - var first = g.First(); - ushort? missing = null; - foreach (var idx in first.Indices) + foreach (var variant in g) { - if (!ContainsIndexCompat(available, idx)) + bool ok = true; + foreach (var idx in variant.Indices) { - missing = idx; + if (!ContainsIndexCompat(available, idx)) + { + ok = false; + lastFail = $"Target bucket '{targetKey}' missing bone index {idx}. (pap raw '{variant.Raw}')"; + break; + } + } + + if (ok) + { + groupOk = true; break; } } - reason = missing.HasValue - ? $"Skeleton '{g.Key}' missing bone index {missing.Value}. (raw '{first.Raw}')" - : $"Skeleton '{g.Key}' missing required bone indices. (raw '{first.Raw}')"; + if (groupOk) break; + } + + if (!groupOk) + { + reason = lastFail + ?? $"Target skeleton missing required bone indices for PAP bucket '{g.Key}'."; return false; } } @@ -2479,7 +2483,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa continue; if (!localBoneSets.TryGetValue(key, out var set)) - localBoneSets[key] = set = new HashSet(); + localBoneSets[key] = set = []; foreach (var v in list) set.Add(v);