rework a lot of stuff: downloads, how to watch a player
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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<string, CharacterCacheDto> _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!);
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<CachedPlayer> _onlineCachedPlayers = new();
|
||||
private readonly List<string> _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)));
|
||||
@@ -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<CharacterData> 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();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\Penumbra\Penumbra.GameData\Penumbra.GameData.csproj" />
|
||||
<ProjectReference Include="..\..\..\Penumbra\Penumbra.PlayerWatch\Penumbra.PlayerWatch.csproj" />
|
||||
<ProjectReference Include="..\..\server\MareSynchronosServer\MareSynchronos.API\MareSynchronos.API.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<string, PlayerCharacter> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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> fileReplacementDto, CancellationToken ct)
|
||||
{
|
||||
IsDownloading = true;
|
||||
|
||||
Logger.Debug("Downloading files");
|
||||
List<FileTransfer> fileTransferList = new List<FileTransfer>();
|
||||
List<DownloadFileDto> downloadFiles = new List<DownloadFileDto>();
|
||||
foreach (var file in fileReplacementDto)
|
||||
{
|
||||
var downloadFileDto = await _fileHub!.InvokeAsync<DownloadFileDto>("GetFileSize", file.Hash, ct);
|
||||
CurrentDownloads.Add(new FileTransfer
|
||||
downloadFiles.Add(await _fileHub!.InvokeAsync<DownloadFileDto>("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<string> 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<string> 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<List<UploadFileDto>>("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<bool>("IsUploadFinished", uploadToken);
|
||||
Logger.Verbose("Uploads open: " + anyUploadsOpen);
|
||||
while (anyUploadsOpen && !uploadToken.IsCancellationRequested)
|
||||
{
|
||||
anyUploadsOpen = await _fileHub!.InvokeAsync<bool>("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)
|
||||
|
||||
@@ -40,70 +40,6 @@ namespace MareSynchronos.WebAPI
|
||||
await CreateConnections();
|
||||
}
|
||||
|
||||
public async Task SendCharacterData(CharacterCacheDto character, List<string> 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<List<UploadFileDto>>("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<bool>("IsUploadFinished", uploadToken);
|
||||
Logger.Verbose("Uploads open: " + anyUploadsOpen);
|
||||
while (anyUploadsOpen && !uploadToken.IsCancellationRequested)
|
||||
{
|
||||
anyUploadsOpen = await _fileHub!.InvokeAsync<bool>("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<List<string>> GetOnlineCharacters()
|
||||
{
|
||||
return await _userHub!.InvokeAsync<List<string>>("GetOnlineCharacters");
|
||||
|
||||
@@ -89,15 +89,17 @@ namespace MareSynchronos.WebAPI
|
||||
|
||||
public List<FileTransfer> CurrentUploads { get; } = new();
|
||||
|
||||
public List<BannedUserDto> BannedUsers { get; private set; } = new();
|
||||
public List<FileTransfer> ForbiddenTransfers { get; } = new();
|
||||
|
||||
public List<ForbiddenFileDto> ForbiddenFiles { get; private set; } = new();
|
||||
public List<BannedUserDto> AdminBannedUsers { get; private set; } = new();
|
||||
|
||||
public List<ForbiddenFileDto> 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<ClientPairDto> PairedClients { get; set; } = new();
|
||||
|
||||
@@ -168,8 +170,8 @@ namespace MareSynchronos.WebAPI
|
||||
|
||||
if (IsModerator)
|
||||
{
|
||||
ForbiddenFiles = await _adminHub.InvokeAsync<List<ForbiddenFileDto>>("GetForbiddenFiles", token);
|
||||
BannedUsers = await _adminHub.InvokeAsync<List<BannedUserDto>>("GetBannedUsers", token);
|
||||
AdminForbiddenFiles = await _adminHub.InvokeAsync<List<ForbiddenFileDto>>("GetForbiddenFiles", token);
|
||||
AdminBannedUsers = await _adminHub.InvokeAsync<List<BannedUserDto>>("GetBannedUsers", token);
|
||||
_adminHub.On<BannedUserDto>("UpdateOrAddBannedUser", UpdateOrAddBannedUserCallback);
|
||||
_adminHub.On<BannedUserDto>("DeleteBannedUser", DeleteBannedUserCallback);
|
||||
_adminHub.On<ForbiddenFileDto>("UpdateOrAddForbiddenFile", UpdateOrAddForbiddenFileCallback);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
Reference in New Issue
Block a user