Merge branch 'cake-attempts-2.0.3' of https://git.lightless-sync.org/Lightless-Sync/LightlessClient into cake-attempts-2.0.3

This commit is contained in:
defnotken
2026-01-02 09:29:22 -06:00

View File

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