Fixed many warnings, moved some classes to their own files.

This commit is contained in:
cake
2025-11-15 04:46:07 +01:00
parent e4a28c70eb
commit b56813c1de
20 changed files with 622 additions and 614 deletions

View File

@@ -279,7 +279,7 @@ public sealed class Plugin : IDalamudPlugin
s.GetRequiredService<LightlessMediator>()));
collection.AddScoped((s) => new NameplateService(s.GetRequiredService<ILogger<NameplateService>>(), s.GetRequiredService<LightlessConfigService>(), namePlateGui, clientState,
s.GetRequiredService<PairManager>(), s.GetRequiredService<LightlessMediator>()));
collection.AddScoped((s) => new NameplateHandler(s.GetRequiredService<ILogger<NameplateHandler>>(), addonLifecycle, gameGui, s.GetRequiredService<DalamudUtilService>(),
collection.AddScoped((s) => new NameplateHandler(s.GetRequiredService<ILogger<NameplateHandler>>(), addonLifecycle, gameGui,
s.GetRequiredService<LightlessConfigService>(), s.GetRequiredService<LightlessMediator>(), clientState, s.GetRequiredService<PairManager>()));
collection.AddHostedService(p => p.GetRequiredService<ConfigurationSaveService>());

View File

@@ -11,7 +11,6 @@ using LightlessSync.WebAPI;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Threading;
namespace LightlessSync.Services;
public class BroadcastService : IHostedService, IMediatorSubscriber
@@ -58,7 +57,7 @@ public class BroadcastService : IHostedService, IMediatorSubscriber
{
if (!_apiController.IsConnected)
{
_logger.LogDebug(context + " skipped, not connected");
_logger.LogDebug("{context} skipped, not connected", context);
return;
}
await action().ConfigureAwait(false);
@@ -372,7 +371,7 @@ public class BroadcastService : IHostedService, IMediatorSubscriber
public async Task<Dictionary<string, BroadcastStatusInfoDto?>> AreUsersBroadcastingAsync(List<string> hashedCids)
{
Dictionary<string, BroadcastStatusInfoDto?> result = new();
Dictionary<string, BroadcastStatusInfoDto?> result = new(StringComparer.Ordinal);
await RequireConnectionAsync(nameof(AreUsersBroadcastingAsync), async () =>
{

View File

@@ -0,0 +1,19 @@
using LightlessSync.API.Data.Enum;
using LightlessSync.Services.CharaData.Models;
using System.Collections.Immutable;
namespace LightlessSync.Services.CharaData;
public sealed class CharacterAnalysisSummary
{
public static CharacterAnalysisSummary Empty { get; } =
new(ImmutableDictionary<ObjectKind, CharacterAnalysisObjectSummary>.Empty);
internal CharacterAnalysisSummary(IImmutableDictionary<ObjectKind, CharacterAnalysisObjectSummary> objects)
{
Objects = objects;
}
public IImmutableDictionary<ObjectKind, CharacterAnalysisObjectSummary> Objects { get; }
public bool HasData => Objects.Any(kvp => kvp.Value.HasEntries);
}

View File

@@ -0,0 +1,8 @@
using System.Runtime.InteropServices;
namespace LightlessSync.Services.CharaData.Models;
[StructLayout(LayoutKind.Auto)]
public readonly record struct CharacterAnalysisObjectSummary(int EntryCount, long TotalTriangles, long TexOriginalBytes, long TexCompressedBytes)
{
public bool HasEntries => EntryCount > 0;
}

View File

@@ -1,16 +1,14 @@
using LightlessSync.API.Data;
using LightlessSync.API.Data.Enum;
using LightlessSync.FileCache;
using LightlessSync.Services.CharaData;
using LightlessSync.Services.CharaData.Models;
using LightlessSync.Services.Mediator;
using LightlessSync.UI;
using LightlessSync.Utils;
using Lumina.Data.Files;
using Microsoft.Extensions.Logging;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace LightlessSync.Services;
public sealed class CharacterAnalyzer : MediatorSubscriberBase, IDisposable
@@ -99,6 +97,7 @@ public sealed class CharacterAnalyzer : MediatorSubscriberBase, IDisposable
public void Dispose()
{
_analysisCts.CancelDispose();
_baseAnalysisCts.Dispose();
}
private async Task BaseAnalysis(CharacterData charaData, CancellationToken token)
@@ -135,7 +134,7 @@ public sealed class CharacterAnalyzer : MediatorSubscriberBase, IDisposable
{
data[fileEntry.Hash] = new FileDataEntry(fileEntry.Hash, ext,
[.. fileEntry.GamePaths],
fileCacheEntries.Select(c => c.ResolvedFilepath).Distinct().ToList(),
[.. fileCacheEntries.Select(c => c.ResolvedFilepath).Distinct(StringComparer.Ordinal)],
entry.Size > 0 ? entry.Size.Value : 0,
entry.CompressedSize > 0 ? entry.CompressedSize.Value : 0,
tris);
@@ -269,23 +268,3 @@ public sealed class CharacterAnalyzer : MediatorSubscriberBase, IDisposable
});
}
}
public readonly record struct CharacterAnalysisObjectSummary(int EntryCount, long TotalTriangles, long TexOriginalBytes, long TexCompressedBytes)
{
public bool HasEntries => EntryCount > 0;
}
public sealed class CharacterAnalysisSummary
{
public static CharacterAnalysisSummary Empty { get; } =
new(ImmutableDictionary<ObjectKind, CharacterAnalysisObjectSummary>.Empty);
internal CharacterAnalysisSummary(IImmutableDictionary<ObjectKind, CharacterAnalysisObjectSummary> objects)
{
Objects = objects;
}
public IImmutableDictionary<ObjectKind, CharacterAnalysisObjectSummary> Objects { get; }
public bool HasData => Objects.Any(kvp => kvp.Value.HasEntries);
}

View File

@@ -95,7 +95,7 @@ internal class ContextMenuService : IHostedService
//Check if it is a real target.
IPlayerCharacter? targetData = GetPlayerFromObjectTable(target);
if (targetData == null || targetData.Address == nint.Zero)
if (targetData == null || targetData.Address == nint.Zero || _clientState.LocalPlayer == null)
return;
//Check if user is directly paired or is own.
@@ -120,7 +120,7 @@ internal class ContextMenuService : IHostedService
PrefixChar = 'L',
UseDefaultPrefix = false,
PrefixColor = 708,
OnClicked = async _ => await HandleSelection(args).ConfigureAwait(false)
OnClicked = _ => HandleSelection(args).ConfigureAwait(false).GetAwaiter().GetResult()
});
}
@@ -200,8 +200,6 @@ internal class ContextMenuService : IHostedService
private static bool IsChineseJapaneseKoreanCharacter(char c) => c >= 0x4E00 && c <= 0x9FFF;
public bool IsWorldValid(uint worldId) => IsWorldValid(GetWorld(worldId));
public static bool IsWorldValid(World world)
{
var name = world.Name.ToString();

View File

@@ -140,14 +140,14 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
public bool IsWine { get; init; }
public unsafe GameObject* GposeTarget
public static unsafe GameObject* GposeTarget
{
get => TargetSystem.Instance()->GPoseTarget;
set => TargetSystem.Instance()->GPoseTarget = value;
}
private unsafe bool HasGposeTarget => GposeTarget != null;
private unsafe int GPoseTargetIdx => !HasGposeTarget ? -1 : GposeTarget->ObjectIndex;
private static unsafe bool HasGposeTarget => GposeTarget != null;
private static unsafe int GPoseTargetIdx => !HasGposeTarget ? -1 : GposeTarget->ObjectIndex;
public async Task<IGameObject?> GetGposeTargetGameObjectAsync()
{
@@ -513,15 +513,11 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
{
logger.LogTrace("[{redrawId}] Waiting for {handler} to finish drawing", redrawId, handler);
curWaitTime += tick;
await Task.Delay(tick).ConfigureAwait(true);
await Task.Delay(tick, ct.Value).ConfigureAwait(true);
}
logger.LogTrace("[{redrawId}] Finished drawing after {curWaitTime}ms", redrawId, curWaitTime);
}
catch (NullReferenceException ex)
{
logger.LogWarning(ex, "Error accessing {handler}, object does not exist anymore?", handler);
}
catch (AccessViolationException ex)
{
logger.LogWarning(ex, "Error accessing {handler}, object does not exist anymore?", handler);

View File

@@ -2,6 +2,7 @@
using LightlessSync.API.Data.Comparer;
using LightlessSync.LightlessConfiguration;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.Profiles;
using LightlessSync.WebAPI;
using Microsoft.Extensions.Logging;
using Serilog.Core;

File diff suppressed because it is too large Load Diff

View File

@@ -47,7 +47,6 @@ public class NameplateService : DisposableMediatorSubscriberBase
.Select(u => (ulong)u.PlayerCharacterId)
.ToHashSet();
var now = DateTime.UtcNow;
var colors = _configService.Current.NameplateColors;
foreach (var handler in handlers)

View File

@@ -23,7 +23,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
private readonly INotificationManager _notificationManager;
private readonly IChatGui _chatGui;
private readonly PairRequestService _pairRequestService;
private readonly HashSet<string> _shownPairRequestNotifications = new();
private readonly HashSet<string> _shownPairRequestNotifications = [];
public NotificationService(
ILogger<NotificationService> logger,
@@ -59,7 +59,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
{
var notification = CreateNotification(title, message, type, duration, actions, soundEffectId);
if (_configService.Current.AutoDismissOnAction && notification.Actions.Any())
if (_configService.Current.AutoDismissOnAction && notification.Actions.Count != 0)
{
WrapActionsWithAutoDismiss(notification);
}
@@ -104,7 +104,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
}
}
private void DismissNotification(LightlessNotification notification)
private static void DismissNotification(LightlessNotification notification)
{
notification.IsDismissed = true;
notification.IsAnimatingOut = true;
@@ -208,10 +208,12 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
Mediator.Publish(new LightlessNotificationMessage(notification));
}
private string FormatDownloadCompleteMessage(string fileName, int fileCount) =>
fileCount > 1
private static string FormatDownloadCompleteMessage(string fileName, int fileCount)
{
return fileCount > 1
? $"Downloaded {fileCount} files successfully."
: $"Downloaded {fileName} successfully.";
}
private List<LightlessNotificationAction> CreateDownloadCompleteActions(Action? onOpenFolder)
{
@@ -257,8 +259,10 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
Mediator.Publish(new LightlessNotificationMessage(notification));
}
private string FormatErrorMessage(string message, Exception? exception) =>
exception != null ? $"{message}\n\nError: {exception.Message}" : message;
private static string FormatErrorMessage(string message, Exception? exception)
{
return exception != null ? $"{message}\n\nError: {exception.Message}" : message;
}
private List<LightlessNotificationAction> CreateErrorActions(Action? onRetry, Action? onViewLog)
{
@@ -332,8 +336,9 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
return string.Join("\n", activeDownloads.Select(x => $"• {x.PlayerName}: {FormatDownloadStatus(x)}"));
}
private string FormatDownloadStatus((string PlayerName, float Progress, string Status) download) =>
download.Status switch
private static string FormatDownloadStatus((string PlayerName, float Progress, string Status) download)
{
return download.Status switch
{
"downloading" => $"{download.Progress:P0}",
"decompressing" => "decompressing",
@@ -341,6 +346,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
"waiting" => "waiting for slot",
_ => download.Status
};
}
private TimeSpan GetDefaultDurationForType(NotificationType type) => type switch
{
@@ -478,13 +484,16 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
});
}
private Dalamud.Interface.ImGuiNotification.NotificationType
ConvertToDalamudNotificationType(NotificationType type) => type switch
private static Dalamud.Interface.ImGuiNotification.NotificationType
ConvertToDalamudNotificationType(NotificationType type)
{
NotificationType.Error => Dalamud.Interface.ImGuiNotification.NotificationType.Error,
NotificationType.Warning => Dalamud.Interface.ImGuiNotification.NotificationType.Warning,
_ => Dalamud.Interface.ImGuiNotification.NotificationType.Info
};
return type switch
{
NotificationType.Error => Dalamud.Interface.ImGuiNotification.NotificationType.Error,
NotificationType.Warning => Dalamud.Interface.ImGuiNotification.NotificationType.Warning,
_ => Dalamud.Interface.ImGuiNotification.NotificationType.Info
};
}
private void ShowChat(NotificationMessage msg)
{
@@ -568,7 +577,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
private void HandlePairRequestsUpdated(PairRequestsUpdatedMessage _)
{
var activeRequests = _pairRequestService.GetActiveRequests();
var activeRequestIds = activeRequests.Select(r => r.HashedCid).ToHashSet();
var activeRequestIds = activeRequests.Select(r => r.HashedCid).ToHashSet(StringComparer.Ordinal);
// Dismiss notifications for requests that are no longer active (expired)
var notificationsToRemove = _shownPairRequestNotifications
@@ -585,7 +594,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
private void HandlePairDownloadStatus(PairDownloadStatusMessage msg)
{
var userDownloads = msg.DownloadStatus.Where(x => x.PlayerName != "Pair Queue").ToList();
var userDownloads = msg.DownloadStatus.Where(x => !string.Equals(x.PlayerName, "Pair Queue", StringComparison.Ordinal)).ToList();
var totalProgress = userDownloads.Count > 0 ? userDownloads.Average(x => x.Progress) : 0f;
var message = BuildPairDownloadMessage(userDownloads, msg.QueueWaiting);
@@ -734,7 +743,7 @@ public class NotificationService : DisposableMediatorSubscriberBase, IHostedServ
return actions;
}
private string GetUserDisplayName(UserData userData, string playerName)
private static string GetUserDisplayName(UserData userData, string playerName)
{
if (!string.IsNullOrEmpty(userData.Alias) && !string.Equals(userData.Alias, userData.UID, StringComparison.Ordinal))
{

View File

@@ -0,0 +1,9 @@
using System.Runtime.InteropServices;
namespace LightlessSync.Services.PairProcessing;
[StructLayout(LayoutKind.Auto)]
public readonly record struct PairProcessingLimiterSnapshot(bool IsEnabled, int Limit, int InFlight, int Waiting)
{
public int Remaining => Math.Max(0, Limit - InFlight);
}

View File

@@ -1,15 +1,13 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using LightlessSync.LightlessConfiguration;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.PairProcessing;
using Microsoft.Extensions.Logging;
namespace LightlessSync.Services;
public sealed class PairProcessingLimiter : DisposableMediatorSubscriberBase
{
private const int HardLimit = 32;
private const int _hardLimit = 32;
private readonly LightlessConfigService _configService;
private readonly object _limitLock = new();
private readonly SemaphoreSlim _semaphore;
@@ -24,8 +22,8 @@ public sealed class PairProcessingLimiter : DisposableMediatorSubscriberBase
{
_configService = configService;
_currentLimit = CalculateLimit();
var initialCount = _configService.Current.EnablePairProcessingLimiter ? _currentLimit : HardLimit;
_semaphore = new SemaphoreSlim(initialCount, HardLimit);
var initialCount = _configService.Current.EnablePairProcessingLimiter ? _currentLimit : _hardLimit;
_semaphore = new SemaphoreSlim(initialCount, _hardLimit);
Mediator.Subscribe<PairProcessingLimitChangedMessage>(this, _ => UpdateSemaphoreLimit());
}
@@ -88,7 +86,7 @@ public sealed class PairProcessingLimiter : DisposableMediatorSubscriberBase
if (!enabled)
{
var releaseAmount = HardLimit - _semaphore.CurrentCount;
var releaseAmount = _hardLimit - _semaphore.CurrentCount;
if (releaseAmount > 0)
{
TryReleaseSemaphore(releaseAmount);
@@ -110,7 +108,7 @@ public sealed class PairProcessingLimiter : DisposableMediatorSubscriberBase
var increment = desiredLimit - _currentLimit;
_pendingIncrements += increment;
var available = HardLimit - _semaphore.CurrentCount;
var available = _hardLimit - _semaphore.CurrentCount;
var toRelease = Math.Min(_pendingIncrements, available);
if (toRelease > 0 && TryReleaseSemaphore(toRelease))
{
@@ -148,7 +146,7 @@ public sealed class PairProcessingLimiter : DisposableMediatorSubscriberBase
private int CalculateLimit()
{
var configured = _configService.Current.MaxConcurrentPairApplications;
return Math.Clamp(configured, 1, HardLimit);
return Math.Clamp(configured, 1, _hardLimit);
}
private bool TryReleaseSemaphore(int count = 1)
@@ -248,8 +246,3 @@ public sealed class PairProcessingLimiter : DisposableMediatorSubscriberBase
}
}
}
public readonly record struct PairProcessingLimiterSnapshot(bool IsEnabled, int Limit, int InFlight, int Waiting)
{
public int Remaining => Math.Max(0, Limit - InFlight);
}

View File

@@ -1,4 +1,4 @@
namespace LightlessSync.Services;
namespace LightlessSync.Services.Profiles;
public record LightlessGroupProfileData(string Base64ProfilePicture, string Description, int[] Tags, bool IsNsfw, bool IsDisabled)
{

View File

@@ -1,4 +1,4 @@
namespace LightlessSync.Services;
namespace LightlessSync.Services.Profiles;
public record LightlessUserProfileData(bool IsFlagged, bool IsNSFW, string Base64ProfilePicture, string Base64SupporterPicture, string Description)
{

View File

@@ -5,6 +5,7 @@ using LightlessSync.LightlessConfiguration.Models;
using LightlessSync.PlayerData.Handlers;
using LightlessSync.Services;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.PairProcessing;
using LightlessSync.WebAPI.Files;
using LightlessSync.WebAPI.Files.Models;
using Microsoft.Extensions.Logging;

View File

@@ -35,7 +35,6 @@ public class EditProfileUi : WindowMediatorSubscriberBase
private bool _wasOpen;
private Vector4 _currentBg = new(0.15f, 0.15f, 0.15f, 1f);
private bool vanityInitialized; // useless for now
private bool textEnabled;
private bool glowEnabled;
private Vector4 textColor;
@@ -86,7 +85,6 @@ public class EditProfileUi : WindowMediatorSubscriberBase
glowColor = glowEnabled ? UIColors.HexToRgba(_apiController.TextGlowColorHex!) : Vector4.Zero;
_savedVanity = new VanityState(textEnabled, glowEnabled, textColor, glowColor);
vanityInitialized = true;
}
protected override void DrawInternal()

View File

@@ -267,7 +267,7 @@ public partial class IntroUi : WindowMediatorSubscriberBase
{
UiSharedService.ColorTextWrapped("Your secret key must be exactly 64 characters long. Don't enter your Lodestone auth here.", ImGuiColors.DalamudRed);
}
else if (_secretKey.Length == 64 && !HexRegex().IsMatch(_secretKey))
else if (_secretKey.Length == 64 && !SecretRegex().IsMatch(_secretKey))
{
UiSharedService.ColorTextWrapped("Your secret key can only contain ABCDEF and the numbers 0-9.", ImGuiColors.DalamudRed);
}
@@ -360,6 +360,6 @@ public partial class IntroUi : WindowMediatorSubscriberBase
_tosParagraphs = [Strings.ToS.Paragraph1, Strings.ToS.Paragraph2, Strings.ToS.Paragraph3, Strings.ToS.Paragraph4, Strings.ToS.Paragraph5, Strings.ToS.Paragraph6];
}
[GeneratedRegex("^([A-F0-9]{2})+")]
private static partial Regex HexRegex();
[GeneratedRegex("^[A-F0-9]{64}$", RegexOptions.Compiled | RegexOptions.CultureInvariant)]
private static partial Regex SecretRegex();
}

View File

@@ -13,13 +13,13 @@ using LightlessSync.API.Dto.User;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.Profiles;
using LightlessSync.UI.Handlers;
using LightlessSync.WebAPI;
using Microsoft.Extensions.Logging;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using System.Globalization;
using System.Linq;
using System.Numerics;
namespace LightlessSync.UI;