up to date with 2.0.3
This commit is contained in:
@@ -114,6 +114,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
private DateTime _nextActorLookupUtc = DateTime.MinValue;
|
||||
private static readonly TimeSpan ActorLookupInterval = TimeSpan.FromSeconds(1);
|
||||
private static readonly SemaphoreSlim ActorInitializationLimiter = new(1, 1);
|
||||
private static readonly SemaphoreSlim _papParseLimiter = new(1, 1);
|
||||
private const int FullyLoadedTimeoutMsPlayer = 30000;
|
||||
private const int FullyLoadedTimeoutMsOther = 5000;
|
||||
private readonly object _actorInitializationGate = new();
|
||||
@@ -2829,13 +2830,13 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
|
||||
var mode = _configService.Current.AnimationValidationMode;
|
||||
var allowBasedShift = _configService.Current.AnimationAllowOneBasedShift;
|
||||
var allownNightIndex = _configService.Current.AnimationAllowNeighborIndexTolerance;
|
||||
var allowNeighborIndex = _configService.Current.AnimationAllowNeighborIndexTolerance;
|
||||
|
||||
if (mode == AnimationValidationMode.Unsafe || papOnly.Count == 0)
|
||||
return 0;
|
||||
|
||||
var boneIndices = await _dalamudUtil.RunOnFrameworkThread(
|
||||
() => _modelAnalyzer.GetSkeletonBoneIndices(handlerForApply))
|
||||
() => _modelAnalyzer.GetSkeletonBoneIndices(handlerForApply))
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (boneIndices == null || boneIndices.Count == 0)
|
||||
@@ -2849,47 +2850,86 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
foreach (var (rawKey, list) in boneIndices)
|
||||
{
|
||||
var key = XivDataAnalyzer.CanonicalizeSkeletonKey(rawKey);
|
||||
if (string.IsNullOrEmpty(key)) continue;
|
||||
if (string.IsNullOrEmpty(key) || list == null || list.Count == 0)
|
||||
continue;
|
||||
|
||||
if (!localBoneSets.TryGetValue(key, out var set))
|
||||
localBoneSets[key] = set = [];
|
||||
localBoneSets[key] = set = new HashSet<ushort>();
|
||||
|
||||
foreach (var v in list)
|
||||
set.Add(v);
|
||||
}
|
||||
|
||||
if (localBoneSets.Count == 0)
|
||||
{
|
||||
var removedCount = papOnly.Count;
|
||||
papOnly.Clear();
|
||||
return removedCount;
|
||||
}
|
||||
|
||||
int removed = 0;
|
||||
|
||||
foreach (var hash in papOnly.Keys.Select(k => k.Hash).Where(h => !string.IsNullOrEmpty(h)).Distinct(StringComparer.OrdinalIgnoreCase).ToList())
|
||||
var groups = papOnly
|
||||
.Where(kvp => !string.IsNullOrEmpty(kvp.Key.Hash))
|
||||
.GroupBy(kvp => kvp.Key.Hash!, StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
foreach (var grp in groups)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
var papIndices = await _dalamudUtil.RunOnFrameworkThread(
|
||||
() => _modelAnalyzer.GetBoneIndicesFromPap(hash!))
|
||||
.ConfigureAwait(false);
|
||||
var hash = grp.Key;
|
||||
|
||||
var papPath = grp.Select(x => x.Value)
|
||||
.FirstOrDefault(p => !string.IsNullOrEmpty(p) && File.Exists(p));
|
||||
|
||||
if (string.IsNullOrEmpty(papPath))
|
||||
continue;
|
||||
|
||||
var havokBytes = await Task.Run(() => XivDataAnalyzer.ReadHavokBytesFromPap(papPath), token)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
if (havokBytes is not { Length: > 8 })
|
||||
continue;
|
||||
|
||||
Dictionary<string, List<ushort>>? papIndices;
|
||||
|
||||
await _papParseLimiter.WaitAsync(token).ConfigureAwait(false);
|
||||
try
|
||||
{
|
||||
papIndices = await _dalamudUtil.RunOnFrameworkThread(
|
||||
() => _modelAnalyzer.ParseHavokBytesOnFrameworkThread(havokBytes, hash, persistToConfig: false))
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_papParseLimiter.Release();
|
||||
}
|
||||
|
||||
if (papIndices == null || papIndices.Count == 0)
|
||||
continue;
|
||||
|
||||
if (papIndices.All(k => k.Value.DefaultIfEmpty().Max() <= 105))
|
||||
if (papIndices.All(k => k.Value == null || k.Value.Count == 0 || k.Value.Max() <= 105))
|
||||
continue;
|
||||
|
||||
if (XivDataAnalyzer.IsPapCompatible(localBoneSets, papIndices, mode, allowBasedShift, allownNightIndex, out var reason))
|
||||
if (XivDataAnalyzer.IsPapCompatible(localBoneSets, papIndices, mode, allowBasedShift, allowNeighborIndex, out var reason))
|
||||
continue;
|
||||
|
||||
var keysToRemove = papOnly.Keys.Where(k => string.Equals(k.Hash, hash, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||
var keysToRemove = grp.Select(x => x.Key).ToList();
|
||||
foreach (var k in keysToRemove)
|
||||
papOnly.Remove(k);
|
||||
|
||||
removed += keysToRemove.Count;
|
||||
|
||||
if (_blockedPapHashes.TryAdd(hash!, 0))
|
||||
Logger.LogWarning("Blocked remote object PAP (hash {hash}) for {handler}: {reason}", hash, GetLogIdentifier(), reason);
|
||||
if (_blockedPapHashes.TryAdd(hash, 0))
|
||||
Logger.LogWarning("Blocked remote object PAP {papPath} (hash {hash}) for {handler}: {reason}",
|
||||
papPath, hash, GetLogIdentifier(), reason);
|
||||
|
||||
if (charaData.FileReplacements.TryGetValue(ObjectKind.Player, out var list))
|
||||
{
|
||||
list.RemoveAll(r => string.Equals(r.Hash, hash, StringComparison.OrdinalIgnoreCase)
|
||||
&& r.GamePaths.Any(p => p.EndsWith(".pap", StringComparison.OrdinalIgnoreCase)));
|
||||
list.RemoveAll(r =>
|
||||
string.Equals(r.Hash, hash, StringComparison.OrdinalIgnoreCase) &&
|
||||
r.GamePaths.Any(p => p.EndsWith(".pap", StringComparison.OrdinalIgnoreCase)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2903,6 +2943,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
return removed;
|
||||
}
|
||||
|
||||
|
||||
private async Task ApplyCustomizeAsync(nint address, string customizeData, ObjectKind kind)
|
||||
{
|
||||
_customizeIds[kind] = await _ipcManager.CustomizePlus.SetBodyScaleAsync(address, customizeData).ConfigureAwait(false);
|
||||
|
||||
Reference in New Issue
Block a user