something something performance
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
namespace MareSynchronos.MareConfiguration.Configurations;
|
||||||
|
|
||||||
|
public class PlayerPerformanceConfig : IMareConfiguration
|
||||||
|
{
|
||||||
|
public int Version { get; set; } = 1;
|
||||||
|
public bool ShowPerformanceIndicator { get; set; } = true;
|
||||||
|
public bool WarnOnExceedingThresholds { get; set; } = true;
|
||||||
|
public bool WarnOnPreferredPermissionsExceedingThresholds { get; set; } = false;
|
||||||
|
public int VRAMSizeWarningThresholdMiB { get; set; } = 375;
|
||||||
|
public int TrisWarningThresholdThousands { get; set; } = 165;
|
||||||
|
public bool AutoPausePlayersExceedingThresholds { get; set; } = false;
|
||||||
|
public bool AutoPausePlayersWithPreferredPermissionsExceedingThresholds { get; set; } = false;
|
||||||
|
public int VRAMSizeAutoPauseThresholdMiB { get; set; } = 550;
|
||||||
|
public int TrisAutoPauseThresholdThousands { get; set; } = 250;
|
||||||
|
public List<string> UIDsToIgnore { get; set; } = new();
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
using MareSynchronos.MareConfiguration.Configurations;
|
||||||
|
|
||||||
|
namespace MareSynchronos.MareConfiguration;
|
||||||
|
|
||||||
|
public class PlayerPerformanceConfigService : ConfigurationServiceBase<PlayerPerformanceConfig>
|
||||||
|
{
|
||||||
|
public const string ConfigName = "playerperformance.json";
|
||||||
|
public PlayerPerformanceConfigService(string configDir) : base(configDir) { }
|
||||||
|
|
||||||
|
protected override string ConfigurationName => ConfigName;
|
||||||
|
}
|
||||||
@@ -21,12 +21,13 @@ public class PairHandlerFactory
|
|||||||
private readonly ILoggerFactory _loggerFactory;
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
private readonly MareMediator _mareMediator;
|
private readonly MareMediator _mareMediator;
|
||||||
private readonly XivDataAnalyzer _xivDataAnalyzer;
|
private readonly XivDataAnalyzer _xivDataAnalyzer;
|
||||||
|
private readonly PlayerPerformanceService _playerPerformanceService;
|
||||||
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
|
private readonly PluginWarningNotificationService _pluginWarningNotificationManager;
|
||||||
|
|
||||||
public PairHandlerFactory(ILoggerFactory loggerFactory, GameObjectHandlerFactory gameObjectHandlerFactory, IpcManager ipcManager,
|
public PairHandlerFactory(ILoggerFactory loggerFactory, GameObjectHandlerFactory gameObjectHandlerFactory, IpcManager ipcManager,
|
||||||
FileDownloadManagerFactory fileDownloadManagerFactory, DalamudUtilService dalamudUtilService,
|
FileDownloadManagerFactory fileDownloadManagerFactory, DalamudUtilService dalamudUtilService,
|
||||||
PluginWarningNotificationService pluginWarningNotificationManager, IHostApplicationLifetime hostApplicationLifetime,
|
PluginWarningNotificationService pluginWarningNotificationManager, IHostApplicationLifetime hostApplicationLifetime,
|
||||||
FileCacheManager fileCacheManager, MareMediator mareMediator, XivDataAnalyzer modelAnalyzer)
|
FileCacheManager fileCacheManager, MareMediator mareMediator, XivDataAnalyzer modelAnalyzer, PlayerPerformanceService playerPerformanceService)
|
||||||
{
|
{
|
||||||
_loggerFactory = loggerFactory;
|
_loggerFactory = loggerFactory;
|
||||||
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
||||||
@@ -38,12 +39,13 @@ public class PairHandlerFactory
|
|||||||
_fileCacheManager = fileCacheManager;
|
_fileCacheManager = fileCacheManager;
|
||||||
_mareMediator = mareMediator;
|
_mareMediator = mareMediator;
|
||||||
_xivDataAnalyzer = modelAnalyzer;
|
_xivDataAnalyzer = modelAnalyzer;
|
||||||
|
_playerPerformanceService = playerPerformanceService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PairHandler Create(OnlineUserIdentDto onlineUserIdentDto)
|
public PairHandler Create(OnlineUserIdentDto onlineUserIdentDto)
|
||||||
{
|
{
|
||||||
return new PairHandler(_loggerFactory.CreateLogger<PairHandler>(), onlineUserIdentDto, _gameObjectHandlerFactory,
|
return new PairHandler(_loggerFactory.CreateLogger<PairHandler>(), onlineUserIdentDto, _gameObjectHandlerFactory,
|
||||||
_ipcManager, _fileDownloadManagerFactory.Create(), _pluginWarningNotificationManager, _dalamudUtilService, _hostApplicationLifetime,
|
_ipcManager, _fileDownloadManagerFactory.Create(), _pluginWarningNotificationManager, _dalamudUtilService, _hostApplicationLifetime,
|
||||||
_fileCacheManager, _mareMediator, _xivDataAnalyzer);
|
_fileCacheManager, _mareMediator, _xivDataAnalyzer, _playerPerformanceService);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,6 +25,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
private readonly FileDownloadManager _downloadManager;
|
private readonly FileDownloadManager _downloadManager;
|
||||||
private readonly FileCacheManager _fileDbManager;
|
private readonly FileCacheManager _fileDbManager;
|
||||||
private readonly XivDataAnalyzer _xivDataAnalyzer;
|
private readonly XivDataAnalyzer _xivDataAnalyzer;
|
||||||
|
private readonly PlayerPerformanceService _playerPerformanceService;
|
||||||
private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
|
private readonly GameObjectHandlerFactory _gameObjectHandlerFactory;
|
||||||
private readonly IpcManager _ipcManager;
|
private readonly IpcManager _ipcManager;
|
||||||
private readonly IHostApplicationLifetime _lifetime;
|
private readonly IHostApplicationLifetime _lifetime;
|
||||||
@@ -41,8 +42,9 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
private Dictionary<ObjectKind, Guid?> _customizeIds = [];
|
private Dictionary<ObjectKind, Guid?> _customizeIds = [];
|
||||||
private bool _redrawOnNextApplication = false;
|
private bool _redrawOnNextApplication = false;
|
||||||
private CombatData? _dataReceivedInDowntime;
|
private CombatData? _dataReceivedInDowntime;
|
||||||
public long LastAppliedDataSize { get; private set; }
|
public long LastAppliedDataBytes { get; private set; }
|
||||||
public long LastAppliedDataTris { get; private set; }
|
public long LastAppliedDataTris { get; private set; }
|
||||||
|
public long LastAppliedApproximateVRAMBytes { get; private set; }
|
||||||
|
|
||||||
public PairHandler(ILogger<PairHandler> logger, OnlineUserIdentDto onlineUser,
|
public PairHandler(ILogger<PairHandler> logger, OnlineUserIdentDto onlineUser,
|
||||||
GameObjectHandlerFactory gameObjectHandlerFactory,
|
GameObjectHandlerFactory gameObjectHandlerFactory,
|
||||||
@@ -50,7 +52,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
PluginWarningNotificationService pluginWarningNotificationManager,
|
PluginWarningNotificationService pluginWarningNotificationManager,
|
||||||
DalamudUtilService dalamudUtil, IHostApplicationLifetime lifetime,
|
DalamudUtilService dalamudUtil, IHostApplicationLifetime lifetime,
|
||||||
FileCacheManager fileDbManager, MareMediator mediator,
|
FileCacheManager fileDbManager, MareMediator mediator,
|
||||||
XivDataAnalyzer modelAnalyzer) : base(logger, mediator)
|
XivDataAnalyzer modelAnalyzer, PlayerPerformanceService playerPerformanceService) : base(logger, mediator)
|
||||||
{
|
{
|
||||||
OnlineUser = onlineUser;
|
OnlineUser = onlineUser;
|
||||||
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
_gameObjectHandlerFactory = gameObjectHandlerFactory;
|
||||||
@@ -61,6 +63,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
_lifetime = lifetime;
|
_lifetime = lifetime;
|
||||||
_fileDbManager = fileDbManager;
|
_fileDbManager = fileDbManager;
|
||||||
_xivDataAnalyzer = modelAnalyzer;
|
_xivDataAnalyzer = modelAnalyzer;
|
||||||
|
_playerPerformanceService = playerPerformanceService;
|
||||||
_penumbraCollection = _ipcManager.Penumbra.CreateTemporaryCollectionAsync(logger, OnlineUser.User.UID).ConfigureAwait(false).GetAwaiter().GetResult();
|
_penumbraCollection = _ipcManager.Penumbra.CreateTemporaryCollectionAsync(logger, OnlineUser.User.UID).ConfigureAwait(false).GetAwaiter().GetResult();
|
||||||
|
|
||||||
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => FrameworkUpdate());
|
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => FrameworkUpdate());
|
||||||
@@ -103,7 +106,7 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
_applicationCancellationTokenSource = _applicationCancellationTokenSource?.CancelRecreate();
|
_applicationCancellationTokenSource = _applicationCancellationTokenSource?.CancelRecreate();
|
||||||
});
|
});
|
||||||
|
|
||||||
LastAppliedDataSize = -1;
|
LastAppliedDataBytes = -1;
|
||||||
LastAppliedDataTris = -1;
|
LastAppliedDataTris = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -384,17 +387,28 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
List<FileReplacementData> toDownloadReplacements = TryCalculateModdedDictionary(applicationBase, charaData, out moddedPaths, downloadToken);
|
List<FileReplacementData> toDownloadReplacements = TryCalculateModdedDictionary(applicationBase, charaData, out moddedPaths, downloadToken);
|
||||||
|
|
||||||
|
LastAppliedApproximateVRAMBytes = -1;
|
||||||
|
|
||||||
while (toDownloadReplacements.Count > 0 && attempts++ <= 10 && !downloadToken.IsCancellationRequested)
|
while (toDownloadReplacements.Count > 0 && attempts++ <= 10 && !downloadToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
_downloadManager.CancelDownload();
|
_downloadManager.CancelDownload();
|
||||||
Logger.LogDebug("[BASE-{appBase}] Downloading missing files for player {name}, {kind}", applicationBase, PlayerName, updatedData);
|
Logger.LogDebug("[BASE-{appBase}] Downloading missing files for player {name}, {kind}", applicationBase, PlayerName, updatedData);
|
||||||
if (toDownloadReplacements.Any())
|
|
||||||
{
|
|
||||||
Mediator.Publish(new EventMessage(new Event(PlayerName, OnlineUser.User, nameof(PairHandler), EventSeverity.Informational,
|
Mediator.Publish(new EventMessage(new Event(PlayerName, OnlineUser.User, nameof(PairHandler), EventSeverity.Informational,
|
||||||
$"Starting download for {toDownloadReplacements.Count} files")));
|
$"Starting download for {toDownloadReplacements.Count} files")));
|
||||||
|
var toDownloadFiles = await _downloadManager.InitiateDownloadList(_charaHandler!, toDownloadReplacements, downloadToken).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (!_playerPerformanceService.TryCalculateVRAMUsage(this, charaData, toDownloadFiles, out long vramDuringDl))
|
||||||
|
{
|
||||||
|
LastAppliedApproximateVRAMBytes = vramDuringDl;
|
||||||
|
_downloadManager.CancelDownload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastAppliedApproximateVRAMBytes = vramDuringDl;
|
||||||
|
|
||||||
await _downloadManager.DownloadFiles(_charaHandler!, toDownloadReplacements, downloadToken).ConfigureAwait(false);
|
await _downloadManager.DownloadFiles(_charaHandler!, toDownloadReplacements, downloadToken).ConfigureAwait(false);
|
||||||
_downloadManager.CancelDownload();
|
_downloadManager.CancelDownload();
|
||||||
}
|
|
||||||
|
|
||||||
if (downloadToken.IsCancellationRequested)
|
if (downloadToken.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
@@ -412,6 +426,13 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
|
await Task.Delay(TimeSpan.FromSeconds(2)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (LastAppliedApproximateVRAMBytes == -1
|
||||||
|
&& !_playerPerformanceService.TryCalculateVRAMUsage(this, charaData, [], out long vramUsage))
|
||||||
|
{
|
||||||
|
LastAppliedApproximateVRAMBytes = vramUsage;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
downloadToken.ThrowIfCancellationRequested();
|
downloadToken.ThrowIfCancellationRequested();
|
||||||
@@ -446,12 +467,18 @@ public sealed class PairHandler : DisposableMediatorSubscriberBase
|
|||||||
{
|
{
|
||||||
await _ipcManager.Penumbra.SetTemporaryModsAsync(Logger, _applicationId, _penumbraCollection,
|
await _ipcManager.Penumbra.SetTemporaryModsAsync(Logger, _applicationId, _penumbraCollection,
|
||||||
moddedPaths.ToDictionary(k => k.Key.GamePath, k => k.Value, StringComparer.Ordinal)).ConfigureAwait(false);
|
moddedPaths.ToDictionary(k => k.Key.GamePath, k => k.Value, StringComparer.Ordinal)).ConfigureAwait(false);
|
||||||
LastAppliedDataSize = -1;
|
LastAppliedDataBytes = -1;
|
||||||
LastAppliedDataTris = -1;
|
LastAppliedDataTris = -1;
|
||||||
foreach (var path in moddedPaths.Values.Distinct(StringComparer.OrdinalIgnoreCase).Select(v => new FileInfo(v)).Where(p => p.Exists))
|
foreach (var path in moddedPaths.Values.Distinct(StringComparer.OrdinalIgnoreCase).Select(v => new FileInfo(v)).Where(p => p.Exists))
|
||||||
{
|
{
|
||||||
if (LastAppliedDataSize == -1) LastAppliedDataSize = 0;
|
if (LastAppliedDataBytes == -1) LastAppliedDataBytes = 0;
|
||||||
LastAppliedDataSize += path.Length;
|
if (LastAppliedApproximateVRAMBytes == -1) LastAppliedApproximateVRAMBytes = 0;
|
||||||
|
|
||||||
|
LastAppliedDataBytes += path.Length;
|
||||||
|
if (path.Name.EndsWith(".tex", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
LastAppliedApproximateVRAMBytes += path.Length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach (var key in moddedPaths.Keys.Where(k => !string.IsNullOrEmpty(k.Hash)))
|
foreach (var key in moddedPaths.Keys.Where(k => !string.IsNullOrEmpty(k.Hash)))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,8 +44,9 @@ public class Pair
|
|||||||
public bool IsVisible => CachedPlayer?.IsVisible ?? false;
|
public bool IsVisible => CachedPlayer?.IsVisible ?? false;
|
||||||
public CharacterData? LastReceivedCharacterData { get; set; }
|
public CharacterData? LastReceivedCharacterData { get; set; }
|
||||||
public string? PlayerName => CachedPlayer?.PlayerName ?? string.Empty;
|
public string? PlayerName => CachedPlayer?.PlayerName ?? string.Empty;
|
||||||
public long LastAppliedDataSize => CachedPlayer?.LastAppliedDataSize ?? -1;
|
public long LastAppliedDataBytes => CachedPlayer?.LastAppliedDataBytes ?? -1;
|
||||||
public long LastAppliedDataTris => CachedPlayer?.LastAppliedDataTris ?? -1;
|
public long LastAppliedDataTris => CachedPlayer?.LastAppliedDataTris ?? -1;
|
||||||
|
public long LastAppliedApproximateVRAMBytes => CachedPlayer?.LastAppliedApproximateVRAMBytes ?? -1;
|
||||||
|
|
||||||
public UserData UserData => UserPair.User;
|
public UserData UserData => UserPair.User;
|
||||||
|
|
||||||
|
|||||||
@@ -110,6 +110,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
collection.AddSingleton<FileCompactor>();
|
collection.AddSingleton<FileCompactor>();
|
||||||
collection.AddSingleton<TagHandler>();
|
collection.AddSingleton<TagHandler>();
|
||||||
collection.AddSingleton<IdDisplayHandler>();
|
collection.AddSingleton<IdDisplayHandler>();
|
||||||
|
collection.AddSingleton<PlayerPerformanceService>();
|
||||||
collection.AddSingleton((s) => new IpcProvider(s.GetRequiredService<ILogger<IpcProvider>>(),
|
collection.AddSingleton((s) => new IpcProvider(s.GetRequiredService<ILogger<IpcProvider>>(),
|
||||||
pluginInterface,
|
pluginInterface,
|
||||||
s.GetRequiredService<MareCharaFileManager>(), s.GetRequiredService<DalamudUtilService>(),
|
s.GetRequiredService<MareCharaFileManager>(), s.GetRequiredService<DalamudUtilService>(),
|
||||||
@@ -150,6 +151,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
collection.AddSingleton((s) => new ServerTagConfigService(pluginInterface.ConfigDirectory.FullName));
|
collection.AddSingleton((s) => new ServerTagConfigService(pluginInterface.ConfigDirectory.FullName));
|
||||||
collection.AddSingleton((s) => new TransientConfigService(pluginInterface.ConfigDirectory.FullName));
|
collection.AddSingleton((s) => new TransientConfigService(pluginInterface.ConfigDirectory.FullName));
|
||||||
collection.AddSingleton((s) => new XivDataStorageService(pluginInterface.ConfigDirectory.FullName));
|
collection.AddSingleton((s) => new XivDataStorageService(pluginInterface.ConfigDirectory.FullName));
|
||||||
|
collection.AddSingleton((s) => new PlayerPerformanceConfigService(pluginInterface.ConfigDirectory.FullName));
|
||||||
collection.AddSingleton((s) => new ConfigurationMigrator(s.GetRequiredService<ILogger<ConfigurationMigrator>>(), pluginInterface));
|
collection.AddSingleton((s) => new ConfigurationMigrator(s.GetRequiredService<ILogger<ConfigurationMigrator>>(), pluginInterface));
|
||||||
collection.AddSingleton<HubFactory>();
|
collection.AddSingleton<HubFactory>();
|
||||||
|
|
||||||
@@ -197,6 +199,7 @@ public sealed class Plugin : IDalamudPlugin
|
|||||||
collection.AddHostedService(p => p.GetRequiredService<DalamudUtilService>());
|
collection.AddHostedService(p => p.GetRequiredService<DalamudUtilService>());
|
||||||
collection.AddHostedService(p => p.GetRequiredService<PerformanceCollectorService>());
|
collection.AddHostedService(p => p.GetRequiredService<PerformanceCollectorService>());
|
||||||
collection.AddHostedService(p => p.GetRequiredService<DtrEntry>());
|
collection.AddHostedService(p => p.GetRequiredService<DtrEntry>());
|
||||||
|
collection.AddHostedService(p => p.GetRequiredService<PlayerPerformanceService>());
|
||||||
collection.AddHostedService(p => p.GetRequiredService<EventAggregator>());
|
collection.AddHostedService(p => p.GetRequiredService<EventAggregator>());
|
||||||
collection.AddHostedService(p => p.GetRequiredService<IpcProvider>());
|
collection.AddHostedService(p => p.GetRequiredService<IpcProvider>());
|
||||||
collection.AddHostedService(p => p.GetRequiredService<MarePlugin>());
|
collection.AddHostedService(p => p.GetRequiredService<MarePlugin>());
|
||||||
|
|||||||
134
MareSynchronos/Services/PlayerPerformanceService.cs
Normal file
134
MareSynchronos/Services/PlayerPerformanceService.cs
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
using MareSynchronos.API.Data;
|
||||||
|
using MareSynchronos.API.Data.Extensions;
|
||||||
|
using MareSynchronos.FileCache;
|
||||||
|
using MareSynchronos.MareConfiguration;
|
||||||
|
using MareSynchronos.PlayerData.Handlers;
|
||||||
|
using MareSynchronos.PlayerData.Pairs;
|
||||||
|
using MareSynchronos.Services.Mediator;
|
||||||
|
using MareSynchronos.UI;
|
||||||
|
using MareSynchronos.Utils;
|
||||||
|
using MareSynchronos.WebAPI;
|
||||||
|
using MareSynchronos.WebAPI.Files.Models;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace MareSynchronos.Services;
|
||||||
|
|
||||||
|
public class PlayerPerformanceService : IHostedService
|
||||||
|
{
|
||||||
|
private readonly ILogger<PlayerPerformanceService> _logger;
|
||||||
|
private readonly MareMediator _mediator;
|
||||||
|
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
|
||||||
|
private readonly FileCacheManager _fileCacheManager;
|
||||||
|
private readonly PairManager _pairManager;
|
||||||
|
private readonly ApiController _apiController;
|
||||||
|
|
||||||
|
public PlayerPerformanceService(ILogger<PlayerPerformanceService> logger, MareMediator mediator,
|
||||||
|
PlayerPerformanceConfigService playerPerformanceConfigService, FileCacheManager fileCacheManager,
|
||||||
|
PairManager pairManager, ApiController apiController)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
_mediator = mediator;
|
||||||
|
_playerPerformanceConfigService = playerPerformanceConfigService;
|
||||||
|
_fileCacheManager = fileCacheManager;
|
||||||
|
_pairManager = pairManager;
|
||||||
|
_apiController = apiController;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryCalculateVRAMUsage(PairHandler pairHandler, CharacterData charaData, List<DownloadFileTransfer> toDownloadFiles, out long vramUsage)
|
||||||
|
{
|
||||||
|
var config = _playerPerformanceConfigService.Current;
|
||||||
|
var pair = _pairManager.GetOnlineUserPairs().First(p => string.Equals(p.UserData.UID, pairHandler.OnlineUser.User.UID, StringComparison.OrdinalIgnoreCase));
|
||||||
|
|
||||||
|
vramUsage = 0;
|
||||||
|
|
||||||
|
if (!charaData.FileReplacements.TryGetValue(API.Data.Enum.ObjectKind.Player, out List<FileReplacementData>? playerReplacements))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var moddedTextureHashes = playerReplacements.Where(p => string.IsNullOrEmpty(p.FileSwapPath) && p.GamePaths.Any(g => g.EndsWith("tex", StringComparison.OrdinalIgnoreCase)))
|
||||||
|
.Select(p => p.Hash)
|
||||||
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
foreach (var hash in moddedTextureHashes.ToList())
|
||||||
|
{
|
||||||
|
long fileSize = 0;
|
||||||
|
|
||||||
|
var download = toDownloadFiles.Find(f => string.Equals(hash, f.Hash, StringComparison.OrdinalIgnoreCase));
|
||||||
|
if (download != null)
|
||||||
|
{
|
||||||
|
fileSize = download.Total;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var fileEntry = _fileCacheManager.GetFileCacheByHash(hash);
|
||||||
|
if (fileEntry == null) continue;
|
||||||
|
|
||||||
|
if (fileEntry.Size == null)
|
||||||
|
{
|
||||||
|
fileEntry.Size = new FileInfo(fileEntry.ResolvedFilepath).Length;
|
||||||
|
_fileCacheManager.UpdateHashedFile(fileEntry, computeProperties: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
fileSize = fileEntry.Size.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
vramUsage += fileSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.LogDebug("Calculated VRAM usage for {p}", pairHandler);
|
||||||
|
|
||||||
|
// no warning of any kind on ignored pairs
|
||||||
|
if (config.UIDsToIgnore
|
||||||
|
.Exists(uid => string.Equals(uid, pair.UserData.Alias, StringComparison.Ordinal) || string.Equals(uid, pair.UserData.UID, StringComparison.Ordinal)))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
bool isPrefPerm = pair.UserPair.OwnPermissions.HasFlag(API.Data.Enum.UserPermissions.Sticky);
|
||||||
|
|
||||||
|
// now check auto pause
|
||||||
|
if (CheckForThreshold(config.AutoPausePlayersExceedingThresholds, config.VRAMSizeAutoPauseThresholdMiB * 1024 * 1024,
|
||||||
|
vramUsage, config.AutoPausePlayersWithPreferredPermissionsExceedingThresholds, isPrefPerm))
|
||||||
|
{
|
||||||
|
_mediator.Publish(new NotificationMessage($"{pair.PlayerName} ({pair.UserData.AliasOrUID}) automatically paused",
|
||||||
|
$"Player {pair.PlayerName} exceeded your configured VRAM auto pause threshold (" +
|
||||||
|
$"{UiSharedService.ByteToString(vramUsage, addSuffix: true)}/{config.VRAMSizeAutoPauseThresholdMiB}MiB)" +
|
||||||
|
$" and has been automatically paused.",
|
||||||
|
MareConfiguration.Models.NotificationType.Warning));
|
||||||
|
|
||||||
|
// pause
|
||||||
|
var perm = pair.UserPair.OwnPermissions.DeepClone();
|
||||||
|
perm.SetPaused(paused: true);
|
||||||
|
_ = _apiController.SetBulkPermissions(new(
|
||||||
|
new(StringComparer.Ordinal) { { pair.UserData.UID, perm } },
|
||||||
|
new(StringComparer.Ordinal)));
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and fucking warnings
|
||||||
|
if (CheckForThreshold(config.WarnOnExceedingThresholds, config.VRAMSizeWarningThresholdMiB * 1024 * 1024,
|
||||||
|
vramUsage, config.WarnOnPreferredPermissionsExceedingThresholds, isPrefPerm))
|
||||||
|
{
|
||||||
|
_mediator.Publish(new NotificationMessage($"{pair.PlayerName} ({pair.UserData.AliasOrUID}) exceeds performance threshold",
|
||||||
|
$"Player {pair.PlayerName} exceeds your configured VRAM warning threshold (" +
|
||||||
|
$"{UiSharedService.ByteToString(vramUsage, true)}/{config.VRAMSizeWarningThresholdMiB}MiB).",
|
||||||
|
MareConfiguration.Models.NotificationType.Warning));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CheckForThreshold(bool thresholdEnabled, long threshold, long value, bool checkForPrefPerm, bool isPrefPerm) =>
|
||||||
|
thresholdEnabled && threshold > 0 && threshold < value && ((checkForPrefPerm && isPrefPerm) || !isPrefPerm);
|
||||||
|
}
|
||||||
@@ -169,7 +169,7 @@ public class ServerConfigurationManager
|
|||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddCurrentCharacterToServer(int serverSelectionIndex = -1, bool addLastSecretKey = false)
|
internal void AddCurrentCharacterToServer(int serverSelectionIndex = -1)
|
||||||
{
|
{
|
||||||
if (serverSelectionIndex == -1) serverSelectionIndex = CurrentServerIndex;
|
if (serverSelectionIndex == -1) serverSelectionIndex = CurrentServerIndex;
|
||||||
var server = GetServerByIndex(serverSelectionIndex);
|
var server = GetServerByIndex(serverSelectionIndex);
|
||||||
@@ -181,7 +181,7 @@ public class ServerConfigurationManager
|
|||||||
{
|
{
|
||||||
CharacterName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(),
|
CharacterName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(),
|
||||||
WorldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult(),
|
WorldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult(),
|
||||||
SecretKeyIdx = addLastSecretKey ? server.SecretKeys.Last().Key : -1,
|
SecretKeyIdx = server.SecretKeys.Last().Key,
|
||||||
});
|
});
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
@@ -189,7 +189,10 @@ public class ServerConfigurationManager
|
|||||||
internal void AddEmptyCharacterToServer(int serverSelectionIndex)
|
internal void AddEmptyCharacterToServer(int serverSelectionIndex)
|
||||||
{
|
{
|
||||||
var server = GetServerByIndex(serverSelectionIndex);
|
var server = GetServerByIndex(serverSelectionIndex);
|
||||||
server.Authentications.Add(new Authentication());
|
server.Authentications.Add(new Authentication()
|
||||||
|
{
|
||||||
|
SecretKeyIdx = server.SecretKeys.Any() ? server.SecretKeys.First().Key : -1,
|
||||||
|
});
|
||||||
Save();
|
Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ public sealed class XivDataAnalyzer
|
|||||||
|
|
||||||
public Task<long> GetTrianglesByHash(string hash)
|
public Task<long> GetTrianglesByHash(string hash)
|
||||||
{
|
{
|
||||||
if (_configService.Current.TriangleDictionary.TryGetValue(hash, out var cachedTris))
|
if (_configService.Current.TriangleDictionary.TryGetValue(hash, out var cachedTris) && cachedTris > 0)
|
||||||
return Task.FromResult(cachedTris);
|
return Task.FromResult(cachedTris);
|
||||||
|
|
||||||
var path = _fileCacheManager.GetFileCacheByHash(hash);
|
var path = _fileCacheManager.GetFileCacheByHash(hash);
|
||||||
@@ -192,13 +192,29 @@ public sealed class XivDataAnalyzer
|
|||||||
var file = _luminaGameData.GetFileFromDisk<MdlFile>(filePath);
|
var file = _luminaGameData.GetFileFromDisk<MdlFile>(filePath);
|
||||||
if (file.FileHeader.LodCount <= 0)
|
if (file.FileHeader.LodCount <= 0)
|
||||||
return Task.FromResult((long)0);
|
return Task.FromResult((long)0);
|
||||||
var meshIdx = file.Lods[0].MeshIndex;
|
long tris = 0;
|
||||||
var meshCnt = file.Lods[0].MeshCount;
|
for (int i = 0; i < file.FileHeader.LodCount; i++)
|
||||||
var tris = file.Meshes.Skip(meshIdx).Take(meshCnt).Sum(p => p.IndexCount) / 3;
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var meshIdx = file.Lods[i].MeshIndex;
|
||||||
|
var meshCnt = file.Lods[i].MeshCount;
|
||||||
|
tris = file.Meshes.Skip(meshIdx).Take(meshCnt).Sum(p => p.IndexCount) / 3;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogDebug(ex, "Could not load lod mesh {mesh} from {path}", i, filePath);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tris > 0)
|
||||||
|
{
|
||||||
_logger.LogDebug("{filePath} => {tris} triangles", filePath, tris);
|
_logger.LogDebug("{filePath} => {tris} triangles", filePath, tris);
|
||||||
_configService.Current.TriangleDictionary[hash] = tris;
|
_configService.Current.TriangleDictionary[hash] = tris;
|
||||||
_configService.Save();
|
_configService.Save();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
return Task.FromResult(tris);
|
return Task.FromResult(tris);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -228,11 +228,15 @@ public class DrawUserPair
|
|||||||
userPairText += UiSharedService.TooltipSeparator + "You are directly Paired";
|
userPairText += UiSharedService.TooltipSeparator + "You are directly Paired";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_pair.LastAppliedDataSize >= 0)
|
if (_pair.LastAppliedDataBytes >= 0)
|
||||||
{
|
{
|
||||||
userPairText += UiSharedService.TooltipSeparator;
|
userPairText += UiSharedService.TooltipSeparator;
|
||||||
userPairText += ((!_pair.IsPaired) ? "(Last) " : string.Empty) + "Mods Info" + Environment.NewLine;
|
userPairText += ((!_pair.IsPaired) ? "(Last) " : string.Empty) + "Mods Info" + Environment.NewLine;
|
||||||
userPairText += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataSize, true);
|
userPairText += "Files Size: " + UiSharedService.ByteToString(_pair.LastAppliedDataBytes, true);
|
||||||
|
if (_pair.LastAppliedApproximateVRAMBytes >= 0)
|
||||||
|
{
|
||||||
|
userPairText += Environment.NewLine + "Approximate max. VRAM Usage: " + UiSharedService.ByteToString(_pair.LastAppliedApproximateVRAMBytes, true);
|
||||||
|
}
|
||||||
if (_pair.LastAppliedDataTris >= 0)
|
if (_pair.LastAppliedDataTris >= 0)
|
||||||
{
|
{
|
||||||
userPairText += Environment.NewLine + "Triangle Count (excl. Vanilla): "
|
userPairText += Environment.NewLine + "Triangle Count (excl. Vanilla): "
|
||||||
|
|||||||
@@ -244,7 +244,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
|
|||||||
FriendlyName = $"Secret Key added on Setup ({DateTime.Now:yyyy-MM-dd})",
|
FriendlyName = $"Secret Key added on Setup ({DateTime.Now:yyyy-MM-dd})",
|
||||||
Key = _secretKey,
|
Key = _secretKey,
|
||||||
});
|
});
|
||||||
_serverConfigurationManager.AddCurrentCharacterToServer(addLastSecretKey: true);
|
_serverConfigurationManager.AddCurrentCharacterToServer();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
private readonly PairManager _pairManager;
|
private readonly PairManager _pairManager;
|
||||||
private readonly PerformanceCollectorService _performanceCollector;
|
private readonly PerformanceCollectorService _performanceCollector;
|
||||||
private readonly ServerConfigurationManager _serverConfigurationManager;
|
private readonly ServerConfigurationManager _serverConfigurationManager;
|
||||||
|
private readonly PlayerPerformanceConfigService _playerPerformanceConfigService;
|
||||||
private readonly UiSharedService _uiShared;
|
private readonly UiSharedService _uiShared;
|
||||||
private bool _deleteAccountPopupModalShown = false;
|
private bool _deleteAccountPopupModalShown = false;
|
||||||
private bool _deleteFilesPopupModalShown = false;
|
private bool _deleteFilesPopupModalShown = false;
|
||||||
@@ -64,6 +65,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
UiSharedService uiShared, MareConfigService configService,
|
UiSharedService uiShared, MareConfigService configService,
|
||||||
MareCharaFileManager mareCharaFileManager, PairManager pairManager,
|
MareCharaFileManager mareCharaFileManager, PairManager pairManager,
|
||||||
ServerConfigurationManager serverConfigurationManager,
|
ServerConfigurationManager serverConfigurationManager,
|
||||||
|
PlayerPerformanceConfigService playerPerformanceConfigService,
|
||||||
MareMediator mediator, PerformanceCollectorService performanceCollector,
|
MareMediator mediator, PerformanceCollectorService performanceCollector,
|
||||||
FileUploadManager fileTransferManager,
|
FileUploadManager fileTransferManager,
|
||||||
FileTransferOrchestrator fileTransferOrchestrator,
|
FileTransferOrchestrator fileTransferOrchestrator,
|
||||||
@@ -76,6 +78,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
_mareCharaFileManager = mareCharaFileManager;
|
_mareCharaFileManager = mareCharaFileManager;
|
||||||
_pairManager = pairManager;
|
_pairManager = pairManager;
|
||||||
_serverConfigurationManager = serverConfigurationManager;
|
_serverConfigurationManager = serverConfigurationManager;
|
||||||
|
_playerPerformanceConfigService = playerPerformanceConfigService;
|
||||||
_performanceCollector = performanceCollector;
|
_performanceCollector = performanceCollector;
|
||||||
_fileTransferManager = fileTransferManager;
|
_fileTransferManager = fileTransferManager;
|
||||||
_fileTransferOrchestrator = fileTransferOrchestrator;
|
_fileTransferOrchestrator = fileTransferOrchestrator;
|
||||||
@@ -118,6 +121,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
public override void OnClose()
|
public override void OnClose()
|
||||||
{
|
{
|
||||||
_uiShared.EditTrackerPosition = false;
|
_uiShared.EditTrackerPosition = false;
|
||||||
|
_uidToAddForIgnore = string.Empty;
|
||||||
|
|
||||||
base.OnClose();
|
base.OnClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1316,6 +1321,156 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void DrawPerformance()
|
||||||
|
{
|
||||||
|
_uiShared.BigText("Performance Settings");
|
||||||
|
UiSharedService.TextWrapped("The configuration options here are to give you more informed warnings and automation when it comes to other performance-intensive synced players.");
|
||||||
|
ImGui.Dummy(new Vector2(10));
|
||||||
|
ImGui.Separator();
|
||||||
|
ImGui.Dummy(new Vector2(10));
|
||||||
|
bool showPerformanceIndicator = _playerPerformanceConfigService.Current.ShowPerformanceIndicator;
|
||||||
|
if (ImGui.Checkbox("Show performance indicator", ref showPerformanceIndicator))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.ShowPerformanceIndicator = showPerformanceIndicator;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Will show a performance indicator when players exceed defined thresholds in the main UI." + Environment.NewLine + "Will use warning thresholds.");
|
||||||
|
bool warnOnExceedingThresholds = _playerPerformanceConfigService.Current.WarnOnExceedingThresholds;
|
||||||
|
if (ImGui.Checkbox("Warn on loading in players exceeding performance thresholds", ref warnOnExceedingThresholds))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.WarnOnExceedingThresholds = warnOnExceedingThresholds;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Mare will print a warning in chat once per session of meeting those people. Will not warn on players with preferred permissions.");
|
||||||
|
using (ImRaii.Disabled(!warnOnExceedingThresholds))
|
||||||
|
{
|
||||||
|
using var indent = ImRaii.PushIndent();
|
||||||
|
var warnOnPref = _playerPerformanceConfigService.Current.WarnOnPreferredPermissionsExceedingThresholds;
|
||||||
|
if (ImGui.Checkbox("Warn also on players with preferred permissions", ref warnOnPref))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.WarnOnPreferredPermissionsExceedingThresholds = warnOnPref;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Mare will also print warnings for players where you enabled preferred permissions.");
|
||||||
|
}
|
||||||
|
using (ImRaii.Disabled(!showPerformanceIndicator && !warnOnExceedingThresholds))
|
||||||
|
{
|
||||||
|
var vram = _playerPerformanceConfigService.Current.VRAMSizeWarningThresholdMiB;
|
||||||
|
var tris = _playerPerformanceConfigService.Current.TrisWarningThresholdThousands;
|
||||||
|
ImGui.SetNextItemWidth(100);
|
||||||
|
if (ImGui.InputInt("Warning VRAM threshold", ref vram))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.VRAMSizeWarningThresholdMiB = vram;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.Text("(MiB)");
|
||||||
|
_uiShared.DrawHelpText("Limit in MiB of approximate VRAM usage to trigger warning or performance indicator on UI." + UiSharedService.TooltipSeparator
|
||||||
|
+ "Default: 375 MiB");
|
||||||
|
ImGui.SetNextItemWidth(100);
|
||||||
|
if (ImGui.InputInt("Warning Triangle threshold", ref tris))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.TrisWarningThresholdThousands = tris;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.Text("(thousand triangles)");
|
||||||
|
_uiShared.DrawHelpText("Limit in approximate used triangles from mods to trigger warning or performance indicator on UI." + UiSharedService.TooltipSeparator
|
||||||
|
+ "Default: 165 thousand");
|
||||||
|
}
|
||||||
|
ImGui.Dummy(new Vector2(10));
|
||||||
|
bool autoPause = _playerPerformanceConfigService.Current.AutoPausePlayersExceedingThresholds;
|
||||||
|
bool autoPauseEveryone = _playerPerformanceConfigService.Current.AutoPausePlayersWithPreferredPermissionsExceedingThresholds;
|
||||||
|
if (ImGui.Checkbox("Automatically pause players exceeding thresholds", ref autoPause))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.AutoPausePlayersExceedingThresholds = autoPause;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("When enabled, it will automatically pause all players without preferred permissions that exceed the thresholds defined below." + Environment.NewLine
|
||||||
|
+ "Will print a warning in chat when a player got paused automatically."
|
||||||
|
+ UiSharedService.TooltipSeparator + "Warning: this will not automatically unpause those people again, you will have to do this manually.");
|
||||||
|
using (ImRaii.Disabled(!autoPause))
|
||||||
|
{
|
||||||
|
using var indent = ImRaii.PushIndent();
|
||||||
|
if (ImGui.Checkbox("Automatically pause also players with preferred permissions", ref autoPauseEveryone))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.AutoPausePlayersWithPreferredPermissionsExceedingThresholds = autoPauseEveryone;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("When enabled, will automatically pause all players regardless of preferred permissions that exceed thresholds defined below." + UiSharedService.TooltipSeparator +
|
||||||
|
"Warning: this will not automatically unpause those people again, you will have to do this manually." + UiSharedService.TooltipSeparator
|
||||||
|
+ "Default: 550 MiB");
|
||||||
|
var vramAuto = _playerPerformanceConfigService.Current.VRAMSizeAutoPauseThresholdMiB;
|
||||||
|
var trisAuto = _playerPerformanceConfigService.Current.TrisAutoPauseThresholdThousands;
|
||||||
|
ImGui.SetNextItemWidth(100);
|
||||||
|
if (ImGui.InputInt("Auto Pause VRAM threshold", ref vramAuto))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.VRAMSizeAutoPauseThresholdMiB = vramAuto;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.Text("(MiB)");
|
||||||
|
_uiShared.DrawHelpText("When a loading in player and their VRAM usage exceeds this amount, automatically pauses the synced player.");
|
||||||
|
ImGui.SetNextItemWidth(100);
|
||||||
|
if (ImGui.InputInt("Auto Pause Triangle threshold", ref trisAuto))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.TrisAutoPauseThresholdThousands = trisAuto;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
ImGui.SameLine();
|
||||||
|
ImGui.Text("(thousand triangles)");
|
||||||
|
_uiShared.DrawHelpText("When a loading in player and their triangle count exceeds this amount, automatically pauses the synced player." + UiSharedService.TooltipSeparator
|
||||||
|
+ "Default: 250 thousand");
|
||||||
|
}
|
||||||
|
ImGui.Dummy(new Vector2(10));
|
||||||
|
_uiShared.BigText("Whitelisted UIDs");
|
||||||
|
UiSharedService.TextWrapped("The entries in the list below will be ignored for all warnings and auto pause operations.");
|
||||||
|
ImGui.Dummy(new Vector2(10));
|
||||||
|
ImGui.SetNextItemWidth(200);
|
||||||
|
ImGui.InputText("##ignoreuid", ref _uidToAddForIgnore, 20);
|
||||||
|
ImGui.SameLine();
|
||||||
|
using (ImRaii.Disabled(string.IsNullOrEmpty(_uidToAddForIgnore)))
|
||||||
|
{
|
||||||
|
if (_uiShared.IconTextButton(FontAwesomeIcon.Plus, "Add UID to whitelist"))
|
||||||
|
{
|
||||||
|
if (!_playerPerformanceConfigService.Current.UIDsToIgnore.Contains(_uidToAddForIgnore, StringComparer.Ordinal))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.UIDsToIgnore.Add(_uidToAddForIgnore);
|
||||||
|
}
|
||||||
|
_uidToAddForIgnore = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_uiShared.DrawHelpText("Hint: UIDs are case sensitive.");
|
||||||
|
var playerList = _playerPerformanceConfigService.Current.UIDsToIgnore;
|
||||||
|
ImGui.SetNextItemWidth(200);
|
||||||
|
using (var lb = ImRaii.ListBox("UID whitelist"))
|
||||||
|
{
|
||||||
|
if (lb)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < playerList.Count; i++)
|
||||||
|
{
|
||||||
|
bool shouldBeSelected = _selectedEntry == i;
|
||||||
|
if (ImGui.Selectable(playerList[i] + "##" + i, shouldBeSelected))
|
||||||
|
{
|
||||||
|
_selectedEntry = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using (ImRaii.Disabled(_selectedEntry == -1))
|
||||||
|
{
|
||||||
|
if (_uiShared.IconTextButton(FontAwesomeIcon.Trash, "Delete selected UID"))
|
||||||
|
{
|
||||||
|
_playerPerformanceConfigService.Current.UIDsToIgnore.RemoveAt(_selectedEntry);
|
||||||
|
_selectedEntry = -1;
|
||||||
|
_playerPerformanceConfigService.Save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private string _uidToAddForIgnore = string.Empty;
|
||||||
|
private int _selectedEntry = -1;
|
||||||
|
|
||||||
private void DrawSettingsContent()
|
private void DrawSettingsContent()
|
||||||
{
|
{
|
||||||
if (_apiController.ServerState is ServerState.Connected)
|
if (_apiController.ServerState is ServerState.Connected)
|
||||||
@@ -1349,6 +1504,12 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
|||||||
ImGui.EndTabItem();
|
ImGui.EndTabItem();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ImGui.BeginTabItem("Performance"))
|
||||||
|
{
|
||||||
|
DrawPerformance();
|
||||||
|
ImGui.EndTabItem();
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui.BeginTabItem("Export & Storage"))
|
if (ImGui.BeginTabItem("Export & Storage"))
|
||||||
{
|
{
|
||||||
DrawFileStorageSettings();
|
DrawFileStorageSettings();
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task DownloadFilesInternal(GameObjectHandler gameObjectHandler, List<FileReplacementData> fileReplacement, CancellationToken ct)
|
public async Task<List<DownloadFileTransfer>> InitiateDownloadList(GameObjectHandler gameObjectHandler, List<FileReplacementData> fileReplacement, CancellationToken ct)
|
||||||
{
|
{
|
||||||
Logger.LogDebug("Download start: {id}", gameObjectHandler.Name);
|
Logger.LogDebug("Download start: {id}", gameObjectHandler.Name);
|
||||||
|
|
||||||
@@ -221,9 +221,6 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
|||||||
|
|
||||||
Logger.LogDebug("Files with size 0 or less: {files}", string.Join(", ", downloadFileInfoFromService.Where(f => f.Size <= 0).Select(f => f.Hash)));
|
Logger.LogDebug("Files with size 0 or less: {files}", string.Join(", ", downloadFileInfoFromService.Where(f => f.Size <= 0).Select(f => f.Hash)));
|
||||||
|
|
||||||
CurrentDownloads = downloadFileInfoFromService.Distinct().Select(d => new DownloadFileTransfer(d))
|
|
||||||
.Where(d => d.CanBeTransferred).ToList();
|
|
||||||
|
|
||||||
foreach (var dto in downloadFileInfoFromService.Where(c => c.IsForbidden))
|
foreach (var dto in downloadFileInfoFromService.Where(c => c.IsForbidden))
|
||||||
{
|
{
|
||||||
if (!_orchestrator.ForbiddenTransfers.Exists(f => string.Equals(f.Hash, dto.Hash, StringComparison.Ordinal)))
|
if (!_orchestrator.ForbiddenTransfers.Exists(f => string.Equals(f.Hash, dto.Hash, StringComparison.Ordinal)))
|
||||||
@@ -232,7 +229,13 @@ public partial class FileDownloadManager : DisposableMediatorSubscriberBase
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var downloadGroups = CurrentDownloads.Where(f => f.CanBeTransferred).GroupBy(f => f.DownloadUri.Host + ":" + f.DownloadUri.Port, StringComparer.Ordinal);
|
return CurrentDownloads = downloadFileInfoFromService.Distinct().Select(d => new DownloadFileTransfer(d))
|
||||||
|
.Where(d => d.CanBeTransferred).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task DownloadFilesInternal(GameObjectHandler gameObjectHandler, List<FileReplacementData> fileReplacement, CancellationToken ct)
|
||||||
|
{
|
||||||
|
var downloadGroups = CurrentDownloads.GroupBy(f => f.DownloadUri.Host + ":" + f.DownloadUri.Port, StringComparer.Ordinal);
|
||||||
|
|
||||||
foreach (var downloadGroup in downloadGroups)
|
foreach (var downloadGroup in downloadGroups)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user