From 36185404025ebdbbea14c800f0bf6e0e7e7f9b10 Mon Sep 17 00:00:00 2001 From: Stanley Dimant Date: Thu, 30 Jun 2022 13:24:35 +0200 Subject: [PATCH] rework a lot of stuff: downloads, how to watch a player --- MareSynchronos.sln | 10 -- .../Factories/CharacterDataFactory.cs | 5 +- .../{Models => Managers}/CachedPlayer.cs | 52 ++++--- MareSynchronos/Managers/FileCacheManager.cs | 19 ++- MareSynchronos/Managers/IpcManager.cs | 4 +- ...ayersManager.cs => OnlinePlayerManager.cs} | 23 ++-- MareSynchronos/Managers/PlayerManager.cs | 75 ++++++---- MareSynchronos/MareSynchronos.csproj | 1 - MareSynchronos/Plugin.cs | 8 +- MareSynchronos/UI/DownloadUi.cs | 20 +-- MareSynchronos/UI/MainUi.cs | 6 +- MareSynchronos/UI/UIShared.cs | 24 ++-- MareSynchronos/Utils/DalamudUtil.cs | 43 +++--- .../WebAPI/ApIController.Functions.Files.cs | 130 +++++++++++++++--- .../WebAPI/ApIController.Functions.Users.cs | 64 --------- .../WebAPI/ApiController.Connectivity.cs | 14 +- .../ApiController.Functions.Callbacks.cs | 12 +- MareSynchronos/WebAPI/Utils/FileTransfer.cs | 42 +++++- 18 files changed, 319 insertions(+), 233 deletions(-) rename MareSynchronos/{Models => Managers}/CachedPlayer.cs (88%) rename MareSynchronos/Managers/{CachedPlayersManager.cs => OnlinePlayerManager.cs} (87%) diff --git a/MareSynchronos.sln b/MareSynchronos.sln index f8cd173..cc723e3 100644 --- a/MareSynchronos.sln +++ b/MareSynchronos.sln @@ -7,8 +7,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronos", "MareSynch EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Penumbra.GameData", "..\..\Penumbra\Penumbra.GameData\Penumbra.GameData.csproj", "{44F7CA6A-898C-4901-ADB8-010BC74FF781}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Penumbra.PlayerWatch", "..\..\Penumbra\Penumbra.PlayerWatch\Penumbra.PlayerWatch.csproj", "{2F26FC2D-03DF-445F-A87B-8708D621E86C}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MareSynchronos.API", "..\server\MareSynchronosServer\MareSynchronos.API\MareSynchronos.API.csproj", "{4C92F86D-9C84-4F58-9C1A-671AEBACA256}" EndProject Global @@ -35,14 +33,6 @@ Global {44F7CA6A-898C-4901-ADB8-010BC74FF781}.Release|Any CPU.Build.0 = Release|Any CPU {44F7CA6A-898C-4901-ADB8-010BC74FF781}.Release|x64.ActiveCfg = Release|Any CPU {44F7CA6A-898C-4901-ADB8-010BC74FF781}.Release|x64.Build.0 = Release|Any CPU - {2F26FC2D-03DF-445F-A87B-8708D621E86C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2F26FC2D-03DF-445F-A87B-8708D621E86C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2F26FC2D-03DF-445F-A87B-8708D621E86C}.Debug|x64.ActiveCfg = Debug|Any CPU - {2F26FC2D-03DF-445F-A87B-8708D621E86C}.Debug|x64.Build.0 = Debug|Any CPU - {2F26FC2D-03DF-445F-A87B-8708D621E86C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2F26FC2D-03DF-445F-A87B-8708D621E86C}.Release|Any CPU.Build.0 = Release|Any CPU - {2F26FC2D-03DF-445F-A87B-8708D621E86C}.Release|x64.ActiveCfg = Release|Any CPU - {2F26FC2D-03DF-445F-A87B-8708D621E86C}.Release|x64.Build.0 = Release|Any CPU {4C92F86D-9C84-4F58-9C1A-671AEBACA256}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {4C92F86D-9C84-4F58-9C1A-671AEBACA256}.Debug|Any CPU.Build.0 = Debug|Any CPU {4C92F86D-9C84-4F58-9C1A-671AEBACA256}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/MareSynchronos/Factories/CharacterDataFactory.cs b/MareSynchronos/Factories/CharacterDataFactory.cs index 3900470..6032c59 100644 --- a/MareSynchronos/Factories/CharacterDataFactory.cs +++ b/MareSynchronos/Factories/CharacterDataFactory.cs @@ -58,9 +58,9 @@ namespace MareSynchronos.Factories public CharacterData BuildCharacterData() { - if (!_dalamudUtil.IsPlayerPresent || !_ipcManager.Initialized) + if (!_ipcManager.Initialized) { - throw new ArgumentException("Player is not present or Penumbra is not connected"); + throw new ArgumentException("Penumbra is not connected"); } return CreateCharacterData(); @@ -74,6 +74,7 @@ namespace MareSynchronos.Factories Logger.Debug("Character is null but it shouldn't be, waiting"); Thread.Sleep(50); } + _dalamudUtil.WaitWhileCharacterIsDrawing(_dalamudUtil.PlayerPointer); var cache = new CharacterData { JobId = _dalamudUtil.PlayerJobId, diff --git a/MareSynchronos/Models/CachedPlayer.cs b/MareSynchronos/Managers/CachedPlayer.cs similarity index 88% rename from MareSynchronos/Models/CachedPlayer.cs rename to MareSynchronos/Managers/CachedPlayer.cs index 8122a83..7c9a382 100644 --- a/MareSynchronos/Models/CachedPlayer.cs +++ b/MareSynchronos/Managers/CachedPlayer.cs @@ -4,16 +4,15 @@ using System.Linq; using System.Threading; using System.Threading.Tasks; using Dalamud.Game.ClientState.Objects.SubKinds; -using Dalamud.Game.ClientState.Objects.Types; using Dalamud.Logging; using MareSynchronos.API; using MareSynchronos.FileCacheDB; -using MareSynchronos.Managers; using MareSynchronos.Utils; using MareSynchronos.WebAPI; using MareSynchronos.WebAPI.Utils; +using Penumbra.GameData.Structs; -namespace MareSynchronos.Models; +namespace MareSynchronos.Managers; public class CachedPlayer { @@ -37,7 +36,6 @@ public class CachedPlayer { WasVisible = _isVisible; _isVisible = value; - } } @@ -60,6 +58,8 @@ public class CachedPlayer private readonly Dictionary _cache = new(); + private CharacterEquipment? _currentCharacterEquipment; + private void ApiControllerOnCharacterReceived(object? sender, CharacterReceivedEventArgs e) { if (string.IsNullOrEmpty(PlayerName) || e.CharacterNameHash != PlayerNameHash) return; @@ -157,12 +157,14 @@ public class CachedPlayer try { Logger.Debug("Restoring state for " + PlayerName); + _dalamudUtil.FrameworkUpdate -= DalamudUtilOnFrameworkUpdate; + _ipcManager.PenumbraRedrawEvent -= IpcManagerOnPenumbraRedrawEvent; + _apiController.CharacterReceived -= ApiControllerOnCharacterReceived; _downloadCancellationTokenSource?.Cancel(); _downloadCancellationTokenSource?.Dispose(); _downloadCancellationTokenSource = null; - _dalamudUtil.RemovePlayerFromWatch(PlayerName); _ipcManager.PenumbraRemoveTemporaryCollection(PlayerName); - if (IsVisible) + if (PlayerCharacter != null) { _ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerName); _ipcManager.GlamourerApplyOnlyEquipment(_lastGlamourerData, PlayerName); @@ -174,9 +176,6 @@ public class CachedPlayer } finally { - _dalamudUtil.PlayerChanged -= WatcherOnPlayerChanged; - _ipcManager.PenumbraRedrawEvent -= IpcManagerOnPenumbraRedrawEvent; - _apiController.CharacterReceived -= ApiControllerOnCharacterReceived; PlayerName = string.Empty; PlayerCharacter = null; IsVisible = false; @@ -189,11 +188,31 @@ public class CachedPlayer PlayerName = character.Name.ToString(); PlayerCharacter = character; Logger.Debug("Initializing Player " + this); - _dalamudUtil.AddPlayerToWatch(PlayerName!); - _dalamudUtil.PlayerChanged += WatcherOnPlayerChanged; + _dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate; _ipcManager.PenumbraRedrawEvent += IpcManagerOnPenumbraRedrawEvent; _apiController.CharacterReceived += ApiControllerOnCharacterReceived; _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerName); + _currentCharacterEquipment = new CharacterEquipment(PlayerCharacter); + _lastPlayerObjectCheck = DateTime.Now; + } + + private void DalamudUtilOnFrameworkUpdate() + { + if (!_dalamudUtil.IsPlayerPresent || !_ipcManager.Initialized || !_apiController.IsConnected) return; + + PlayerCharacter = _dalamudUtil.GetPlayerCharacterFromObjectTableByName(PlayerName!); + if (PlayerCharacter == null) + { + DisposePlayer(); + return; + } + + if (!_currentCharacterEquipment!.CompareAndUpdate(PlayerCharacter)) + { + OnPlayerChanged(); + } + + IsVisible = true; } public override string ToString() @@ -205,7 +224,7 @@ public class CachedPlayer private void IpcManagerOnPenumbraRedrawEvent(object? sender, EventArgs e) { - var player = _dalamudUtil.GetPlayerCharacterFromObjectTableIndex((int)sender!); + var player = _dalamudUtil.GetPlayerCharacterFromObjectTableByIndex((int)sender!); if (player == null || player.Name.ToString() != PlayerName) return; if (!_penumbraRedrawEventTask?.IsCompleted ?? false) return; @@ -228,16 +247,11 @@ public class CachedPlayer }); } - private void WatcherOnPlayerChanged(Character actor) + private void OnPlayerChanged() { - if (actor.Name.ToString() != PlayerName) return; Logger.Debug($"Player {PlayerName} changed, PenumbraRedraw is {RequestedPenumbraRedraw}"); PlayerCharacter = _dalamudUtil.GetPlayerCharacterFromObjectTableByName(PlayerName!); - if (PlayerCharacter is null) - { - Logger.Debug($"Invalid PlayerCharacter for {PlayerName}"); - } - else if (!RequestedPenumbraRedraw && PlayerCharacter is not null) + if (!RequestedPenumbraRedraw && PlayerCharacter is not null) { Logger.Debug($"Saving new Glamourer data"); _lastGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerName!); diff --git a/MareSynchronos/Managers/FileCacheManager.cs b/MareSynchronos/Managers/FileCacheManager.cs index 4aa7d4d..ff4c5ce 100644 --- a/MareSynchronos/Managers/FileCacheManager.cs +++ b/MareSynchronos/Managers/FileCacheManager.cs @@ -19,8 +19,8 @@ namespace MareSynchronos.Managers private FileSystemWatcher? _cacheDirWatcher; private FileSystemWatcher? _penumbraDirWatcher; private Task? _rescanTask; - private CancellationTokenSource? _rescanTaskCancellationTokenSource; - private CancellationTokenSource? _rescanTaskRunCancellationTokenSource; + private CancellationTokenSource _rescanTaskCancellationTokenSource = new CancellationTokenSource(); + private CancellationTokenSource _rescanTaskRunCancellationTokenSource = new CancellationTokenSource(); private CancellationTokenSource? _scanCancellationTokenSource; private Task? _scanTask; public FileCacheManager(IpcManager ipcManager, Configuration pluginConfiguration) @@ -94,7 +94,6 @@ namespace MareSynchronos.Managers _penumbraDirWatcher = new FileSystemWatcher(_ipcManager.PenumbraModDirectory()!) { IncludeSubdirectories = true, - InternalBufferSize = 1048576 }; _penumbraDirWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size; _penumbraDirWatcher.Deleted += OnModified; @@ -108,8 +107,7 @@ namespace MareSynchronos.Managers _cacheDirWatcher = new FileSystemWatcher(_pluginConfiguration.CacheFolder) { - IncludeSubdirectories = true, - InternalBufferSize = 1048576 + IncludeSubdirectories = false, }; _cacheDirWatcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.Size; _cacheDirWatcher.Deleted += OnModified; @@ -150,7 +148,7 @@ namespace MareSynchronos.Managers private void OnModified(object sender, FileSystemEventArgs e) { _modifiedFiles.Add(e.FullPath); - Task.Run(() => _ = RescanTask()); + _ = StartRescan(); } private void RecalculateFileCacheSize() @@ -169,12 +167,12 @@ namespace MareSynchronos.Managers } } - public async Task RescanTask(bool force = false) + public async Task StartRescan(bool force = false) { - _rescanTaskRunCancellationTokenSource?.Cancel(); + _rescanTaskRunCancellationTokenSource.Cancel(); _rescanTaskRunCancellationTokenSource = new CancellationTokenSource(); var token = _rescanTaskRunCancellationTokenSource.Token; - if(!force) + if (!force) await Task.Delay(TimeSpan.FromSeconds(1), token); while ((!_rescanTask?.IsCompleted ?? false) && !token.IsCancellationRequested) { @@ -183,11 +181,10 @@ namespace MareSynchronos.Managers if (token.IsCancellationRequested) return; - PluginLog.Debug("File changes detected, scanning the changes"); + PluginLog.Debug("File changes detected, scanning the changes "); if (!_modifiedFiles.Any()) return; - _rescanTaskCancellationTokenSource = new CancellationTokenSource(); _rescanTask = Task.Run(async () => { var listCopy = _modifiedFiles.ToList(); diff --git a/MareSynchronos/Managers/IpcManager.cs b/MareSynchronos/Managers/IpcManager.cs index 585a9c5..41b3e95 100644 --- a/MareSynchronos/Managers/IpcManager.cs +++ b/MareSynchronos/Managers/IpcManager.cs @@ -119,14 +119,14 @@ namespace MareSynchronos.Managers public void GlamourerApplyOnlyEquipment(string customization, string characterName) { - if (!CheckGlamourerApi()) return; + if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; Logger.Debug("Glamourer apply only equipment to " + characterName); _glamourerApplyOnlyEquipment!.InvokeAction(customization, characterName); } public void GlamourerApplyOnlyCustomization(string customization, string characterName) { - if (!CheckGlamourerApi()) return; + if (!CheckGlamourerApi() || string.IsNullOrEmpty(customization)) return; Logger.Debug("Glamourer apply only customization to " + characterName); _glamourerApplyOnlyCustomization!.InvokeAction(customization, characterName); } diff --git a/MareSynchronos/Managers/CachedPlayersManager.cs b/MareSynchronos/Managers/OnlinePlayerManager.cs similarity index 87% rename from MareSynchronos/Managers/CachedPlayersManager.cs rename to MareSynchronos/Managers/OnlinePlayerManager.cs index b4dcc95..028ec8f 100644 --- a/MareSynchronos/Managers/CachedPlayersManager.cs +++ b/MareSynchronos/Managers/OnlinePlayerManager.cs @@ -3,25 +3,23 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Dalamud.Game; -using MareSynchronos.Models; using MareSynchronos.Utils; using MareSynchronos.WebAPI; namespace MareSynchronos.Managers; -public class CachedPlayersManager : IDisposable +public class OnlinePlayerManager : IDisposable { private readonly ApiController _apiController; private readonly DalamudUtil _dalamudUtil; private readonly Framework _framework; private readonly IpcManager _ipcManager; private readonly List _onlineCachedPlayers = new(); - private readonly List _localVisiblePlayers = new(); private DateTime _lastPlayerObjectCheck = DateTime.Now; - public CachedPlayersManager(Framework framework, ApiController apiController, DalamudUtil dalamudUtil, IpcManager ipcManager) + public OnlinePlayerManager(Framework framework, ApiController apiController, DalamudUtil dalamudUtil, IpcManager ipcManager) { - Logger.Debug("Creating " + nameof(CachedPlayersManager)); + Logger.Debug("Creating " + nameof(OnlinePlayerManager)); _framework = framework; _apiController = apiController; @@ -74,7 +72,7 @@ public class CachedPlayersManager : IDisposable public void Dispose() { - Logger.Debug("Disposing " + nameof(CachedPlayersManager)); + Logger.Debug("Disposing " + nameof(OnlinePlayerManager)); RestoreAllCharacters(); @@ -142,9 +140,9 @@ public class CachedPlayersManager : IDisposable private void RemovePlayer(string characterHash) { - var cachedPlayer = _onlineCachedPlayers.Single(p => p.PlayerNameHash == characterHash); + var cachedPlayer = _onlineCachedPlayers.First(p => p.PlayerNameHash == characterHash); cachedPlayer.DisposePlayer(); - _onlineCachedPlayers.Remove(cachedPlayer); + _onlineCachedPlayers.RemoveAll(c => c.PlayerNameHash == cachedPlayer.PlayerNameHash); } private void FrameworkOnUpdate(Framework framework) @@ -153,26 +151,21 @@ public class CachedPlayersManager : IDisposable if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(0.25)) return; - _localVisiblePlayers.Clear(); var playerCharacters = _dalamudUtil.GetPlayerCharacters(); foreach (var pChar in playerCharacters) { var pObjName = pChar.Name.ToString(); - _localVisiblePlayers.Add(pObjName); - var existingCachedPlayer = _onlineCachedPlayers.SingleOrDefault(p => p.PlayerName == pObjName); + var hashedName = Crypto.GetHash256(pChar); + var existingCachedPlayer = _onlineCachedPlayers.SingleOrDefault(p => p.PlayerNameHash == hashedName && !string.IsNullOrEmpty(p.PlayerName)); if (existingCachedPlayer != null) { existingCachedPlayer.IsVisible = true; continue; } - var hashedName = Crypto.GetHash256(pChar); _onlineCachedPlayers.SingleOrDefault(p => p.PlayerNameHash == hashedName)?.InitializePlayer(pChar); } - _onlineCachedPlayers.Where(p => !string.IsNullOrEmpty(p.PlayerName) && !_localVisiblePlayers.Contains(p.PlayerName)) - .ToList().ForEach(p => p.DisposePlayer()); - Task.Run(async () => await UpdatePlayersFromService(_onlineCachedPlayers .Where(p => p.PlayerCharacter != null && p.IsVisible && !p.WasVisible) .ToDictionary(k => k.PlayerNameHash, k => (int)k.PlayerCharacter!.ClassJob.Id))); diff --git a/MareSynchronos/Managers/PlayerManager.cs b/MareSynchronos/Managers/PlayerManager.cs index 588258a..62d27e4 100644 --- a/MareSynchronos/Managers/PlayerManager.cs +++ b/MareSynchronos/Managers/PlayerManager.cs @@ -9,31 +9,34 @@ using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; +using Dalamud.Game.ClientState.Objects; +using Penumbra.GameData.Structs; namespace MareSynchronos.Managers { public class PlayerManager : IDisposable { private readonly ApiController _apiController; - private readonly CachedPlayersManager _cachedPlayersManager; + private readonly OnlinePlayerManager _onlinePlayerManager; private readonly CharacterDataFactory _characterDataFactory; private readonly DalamudUtil _dalamudUtil; private readonly IpcManager _ipcManager; private string _lastSentHash = string.Empty; private CancellationTokenSource? _playerChangedCts; + private DateTime _lastPlayerObjectCheck; + private CharacterEquipment _currentCharacterEquipment; public PlayerManager(ApiController apiController, IpcManager ipcManager, - CharacterDataFactory characterDataFactory, CachedPlayersManager cachedPlayersManager, DalamudUtil dalamudUtil) + CharacterDataFactory characterDataFactory, OnlinePlayerManager onlinePlayerManager, DalamudUtil dalamudUtil) { Logger.Debug("Creating " + nameof(PlayerManager)); _apiController = apiController; _ipcManager = ipcManager; _characterDataFactory = characterDataFactory; - _cachedPlayersManager = cachedPlayersManager; + _onlinePlayerManager = onlinePlayerManager; _dalamudUtil = dalamudUtil; - _dalamudUtil.AddPlayerToWatch(_dalamudUtil.PlayerName); _apiController.Connected += ApiController_Connected; _apiController.Disconnected += ApiController_Disconnected; @@ -48,12 +51,25 @@ namespace MareSynchronos.Managers { Logger.Debug("Disposing " + nameof(PlayerManager)); - _dalamudUtil.RemovePlayerFromWatch(_dalamudUtil.PlayerName); _apiController.Connected -= ApiController_Connected; _apiController.Disconnected -= ApiController_Disconnected; _ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent; - _dalamudUtil.PlayerChanged -= Watcher_PlayerChanged; + _dalamudUtil.FrameworkUpdate -= DalamudUtilOnFrameworkUpdate; + } + + private void DalamudUtilOnFrameworkUpdate() + { + if (!_dalamudUtil.IsPlayerPresent || !_ipcManager.Initialized || !_apiController.IsConnected) return; + + if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(0.25)) return; + + if (_dalamudUtil.IsPlayerPresent && !_currentCharacterEquipment!.CompareAndUpdate(_dalamudUtil.PlayerCharacter)) + { + OnPlayerChanged(); + } + + _lastPlayerObjectCheck = DateTime.Now; } private void ApiController_Connected(object? sender, EventArgs args) @@ -64,11 +80,13 @@ namespace MareSynchronos.Managers Task.WaitAll(apiTask); - _cachedPlayersManager.AddInitialPairs(apiTask.Result); + _onlinePlayerManager.AddInitialPairs(apiTask.Result); _ipcManager.PenumbraRedrawEvent += IpcManager_PenumbraRedrawEvent; - _dalamudUtil.PlayerChanged += Watcher_PlayerChanged; - PlayerChanged(_dalamudUtil.PlayerName); + _dalamudUtil.FrameworkUpdate += DalamudUtilOnFrameworkUpdate; + + _currentCharacterEquipment = new CharacterEquipment(_dalamudUtil.PlayerCharacter); + PlayerChanged(); } private void ApiController_Disconnected(object? sender, EventArgs args) @@ -76,7 +94,7 @@ namespace MareSynchronos.Managers Logger.Debug(nameof(ApiController_Disconnected)); _ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent; - _dalamudUtil.PlayerChanged -= Watcher_PlayerChanged; + _dalamudUtil.FrameworkUpdate -= DalamudUtilOnFrameworkUpdate; } private async Task CreateFullCharacterCache(CancellationToken token) @@ -102,19 +120,32 @@ namespace MareSynchronos.Managers private void IpcManager_PenumbraRedrawEvent(object? objectTableIndex, EventArgs e) { - var player = _dalamudUtil.GetPlayerCharacterFromObjectTableIndex((int)objectTableIndex!); + var player = _dalamudUtil.GetPlayerCharacterFromObjectTableByIndex((int)objectTableIndex!); if (player != null && player.Name.ToString() != _dalamudUtil.PlayerName) return; Logger.Debug("Penumbra Redraw Event for " + _dalamudUtil.PlayerName); - PlayerChanged(_dalamudUtil.PlayerName); + PlayerChanged(); } - private void PlayerChanged(string name) + private void PlayerChanged() { - Logger.Debug("Player changed: " + name); + Logger.Debug("Player changed: " + _dalamudUtil.PlayerName); _playerChangedCts?.Cancel(); _playerChangedCts = new CancellationTokenSource(); var token = _playerChangedCts.Token; + // fix for redraw from anamnesis + while ((!_dalamudUtil.IsPlayerPresent || _dalamudUtil.PlayerName == "--") && !token.IsCancellationRequested) + { + Logger.Debug("Waiting Until Player is Present"); + Thread.Sleep(100); + } + + if (token.IsCancellationRequested) + { + Logger.Debug("Cancelled"); + return; + } + if (!_ipcManager.Initialized) { Logger.Warn("Penumbra not active, doing nothing."); @@ -159,22 +190,12 @@ namespace MareSynchronos.Managers }, token); } - private void Watcher_PlayerChanged(Dalamud.Game.ClientState.Objects.Types.Character actor) + private void OnPlayerChanged() { Task.Run(() => { - // fix for redraw from anamnesis - while (!_dalamudUtil.IsPlayerPresent) - { - Logger.Debug("Waiting Until Player is Present"); - Thread.Sleep(100); - } - - if (actor.Name.ToString() == _dalamudUtil.PlayerName) - { - Logger.Debug("Watcher: PlayerChanged"); - PlayerChanged(actor.Name.ToString()); - } + Logger.Debug("Watcher: PlayerChanged"); + PlayerChanged(); }); } diff --git a/MareSynchronos/MareSynchronos.csproj b/MareSynchronos/MareSynchronos.csproj index dffcd3f..07b10a6 100644 --- a/MareSynchronos/MareSynchronos.csproj +++ b/MareSynchronos/MareSynchronos.csproj @@ -33,7 +33,6 @@ - diff --git a/MareSynchronos/Plugin.cs b/MareSynchronos/Plugin.cs index bfcfeca..f15ddb5 100644 --- a/MareSynchronos/Plugin.cs +++ b/MareSynchronos/Plugin.cs @@ -13,7 +13,6 @@ using MareSynchronos.WebAPI; using Dalamud.Interface.Windowing; using MareSynchronos.UI; using MareSynchronos.Utils; -using Penumbra.PlayerWatch; namespace MareSynchronos { @@ -32,7 +31,7 @@ namespace MareSynchronos private readonly WindowSystem _windowSystem; private PlayerManager? _playerManager; private readonly DalamudUtil _dalamudUtil; - private CachedPlayersManager? _characterCacheManager; + private OnlinePlayerManager? _characterCacheManager; private readonly DownloadUi _downloadUi; private readonly FileDialogManager _fileDialogManager; @@ -52,7 +51,7 @@ namespace MareSynchronos new FileCacheContext().Dispose(); // make sure db is initialized I guess // those can be initialized outside of game login - _dalamudUtil = new DalamudUtil(clientState, objectTable, PlayerWatchFactory.Create(framework, clientState, objectTable)); + _dalamudUtil = new DalamudUtil(clientState, objectTable, framework); _apiController = new ApiController(_configuration, _dalamudUtil); _ipcManager = new IpcManager(PluginInterface); @@ -115,7 +114,6 @@ namespace MareSynchronos _ipcManager?.Dispose(); _playerManager?.Dispose(); _characterCacheManager?.Dispose(); - _dalamudUtil.Dispose(); } @@ -170,7 +168,7 @@ namespace MareSynchronos { var characterCacheFactory = new CharacterDataFactory(_dalamudUtil, _ipcManager); - _characterCacheManager = new CachedPlayersManager(_framework, + _characterCacheManager = new OnlinePlayerManager(_framework, _apiController, _dalamudUtil, _ipcManager); _playerManager = new PlayerManager(_apiController, _ipcManager, characterCacheFactory, _characterCacheManager, _dalamudUtil); diff --git a/MareSynchronos/UI/DownloadUi.cs b/MareSynchronos/UI/DownloadUi.cs index a5e013d..0cf359c 100644 --- a/MareSynchronos/UI/DownloadUi.cs +++ b/MareSynchronos/UI/DownloadUi.cs @@ -52,10 +52,11 @@ public class DownloadUi : Window, IDisposable if (_apiController.CurrentUploads.Any()) { - var doneUploads = _apiController.CurrentUploads.Count(c => c.Total == c.Transferred); - var totalUploads = _apiController.CurrentUploads.Count; - var totalUploaded = _apiController.CurrentUploads.Sum(c => c.Transferred); - var totalToUpload = _apiController.CurrentUploads.Sum(c => c.Total); + var currentUploads = _apiController.CurrentUploads.ToList(); + var doneUploads = currentUploads.Count(c => c.IsTransferred); + var totalUploads = currentUploads.Count; + var totalUploaded = currentUploads.Sum(c => c.Transferred); + var totalToUpload = currentUploads.Sum(c => c.Total); UiShared.DrawOutlinedFont(drawList, "▲", new Vector2(basePosition.X + 0, basePosition.Y + (int)(yDistance * 0.5)), UiShared.Color(255, 255, 255, 255), UiShared.Color(0, 0, 0, 255), 2); @@ -69,11 +70,12 @@ public class DownloadUi : Window, IDisposable if (_apiController.CurrentDownloads.Any()) { - var multBase = _apiController.CurrentUploads.Any() ? 0 : 2; - var doneDownloads = _apiController.CurrentDownloads.Count(c => c.Total == c.Transferred); - var totalDownloads = _apiController.CurrentDownloads.Count; - var totalDownloaded = _apiController.CurrentDownloads.Sum(c => c.Transferred); - var totalToDownload = _apiController.CurrentDownloads.Sum(c => c.Total); + var currentDownloads = _apiController.CurrentDownloads.ToList(); + var multBase = currentDownloads.Any() ? 0 : 2; + var doneDownloads = currentDownloads.Count(c => c.IsTransferred); + var totalDownloads = currentDownloads.Count; + var totalDownloaded = currentDownloads.Sum(c => c.Transferred); + var totalToDownload = currentDownloads.Sum(c => c.Total); UiShared.DrawOutlinedFont(drawList, "▼", new Vector2(basePosition.X + 0, basePosition.Y + (int)(yDistance * multBase + (yDistance * 0.5))), UiShared.Color(255, 255, 255, 255), UiShared.Color(0, 0, 0, 255), 2); diff --git a/MareSynchronos/UI/MainUi.cs b/MareSynchronos/UI/MainUi.cs index 746f90f..7558bba 100644 --- a/MareSynchronos/UI/MainUi.cs +++ b/MareSynchronos/UI/MainUi.cs @@ -132,7 +132,7 @@ namespace MareSynchronos.UI ImGui.TableHeadersRow(); - foreach (var forbiddenFile in _apiController.ForbiddenFiles) + foreach (var forbiddenFile in _apiController.AdminForbiddenFiles) { ImGui.TableNextColumn(); @@ -203,7 +203,7 @@ namespace MareSynchronos.UI ImGui.TableHeadersRow(); - foreach (var bannedUser in _apiController.BannedUsers) + foreach (var bannedUser in _apiController.AdminBannedUsers) { ImGui.TableNextColumn(); ImGui.Text(bannedUser.CharacterHash); @@ -581,7 +581,7 @@ namespace MareSynchronos.UI File.Delete(file); } - _uiShared.ForceRescan(); + //_uiShared.ForceRescan(); }); } ImGui.TreePop(); diff --git a/MareSynchronos/UI/UIShared.cs b/MareSynchronos/UI/UIShared.cs index 47c26d6..b2c4c08 100644 --- a/MareSynchronos/UI/UIShared.cs +++ b/MareSynchronos/UI/UIShared.cs @@ -32,6 +32,7 @@ namespace MareSynchronos.UI _fileDialogManager = fileDialogManager; _pluginConfiguration = pluginConfiguration; _dalamudUtil = dalamudUtil; + isDirectoryWritable = IsDirectoryWritable(_pluginConfiguration.CacheFolder); } public bool DrawOtherPluginState() @@ -58,11 +59,6 @@ namespace MareSynchronos.UI return true; } - public void ForceRescan() - { - Task.Run(() => _ = _fileCacheManager.RescanTask(true)); - } - public void DrawFileScanState() { ImGui.Text("File Scanner Status"); @@ -300,7 +296,9 @@ namespace MareSynchronos.UI if (ImGui.InputText("Cache Folder##cache", ref cacheDirectory, 255)) { _pluginConfiguration.CacheFolder = cacheDirectory; - if (!string.IsNullOrEmpty(_pluginConfiguration.CacheFolder) && Directory.Exists(_pluginConfiguration.CacheFolder)) + if (!string.IsNullOrEmpty(_pluginConfiguration.CacheFolder) + && Directory.Exists(_pluginConfiguration.CacheFolder) + && (isDirectoryWritable = IsDirectoryWritable(_pluginConfiguration.CacheFolder))) { _pluginConfiguration.Save(); _fileCacheManager.StartWatchers(); @@ -317,20 +315,26 @@ namespace MareSynchronos.UI if (!success) return; _pluginConfiguration.CacheFolder = path; - _pluginConfiguration.Save(); - _fileCacheManager.StartWatchers(); + isDirectoryWritable = IsDirectoryWritable(_pluginConfiguration.CacheFolder); + if (isDirectoryWritable) + { + _pluginConfiguration.Save(); + _fileCacheManager.StartWatchers(); + } }); } ImGui.PopFont(); - if (!Directory.Exists(cacheDirectory) || !IsDirectoryWritable(cacheDirectory)) + if (!Directory.Exists(cacheDirectory) || !isDirectoryWritable) { ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudRed); - TextWrapped("The folder you selected does not exist. Please provide a valid path."); + TextWrapped("The folder you selected does not exist or cannot be written to. Please provide a valid path."); ImGui.PopStyleColor(); } } + private bool isDirectoryWritable = false; + public bool IsDirectoryWritable(string dirPath, bool throwIfFails = false) { try diff --git a/MareSynchronos/Utils/DalamudUtil.cs b/MareSynchronos/Utils/DalamudUtil.cs index 176b706..289f604 100644 --- a/MareSynchronos/Utils/DalamudUtil.cs +++ b/MareSynchronos/Utils/DalamudUtil.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using Dalamud.Game; using Dalamud.Game.ClientState; using Dalamud.Game.ClientState.Objects; using Dalamud.Game.ClientState.Objects.SubKinds; using Dalamud.Game.ClientState.Objects.Types; -using Penumbra.PlayerWatch; using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject; namespace MareSynchronos.Utils @@ -16,30 +16,37 @@ namespace MareSynchronos.Utils public delegate void LogIn(); public delegate void LogOut(); + public delegate void FrameworkUpdate(); + public class DalamudUtil : IDisposable { private readonly ClientState _clientState; private readonly ObjectTable _objectTable; - private readonly IPlayerWatcher _watcher; + private readonly Framework _framework; public event PlayerChange? PlayerChanged; public event LogIn? LogIn; public event LogOut? LogOut; + public event FrameworkUpdate? FrameworkUpdate; - public DalamudUtil(ClientState clientState, ObjectTable objectTable, IPlayerWatcher watcher) + public DalamudUtil(ClientState clientState, ObjectTable objectTable, Framework framework) { _clientState = clientState; _objectTable = objectTable; - _watcher = watcher; - _watcher.Enable(); - _watcher.PlayerChanged += WatcherOnPlayerChanged; + _framework = framework; _clientState.Login += ClientStateOnLogin; _clientState.Logout += ClientStateOnLogout; + _framework.Update += FrameworkOnUpdate; if (IsLoggedIn) { ClientStateOnLogin(null, EventArgs.Empty); } } + private void FrameworkOnUpdate(Framework framework) + { + FrameworkUpdate?.Invoke(); + } + private void ClientStateOnLogout(object? sender, EventArgs e) { LogOut?.Invoke(); @@ -57,17 +64,6 @@ namespace MareSynchronos.Utils PlayerChanged?.Invoke(actor); } - - public void AddPlayerToWatch(string playerName) - { - _watcher.AddPlayerToWatch(playerName); - } - - public void RemovePlayerFromWatch(string playerName) - { - _watcher.RemovePlayerFromWatch(playerName); - } - public bool IsPlayerPresent => _clientState.LocalPlayer != null; public string PlayerName => _clientState.LocalPlayer?.Name.ToString() ?? "--"; @@ -76,6 +72,8 @@ namespace MareSynchronos.Utils public IntPtr PlayerPointer => _clientState.LocalPlayer!.Address; + public PlayerCharacter PlayerCharacter => _clientState.LocalPlayer!; + public string PlayerNameHashed => Crypto.GetHash256(PlayerName + _clientState.LocalPlayer!.HomeWorld.Id); public Dictionary GetLocalPlayers() @@ -105,7 +103,7 @@ namespace MareSynchronos.Utils obj.Name.ToString() != PlayerName).Select(p => (PlayerCharacter)p).ToList(); } - public PlayerCharacter? GetPlayerCharacterFromObjectTableIndex(int index) + public PlayerCharacter? GetPlayerCharacterFromObjectTableByIndex(int index) { var objTableObj = _objectTable[index]; if (objTableObj!.ObjectKind != Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player) return null; @@ -132,8 +130,8 @@ namespace MareSynchronos.Utils // ReSharper disable once LoopVariableIsNeverChangedInsideLoop while ((obj->RenderFlags & 0b100000000000) == 0b100000000000 && (!ct?.IsCancellationRequested ?? true)) // 0b100000000000 is "still rendering" or something { - Logger.Debug("Waiting for character to finish drawing"); - Thread.Sleep(1000); + Logger.Verbose("Waiting for character to finish drawing"); + Thread.Sleep(250); } if (ct?.IsCancellationRequested ?? false) return; @@ -145,8 +143,9 @@ namespace MareSynchronos.Utils public void Dispose() { - _watcher.Disable(); - _watcher.Dispose(); + _clientState.Login -= ClientStateOnLogin; + _clientState.Logout -= ClientStateOnLogout; + _framework.Update -= FrameworkOnUpdate; } } } diff --git a/MareSynchronos/WebAPI/ApIController.Functions.Files.cs b/MareSynchronos/WebAPI/ApIController.Functions.Files.cs index 0b9fc1c..6886ec1 100644 --- a/MareSynchronos/WebAPI/ApIController.Functions.Files.cs +++ b/MareSynchronos/WebAPI/ApIController.Functions.Files.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; +using Dalamud.Logging; using LZ4; using MareSynchronos.API; using MareSynchronos.FileCacheDB; @@ -49,31 +50,60 @@ namespace MareSynchronos.WebAPI public async Task DownloadFiles(List fileReplacementDto, CancellationToken ct) { - IsDownloading = true; - + Logger.Debug("Downloading files"); + List fileTransferList = new List(); + List downloadFiles = new List(); foreach (var file in fileReplacementDto) { - var downloadFileDto = await _fileHub!.InvokeAsync("GetFileSize", file.Hash, ct); - CurrentDownloads.Add(new FileTransfer + downloadFiles.Add(await _fileHub!.InvokeAsync("GetFileSize", file.Hash, ct)); + /*var downloadFileDto = ; + var downloadFileTransfer = new DownloadFileTransfer(downloadFileDto); + if (CurrentDownloads.Any(f => f.Hash == downloadFileTransfer.Hash)) { - Total = downloadFileDto.Size, - Hash = downloadFileDto.Hash - }); - } + if (fileTransferList.All(f => f.Hash != downloadFileTransfer.Hash)) + { + fileTransferList.Add(downloadFileTransfer); + } - List downloadedHashes = new(); - foreach (var file in fileReplacementDto.Where(f => CurrentDownloads.Single(t => f.Hash == t.Hash).Transferred > 0)) - { - if (downloadedHashes.Contains(file.Hash)) - { continue; } + if (fileTransferList.All(f => f.Hash != downloadFileTransfer.Hash)) + { + fileTransferList.Add(downloadFileTransfer); + } + CurrentDownloads.Add(new DownloadFileTransfer(downloadFileDto));*/ + } + + downloadFiles = downloadFiles.Distinct().ToList(); + + foreach (var dto in downloadFiles) + { + var downloadFileTransfer = new DownloadFileTransfer(dto); + if (CurrentDownloads.All(f => f.Hash != downloadFileTransfer.Hash)) + { + CurrentDownloads.Add(downloadFileTransfer); + } + + fileTransferList.Add(downloadFileTransfer); + } + + foreach (var file in CurrentDownloads.Where(c => c.IsForbidden)) + { + if (ForbiddenTransfers.All(f => f.Hash != file.Hash)) + { + ForbiddenTransfers.Add(file); + } + } + + foreach (var file in fileTransferList.Where(f => f.CanBeTransferred)) + { var hash = file.Hash; var tempFile = await DownloadFile(hash, ct); if (ct.IsCancellationRequested) { File.Delete(tempFile); + CurrentDownloads.RemoveAll(d => fileReplacementDto.Any(f => f.Hash == d.Hash)); break; } @@ -94,7 +124,6 @@ namespace MareSynchronos.WebAPI fi.CreationTime = RandomDayFunc().Invoke(); fi.LastAccessTime = RandomDayFunc().Invoke(); fi.LastWriteTime = RandomDayFunc().Invoke(); - downloadedHashes.Add(hash); } var allFilesInDb = false; @@ -102,14 +131,81 @@ namespace MareSynchronos.WebAPI { await using (var db = new FileCacheContext()) { - allFilesInDb = downloadedHashes.All(h => db.FileCaches.Any(f => f.Hash == h)); + allFilesInDb = fileTransferList.Where(c => c.CanBeTransferred).All(h => db.FileCaches.Any(f => f.Hash == h.Hash)); } await Task.Delay(250, ct); } - CurrentDownloads.Clear(); - IsDownloading = false; + CurrentDownloads.RemoveAll(d => d.Transferred == d.Total); + } + + public async Task SendCharacterData(CharacterCacheDto character, List visibleCharacterIds) + { + if (!IsConnected || SecretKey == "-") return; + Logger.Debug("Sending Character data to service " + ApiUri); + + CancelUpload(); + _uploadCancellationTokenSource = new CancellationTokenSource(); + var uploadToken = _uploadCancellationTokenSource.Token; + Logger.Verbose("New Token Created"); + + var filesToUpload = await _fileHub!.InvokeAsync>("SendFiles", character.FileReplacements.Select(c => c.Hash).Distinct(), uploadToken); + + foreach (var file in filesToUpload.Where(f => !f.IsForbidden)) + { + await using var db = new FileCacheContext(); + CurrentUploads.Add(new UploadFileTransfer(file) + { + Total = new FileInfo(db.FileCaches.First(f => f.Hash == file.Hash).Filepath).Length + }); + } + + foreach (var file in CurrentUploads.Where(c => c.IsForbidden)) + { + if (ForbiddenTransfers.All(f => f.Hash != file.Hash)) + { + ForbiddenTransfers.Add(file); + } + } + + Logger.Verbose("Compressing and uploading files"); + foreach (var file in CurrentUploads.Where(f => f.CanBeTransferred && !f.IsTransferred)) + { + Logger.Verbose("Compressing and uploading " + file); + var data = await GetCompressedFileData(file.Hash, uploadToken); + CurrentUploads.Single(e => e.Hash == data.Item1).Total = data.Item2.Length; + _ = UploadFile(data.Item2, file.Hash, uploadToken); + if (!uploadToken.IsCancellationRequested) continue; + Logger.Warn("Cancel in filesToUpload loop detected"); + CurrentUploads.Clear(); + break; + } + + Logger.Verbose("Upload tasks complete, waiting for server to confirm"); + var anyUploadsOpen = await _fileHub!.InvokeAsync("IsUploadFinished", uploadToken); + Logger.Verbose("Uploads open: " + anyUploadsOpen); + while (anyUploadsOpen && !uploadToken.IsCancellationRequested) + { + anyUploadsOpen = await _fileHub!.InvokeAsync("IsUploadFinished", uploadToken); + await Task.Delay(TimeSpan.FromSeconds(0.5), uploadToken); + Logger.Verbose("Waiting for uploads to finish"); + } + + CurrentUploads.Clear(); + + if (!uploadToken.IsCancellationRequested) + { + Logger.Verbose("=== Pushing character data ==="); + await _userHub!.InvokeAsync("PushCharacterData", character, visibleCharacterIds, uploadToken); + } + else + { + Logger.Warn("=== Upload operation was cancelled ==="); + } + + Logger.Verbose("Upload complete for " + character.Hash); + _uploadCancellationTokenSource = null; } private async Task<(string, byte[])> GetCompressedFileData(string fileHash, CancellationToken uploadToken) diff --git a/MareSynchronos/WebAPI/ApIController.Functions.Users.cs b/MareSynchronos/WebAPI/ApIController.Functions.Users.cs index ced2425..af4be77 100644 --- a/MareSynchronos/WebAPI/ApIController.Functions.Users.cs +++ b/MareSynchronos/WebAPI/ApIController.Functions.Users.cs @@ -40,70 +40,6 @@ namespace MareSynchronos.WebAPI await CreateConnections(); } - public async Task SendCharacterData(CharacterCacheDto character, List visibleCharacterIds) - { - if (!IsConnected || SecretKey == "-") return; - Logger.Debug("Sending Character data to service " + ApiUri); - - CancelUpload(); - _uploadCancellationTokenSource = new CancellationTokenSource(); - var uploadToken = _uploadCancellationTokenSource.Token; - Logger.Verbose("New Token Created"); - - var filesToUpload = await _fileHub!.InvokeAsync>("SendFiles", character.FileReplacements.Select(c => c.Hash).Distinct(), uploadToken); - - IsUploading = true; - - foreach (var file in filesToUpload.Where(f => f.IsForbidden == false)) - { - await using var db = new FileCacheContext(); - CurrentUploads.Add(new FileTransfer() - { - Hash = file.Hash, - Total = new FileInfo(db.FileCaches.First(f => f.Hash == file.Hash).Filepath).Length - }); - } - - Logger.Verbose("Compressing and uploading files"); - foreach (var file in filesToUpload) - { - Logger.Verbose("Compressing and uploading " + file); - var data = await GetCompressedFileData(file.Hash, uploadToken); - CurrentUploads.Single(e => e.Hash == data.Item1).Total = data.Item2.Length; - _ = UploadFile(data.Item2, file.Hash, uploadToken); - if (!uploadToken.IsCancellationRequested) continue; - Logger.Warn("Cancel in filesToUpload loop detected"); - CurrentUploads.Clear(); - break; - } - - Logger.Verbose("Upload tasks complete, waiting for server to confirm"); - var anyUploadsOpen = await _fileHub!.InvokeAsync("IsUploadFinished", uploadToken); - Logger.Verbose("Uploads open: " + anyUploadsOpen); - while (anyUploadsOpen && !uploadToken.IsCancellationRequested) - { - anyUploadsOpen = await _fileHub!.InvokeAsync("IsUploadFinished", uploadToken); - await Task.Delay(TimeSpan.FromSeconds(0.5), uploadToken); - Logger.Verbose("Waiting for uploads to finish"); - } - - CurrentUploads.Clear(); - IsUploading = false; - - if (!uploadToken.IsCancellationRequested) - { - Logger.Verbose("=== Pushing character data ==="); - await _userHub!.InvokeAsync("PushCharacterData", character, visibleCharacterIds, uploadToken); - } - else - { - Logger.Warn("=== Upload operation was cancelled ==="); - } - - Logger.Verbose("Upload complete for " + character.Hash); - _uploadCancellationTokenSource = null; - } - public async Task> GetOnlineCharacters() { return await _userHub!.InvokeAsync>("GetOnlineCharacters"); diff --git a/MareSynchronos/WebAPI/ApiController.Connectivity.cs b/MareSynchronos/WebAPI/ApiController.Connectivity.cs index 5167279..da5f59a 100644 --- a/MareSynchronos/WebAPI/ApiController.Connectivity.cs +++ b/MareSynchronos/WebAPI/ApiController.Connectivity.cs @@ -89,15 +89,17 @@ namespace MareSynchronos.WebAPI public List CurrentUploads { get; } = new(); - public List BannedUsers { get; private set; } = new(); + public List ForbiddenTransfers { get; } = new(); - public List ForbiddenFiles { get; private set; } = new(); + public List AdminBannedUsers { get; private set; } = new(); + + public List AdminForbiddenFiles { get; private set; } = new(); public bool IsConnected => !string.IsNullOrEmpty(UID); - public bool IsDownloading { get; private set; } + public bool IsDownloading => CurrentDownloads.Count > 0; - public bool IsUploading { get; private set; } + public bool IsUploading => CurrentUploads.Count > 0; public List PairedClients { get; set; } = new(); @@ -168,8 +170,8 @@ namespace MareSynchronos.WebAPI if (IsModerator) { - ForbiddenFiles = await _adminHub.InvokeAsync>("GetForbiddenFiles", token); - BannedUsers = await _adminHub.InvokeAsync>("GetBannedUsers", token); + AdminForbiddenFiles = await _adminHub.InvokeAsync>("GetForbiddenFiles", token); + AdminBannedUsers = await _adminHub.InvokeAsync>("GetBannedUsers", token); _adminHub.On("UpdateOrAddBannedUser", UpdateOrAddBannedUserCallback); _adminHub.On("DeleteBannedUser", DeleteBannedUserCallback); _adminHub.On("UpdateOrAddForbiddenFile", UpdateOrAddForbiddenFileCallback); diff --git a/MareSynchronos/WebAPI/ApiController.Functions.Callbacks.cs b/MareSynchronos/WebAPI/ApiController.Functions.Callbacks.cs index b9d1900..4ad9256 100644 --- a/MareSynchronos/WebAPI/ApiController.Functions.Callbacks.cs +++ b/MareSynchronos/WebAPI/ApiController.Functions.Callbacks.cs @@ -54,10 +54,10 @@ namespace MareSynchronos.WebAPI private void UpdateOrAddBannedUserCallback(BannedUserDto obj) { - var user = BannedUsers.SingleOrDefault(b => b.CharacterHash == obj.CharacterHash); + var user = AdminBannedUsers.SingleOrDefault(b => b.CharacterHash == obj.CharacterHash); if (user == null) { - BannedUsers.Add(obj); + AdminBannedUsers.Add(obj); } else { @@ -67,15 +67,15 @@ namespace MareSynchronos.WebAPI private void DeleteBannedUserCallback(BannedUserDto obj) { - BannedUsers.RemoveAll(a => a.CharacterHash == obj.CharacterHash); + AdminBannedUsers.RemoveAll(a => a.CharacterHash == obj.CharacterHash); } private void UpdateOrAddForbiddenFileCallback(ForbiddenFileDto obj) { - var user = ForbiddenFiles.SingleOrDefault(b => b.Hash == obj.Hash); + var user = AdminForbiddenFiles.SingleOrDefault(b => b.Hash == obj.Hash); if (user == null) { - ForbiddenFiles.Add(obj); + AdminForbiddenFiles.Add(obj); } else { @@ -85,7 +85,7 @@ namespace MareSynchronos.WebAPI private void DeleteForbiddenFileCallback(ForbiddenFileDto obj) { - ForbiddenFiles.RemoveAll(f => f.Hash == obj.Hash); + AdminForbiddenFiles.RemoveAll(f => f.Hash == obj.Hash); } } } diff --git a/MareSynchronos/WebAPI/Utils/FileTransfer.cs b/MareSynchronos/WebAPI/Utils/FileTransfer.cs index 8a3c0b9..24c4020 100644 --- a/MareSynchronos/WebAPI/Utils/FileTransfer.cs +++ b/MareSynchronos/WebAPI/Utils/FileTransfer.cs @@ -1,8 +1,42 @@ -namespace MareSynchronos.WebAPI.Utils; +using MareSynchronos.API; -public class FileTransfer +namespace MareSynchronos.WebAPI.Utils; + +public abstract class FileTransfer { + protected readonly ITransferFileDto TransferDto; + + protected FileTransfer(ITransferFileDto transferDto) + { + TransferDto = transferDto; + } + + public string ForbiddenBy => TransferDto.ForbiddenBy; public long Transferred { get; set; } = 0; - public long Total { get; set; } = 0; - public string Hash { get; set; } = string.Empty; + public abstract long Total { get; set; } + public string Hash => TransferDto.Hash; + public bool IsInTransfer => Transferred != Total && Transferred > 0; + public bool IsTransferred => Transferred == Total; + public virtual bool CanBeTransferred => !TransferDto.IsForbidden; + public bool IsForbidden => TransferDto.IsForbidden; +} + +public class UploadFileTransfer : FileTransfer +{ + public UploadFileTransfer(UploadFileDto dto) : base(dto) { } + public override long Total { get; set; } +} + +public class DownloadFileTransfer : FileTransfer +{ + private DownloadFileDto Dto => (DownloadFileDto)TransferDto; + public DownloadFileTransfer(DownloadFileDto dto) : base(dto) { } + + public override long Total + { + set { } + get => Dto.Size; + } + + public override bool CanBeTransferred => Dto.FileExists && !Dto.IsForbidden && Dto.Size > 0; } \ No newline at end of file