Merge pull request 'Fixed amount of lightfinder users, added user names in the server info list for lightfinder. Added /lightless command' (#75) from lightfinder-dtr-changes into 1.12.4

Reviewed-on: #75
Reviewed-by: defnotken <defnotken@noreply.git.lightless-sync.org>
Reviewed-by: choco <choco@noreply.git.lightless-sync.org>
This commit was merged in pull request #75.
This commit is contained in:
2025-11-06 18:13:33 +01:00
4 changed files with 69 additions and 33 deletions

View File

@@ -28,7 +28,7 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
private readonly CancellationTokenSource _cleanupCts = new();
private Task? _cleanupTask;
private int _checkEveryFrames = 20;
private readonly int _checkEveryFrames = 20;
private int _frameCounter = 0;
private int _lookupsThisFrame = 0;
private const int MaxLookupsPerFrame = 30;
@@ -221,6 +221,16 @@ public class BroadcastScannerService : DisposableMediatorSubscriberBase, IDispos
(excludeHashedCid is null || !comparer.Equals(entry.Key, excludeHashedCid)));
}
public List<KeyValuePair<string, BroadcastEntry>> GetActiveBroadcasts(string? excludeHashedCid = null)
{
var now = DateTime.UtcNow;
var comparer = StringComparer.Ordinal;
return [.. _broadcastCache.Where(entry =>
entry.Value.IsBroadcasting &&
entry.Value.ExpiryTime > now &&
(excludeHashedCid is null || !comparer.Equals(entry.Key, excludeHashedCid)))];
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);

View File

@@ -13,7 +13,8 @@ namespace LightlessSync.Services;
public sealed class CommandManagerService : IDisposable
{
private const string _commandName = "/light";
private const string _longName = "/lightless";
private const string _shortName = "/light";
private readonly ApiController _apiController;
private readonly ICommandManager _commandManager;
@@ -34,7 +35,11 @@ public sealed class CommandManagerService : IDisposable
_apiController = apiController;
_mediator = mediator;
_lightlessConfigService = lightlessConfigService;
_commandManager.AddHandler(_commandName, new CommandInfo(OnCommand)
_commandManager.AddHandler(_longName, new CommandInfo(OnCommand)
{
HelpMessage = $"\u2191;"
});
_commandManager.AddHandler(_shortName, new CommandInfo(OnCommand)
{
HelpMessage = "Opens the Lightless Sync UI" + Environment.NewLine + Environment.NewLine +
"Additionally possible commands:" + Environment.NewLine +
@@ -49,7 +54,8 @@ public sealed class CommandManagerService : IDisposable
public void Dispose()
{
_commandManager.RemoveHandler(_commandName);
_commandManager.RemoveHandler(_longName);
_commandManager.RemoveHandler(_shortName);
}
private void OnCommand(string command, string args)

View File

@@ -1,7 +1,3 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using LightlessSync.LightlessConfiguration.Models;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services.Mediator;
@@ -14,10 +10,10 @@ public sealed class PairRequestService : DisposableMediatorSubscriberBase
private readonly DalamudUtilService _dalamudUtil;
private readonly PairManager _pairManager;
private readonly Lazy<WebAPI.ApiController> _apiController;
private readonly object _syncRoot = new();
private readonly Lock _syncRoot = new();
private readonly List<PairRequestEntry> _requests = [];
private static readonly TimeSpan Expiration = TimeSpan.FromMinutes(5);
private static readonly TimeSpan _expiration = TimeSpan.FromMinutes(5);
public PairRequestService(
ILogger<PairRequestService> logger,
@@ -189,7 +185,7 @@ public sealed class PairRequestService : DisposableMediatorSubscriberBase
}
var now = DateTime.UtcNow;
return _requests.RemoveAll(r => now - r.ReceivedAt > Expiration) > 0;
return _requests.RemoveAll(r => now - r.ReceivedAt > _expiration) > 0;
}
public void AcceptPairRequest(string hashedCid, string displayName)

View File

@@ -2,19 +2,22 @@ using Dalamud.Game.Gui.Dtr;
using Dalamud.Game.Text.SeStringHandling;
using Dalamud.Game.Text.SeStringHandling.Payloads;
using Dalamud.Plugin.Services;
using Dalamud.Utility;
using LightlessSync.LightlessConfiguration;
using LightlessSync.LightlessConfiguration.Configurations;
using LightlessSync.PlayerData.Pairs;
using LightlessSync.Services;
using LightlessSync.Services.Mediator;
using LightlessSync.Services.ServerConfiguration;
using LightlessSync.Utils;
using LightlessSync.WebAPI;
using LightlessSync.WebAPI.SignalR.Utils;
using LightlessSync.Utils;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using System.Runtime.InteropServices;
using System.Text;
using static LightlessSync.Services.PairRequestService;
namespace LightlessSync.UI;
@@ -106,7 +109,7 @@ public sealed class DtrEntry : IDisposable, IHostedService
}
catch (OperationCanceledException)
{
_logger.LogInformation("Lightfinder operation was canceled.");
}
finally
{
@@ -363,29 +366,46 @@ public sealed class DtrEntry : IDisposable, IHostedService
}
}
private int GetNearbyBroadcastCount()
{
var localHashedCid = GetLocalHashedCid();
return _broadcastScannerService.CountActiveBroadcasts(
string.IsNullOrEmpty(localHashedCid) ? null : localHashedCid);
}
private int GetPendingPairRequestCount()
private List<string> GetNearbyBroadcasts()
{
try
{
return _pairRequestService.GetActiveRequests().Count;
var localHashedCid = GetLocalHashedCid();
return [.. _broadcastScannerService
.GetActiveBroadcasts(string.IsNullOrEmpty(localHashedCid) ? null : localHashedCid)
.Select(b => _dalamudUtilService.FindPlayerByNameHash(b.Key).Name)];
}
catch (Exception ex)
{
var now = DateTime.UtcNow;
if (now >= _pairRequestNextErrorLog)
{
_logger.LogDebug(ex, "Failed to retrieve nearby broadcasts for Lightfinder DTR entry.");
_pairRequestNextErrorLog = now + _localHashedCidErrorCooldown;
}
return [];
}
}
private IReadOnlyList<PairRequestDisplay> GetPendingPairRequest()
{
try
{
return _pairRequestService.GetActiveRequests();
}
catch (Exception ex)
{
var now = DateTime.UtcNow;
if (now >= _pairRequestNextErrorLog)
{
_logger.LogDebug(ex, "Failed to retrieve pair request count for Lightfinder DTR entry.");
_pairRequestNextErrorLog = now + _localHashedCidErrorCooldown;
}
return 0;
return [];
}
}
@@ -400,23 +420,15 @@ public sealed class DtrEntry : IDisposable, IHostedService
if (_broadcastService.IsBroadcasting)
{
var tooltipBuilder = new StringBuilder("Lightfinder - Enabled");
switch (config.LightfinderDtrDisplayMode)
{
case LightfinderDtrDisplayMode.PendingPairRequests:
{
var requestCount = GetPendingPairRequestCount();
tooltipBuilder.AppendLine();
tooltipBuilder.Append("Pending pair requests: ").Append(requestCount);
return ($"{icon} Requests {requestCount}", SwapColorChannels(config.DtrColorsLightfinderEnabled), tooltipBuilder.ToString());
return FormatTooltip("Pending pair requests", GetPendingPairRequest().Select(x => x.DisplayName), icon, SwapColorChannels(config.DtrColorsLightfinderEnabled));
}
default:
{
var broadcastCount = GetNearbyBroadcastCount();
tooltipBuilder.AppendLine();
tooltipBuilder.Append("Nearby Lightfinder users: ").Append(broadcastCount);
return ($"{icon} {broadcastCount}", SwapColorChannels(config.DtrColorsLightfinderEnabled), tooltipBuilder.ToString());
return FormatTooltip("Nearby Lightfinder users", GetNearbyBroadcasts(), icon, SwapColorChannels(config.DtrColorsLightfinderEnabled));
}
}
}
@@ -433,6 +445,18 @@ public sealed class DtrEntry : IDisposable, IHostedService
return ($"{icon} OFF", colors, tooltip.ToString());
}
private (string, Colors, string) FormatTooltip(string title, IEnumerable<string> names, string icon, Colors color)
{
var list = names.Where(x => !string.IsNullOrEmpty(x)).ToList();
var tooltip = new StringBuilder()
.Append($"Lightfinder - Enabled{Environment.NewLine}")
.Append($"{title}: {list.Count}{Environment.NewLine}")
.AppendJoin(Environment.NewLine, list)
.ToString();
return ($"{icon} {list.Count}", color, tooltip);
}
private static string BuildLightfinderTooltip(string baseTooltip)
{
var builder = new StringBuilder();