skip decimation for direct pairs and make it a toggle in settings
This commit is contained in:
@@ -22,10 +22,12 @@ public class PlayerPerformanceConfig : ILightlessConfiguration
|
||||
public int TextureDownscaleMaxDimension { get; set; } = 2048;
|
||||
public bool OnlyDownscaleUncompressedTextures { get; set; } = true;
|
||||
public bool KeepOriginalTextureFiles { get; set; } = false;
|
||||
public bool SkipTextureDownscaleForPreferredPairs { get; set; } = true;
|
||||
public bool EnableModelDecimation { get; set; } = false;
|
||||
public int ModelDecimationTriangleThreshold { get; set; } = 50_000;
|
||||
public double ModelDecimationTargetRatio { get; set; } = 0.8;
|
||||
public bool KeepOriginalModelFiles { get; set; } = true;
|
||||
public bool SkipModelDecimationForPreferredPairs { get; set; } = true;
|
||||
public bool ModelDecimationAllowBody { get; set; } = false;
|
||||
public bool ModelDecimationAllowFaceHead { get; set; } = false;
|
||||
public bool ModelDecimationAllowTail { get; set; } = false;
|
||||
|
||||
@@ -146,7 +146,8 @@ public class PlayerDataFactory
|
||||
fragment.FileReplacements =
|
||||
new HashSet<FileReplacement>(resolvedPaths.Select(c => new FileReplacement([.. c.Value], c.Key)), FileReplacementComparer.Instance)
|
||||
.Where(p => p.HasFileReplacement).ToHashSet();
|
||||
fragment.FileReplacements.RemoveWhere(c => c.GamePaths.Any(g => !CacheMonitor.AllowedFileExtensions.Any(e => g.EndsWith(e, StringComparison.OrdinalIgnoreCase))));
|
||||
var allowedExtensions = CacheMonitor.AllowedFileExtensions;
|
||||
fragment.FileReplacements.RemoveWhere(c => c.GamePaths.Any(g => !allowedExtensions.Any(e => g.EndsWith(e, StringComparison.OrdinalIgnoreCase))));
|
||||
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -194,7 +195,9 @@ public class PlayerDataFactory
|
||||
|
||||
// get all remaining paths and resolve them
|
||||
var transientPaths = ManageSemiTransientData(objectKind);
|
||||
var resolvedTransientPaths = await GetFileReplacementsFromPaths(playerRelatedObject, transientPaths, new HashSet<string>(StringComparer.Ordinal)).ConfigureAwait(false);
|
||||
var resolvedTransientPaths = transientPaths.Count == 0
|
||||
? new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase).AsReadOnly()
|
||||
: await GetFileReplacementsFromPaths(playerRelatedObject, transientPaths, new HashSet<string>(StringComparer.Ordinal)).ConfigureAwait(false);
|
||||
|
||||
if (logDebug)
|
||||
{
|
||||
@@ -377,7 +380,15 @@ public class PlayerDataFactory
|
||||
{
|
||||
var forwardPaths = forwardResolve.ToArray();
|
||||
var reversePaths = reverseResolve.ToArray();
|
||||
Dictionary<string, List<string>> resolvedPaths = new(StringComparer.Ordinal);
|
||||
if (forwardPaths.Length == 0 && reversePaths.Length == 0)
|
||||
{
|
||||
return new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase).AsReadOnly();
|
||||
}
|
||||
|
||||
var forwardPathsLower = forwardPaths.Length == 0 ? Array.Empty<string>() : forwardPaths.Select(p => p.ToLowerInvariant()).ToArray();
|
||||
var reversePathsLower = reversePaths.Length == 0 ? Array.Empty<string>() : reversePaths.Select(p => p.ToLowerInvariant()).ToArray();
|
||||
|
||||
Dictionary<string, List<string>> resolvedPaths = new(forwardPaths.Length + reversePaths.Length, StringComparer.Ordinal);
|
||||
if (handler.ObjectKind != ObjectKind.Player)
|
||||
{
|
||||
var (objectIndex, forwardResolved, reverseResolved) = await _dalamudUtil.RunOnFrameworkThread(() =>
|
||||
@@ -415,24 +426,29 @@ public class PlayerDataFactory
|
||||
|
||||
if (resolvedPaths.TryGetValue(filePath, out var list))
|
||||
{
|
||||
list.Add(forwardPaths[i].ToLowerInvariant());
|
||||
list.Add(forwardPathsLower[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedPaths[filePath] = [forwardPaths[i].ToLowerInvariant()];
|
||||
resolvedPaths[filePath] = [forwardPathsLower[i]];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < reversePaths.Length; i++)
|
||||
{
|
||||
var filePath = reversePaths[i].ToLowerInvariant();
|
||||
var filePath = reversePathsLower[i];
|
||||
var reverseResolvedLower = new string[reverseResolved[i].Length];
|
||||
for (var j = 0; j < reverseResolvedLower.Length; j++)
|
||||
{
|
||||
reverseResolvedLower[j] = reverseResolved[i][j].ToLowerInvariant();
|
||||
}
|
||||
if (resolvedPaths.TryGetValue(filePath, out var list))
|
||||
{
|
||||
list.AddRange(reverseResolved[i].Select(c => c.ToLowerInvariant()));
|
||||
list.AddRange(reverseResolvedLower);
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedPaths[filePath] = new List<string>(reverseResolved[i].Select(c => c.ToLowerInvariant()).ToList());
|
||||
resolvedPaths[filePath] = new List<string>(reverseResolvedLower);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -446,24 +462,29 @@ public class PlayerDataFactory
|
||||
var filePath = forward[i].ToLowerInvariant();
|
||||
if (resolvedPaths.TryGetValue(filePath, out var list))
|
||||
{
|
||||
list.Add(forwardPaths[i].ToLowerInvariant());
|
||||
list.Add(forwardPathsLower[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedPaths[filePath] = [forwardPaths[i].ToLowerInvariant()];
|
||||
resolvedPaths[filePath] = [forwardPathsLower[i]];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < reversePaths.Length; i++)
|
||||
{
|
||||
var filePath = reversePaths[i].ToLowerInvariant();
|
||||
var filePath = reversePathsLower[i];
|
||||
var reverseResolvedLower = new string[reverse[i].Length];
|
||||
for (var j = 0; j < reverseResolvedLower.Length; j++)
|
||||
{
|
||||
reverseResolvedLower[j] = reverse[i][j].ToLowerInvariant();
|
||||
}
|
||||
if (resolvedPaths.TryGetValue(filePath, out var list))
|
||||
{
|
||||
list.AddRange(reverse[i].Select(c => c.ToLowerInvariant()));
|
||||
list.AddRange(reverseResolvedLower);
|
||||
}
|
||||
else
|
||||
{
|
||||
resolvedPaths[filePath] = new List<string>(reverse[i].Select(c => c.ToLowerInvariant()).ToList());
|
||||
resolvedPaths[filePath] = new List<string>(reverseResolvedLower);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ using LightlessSync.API.Data.Enum;
|
||||
using LightlessSync.API.Data.Extensions;
|
||||
using LightlessSync.FileCache;
|
||||
using LightlessSync.Interop.Ipc;
|
||||
using LightlessSync.LightlessConfiguration;
|
||||
using LightlessSync.PlayerData.Factories;
|
||||
using LightlessSync.PlayerData.Handlers;
|
||||
using LightlessSync.Services;
|
||||
@@ -38,6 +39,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
private readonly ActorObjectService _actorObjectService;
|
||||
private readonly FileDownloadManager _downloadManager;
|
||||
private readonly FileCacheManager _fileDbManager;
|
||||
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
|
||||
private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly IHostApplicationLifetime _lifetime;
|
||||
@@ -197,6 +199,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
ActorObjectService actorObjectService,
|
||||
IHostApplicationLifetime lifetime,
|
||||
FileCacheManager fileDbManager,
|
||||
PlayerPerformanceConfigService playerPerformanceConfigService,
|
||||
PlayerPerformanceService playerPerformanceService,
|
||||
PairProcessingLimiter pairProcessingLimiter,
|
||||
ServerConfigurationManager serverConfigManager,
|
||||
@@ -217,6 +220,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
_actorObjectService = actorObjectService;
|
||||
_lifetime = lifetime;
|
||||
_fileDbManager = fileDbManager;
|
||||
_playerPerformanceConfigService = playerPerformanceConfigService;
|
||||
_playerPerformanceService = playerPerformanceService;
|
||||
_pairProcessingLimiter = pairProcessingLimiter;
|
||||
_serverConfigManager = serverConfigManager;
|
||||
@@ -522,11 +526,31 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
return GetCurrentPairs().Any(predicate);
|
||||
}
|
||||
|
||||
private bool ShouldSkipDownscale()
|
||||
private bool IsPreferredDirectPair()
|
||||
{
|
||||
return GetCurrentPairs().Any(p => p.IsDirectlyPaired && p.SelfToOtherPermissions.IsSticky());
|
||||
}
|
||||
|
||||
private bool ShouldSkipDownscale()
|
||||
{
|
||||
if (!_playerPerformanceConfigService.Current.SkipTextureDownscaleForPreferredPairs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsPreferredDirectPair();
|
||||
}
|
||||
|
||||
private bool ShouldSkipDecimation()
|
||||
{
|
||||
if (!_playerPerformanceConfigService.Current.SkipModelDecimationForPreferredPairs)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return IsPreferredDirectPair();
|
||||
}
|
||||
|
||||
private bool IsPaused()
|
||||
{
|
||||
var pairs = GetCurrentPairs();
|
||||
@@ -1843,6 +1867,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
try
|
||||
{
|
||||
bool skipDownscaleForPair = ShouldSkipDownscale();
|
||||
bool skipDecimationForPair = ShouldSkipDecimation();
|
||||
var user = GetPrimaryUserData();
|
||||
Dictionary<(string GamePath, string? Hash), string> moddedPaths;
|
||||
List<FileReplacementData> missingReplacements = [];
|
||||
@@ -1881,7 +1906,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
}
|
||||
|
||||
var handlerForDownload = _charaHandler;
|
||||
_pairDownloadTask = Task.Run(async () => await _downloadManager.DownloadFiles(handlerForDownload, toDownloadReplacements, downloadToken, skipDownscaleForPair).ConfigureAwait(false));
|
||||
_pairDownloadTask = Task.Run(async () => await _downloadManager.DownloadFiles(handlerForDownload, toDownloadReplacements, downloadToken, skipDownscaleForPair, skipDecimationForPair).ConfigureAwait(false));
|
||||
|
||||
await _pairDownloadTask.ConfigureAwait(false);
|
||||
|
||||
@@ -1904,7 +1929,10 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
{
|
||||
await _textureDownscaleService.WaitForPendingJobsAsync(downloadedTextureHashes, downloadToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (!skipDecimationForPair)
|
||||
{
|
||||
var downloadedModelHashes = toDownloadReplacements
|
||||
.Where(static replacement => replacement.GamePaths.Any(static path => path.EndsWith(".mdl", StringComparison.OrdinalIgnoreCase)))
|
||||
.Select(static replacement => replacement.Hash)
|
||||
@@ -2388,6 +2416,7 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
ConcurrentDictionary<(string GamePath, string? Hash), string> outputDict = new();
|
||||
bool hasMigrationChanges = false;
|
||||
bool skipDownscaleForPair = ShouldSkipDownscale();
|
||||
bool skipDecimationForPair = ShouldSkipDecimation();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -2419,16 +2448,13 @@ internal sealed class PairHandlerAdapter : DisposableMediatorSubscriberBase, IPa
|
||||
foreach (var gamePath in item.GamePaths)
|
||||
{
|
||||
var preferredPath = fileCache.ResolvedFilepath;
|
||||
if (!skipDownscaleForPair)
|
||||
if (!skipDownscaleForPair && gamePath.EndsWith(".tex", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
if (gamePath.EndsWith(".tex", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
preferredPath = _textureDownscaleService.GetPreferredPath(item.Hash, fileCache.ResolvedFilepath);
|
||||
}
|
||||
else if (gamePath.EndsWith(".mdl", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
preferredPath = _modelDecimationService.GetPreferredPath(item.Hash, fileCache.ResolvedFilepath);
|
||||
}
|
||||
preferredPath = _textureDownscaleService.GetPreferredPath(item.Hash, fileCache.ResolvedFilepath);
|
||||
}
|
||||
else if (!skipDecimationForPair && gamePath.EndsWith(".mdl", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
preferredPath = _modelDecimationService.GetPreferredPath(item.Hash, fileCache.ResolvedFilepath);
|
||||
}
|
||||
outputDict[(gamePath, item.Hash)] = preferredPath;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using LightlessSync.FileCache;
|
||||
using LightlessSync.Interop.Ipc;
|
||||
using LightlessSync.LightlessConfiguration;
|
||||
using LightlessSync.PlayerData.Factories;
|
||||
using LightlessSync.Services;
|
||||
using LightlessSync.Services.ActorTracking;
|
||||
@@ -27,6 +28,7 @@ internal sealed class PairHandlerAdapterFactory : IPairHandlerAdapterFactory
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly IHostApplicationLifetime _lifetime;
|
||||
private readonly FileCacheManager _fileCacheManager;
|
||||
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
|
||||
private readonly PlayerPerformanceService _playerPerformanceService;
|
||||
private readonly PairProcessingLimiter _pairProcessingLimiter;
|
||||
private readonly ServerConfigurationManager _serverConfigManager;
|
||||
@@ -49,6 +51,7 @@ internal sealed class PairHandlerAdapterFactory : IPairHandlerAdapterFactory
|
||||
IFramework framework,
|
||||
IHostApplicationLifetime lifetime,
|
||||
FileCacheManager fileCacheManager,
|
||||
PlayerPerformanceConfigService playerPerformanceConfigService,
|
||||
PlayerPerformanceService playerPerformanceService,
|
||||
PairProcessingLimiter pairProcessingLimiter,
|
||||
ServerConfigurationManager serverConfigManager,
|
||||
@@ -69,6 +72,7 @@ internal sealed class PairHandlerAdapterFactory : IPairHandlerAdapterFactory
|
||||
_framework = framework;
|
||||
_lifetime = lifetime;
|
||||
_fileCacheManager = fileCacheManager;
|
||||
_playerPerformanceConfigService = playerPerformanceConfigService;
|
||||
_playerPerformanceService = playerPerformanceService;
|
||||
_pairProcessingLimiter = pairProcessingLimiter;
|
||||
_serverConfigManager = serverConfigManager;
|
||||
@@ -98,6 +102,7 @@ internal sealed class PairHandlerAdapterFactory : IPairHandlerAdapterFactory
|
||||
actorObjectService,
|
||||
_lifetime,
|
||||
_fileCacheManager,
|
||||
_playerPerformanceConfigService,
|
||||
_playerPerformanceService,
|
||||
_pairProcessingLimiter,
|
||||
_serverConfigManager,
|
||||
|
||||
@@ -129,6 +129,8 @@ public class PlayerPerformanceService
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.ToList();
|
||||
|
||||
var skipDecimation = config.SkipModelDecimationForPreferredPairs && pairHandler.IsDirectlyPaired && pairHandler.HasStickyPermissions;
|
||||
|
||||
foreach (var hash in moddedModelHashes)
|
||||
{
|
||||
var tris = await _xivDataAnalyzer.GetTrianglesByHash(hash).ConfigureAwait(false);
|
||||
@@ -138,7 +140,12 @@ public class PlayerPerformanceService
|
||||
var fileEntry = _fileCacheManager.GetFileCacheByHash(hash);
|
||||
if (fileEntry != null)
|
||||
{
|
||||
var preferredPath = _modelDecimationService.GetPreferredPath(hash, fileEntry.ResolvedFilepath);
|
||||
var preferredPath = fileEntry.ResolvedFilepath;
|
||||
if (!skipDecimation)
|
||||
{
|
||||
preferredPath = _modelDecimationService.GetPreferredPath(hash, fileEntry.ResolvedFilepath);
|
||||
}
|
||||
|
||||
if (!string.Equals(preferredPath, fileEntry.ResolvedFilepath, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var decimatedTris = await _xivDataAnalyzer.GetEffectiveTrianglesByHash(hash, preferredPath).ConfigureAwait(false);
|
||||
@@ -192,7 +199,9 @@ public class PlayerPerformanceService
|
||||
public bool ComputeAndAutoPauseOnVRAMUsageThresholds(IPairPerformanceSubject pairHandler, CharacterData charaData, List<DownloadFileTransfer> toDownloadFiles)
|
||||
{
|
||||
var config = _playerPerformanceConfigService.Current;
|
||||
bool skipDownscale = pairHandler.IsDirectlyPaired && pairHandler.HasStickyPermissions;
|
||||
bool skipDownscale = config.SkipTextureDownscaleForPreferredPairs
|
||||
&& pairHandler.IsDirectlyPaired
|
||||
&& pairHandler.HasStickyPermissions;
|
||||
|
||||
long vramUsage = 0;
|
||||
long effectiveVramUsage = 0;
|
||||
|
||||
@@ -3590,6 +3590,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.SameLine();
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), new SeStringUtils.RichTextEntry("If disabled, saved + effective VRAM usage information will not work.", UIColors.Get("LightlessYellow")));
|
||||
|
||||
var skipPreferredDownscale = textureConfig.SkipTextureDownscaleForPreferredPairs;
|
||||
if (ImGui.Checkbox("Skip downscale for preferred/direct pairs", ref skipPreferredDownscale))
|
||||
{
|
||||
textureConfig.SkipTextureDownscaleForPreferredPairs = skipPreferredDownscale;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When enabled, textures for direct pairs with preferred permissions are left untouched.");
|
||||
|
||||
if (!textureConfig.EnableNonIndexTextureMipTrim && !textureConfig.EnableIndexTextureDownscale)
|
||||
{
|
||||
UiSharedService.ColorTextWrapped("Both trimming and downscale are disabled. Lightless will keep original textures regardless of size.", UIColors.Get("DimRed"));
|
||||
@@ -3649,6 +3657,14 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
ImGui.SameLine();
|
||||
_uiShared.DrawNoteLine("! ", UIColors.Get("LightlessYellow"), new SeStringUtils.RichTextEntry("If disabled, saved + effective triangle usage information will not work.", UIColors.Get("LightlessYellow")));
|
||||
|
||||
var skipPreferredDecimation = performanceConfig.SkipModelDecimationForPreferredPairs;
|
||||
if (ImGui.Checkbox("Skip decimation for preferred/direct pairs", ref skipPreferredDecimation))
|
||||
{
|
||||
performanceConfig.SkipModelDecimationForPreferredPairs = skipPreferredDecimation;
|
||||
_playerPerformanceConfigService.Save();
|
||||
}
|
||||
_uiShared.DrawHelpText("When enabled, models for direct pairs with preferred permissions are left untouched.");
|
||||
|
||||
var triangleThreshold = performanceConfig.ModelDecimationTriangleThreshold;
|
||||
ImGui.SetNextItemWidth(300 * ImGuiHelpers.GlobalScale);
|
||||
if (ImGui.SliderInt("Decimate models above", ref triangleThreshold, 10_000, 100_000))
|
||||
|
||||
@@ -89,12 +89,12 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
CurrentOwnerToken = null;
|
||||
}
|
||||
|
||||
public async Task DownloadFiles(GameObjectHandler? gameObject, List<FileReplacementData> fileReplacementDto, CancellationToken ct, bool skipDownscale = false)
|
||||
public async Task DownloadFiles(GameObjectHandler? gameObject, List<FileReplacementData> fileReplacementDto, CancellationToken ct, bool skipDownscale = false, bool skipDecimation = false)
|
||||
{
|
||||
Mediator.Publish(new HaltScanMessage(nameof(DownloadFiles)));
|
||||
try
|
||||
{
|
||||
await DownloadFilesInternal(gameObject, fileReplacementDto, ct, skipDownscale).ConfigureAwait(false);
|
||||
await DownloadFilesInternal(gameObject, fileReplacementDto, ct, skipDownscale, skipDecimation).ConfigureAwait(false);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -498,7 +498,8 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
IReadOnlyDictionary<string, long> rawSizeLookup,
|
||||
string downloadLabel,
|
||||
CancellationToken ct,
|
||||
bool skipDownscale)
|
||||
bool skipDownscale,
|
||||
bool skipDecimation)
|
||||
{
|
||||
SetStatus(downloadStatusKey, DownloadStatus.Decompressing);
|
||||
MarkTransferredFiles(downloadStatusKey, 1);
|
||||
@@ -552,7 +553,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
}
|
||||
|
||||
await _fileCompactor.WriteAllBytesAsync(filePath, decompressed, ct).ConfigureAwait(false);
|
||||
PersistFileToStorage(fileHash, filePath, repl.GamePath, skipDownscale);
|
||||
PersistFileToStorage(fileHash, filePath, repl.GamePath, skipDownscale, skipDecimation);
|
||||
}
|
||||
catch (EndOfStreamException)
|
||||
{
|
||||
@@ -638,7 +639,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
yield return items.GetRange(i, Math.Min(chunkSize, items.Count - i));
|
||||
}
|
||||
|
||||
private async Task DownloadFilesInternal(GameObjectHandler? gameObjectHandler, List<FileReplacementData> fileReplacement, CancellationToken ct, bool skipDownscale)
|
||||
private async Task DownloadFilesInternal(GameObjectHandler? gameObjectHandler, List<FileReplacementData> fileReplacement, CancellationToken ct, bool skipDownscale, bool skipDecimation)
|
||||
{
|
||||
var objectName = gameObjectHandler?.Name ?? "Unknown";
|
||||
|
||||
@@ -742,13 +743,13 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
Task batchTask = batchChunks.Length == 0
|
||||
? Task.CompletedTask
|
||||
: Parallel.ForEachAsync(batchChunks, new ParallelOptions { MaxDegreeOfParallelism = workerDop, CancellationToken = ct },
|
||||
async (chunk, token) => await ProcessBatchChunkAsync(chunk, replacementLookup, rawSizeLookup, token, skipDownscale).ConfigureAwait(false));
|
||||
async (chunk, token) => await ProcessBatchChunkAsync(chunk, replacementLookup, rawSizeLookup, token, skipDownscale, skipDecimation).ConfigureAwait(false));
|
||||
|
||||
// direct downloads
|
||||
Task directTask = directDownloads.Count == 0
|
||||
? Task.CompletedTask
|
||||
: Parallel.ForEachAsync(directDownloads, new ParallelOptions { MaxDegreeOfParallelism = workerDop, CancellationToken = ct },
|
||||
async (d, token) => await ProcessDirectAsync(d, replacementLookup, rawSizeLookup, token, skipDownscale).ConfigureAwait(false));
|
||||
async (d, token) => await ProcessDirectAsync(d, replacementLookup, rawSizeLookup, token, skipDownscale, skipDecimation).ConfigureAwait(false));
|
||||
|
||||
await Task.WhenAll(batchTask, directTask).ConfigureAwait(false);
|
||||
|
||||
@@ -761,7 +762,8 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
Dictionary<string, (string Extension, string GamePath)> replacementLookup,
|
||||
IReadOnlyDictionary<string, long> rawSizeLookup,
|
||||
CancellationToken ct,
|
||||
bool skipDownscale)
|
||||
bool skipDownscale,
|
||||
bool skipDecimation)
|
||||
{
|
||||
var statusKey = chunk.StatusKey;
|
||||
|
||||
@@ -795,7 +797,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
return;
|
||||
}
|
||||
|
||||
await DecompressBlockFileAsync(statusKey, blockFile, replacementLookup, rawSizeLookup, fi.Name, ct, skipDownscale).ConfigureAwait(false);
|
||||
await DecompressBlockFileAsync(statusKey, blockFile, replacementLookup, rawSizeLookup, fi.Name, ct, skipDownscale, skipDecimation).ConfigureAwait(false);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
@@ -817,7 +819,8 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
Dictionary<string, (string Extension, string GamePath)> replacementLookup,
|
||||
IReadOnlyDictionary<string, long> rawSizeLookup,
|
||||
CancellationToken ct,
|
||||
bool skipDownscale)
|
||||
bool skipDownscale,
|
||||
bool skipDecimation)
|
||||
{
|
||||
var progress = CreateInlineProgress(bytes =>
|
||||
{
|
||||
@@ -827,7 +830,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
|
||||
if (!ShouldUseDirectDownloads() || string.IsNullOrEmpty(directDownload.DirectDownloadUrl))
|
||||
{
|
||||
await ProcessDirectAsQueuedFallbackAsync(directDownload, replacementLookup, rawSizeLookup, progress, ct, skipDownscale).ConfigureAwait(false);
|
||||
await ProcessDirectAsQueuedFallbackAsync(directDownload, replacementLookup, rawSizeLookup, progress, ct, skipDownscale, skipDecimation).ConfigureAwait(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -875,7 +878,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
}
|
||||
|
||||
await _fileCompactor.WriteAllBytesAsync(finalFilename, decompressedBytes, ct).ConfigureAwait(false);
|
||||
PersistFileToStorage(directDownload.Hash, finalFilename, repl.GamePath, skipDownscale);
|
||||
PersistFileToStorage(directDownload.Hash, finalFilename, repl.GamePath, skipDownscale, skipDecimation);
|
||||
|
||||
MarkTransferredFiles(directDownload.DirectDownloadUrl!, 1);
|
||||
SetStatus(directDownload.DirectDownloadUrl!, DownloadStatus.Completed);
|
||||
@@ -902,7 +905,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
|
||||
try
|
||||
{
|
||||
await ProcessDirectAsQueuedFallbackAsync(directDownload, replacementLookup, rawSizeLookup, progress, ct, skipDownscale).ConfigureAwait(false);
|
||||
await ProcessDirectAsQueuedFallbackAsync(directDownload, replacementLookup, rawSizeLookup, progress, ct, skipDownscale, skipDecimation).ConfigureAwait(false);
|
||||
|
||||
if (!expectedDirectDownloadFailure && failureCount >= 3 && !_disableDirectDownloads)
|
||||
{
|
||||
@@ -932,7 +935,8 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
IReadOnlyDictionary<string, long> rawSizeLookup,
|
||||
IProgress<long> progress,
|
||||
CancellationToken ct,
|
||||
bool skipDownscale)
|
||||
bool skipDownscale,
|
||||
bool skipDecimation)
|
||||
{
|
||||
if (string.IsNullOrEmpty(directDownload.DirectDownloadUrl))
|
||||
throw new InvalidOperationException("Direct download fallback requested without a direct download URL.");
|
||||
@@ -957,7 +961,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
if (!File.Exists(blockFile))
|
||||
throw new FileNotFoundException("Block file missing after direct download fallback.", blockFile);
|
||||
|
||||
await DecompressBlockFileAsync(statusKey, blockFile, replacementLookup, rawSizeLookup, $"fallback-{directDownload.Hash}", ct, skipDownscale)
|
||||
await DecompressBlockFileAsync(statusKey, blockFile, replacementLookup, rawSizeLookup, $"fallback-{directDownload.Hash}", ct, skipDownscale, skipDecimation)
|
||||
.ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
@@ -986,7 +990,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
return await response.Content.ReadFromJsonAsync<List<DownloadFileDto>>(cancellationToken: ct).ConfigureAwait(false) ?? [];
|
||||
}
|
||||
|
||||
private void PersistFileToStorage(string fileHash, string filePath, string gamePath, bool skipDownscale)
|
||||
private void PersistFileToStorage(string fileHash, string filePath, string gamePath, bool skipDownscale, bool skipDecimation)
|
||||
{
|
||||
var fi = new FileInfo(filePath);
|
||||
|
||||
@@ -1014,7 +1018,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
||||
() => _textureMetadataHelper.DetermineMapKind(gamePath, filePath));
|
||||
}
|
||||
|
||||
if (!skipDownscale && _modelDecimationService.ShouldScheduleDecimation(fileHash, filePath, gamePath))
|
||||
if (!skipDecimation && _modelDecimationService.ShouldScheduleDecimation(fileHash, filePath, gamePath))
|
||||
{
|
||||
_modelDecimationService.ScheduleDecimation(fileHash, filePath, gamePath);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user