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,21 +2378,33 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
return false; return false;
} }
var relevant = groups.Where(g => localBoneSets.ContainsKey(g.Key)).ToList();
if (relevant.Count == 0)
{
var papKeys = string.Join(", ", groups.Select(g => g.Key).Distinct(StringComparer.OrdinalIgnoreCase)); var papKeys = string.Join(", ", groups.Select(g => g.Key).Distinct(StringComparer.OrdinalIgnoreCase));
var localKeys = string.Join(", ", localBoneSets.Keys); var targetKeys = string.Join(", ", targetBoneSets.Keys);
reason = $"No matching skeleton bucket between PAP [{papKeys}] and local [{localKeys}].";
foreach (var g in groups)
{
var candidates = targetBoneSets
.Where(kvp => string.Equals(kvp.Key, g.Key, StringComparison.OrdinalIgnoreCase))
.ToList();
if (candidates.Count == 0)
{
if (targetBoneSets.Count == 1)
{
candidates = targetBoneSets.ToList();
}
else
{
reason = $"No matching skeleton bucket between PAP [{papKeys}] and target [{targetKeys}].";
return false; return false;
} }
}
foreach (var g in relevant) bool groupOk = false;
string? lastFail = null;
foreach (var (targetKey, available) in candidates)
{ {
var available = localBoneSets[g.Key];
bool anyVariantOk = false;
foreach (var variant in g) foreach (var variant in g)
{ {
bool ok = true; bool ok = true;
@@ -2401,33 +2413,25 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
if (!ContainsIndexCompat(available, idx)) if (!ContainsIndexCompat(available, idx))
{ {
ok = false; ok = false;
lastFail = $"Target bucket '{targetKey}' missing bone index {idx}. (pap raw '{variant.Raw}')";
break; break;
} }
} }
if (ok) if (ok)
{ {
anyVariantOk = true; groupOk = true;
break; break;
} }
} }
if (!anyVariantOk) if (groupOk) break;
{
var first = g.First();
ushort? missing = null;
foreach (var idx in first.Indices)
{
if (!ContainsIndexCompat(available, idx))
{
missing = idx;
break;
}
} }
reason = missing.HasValue if (!groupOk)
? $"Skeleton '{g.Key}' missing bone index {missing.Value}. (raw '{first.Raw}')" {
: $"Skeleton '{g.Key}' missing required bone indices. (raw '{first.Raw}')"; 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);