using MareSynchronos.API.Data; using MareSynchronos.Services; using MareSynchronos.Services.Mediator; using MareSynchronos.Utils; using MareSynchronos.WebAPI; using MareSynchronos.WebAPI.Files; using MessagePack.Formatters; 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 readonly List _previouslyVisiblePlayers = []; private Task? _fileUploadTask = null; private readonly HashSet _usersToPushDataTo = []; public VisibleUserDataDistributor(ILogger logger, ApiController apiController, DalamudUtilService dalamudUtil, PairManager pairManager, MareMediator mediator, FileUploadManager fileTransferManager) : base(logger, mediator) { _apiController = apiController; _dalamudUtil = dalamudUtil; _pairManager = pairManager; _fileTransferManager = fileTransferManager; Mediator.Subscribe(this, (_) => FrameworkOnUpdate()); Mediator.Subscribe(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(this, (_) => PushToAllVisibleUsers()); Mediator.Subscribe(this, (_) => _previouslyVisiblePlayers.Clear()); } 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 () => { if (_fileUploadTask == null || (_fileUploadTask?.IsCompleted ?? false) || forced) { _fileUploadTask = _fileTransferManager.UploadFiles(_lastCreatedData.DeepClone(), [.. _usersToPushDataTo]); } if (_fileUploadTask != null) { var dataToSend = await _fileUploadTask.ConfigureAwait(false); await _apiController.PushCharacterData(dataToSend, [.. _usersToPushDataTo]).ConfigureAwait(false); _usersToPushDataTo.Clear(); } }); } }