125 lines
5.0 KiB
C#
125 lines
5.0 KiB
C#
using MareSynchronos.API.Data;
|
|
using MareSynchronos.Services;
|
|
using MareSynchronos.Services.Mediator;
|
|
using MareSynchronos.Utils;
|
|
using MareSynchronos.WebAPI;
|
|
using MareSynchronos.WebAPI.Files;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace MareSynchronos.PlayerData.Pairs;
|
|
|
|
public class VisibleUserDataDistributor : DisposableMediatorSubscriberBase
|
|
{
|
|
private readonly ApiController _apiController;
|
|
private readonly DalamudUtilService _dalamudUtil;
|
|
private readonly FileUploadManager _fileTransferManager;
|
|
private readonly PairManager _pairManager;
|
|
private CharacterData? _lastCreatedData;
|
|
private CharacterData? _uploadingCharacterData = null;
|
|
private readonly List<UserData> _previouslyVisiblePlayers = [];
|
|
private Task<CharacterData>? _fileUploadTask = null;
|
|
private readonly HashSet<UserData> _usersToPushDataTo = [];
|
|
private readonly SemaphoreSlim _pushDataSemaphore = new(1, 1);
|
|
private readonly CancellationTokenSource _runtimeCts = new();
|
|
|
|
|
|
public VisibleUserDataDistributor(ILogger<VisibleUserDataDistributor> logger, ApiController apiController, DalamudUtilService dalamudUtil,
|
|
PairManager pairManager, MareMediator mediator, FileUploadManager fileTransferManager) : base(logger, mediator)
|
|
{
|
|
_apiController = apiController;
|
|
_dalamudUtil = dalamudUtil;
|
|
_pairManager = pairManager;
|
|
_fileTransferManager = fileTransferManager;
|
|
Mediator.Subscribe<DelayedFrameworkUpdateMessage>(this, (_) => FrameworkOnUpdate());
|
|
Mediator.Subscribe<CharacterDataCreatedMessage>(this, (msg) =>
|
|
{
|
|
var newData = msg.CharacterData;
|
|
if (_lastCreatedData == null || (!string.Equals(newData.DataHash.Value, _lastCreatedData.DataHash.Value, StringComparison.Ordinal)))
|
|
{
|
|
Logger.LogDebug("Pushing data for visible players");
|
|
_lastCreatedData = newData;
|
|
PushToAllVisibleUsers(forced: true);
|
|
}
|
|
else
|
|
{
|
|
Logger.LogDebug("Not sending data for {hash}", newData.DataHash.Value);
|
|
}
|
|
});
|
|
|
|
Mediator.Subscribe<ConnectedMessage>(this, (_) => PushToAllVisibleUsers());
|
|
Mediator.Subscribe<DisconnectedMessage>(this, (_) => _previouslyVisiblePlayers.Clear());
|
|
}
|
|
|
|
protected override void Dispose(bool disposing)
|
|
{
|
|
if (disposing)
|
|
{
|
|
_runtimeCts.Cancel();
|
|
_runtimeCts.Dispose();
|
|
}
|
|
|
|
base.Dispose(disposing);
|
|
}
|
|
|
|
private void PushToAllVisibleUsers(bool forced = false)
|
|
{
|
|
foreach (var user in _pairManager.GetVisibleUsers())
|
|
{
|
|
_usersToPushDataTo.Add(user);
|
|
}
|
|
PushCharacterData(forced);
|
|
}
|
|
|
|
private void FrameworkOnUpdate()
|
|
{
|
|
if (!_dalamudUtil.GetIsPlayerPresent() || !_apiController.IsConnected) return;
|
|
|
|
var allVisibleUsers = _pairManager.GetVisibleUsers();
|
|
var newVisibleUsers = allVisibleUsers.Except(_previouslyVisiblePlayers).ToList();
|
|
_previouslyVisiblePlayers.Clear();
|
|
_previouslyVisiblePlayers.AddRange(allVisibleUsers);
|
|
if (newVisibleUsers.Count == 0) return;
|
|
|
|
Logger.LogTrace("Has new visible players, pushing character data to {users}", string.Join(", ", newVisibleUsers.Select(k => k.AliasOrUID)));
|
|
foreach (var user in newVisibleUsers)
|
|
{
|
|
_usersToPushDataTo.Add(user);
|
|
}
|
|
PushCharacterData();
|
|
}
|
|
|
|
private void PushCharacterData(bool forced = false)
|
|
{
|
|
if (_lastCreatedData == null) return;
|
|
|
|
_ = Task.Run(async () =>
|
|
{
|
|
forced |= _uploadingCharacterData?.DataHash != _lastCreatedData.DataHash;
|
|
|
|
if (_fileUploadTask == null || (_fileUploadTask?.IsCompleted ?? false) || forced)
|
|
{
|
|
_uploadingCharacterData = _lastCreatedData.DeepClone();
|
|
Logger.LogDebug("Starting UploadTask for {hash}, Reason: TaskIsNull: {task}, TaskIsCompleted: {taskCpl}, Forced: {frc}",
|
|
_lastCreatedData.DataHash, _fileUploadTask == null, _fileUploadTask?.IsCompleted ?? false, forced);
|
|
_fileUploadTask = _fileTransferManager.UploadFiles(_uploadingCharacterData, [.. _usersToPushDataTo]);
|
|
}
|
|
|
|
if (_fileUploadTask != null)
|
|
{
|
|
var dataToSend = await _fileUploadTask.ConfigureAwait(false);
|
|
await _pushDataSemaphore.WaitAsync(_runtimeCts.Token).ConfigureAwait(false);
|
|
try
|
|
{
|
|
if (!_usersToPushDataTo.Any()) return;
|
|
Logger.LogDebug("Pushing {data} to {users}", dataToSend.DataHash, string.Join(", ", _usersToPushDataTo.Select(k => k.AliasOrUID)));
|
|
await _apiController.PushCharacterData(dataToSend, [.. _usersToPushDataTo]).ConfigureAwait(false);
|
|
_usersToPushDataTo.Clear();
|
|
}
|
|
finally
|
|
{
|
|
_pushDataSemaphore.Release();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
} |