Add VisibilityService to improve tick performance with many online pairs

This commit is contained in:
Loporrit
2025-05-14 12:01:29 +00:00
parent e603539319
commit fae8941dce
6 changed files with 73 additions and 11 deletions

View File

@@ -19,7 +19,7 @@ namespace MareSynchronos.Services;
public class DalamudUtilService : IHostedService, IMediatorSubscriber
{
internal struct PlayerCharacter
public struct PlayerCharacter
{
public uint ObjectId;
public string Name;
@@ -390,7 +390,7 @@ public class DalamudUtilService : IHostedService, IMediatorSubscriber
return _gameGui.WorldToScreen(obj.Position, out var screenPos) ? screenPos : Vector2.Zero;
}
internal PlayerCharacter FindPlayerByNameHash(string ident)
public PlayerCharacter FindPlayerByNameHash(string ident)
{
_playerCharas.TryGetValue(ident, out var result);
return result;

View File

@@ -72,6 +72,7 @@ public record ProfilePopoutToggle(Pair? Pair) : MessageBase;
public record CompactUiChange(Vector2 Size, Vector2 Position) : MessageBase;
public record ProfileOpenStandaloneMessage(Pair Pair) : MessageBase;
public record RemoveWindowMessage(WindowMediatorSubscriberBase Window) : MessageBase;
public record PlayerVisibilityMessage(string Ident, bool IsVisible) : KeyedMessage(Ident, SameThread: true);
public record PairHandlerVisibleMessage(PairHandler Player) : MessageBase;
public record OpenReportPopupMessage(Pair PairToReport) : MessageBase;
public record OpenBanUserPopupMessage(Pair PairToBan, GroupFullInfoDto GroupFullInfoDto) : MessageBase;

View File

@@ -0,0 +1,51 @@
using MareSynchronos.Services.Mediator;
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
namespace MareSynchronos.Services;
// Detect when players of interest are visible
public class VisibilityService : DisposableMediatorSubscriberBase
{
private readonly DalamudUtilService _dalamudUtil;
private ConcurrentDictionary<string, bool> _trackedPlayerVisibility = new();
private ConcurrentQueue<string> _removedPlayerMessageQueue = new();
public VisibilityService(ILogger<PairAnalyzer> logger, MareMediator mediator, DalamudUtilService dalamudUtil)
: base(logger, mediator)
{
_dalamudUtil = dalamudUtil;
Mediator.Subscribe<FrameworkUpdateMessage>(this, (_) => FrameworkUpdate());
}
public void StartTracking(string ident)
{
_trackedPlayerVisibility.TryAdd(ident, false);
}
public void StopTracking(string ident)
{
// No PairVisibilityMessage is emitted if the player was visible when removed
_trackedPlayerVisibility.TryRemove(ident, out _);
}
private void FrameworkUpdate()
{
foreach (var player in _trackedPlayerVisibility)
{
string ident = player.Key;
var findResult = _dalamudUtil.FindPlayerByNameHash(ident);
if (!player.Value && findResult.ObjectId != 0)
{
if (_trackedPlayerVisibility.TryUpdate(ident, newValue: true, comparisonValue: false))
Mediator.Publish<PlayerVisibilityMessage>(new(ident, IsVisible: true));
}
else if (player.Value && findResult.ObjectId == 0)
{
if (_trackedPlayerVisibility.TryUpdate(ident, newValue: false, comparisonValue: true))
Mediator.Publish<PlayerVisibilityMessage>(new(ident, IsVisible: false));
}
}
}
}