rework the whole connection garbage/custom servers, other cleanups/refactors
This commit is contained in:
		| @@ -25,6 +25,7 @@ namespace MareSynchronos | |||||||
|  |  | ||||||
|         public string CacheFolder { get; set; } = string.Empty; |         public string CacheFolder { get; set; } = string.Empty; | ||||||
|         public Dictionary<string, string> ClientSecret { get; set; } = new(); |         public Dictionary<string, string> ClientSecret { get; set; } = new(); | ||||||
|  |         public Dictionary<string, string> CustomServerList { get; set; } = new(); | ||||||
|         [JsonIgnore] |         [JsonIgnore] | ||||||
|         public bool HasValidSetup => AcceptedAgreement && InitialScanComplete && !string.IsNullOrEmpty(CacheFolder) && |         public bool HasValidSetup => AcceptedAgreement && InitialScanComplete && !string.IsNullOrEmpty(CacheFolder) && | ||||||
|                                      Directory.Exists(CacheFolder) && ClientSecret.ContainsKey(ApiUri); |                                      Directory.Exists(CacheFolder) && ClientSecret.ContainsKey(ApiUri); | ||||||
| @@ -46,7 +47,6 @@ namespace MareSynchronos | |||||||
|  |  | ||||||
|         public bool FullPause { get; set; } = false; |         public bool FullPause { get; set; } = false; | ||||||
|         public Dictionary<string, string> UidComments { get; set; } = new(); |         public Dictionary<string, string> UidComments { get; set; } = new(); | ||||||
|         public bool UseCustomService { get; set; } = false; |  | ||||||
|         public int Version { get; set; } = 0; |         public int Version { get; set; } = 0; | ||||||
|  |  | ||||||
|         public bool ShowTransferWindow { get; set; } = true; |         public bool ShowTransferWindow { get; set; } = true; | ||||||
|   | |||||||
| @@ -4,12 +4,9 @@ using System.Linq; | |||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Dalamud.Game; | using Dalamud.Game; | ||||||
| using Dalamud.Game.ClientState; | using Dalamud.Game.ClientState; | ||||||
| using Dalamud.Game.ClientState.Objects; |  | ||||||
| using Dalamud.Game.ClientState.Objects.SubKinds; |  | ||||||
| using MareSynchronos.Models; | using MareSynchronos.Models; | ||||||
| using MareSynchronos.Utils; | using MareSynchronos.Utils; | ||||||
| using MareSynchronos.WebAPI; | using MareSynchronos.WebAPI; | ||||||
| using Penumbra.PlayerWatch; |  | ||||||
|  |  | ||||||
| namespace MareSynchronos.Managers; | namespace MareSynchronos.Managers; | ||||||
|  |  | ||||||
| @@ -20,23 +17,20 @@ public class CachedPlayersManager : IDisposable | |||||||
|     private readonly DalamudUtil _dalamudUtil; |     private readonly DalamudUtil _dalamudUtil; | ||||||
|     private readonly Framework _framework; |     private readonly Framework _framework; | ||||||
|     private readonly IpcManager _ipcManager; |     private readonly IpcManager _ipcManager; | ||||||
|     private readonly IPlayerWatcher _watcher; |  | ||||||
|     private readonly ObjectTable _objectTable; |  | ||||||
|     private readonly List<CachedPlayer> _onlineCachedPlayers = new(); |     private readonly List<CachedPlayer> _onlineCachedPlayers = new(); | ||||||
|     private readonly List<string> _localVisiblePlayers = new(); |     private readonly List<string> _localVisiblePlayers = new(); | ||||||
|     private DateTime _lastPlayerObjectCheck = DateTime.Now; |     private DateTime _lastPlayerObjectCheck = DateTime.Now; | ||||||
|  |  | ||||||
|     public CachedPlayersManager(ClientState clientState, Framework framework, ObjectTable objectTable, ApiController apiController, DalamudUtil dalamudUtil, IpcManager ipcManager, IPlayerWatcher watcher) |     public CachedPlayersManager(ClientState clientState, Framework framework, | ||||||
|  |         ApiController apiController, DalamudUtil dalamudUtil, IpcManager ipcManager) | ||||||
|     { |     { | ||||||
|         Logger.Debug("Creating " + nameof(CachedPlayersManager)); |         Logger.Debug("Creating " + nameof(CachedPlayersManager)); | ||||||
|  |  | ||||||
|         _clientState = clientState; |         _clientState = clientState; | ||||||
|         _framework = framework; |         _framework = framework; | ||||||
|         _objectTable = objectTable; |  | ||||||
|         _apiController = apiController; |         _apiController = apiController; | ||||||
|         _dalamudUtil = dalamudUtil; |         _dalamudUtil = dalamudUtil; | ||||||
|         _ipcManager = ipcManager; |         _ipcManager = ipcManager; | ||||||
|         _watcher = watcher; |  | ||||||
|  |  | ||||||
|         _clientState.Login += ClientStateOnLogin; |         _clientState.Login += ClientStateOnLogin; | ||||||
|         _clientState.Logout += ClientStateOnLogout; |         _clientState.Logout += ClientStateOnLogout; | ||||||
| @@ -53,7 +47,7 @@ public class CachedPlayersManager : IDisposable | |||||||
|             ClientStateOnLogin(null, EventArgs.Empty); |             ClientStateOnLogin(null, EventArgs.Empty); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |      | ||||||
|     private void IpcManagerOnPenumbraDisposed(object? sender, EventArgs e) |     private void IpcManagerOnPenumbraDisposed(object? sender, EventArgs e) | ||||||
|     { |     { | ||||||
|         _onlineCachedPlayers.ForEach(p => p.DisposePlayer()); |         _onlineCachedPlayers.ForEach(p => p.DisposePlayer()); | ||||||
| @@ -159,14 +153,10 @@ public class CachedPlayersManager : IDisposable | |||||||
|         if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(0.25)) return; |         if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(0.25)) return; | ||||||
|  |  | ||||||
|         _localVisiblePlayers.Clear(); |         _localVisiblePlayers.Clear(); | ||||||
|         string ownName = _dalamudUtil.PlayerName; |         var playerCharacters = _dalamudUtil.GetPlayerCharacters(); | ||||||
|         var playerCharacters = _objectTable.Where(obj => |         foreach (var pChar in playerCharacters) | ||||||
|             obj.ObjectKind == Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player && |  | ||||||
|             obj.Name.ToString() != ownName).ToList(); |  | ||||||
|         foreach (var obj in playerCharacters) |  | ||||||
|         { |         { | ||||||
|             var pObj = (PlayerCharacter)obj; |             var pObjName = pChar.Name.ToString(); | ||||||
|             var pObjName = pObj.Name.ToString(); |  | ||||||
|             _localVisiblePlayers.Add(pObjName); |             _localVisiblePlayers.Add(pObjName); | ||||||
|             var existingCachedPlayer = _onlineCachedPlayers.SingleOrDefault(p => p.PlayerName == pObjName); |             var existingCachedPlayer = _onlineCachedPlayers.SingleOrDefault(p => p.PlayerName == pObjName); | ||||||
|             if (existingCachedPlayer != null) |             if (existingCachedPlayer != null) | ||||||
| @@ -175,8 +165,8 @@ public class CachedPlayersManager : IDisposable | |||||||
|                 continue; |                 continue; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             var hashedName = Crypto.GetHash256(pObj.Name.ToString() + pObj.HomeWorld.Id.ToString()); |             var hashedName = Crypto.GetHash256(pChar); | ||||||
|             _onlineCachedPlayers.SingleOrDefault(p => p.PlayerNameHash == hashedName)?.InitializePlayer(pObj); |             _onlineCachedPlayers.SingleOrDefault(p => p.PlayerNameHash == hashedName)?.InitializePlayer(pChar); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         _onlineCachedPlayers.Where(p => !string.IsNullOrEmpty(p.PlayerName) && !_localVisiblePlayers.Contains(p.PlayerName)) |         _onlineCachedPlayers.Where(p => !string.IsNullOrEmpty(p.PlayerName) && !_localVisiblePlayers.Contains(p.PlayerName)) | ||||||
| @@ -191,6 +181,6 @@ public class CachedPlayersManager : IDisposable | |||||||
|  |  | ||||||
|     private CachedPlayer CreateCachedPlayer(string hashedName) |     private CachedPlayer CreateCachedPlayer(string hashedName) | ||||||
|     { |     { | ||||||
|         return new CachedPlayer(hashedName, _ipcManager, _apiController, _dalamudUtil, _watcher); |         return new CachedPlayer(hashedName, _ipcManager, _apiController, _dalamudUtil); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| @@ -34,12 +34,10 @@ namespace MareSynchronos.Managers | |||||||
|  |  | ||||||
|         private void StartWatchersAndScan() |         private void StartWatchersAndScan() | ||||||
|         { |         { | ||||||
|             if (_ipcManager.Initialized && _pluginConfiguration.HasValidSetup) |             if (!_ipcManager.Initialized || !_pluginConfiguration.HasValidSetup) return; | ||||||
|             { |             Logger.Debug("Penumbra is active, configuration is valid, starting watchers and scan"); | ||||||
|                 Logger.Debug("Penumbra is active, configuration is valid, starting watchers and scan"); |             StartWatchers(); | ||||||
|                 StartWatchers(); |             StartInitialScan(); | ||||||
|                 StartInitialScan(); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void IpcManagerOnPenumbraInitialized(object? sender, EventArgs e) |         private void IpcManagerOnPenumbraInitialized(object? sender, EventArgs e) | ||||||
|   | |||||||
| @@ -146,7 +146,9 @@ namespace MareSynchronos.Managers | |||||||
|         { |         { | ||||||
|             if (!CheckPenumbraApi()) return string.Empty; |             if (!CheckPenumbraApi()) return string.Empty; | ||||||
|             Logger.Debug("Creating temp collection for " + characterName); |             Logger.Debug("Creating temp collection for " + characterName); | ||||||
|             return _penumbraCreateTemporaryCollection.InvokeFunc("MareSynchronos", characterName, true).Item2; |             var ret = _penumbraCreateTemporaryCollection.InvokeFunc("MareSynchronos", characterName, true); | ||||||
|  |             Logger.Debug("Penumbra ret: " + ret.Item1); | ||||||
|  |             return ret.Item2; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public string PenumbraGetMetaManipulations(string characterName) |         public string PenumbraGetMetaManipulations(string characterName) | ||||||
|   | |||||||
| @@ -4,7 +4,6 @@ using MareSynchronos.Models; | |||||||
| using MareSynchronos.Utils; | using MareSynchronos.Utils; | ||||||
| using MareSynchronos.WebAPI; | using MareSynchronos.WebAPI; | ||||||
| using Newtonsoft.Json; | using Newtonsoft.Json; | ||||||
| using Penumbra.PlayerWatch; |  | ||||||
| using System; | using System; | ||||||
| using System.Diagnostics; | using System.Diagnostics; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| @@ -20,12 +19,11 @@ namespace MareSynchronos.Managers | |||||||
|         private readonly CharacterDataFactory _characterDataFactory; |         private readonly CharacterDataFactory _characterDataFactory; | ||||||
|         private readonly DalamudUtil _dalamudUtil; |         private readonly DalamudUtil _dalamudUtil; | ||||||
|         private readonly IpcManager _ipcManager; |         private readonly IpcManager _ipcManager; | ||||||
|         private readonly IPlayerWatcher _watcher; |  | ||||||
|         private string _lastSentHash = string.Empty; |         private string _lastSentHash = string.Empty; | ||||||
|         private Task? _playerChangedTask; |         private Task? _playerChangedTask; | ||||||
|  |  | ||||||
|         public PlayerManager(ApiController apiController, IpcManager ipcManager, |         public PlayerManager(ApiController apiController, IpcManager ipcManager, | ||||||
|             CharacterDataFactory characterDataFactory, CachedPlayersManager cachedPlayersManager, DalamudUtil dalamudUtil, IPlayerWatcher watcher) |             CharacterDataFactory characterDataFactory, CachedPlayersManager cachedPlayersManager, DalamudUtil dalamudUtil) | ||||||
|         { |         { | ||||||
|             Logger.Debug("Creating " + nameof(PlayerManager)); |             Logger.Debug("Creating " + nameof(PlayerManager)); | ||||||
|  |  | ||||||
| @@ -34,9 +32,8 @@ namespace MareSynchronos.Managers | |||||||
|             _characterDataFactory = characterDataFactory; |             _characterDataFactory = characterDataFactory; | ||||||
|             _cachedPlayersManager = cachedPlayersManager; |             _cachedPlayersManager = cachedPlayersManager; | ||||||
|             _dalamudUtil = dalamudUtil; |             _dalamudUtil = dalamudUtil; | ||||||
|             _watcher = watcher; |  | ||||||
|  |  | ||||||
|             _watcher.AddPlayerToWatch(_dalamudUtil.PlayerName); |             _dalamudUtil.AddPlayerToWatch(_dalamudUtil.PlayerName); | ||||||
|             _apiController.Connected += ApiController_Connected; |             _apiController.Connected += ApiController_Connected; | ||||||
|             _apiController.Disconnected += ApiController_Disconnected; |             _apiController.Disconnected += ApiController_Disconnected; | ||||||
|  |  | ||||||
| @@ -54,7 +51,7 @@ namespace MareSynchronos.Managers | |||||||
|             _ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent; |             _ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent; | ||||||
|             _apiController.Connected -= ApiController_Connected; |             _apiController.Connected -= ApiController_Connected; | ||||||
|             _apiController.Disconnected -= ApiController_Disconnected; |             _apiController.Disconnected -= ApiController_Disconnected; | ||||||
|             _watcher.PlayerChanged -= Watcher_PlayerChanged; |             _dalamudUtil.PlayerChanged -= Watcher_PlayerChanged; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ApiController_Connected(object? sender, EventArgs args) |         private void ApiController_Connected(object? sender, EventArgs args) | ||||||
| @@ -69,7 +66,7 @@ namespace MareSynchronos.Managers | |||||||
|  |  | ||||||
|             _ipcManager.PenumbraRedrawEvent += IpcManager_PenumbraRedrawEvent; |             _ipcManager.PenumbraRedrawEvent += IpcManager_PenumbraRedrawEvent; | ||||||
|             _ipcManager.PenumbraRedraw(_dalamudUtil.PlayerName); |             _ipcManager.PenumbraRedraw(_dalamudUtil.PlayerName); | ||||||
|             _watcher.PlayerChanged += Watcher_PlayerChanged; |             _dalamudUtil.PlayerChanged += Watcher_PlayerChanged; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ApiController_Disconnected(object? sender, EventArgs args) |         private void ApiController_Disconnected(object? sender, EventArgs args) | ||||||
| @@ -77,7 +74,7 @@ namespace MareSynchronos.Managers | |||||||
|             Logger.Debug(nameof(ApiController_Disconnected)); |             Logger.Debug(nameof(ApiController_Disconnected)); | ||||||
|  |  | ||||||
|             _ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent; |             _ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent; | ||||||
|             _watcher.PlayerChanged -= Watcher_PlayerChanged; |             _dalamudUtil.PlayerChanged -= Watcher_PlayerChanged; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private async Task<CharacterData> CreateFullCharacterCache() |         private async Task<CharacterData> CreateFullCharacterCache() | ||||||
|   | |||||||
| @@ -11,7 +11,6 @@ using MareSynchronos.FileCacheDB; | |||||||
| using MareSynchronos.Managers; | using MareSynchronos.Managers; | ||||||
| using MareSynchronos.Utils; | using MareSynchronos.Utils; | ||||||
| using MareSynchronos.WebAPI; | using MareSynchronos.WebAPI; | ||||||
| using Penumbra.PlayerWatch; |  | ||||||
|  |  | ||||||
| namespace MareSynchronos.Models; | namespace MareSynchronos.Models; | ||||||
|  |  | ||||||
| @@ -20,16 +19,14 @@ public class CachedPlayer | |||||||
|     private readonly DalamudUtil _dalamudUtil; |     private readonly DalamudUtil _dalamudUtil; | ||||||
|     private readonly IpcManager _ipcManager; |     private readonly IpcManager _ipcManager; | ||||||
|     private readonly ApiController _apiController; |     private readonly ApiController _apiController; | ||||||
|     private readonly IPlayerWatcher _watcher; |  | ||||||
|     private bool _isVisible; |     private bool _isVisible; | ||||||
|  |  | ||||||
|     public CachedPlayer(string nameHash, IpcManager ipcManager, ApiController apiController, DalamudUtil dalamudUtil, IPlayerWatcher watcher) |     public CachedPlayer(string nameHash, IpcManager ipcManager, ApiController apiController, DalamudUtil dalamudUtil) | ||||||
|     { |     { | ||||||
|         PlayerNameHash = nameHash; |         PlayerNameHash = nameHash; | ||||||
|         _ipcManager = ipcManager; |         _ipcManager = ipcManager; | ||||||
|         _apiController = apiController; |         _apiController = apiController; | ||||||
|         _dalamudUtil = dalamudUtil; |         _dalamudUtil = dalamudUtil; | ||||||
|         _watcher = watcher; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public bool IsVisible |     public bool IsVisible | ||||||
| @@ -165,7 +162,7 @@ public class CachedPlayer | |||||||
|             _downloadCancellationTokenSource?.Cancel(); |             _downloadCancellationTokenSource?.Cancel(); | ||||||
|             _downloadCancellationTokenSource?.Dispose(); |             _downloadCancellationTokenSource?.Dispose(); | ||||||
|             _downloadCancellationTokenSource = null; |             _downloadCancellationTokenSource = null; | ||||||
|             _watcher.RemovePlayerFromWatch(PlayerName); |             _dalamudUtil.RemovePlayerFromWatch(PlayerName); | ||||||
|             _ipcManager.PenumbraRemoveTemporaryCollection(PlayerName); |             _ipcManager.PenumbraRemoveTemporaryCollection(PlayerName); | ||||||
|             _ipcManager.GlamourerRevertCharacterCustomization(PlayerName); |             _ipcManager.GlamourerRevertCharacterCustomization(PlayerName); | ||||||
|             _ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerName); |             _ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerName); | ||||||
| @@ -177,7 +174,7 @@ public class CachedPlayer | |||||||
|         } |         } | ||||||
|         finally |         finally | ||||||
|         { |         { | ||||||
|             _watcher.PlayerChanged -= WatcherOnPlayerChanged; |             _dalamudUtil.PlayerChanged -= WatcherOnPlayerChanged; | ||||||
|             _ipcManager.PenumbraRedrawEvent -= IpcManagerOnPenumbraRedrawEvent; |             _ipcManager.PenumbraRedrawEvent -= IpcManagerOnPenumbraRedrawEvent; | ||||||
|             _apiController.CharacterReceived -= ApiControllerOnCharacterReceived; |             _apiController.CharacterReceived -= ApiControllerOnCharacterReceived; | ||||||
|             PlayerName = string.Empty; |             PlayerName = string.Empty; | ||||||
| @@ -191,8 +188,8 @@ public class CachedPlayer | |||||||
|         PlayerName = character.Name.ToString(); |         PlayerName = character.Name.ToString(); | ||||||
|         PlayerCharacter = character; |         PlayerCharacter = character; | ||||||
|         Logger.Debug("Initializing Player " + this); |         Logger.Debug("Initializing Player " + this); | ||||||
|         _watcher.AddPlayerToWatch(PlayerName!); |         _dalamudUtil.AddPlayerToWatch(PlayerName!); | ||||||
|         _watcher.PlayerChanged += WatcherOnPlayerChanged; |         _dalamudUtil.PlayerChanged += WatcherOnPlayerChanged; | ||||||
|         _ipcManager.PenumbraRedrawEvent += IpcManagerOnPenumbraRedrawEvent; |         _ipcManager.PenumbraRedrawEvent += IpcManagerOnPenumbraRedrawEvent; | ||||||
|         _apiController.CharacterReceived += ApiControllerOnCharacterReceived; |         _apiController.CharacterReceived += ApiControllerOnCharacterReceived; | ||||||
|         _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerName); |         _originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerName); | ||||||
| @@ -203,15 +200,15 @@ public class CachedPlayer | |||||||
|         return PlayerNameHash + ":" + PlayerName + ":HasChar " + (PlayerCharacter != null); |         return PlayerNameHash + ":" + PlayerName + ":HasChar " + (PlayerCharacter != null); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private Task? penumbraRedrawEventTask; |     private Task? _penumbraRedrawEventTask; | ||||||
|  |  | ||||||
|     private void IpcManagerOnPenumbraRedrawEvent(object? sender, EventArgs e) |     private void IpcManagerOnPenumbraRedrawEvent(object? sender, EventArgs e) | ||||||
|     { |     { | ||||||
|         var player = _dalamudUtil.GetPlayerCharacterFromObjectTableIndex((int)sender!); |         var player = _dalamudUtil.GetPlayerCharacterFromObjectTableIndex((int)sender!); | ||||||
|         if (player == null || player.Name.ToString() != PlayerName) return; |         if (player == null || player.Name.ToString() != PlayerName) return; | ||||||
|         if (!penumbraRedrawEventTask?.IsCompleted ?? false) return; |         if (!_penumbraRedrawEventTask?.IsCompleted ?? false) return; | ||||||
|  |  | ||||||
|         penumbraRedrawEventTask = Task.Run(() => |         _penumbraRedrawEventTask = Task.Run(() => | ||||||
|         { |         { | ||||||
|             PlayerCharacter = player; |             PlayerCharacter = player; | ||||||
|             _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerCharacter.Address); |             _dalamudUtil.WaitWhileCharacterIsDrawing(PlayerCharacter.Address); | ||||||
|   | |||||||
| @@ -28,14 +28,12 @@ namespace MareSynchronos | |||||||
|         private readonly FileCacheManager _fileCacheManager; |         private readonly FileCacheManager _fileCacheManager; | ||||||
|         private readonly IntroUi _introUi; |         private readonly IntroUi _introUi; | ||||||
|         private readonly IpcManager _ipcManager; |         private readonly IpcManager _ipcManager; | ||||||
|         private readonly ObjectTable _objectTable; |  | ||||||
|         public static DalamudPluginInterface PluginInterface { get; set; } |         public static DalamudPluginInterface PluginInterface { get; set; } | ||||||
|         private readonly PluginUi _pluginUi; |         private readonly PluginUi _pluginUi; | ||||||
|         private readonly WindowSystem _windowSystem; |         private readonly WindowSystem _windowSystem; | ||||||
|         private PlayerManager? _playerManager; |         private PlayerManager? _playerManager; | ||||||
|         private readonly DalamudUtil _dalamudUtil; |         private readonly DalamudUtil _dalamudUtil; | ||||||
|         private CachedPlayersManager? _characterCacheManager; |         private CachedPlayersManager? _characterCacheManager; | ||||||
|         private readonly IPlayerWatcher _playerWatcher; |  | ||||||
|         private readonly DownloadUi _downloadUi; |         private readonly DownloadUi _downloadUi; | ||||||
|         private readonly FileDialogManager _fileDialogManager; |         private readonly FileDialogManager _fileDialogManager; | ||||||
|  |  | ||||||
| @@ -46,7 +44,6 @@ namespace MareSynchronos | |||||||
|             PluginInterface = pluginInterface; |             PluginInterface = pluginInterface; | ||||||
|             _commandManager = commandManager; |             _commandManager = commandManager; | ||||||
|             _framework = framework; |             _framework = framework; | ||||||
|             _objectTable = objectTable; |  | ||||||
|             _clientState = clientState; |             _clientState = clientState; | ||||||
|             _configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration(); |             _configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration(); | ||||||
|             _configuration.Initialize(PluginInterface); |             _configuration.Initialize(PluginInterface); | ||||||
| @@ -74,13 +71,11 @@ namespace MareSynchronos | |||||||
|             }; |             }; | ||||||
|             _downloadUi = new DownloadUi(_windowSystem, _configuration, _apiController); |             _downloadUi = new DownloadUi(_windowSystem, _configuration, _apiController); | ||||||
|  |  | ||||||
|             _dalamudUtil = new DalamudUtil(_clientState, _objectTable); |             _dalamudUtil = new DalamudUtil(_clientState, objectTable, PlayerWatchFactory.Create(framework, _clientState, objectTable)); | ||||||
|             _playerWatcher = PlayerWatchFactory.Create(framework, _clientState, _objectTable); |  | ||||||
|             _playerWatcher.Enable(); |  | ||||||
|  |  | ||||||
|             clientState.Login += ClientState_Login; |             clientState.Login += ClientState_Login; | ||||||
|             clientState.Logout += ClientState_Logout; |             clientState.Logout += ClientState_Logout; | ||||||
|             _apiController.AccountDeleted += ApiControllerOnAccountDeleted; |             _apiController.ChangingServers += ApiControllerOnChangingServers; | ||||||
|  |  | ||||||
|             if (clientState.IsLoggedIn) |             if (clientState.IsLoggedIn) | ||||||
|             { |             { | ||||||
| @@ -88,19 +83,17 @@ namespace MareSynchronos | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ApiControllerOnAccountDeleted(object? sender, EventArgs e) |         private void ApiControllerOnChangingServers(object? sender, EventArgs e) | ||||||
|         { |         { | ||||||
|             _pluginUi.IsOpen = false; |             _pluginUi.IsOpen = false; | ||||||
|             _introUi.IsOpen = true; |             _introUi.IsOpen = true; | ||||||
|             _characterCacheManager?.Dispose(); |  | ||||||
|             _playerManager?.Dispose(); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public string Name => "Mare Synchronos"; |         public string Name => "Mare Synchronos"; | ||||||
|         public void Dispose() |         public void Dispose() | ||||||
|         { |         { | ||||||
|             Logger.Debug("Disposing " + Name); |             Logger.Debug("Disposing " + Name); | ||||||
|             _apiController.AccountDeleted -= ApiControllerOnAccountDeleted; |             _apiController.ChangingServers -= ApiControllerOnChangingServers; | ||||||
|             _apiController?.Dispose(); |             _apiController?.Dispose(); | ||||||
|  |  | ||||||
|             _commandManager.RemoveHandler(CommandName); |             _commandManager.RemoveHandler(CommandName); | ||||||
| @@ -115,8 +108,7 @@ namespace MareSynchronos | |||||||
|             _ipcManager?.Dispose(); |             _ipcManager?.Dispose(); | ||||||
|             _playerManager?.Dispose(); |             _playerManager?.Dispose(); | ||||||
|             _characterCacheManager?.Dispose(); |             _characterCacheManager?.Dispose(); | ||||||
|             _playerWatcher.Disable(); |             _dalamudUtil.Dispose(); | ||||||
|             _playerWatcher.Dispose(); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |  | ||||||
| @@ -152,30 +144,32 @@ namespace MareSynchronos | |||||||
|  |  | ||||||
|         public void ReLaunchCharacterManager() |         public void ReLaunchCharacterManager() | ||||||
|         { |         { | ||||||
|             _playerManager?.Dispose(); |  | ||||||
|             _characterCacheManager?.Dispose(); |             _characterCacheManager?.Dispose(); | ||||||
|  |             _playerManager?.Dispose(); | ||||||
|  |  | ||||||
|             Task.Run(async () => |             Task.Run(WaitForPlayerAndLaunchCharacterManager); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private async Task WaitForPlayerAndLaunchCharacterManager() | ||||||
|  |         { | ||||||
|  |             while (!_dalamudUtil.IsPlayerPresent) | ||||||
|             { |             { | ||||||
|                 while (!_dalamudUtil.IsPlayerPresent) |                 await Task.Delay(100); | ||||||
|                 { |             } | ||||||
|                     await Task.Delay(100); |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 try |             try | ||||||
|                 { |             { | ||||||
|                     var characterCacheFactory = |                 var characterCacheFactory = | ||||||
|                         new CharacterDataFactory(_dalamudUtil, _ipcManager); |                     new CharacterDataFactory(_dalamudUtil, _ipcManager); | ||||||
|                     _characterCacheManager = new CachedPlayersManager(_clientState, _framework, _objectTable, |                 _characterCacheManager = new CachedPlayersManager(_clientState, _framework, | ||||||
|                         _apiController, _dalamudUtil, _ipcManager, _playerWatcher); |                     _apiController, _dalamudUtil, _ipcManager); | ||||||
|                     _playerManager = new PlayerManager(_apiController, _ipcManager, |                 _playerManager = new PlayerManager(_apiController, _ipcManager, | ||||||
|                         characterCacheFactory, _characterCacheManager, _dalamudUtil, _playerWatcher); |                     characterCacheFactory, _characterCacheManager, _dalamudUtil); | ||||||
|                 } |             } | ||||||
|                 catch (Exception ex) |             catch (Exception ex) | ||||||
|                 { |             { | ||||||
|                     Logger.Debug(ex.Message); |                 Logger.Debug(ex.Message); | ||||||
|                 } |             } | ||||||
|             }); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void Draw() |         private void Draw() | ||||||
|   | |||||||
| @@ -51,31 +51,20 @@ namespace MareSynchronos.UI | |||||||
|                 return; |                 return; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (_apiController.SecretKey != "-" && !_apiController.IsConnected && _apiController.ServerAlive) |             var pluginState = _uiShared.DrawOtherPluginState(); | ||||||
|             { |  | ||||||
|                 if (ImGui.Button("Reset Secret Key")) |  | ||||||
|                 { |  | ||||||
|                     _configuration.ClientSecret.Clear(); |  | ||||||
|                     _configuration.Save(); |  | ||||||
|                     _apiController.RestartHeartbeat(); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 var pluginState = _uiShared.DrawOtherPluginState(); |  | ||||||
|  |  | ||||||
|                 DrawSettingsContent(pluginState); |             if (pluginState) | ||||||
|             } |                 DrawSettingsContent(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void DrawSettingsContent(bool pluginState) |         private void DrawSettingsContent() | ||||||
|         { |         { | ||||||
|             _uiShared.PrintServerState(); |             _uiShared.PrintServerState(); | ||||||
|             ImGui.Separator(); |             ImGui.Separator(); | ||||||
|             ImGui.SetWindowFontScale(1.2f); |             ImGui.SetWindowFontScale(1.2f); | ||||||
|             ImGui.Text("Your UID"); |             ImGui.Text("Your UID"); | ||||||
|             ImGui.SameLine(); |             ImGui.SameLine(); | ||||||
|             if (_apiController.ServerAlive) |             if (_apiController.IsConnected) | ||||||
|             { |             { | ||||||
|                 ImGui.TextColored(ImGuiColors.ParsedGreen, _apiController.UID); |                 ImGui.TextColored(ImGuiColors.ParsedGreen, _apiController.UID); | ||||||
|                 ImGui.SameLine(); |                 ImGui.SameLine(); | ||||||
| @@ -89,18 +78,18 @@ namespace MareSynchronos.UI | |||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
|                 ImGui.TextColored(ImGuiColors.DalamudRed, "No UID (Service unavailable)"); |                 string error = _configuration.FullPause ? "Fully Paused" : "Service unavailable"; | ||||||
|  |                 ImGui.TextColored(ImGuiColors.DalamudRed, $"No UID ({error})"); | ||||||
|                 ImGui.SetWindowFontScale(1.0f); |                 ImGui.SetWindowFontScale(1.0f); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             ImGui.Separator(); |             ImGui.Separator(); | ||||||
|             if (_apiController.ServerAlive) |             if (_apiController.IsConnected) | ||||||
|                 DrawPairedClientsContent(); |                 DrawPairedClientsContent(); | ||||||
|             DrawFileCacheSettings(); |             DrawFileCacheSettings(); | ||||||
|             if (_apiController.ServerAlive) |             if (_apiController.IsConnected) | ||||||
|                 DrawCurrentTransfers(); |                 DrawCurrentTransfers(); | ||||||
|             DrawAdministration(_apiController.ServerAlive); |             DrawAdministration(_apiController.IsConnected); | ||||||
|  |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private bool _deleteFilesPopupModalShown = false; |         private bool _deleteFilesPopupModalShown = false; | ||||||
| @@ -181,15 +170,39 @@ namespace MareSynchronos.UI | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 var marePaused = _configuration.FullPause; |                 if (!_configuration.FullPause) | ||||||
|                 if (ImGui.Checkbox("Pause Mare Synchronos", ref marePaused)) |  | ||||||
|                 { |                 { | ||||||
|                     _configuration.FullPause = marePaused; |                     ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow); | ||||||
|                     _configuration.Save(); |                     UiShared.TextWrapped("Note: to change servers you need to pause Mare Synchronos."); | ||||||
|                     _apiController.RestartHeartbeat(); |                     ImGui.PopStyleColor(); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 var marePaused = _configuration.FullPause; | ||||||
|  |  | ||||||
|  |                 if (_configuration.HasValidSetup) | ||||||
|  |                 { | ||||||
|  |                     if (ImGui.Checkbox("Pause Mare Synchronos", ref marePaused)) | ||||||
|  |                     { | ||||||
|  |                         _configuration.FullPause = marePaused; | ||||||
|  |                         _configuration.Save(); | ||||||
|  |                         Task.Run(_apiController.CreateConnections); | ||||||
|  |                     } | ||||||
|  |  | ||||||
|  |                     UiShared.DrawHelpText("Completely pauses the sync and clear your current data (not uploaded files) on the service."); | ||||||
|  |                 } | ||||||
|  |                 else | ||||||
|  |                 { | ||||||
|  |                     ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow); | ||||||
|  |                     ImGui.TextUnformatted("You cannot resume pause without a valid account on the service."); | ||||||
|  |                     ImGui.PopStyleColor(); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                 if (marePaused) | ||||||
|  |                 { | ||||||
|  |                     _uiShared.DrawServiceSelection(); | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 UiShared.DrawHelpText("Completely pauses the sync and clear your current data (not uploaded files) on the service."); |  | ||||||
|  |  | ||||||
|                 ImGui.TreePop(); |                 ImGui.TreePop(); | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| using System; | using System; | ||||||
| using System.IO; | using System.IO; | ||||||
|  | using System.Linq; | ||||||
| using System.Numerics; | using System.Numerics; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Dalamud.Interface; | using Dalamud.Interface; | ||||||
| @@ -74,7 +75,10 @@ namespace MareSynchronos.UI | |||||||
|  |  | ||||||
|         public void PrintServerState() |         public void PrintServerState() | ||||||
|         { |         { | ||||||
|             ImGui.Text("Service status of " + (string.IsNullOrEmpty(_pluginConfiguration.ApiUri) ? ApiController.MainServer : _pluginConfiguration.ApiUri)); |             var serverName = _apiController.ServerDictionary.ContainsKey(_pluginConfiguration.ApiUri) | ||||||
|  |                 ? _apiController.ServerDictionary[_pluginConfiguration.ApiUri] | ||||||
|  |                 : _pluginConfiguration.ApiUri; | ||||||
|  |             ImGui.Text("Service status of " + serverName); | ||||||
|             ImGui.SameLine(); |             ImGui.SameLine(); | ||||||
|             var color = _apiController.ServerAlive ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed; |             var color = _apiController.ServerAlive ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed; | ||||||
|             ImGui.TextColored(color, _apiController.ServerAlive ? "Available" : "Unavailable"); |             ImGui.TextColored(color, _apiController.ServerAlive ? "Available" : "Unavailable"); | ||||||
| @@ -132,59 +136,91 @@ namespace MareSynchronos.UI | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         private int _serverSelectionIndex = 0; |         private int _serverSelectionIndex = 0; | ||||||
|  |         private string _customServerName = ""; | ||||||
|  |         private string _customServerUri = ""; | ||||||
|  |  | ||||||
|         public void DrawServiceSelection() |         public void DrawServiceSelection() | ||||||
|         { |         { | ||||||
|             string[] comboEntries = new[] { ApiController.MainServer, "Custom Service" }; |             string[] comboEntries = _apiController.ServerDictionary.Values.ToArray(); | ||||||
|             if (ImGui.BeginCombo("Service", comboEntries[_serverSelectionIndex])) |             _serverSelectionIndex = Array.IndexOf(_apiController.ServerDictionary.Keys.ToArray(), _pluginConfiguration.ApiUri); | ||||||
|  |             if (ImGui.BeginCombo("Select Service", comboEntries[_serverSelectionIndex])) | ||||||
|             { |             { | ||||||
|                 for (int n = 0; n < comboEntries.Length; n++) |                 for (int i = 0; i < comboEntries.Length; i++) | ||||||
|                 { |                 { | ||||||
|                     bool isSelected = _serverSelectionIndex == n; |                     bool isSelected = _serverSelectionIndex == i; | ||||||
|                     if (ImGui.Selectable(comboEntries[n], isSelected)) |                     if (ImGui.Selectable(comboEntries[i], isSelected)) | ||||||
|                     { |                     { | ||||||
|                         _serverSelectionIndex = n; |                         _pluginConfiguration.ApiUri = _apiController.ServerDictionary.Single(k => k.Value == comboEntries[i]).Key; | ||||||
|  |                         _pluginConfiguration.Save(); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if (isSelected) |                     if (isSelected) | ||||||
|                     { |                     { | ||||||
|                         ImGui.SetItemDefaultFocus(); |                         ImGui.SetItemDefaultFocus(); | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     bool useCustomService = _serverSelectionIndex != 0; |  | ||||||
|  |  | ||||||
|                     if (_apiController.UseCustomService != useCustomService) |  | ||||||
|                     { |  | ||||||
|                         _apiController.UseCustomService = useCustomService; |  | ||||||
|                         _pluginConfiguration.Save(); |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 ImGui.EndCombo(); |                 ImGui.EndCombo(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             if (_apiController.UseCustomService) |             if (_serverSelectionIndex != 0) | ||||||
|             { |             { | ||||||
|                 string serviceAddress = _pluginConfiguration.ApiUri; |                 ImGui.SameLine(); | ||||||
|                 if (ImGui.InputText("Service address", ref serviceAddress, 255)) |                 ImGui.PushFont(UiBuilder.IconFont); | ||||||
|  |                 if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString() + "##deleteService")) | ||||||
|                 { |                 { | ||||||
|                     if (_pluginConfiguration.ApiUri != serviceAddress) |                     _pluginConfiguration.CustomServerList.Remove(_pluginConfiguration.ApiUri); | ||||||
|                     { |                     _pluginConfiguration.ApiUri = ApiController.MainServiceUri; | ||||||
|                         _pluginConfiguration.ApiUri = serviceAddress; |                     _pluginConfiguration.Save(); | ||||||
|                         _apiController.RestartHeartbeat(); |  | ||||||
|                         _pluginConfiguration.Save(); |  | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|  |                 ImGui.PopFont(); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             PrintServerState(); |             PrintServerState(); | ||||||
|             if (_apiController.ServerAlive) |  | ||||||
|  |             if (_apiController.ServerAlive && !_pluginConfiguration.ClientSecret.ContainsKey(_pluginConfiguration.ApiUri)) | ||||||
|             { |             { | ||||||
|                 if (ImGui.Button("Register")) |                 if (ImGui.Button("Register")) | ||||||
|                 { |                 { | ||||||
|  |                     _pluginConfiguration.FullPause = false; | ||||||
|  |                     _pluginConfiguration.Save(); | ||||||
|                     Task.WaitAll(_apiController.Register()); |                     Task.WaitAll(_apiController.Register()); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |             else | ||||||
|  |             { | ||||||
|  |                 ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow); | ||||||
|  |                 TextWrapped("You already have an account on this server."); | ||||||
|  |                 ImGui.PopStyleColor(); | ||||||
|  |                 ImGui.SameLine(); | ||||||
|  |                 if (ImGui.Button("Connect##connectToService")) | ||||||
|  |                 { | ||||||
|  |                     _pluginConfiguration.FullPause = false; | ||||||
|  |                     _pluginConfiguration.Save(); | ||||||
|  |                     Task.Run(_apiController.CreateConnections); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (ImGui.TreeNode("Custom Service")) | ||||||
|  |             { | ||||||
|  |                 ImGui.SetNextItemWidth(250); | ||||||
|  |                 ImGui.InputText("Custom Service Name", ref _customServerName, 255); | ||||||
|  |                 ImGui.SetNextItemWidth(250); | ||||||
|  |                 ImGui.InputText("Custom Service Address", ref _customServerUri, 255); | ||||||
|  |                 if (ImGui.Button("Add Custom Service")) | ||||||
|  |                 { | ||||||
|  |                     if (!string.IsNullOrEmpty(_customServerUri)  | ||||||
|  |                         && !string.IsNullOrEmpty(_customServerName) | ||||||
|  |                         && !_pluginConfiguration.CustomServerList.ContainsValue(_customServerName)) | ||||||
|  |                     { | ||||||
|  |                         _pluginConfiguration.CustomServerList[_customServerUri] = _customServerName; | ||||||
|  |                         _customServerUri = string.Empty; | ||||||
|  |                         _customServerName = string.Empty; | ||||||
|  |                         _pluginConfiguration.Save(); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 ImGui.TreePop(); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static void DrawHelpText(string helpText) |         public static void DrawHelpText(string helpText) | ||||||
|   | |||||||
| @@ -2,6 +2,7 @@ | |||||||
| using System.IO; | using System.IO; | ||||||
| using System.Security.Cryptography; | using System.Security.Cryptography; | ||||||
| using System.Text; | using System.Text; | ||||||
|  | using Dalamud.Game.ClientState.Objects.SubKinds; | ||||||
|  |  | ||||||
| namespace MareSynchronos.Utils | namespace MareSynchronos.Utils | ||||||
| { | { | ||||||
| @@ -24,5 +25,11 @@ namespace MareSynchronos.Utils | |||||||
|             using SHA256CryptoServiceProvider cryptoProvider = new(); |             using SHA256CryptoServiceProvider cryptoProvider = new(); | ||||||
|             return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToHash))).Replace("-", ""); |             return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(stringToHash))).Replace("-", ""); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public static string GetHash256(PlayerCharacter character) | ||||||
|  |         { | ||||||
|  |             using SHA256CryptoServiceProvider cryptoProvider = new(); | ||||||
|  |             return BitConverter.ToString(cryptoProvider.ComputeHash(Encoding.UTF8.GetBytes(character.Name + character.HomeWorld.Id.ToString()))).Replace("-", ""); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,22 +1,48 @@ | |||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using System.Linq; | ||||||
| using System.Threading; | using System.Threading; | ||||||
| using Dalamud.Game.ClientState; | using Dalamud.Game.ClientState; | ||||||
| using Dalamud.Game.ClientState.Objects; | using Dalamud.Game.ClientState.Objects; | ||||||
| using Dalamud.Game.ClientState.Objects.SubKinds; | using Dalamud.Game.ClientState.Objects.SubKinds; | ||||||
| using FFXIVClientStructs.FFXIV.Client.Game.Object; | using Dalamud.Game.ClientState.Objects.Types; | ||||||
|  | using Penumbra.PlayerWatch; | ||||||
|  | using GameObject = FFXIVClientStructs.FFXIV.Client.Game.Object.GameObject; | ||||||
|  |  | ||||||
| namespace MareSynchronos.Utils | namespace MareSynchronos.Utils | ||||||
| { | { | ||||||
|     public class DalamudUtil |     public delegate void PlayerChange(Character actor); | ||||||
|  |  | ||||||
|  |     public class DalamudUtil : IDisposable | ||||||
|     { |     { | ||||||
|         private readonly ClientState _clientState; |         private readonly ClientState _clientState; | ||||||
|         private readonly ObjectTable _objectTable; |         private readonly ObjectTable _objectTable; | ||||||
|  |         private readonly IPlayerWatcher _watcher; | ||||||
|  |         public event PlayerChange? PlayerChanged; | ||||||
|  |  | ||||||
|         public DalamudUtil(ClientState clientState, ObjectTable objectTable) |         public DalamudUtil(ClientState clientState, ObjectTable objectTable, IPlayerWatcher watcher) | ||||||
|         { |         { | ||||||
|             _clientState = clientState; |             _clientState = clientState; | ||||||
|             _objectTable = objectTable; |             _objectTable = objectTable; | ||||||
|  |             _watcher = watcher; | ||||||
|  |             _watcher.Enable(); | ||||||
|  |             _watcher.PlayerChanged += WatcherOnPlayerChanged; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void WatcherOnPlayerChanged(Character actor) | ||||||
|  |         { | ||||||
|  |             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 bool IsPlayerPresent => _clientState.LocalPlayer != null; | ||||||
| @@ -49,6 +75,13 @@ namespace MareSynchronos.Utils | |||||||
|             return allLocalPlayers; |             return allLocalPlayers; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public List<PlayerCharacter> GetPlayerCharacters() | ||||||
|  |         { | ||||||
|  |             return _objectTable.Where(obj => | ||||||
|  |                 obj.ObjectKind == Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player && | ||||||
|  |                 obj.Name.ToString() != PlayerName).Select(p => (PlayerCharacter)p).ToList(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         public PlayerCharacter? GetPlayerCharacterFromObjectTableIndex(int index) |         public PlayerCharacter? GetPlayerCharacterFromObjectTableIndex(int index) | ||||||
|         { |         { | ||||||
|             var objTableObj = _objectTable[index]; |             var objTableObj = _objectTable[index]; | ||||||
| @@ -85,5 +118,11 @@ namespace MareSynchronos.Utils | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void WaitWhileSelfIsDrawing() => WaitWhileCharacterIsDrawing(_clientState.LocalPlayer?.Address ?? new IntPtr()); |         public void WaitWhileSelfIsDrawing() => WaitWhileCharacterIsDrawing(_clientState.LocalPlayer?.Address ?? new IntPtr()); | ||||||
|  |  | ||||||
|  |         public void Dispose() | ||||||
|  |         { | ||||||
|  |             _watcher.Disable(); | ||||||
|  |             _watcher.Dispose(); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,17 +16,28 @@ using Microsoft.AspNetCore.SignalR.Client; | |||||||
|  |  | ||||||
| namespace MareSynchronos.WebAPI | namespace MareSynchronos.WebAPI | ||||||
| { | { | ||||||
|     public class ApiController : IDisposable |     public partial class ApiController : IDisposable | ||||||
|     { |     { | ||||||
|         public const string MainServer = "Lunae Crescere Incipientis (Central Server EU)"; | #if DEBUG | ||||||
|  |         public const string MainServer = "darkarchons Debug Server (Dev Server (CH))"; | ||||||
|         public const string MainServiceUri = "https://darkarchon.internet-box.ch:5001"; |         public const string MainServiceUri = "https://darkarchon.internet-box.ch:5001"; | ||||||
|         readonly CancellationTokenSource _cts; | #else | ||||||
|  |         public const string MainServer = "Lunae Crescere Incipientis (Central Server EU)"; | ||||||
|  |         public const string MainServiceUri = "to be defined"; | ||||||
|  | #endif | ||||||
|  |  | ||||||
|         private readonly Configuration _pluginConfiguration; |         private readonly Configuration _pluginConfiguration; | ||||||
|  |  | ||||||
|  |         private CancellationTokenSource _cts; | ||||||
|  |  | ||||||
|         private HubConnection? _fileHub; |         private HubConnection? _fileHub; | ||||||
|  |  | ||||||
|         private HubConnection? _heartbeatHub; |         private HubConnection? _heartbeatHub; | ||||||
|  |  | ||||||
|         private CancellationTokenSource? _uploadCancellationTokenSource; |         private CancellationTokenSource? _uploadCancellationTokenSource; | ||||||
|  |  | ||||||
|         private HubConnection? _userHub; |         private HubConnection? _userHub; | ||||||
|  |  | ||||||
|         public ApiController(Configuration pluginConfiguration) |         public ApiController(Configuration pluginConfiguration) | ||||||
|         { |         { | ||||||
|             Logger.Debug("Creating " + nameof(ApiController)); |             Logger.Debug("Creating " + nameof(ApiController)); | ||||||
| @@ -34,9 +45,11 @@ namespace MareSynchronos.WebAPI | |||||||
|             _pluginConfiguration = pluginConfiguration; |             _pluginConfiguration = pluginConfiguration; | ||||||
|             _cts = new CancellationTokenSource(); |             _cts = new CancellationTokenSource(); | ||||||
|  |  | ||||||
|             _ = Heartbeat(); |             Task.Run(CreateConnections); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         public event EventHandler? ChangingServers; | ||||||
|  |  | ||||||
|         public event EventHandler<CharacterReceivedEventArgs>? CharacterReceived; |         public event EventHandler<CharacterReceivedEventArgs>? CharacterReceived; | ||||||
|  |  | ||||||
|         public event EventHandler? Connected; |         public event EventHandler? Connected; | ||||||
| @@ -50,30 +63,165 @@ namespace MareSynchronos.WebAPI | |||||||
|         public event EventHandler? PairedWithOther; |         public event EventHandler? PairedWithOther; | ||||||
|  |  | ||||||
|         public event EventHandler? UnpairedFromOther; |         public event EventHandler? UnpairedFromOther; | ||||||
|         public event EventHandler? AccountDeleted; |  | ||||||
|  |  | ||||||
|         public ConcurrentDictionary<string, (long, long)> CurrentDownloads { get; } = new(); |         public ConcurrentDictionary<string, (long, long)> CurrentDownloads { get; } = new(); | ||||||
|  |  | ||||||
|         public ConcurrentDictionary<string, (long, long)> CurrentUploads { get; } = new(); |         public ConcurrentDictionary<string, (long, long)> CurrentUploads { get; } = new(); | ||||||
|  |  | ||||||
|         public bool IsConnected => !string.IsNullOrEmpty(UID); |         public bool IsConnected => !string.IsNullOrEmpty(UID); | ||||||
|  |  | ||||||
|         public bool IsDownloading { get; private set; } |         public bool IsDownloading { get; private set; } | ||||||
|  |  | ||||||
|         public bool IsUploading { get; private set; } |         public bool IsUploading { get; private set; } | ||||||
|  |  | ||||||
|         public List<ClientPairDto> PairedClients { get; set; } = new(); |         public List<ClientPairDto> PairedClients { get; set; } = new(); | ||||||
|  |  | ||||||
|         public string SecretKey => _pluginConfiguration.ClientSecret.ContainsKey(ApiUri) ? _pluginConfiguration.ClientSecret[ApiUri] : "-"; |         public string SecretKey => _pluginConfiguration.ClientSecret.ContainsKey(ApiUri) ? _pluginConfiguration.ClientSecret[ApiUri] : "-"; | ||||||
|  |  | ||||||
|         public bool ServerAlive => |         public bool ServerAlive => | ||||||
|             (_heartbeatHub?.State ?? HubConnectionState.Disconnected) == HubConnectionState.Connected; |             (_heartbeatHub?.State ?? HubConnectionState.Disconnected) == HubConnectionState.Connected; | ||||||
|  |  | ||||||
|  |         public Dictionary<string, string> ServerDictionary => new Dictionary<string, string>() { { MainServiceUri, MainServer } } | ||||||
|  |             .Concat(_pluginConfiguration.CustomServerList) | ||||||
|  |             .ToDictionary(k => k.Key, k => k.Value); | ||||||
|         public string UID { get; private set; } = string.Empty; |         public string UID { get; private set; } = string.Empty; | ||||||
|         public bool UseCustomService |  | ||||||
|  |         private string ApiUri => _pluginConfiguration.ApiUri; | ||||||
|  |  | ||||||
|  |         public async Task CreateConnections() | ||||||
|         { |         { | ||||||
|             get => _pluginConfiguration.UseCustomService; |             _cts = new CancellationTokenSource(); | ||||||
|             set |             var token = _cts.Token; | ||||||
|  |             await StopAllConnections(token); | ||||||
|  |  | ||||||
|  |             while (!ServerAlive && !token.IsCancellationRequested) | ||||||
|             { |             { | ||||||
|                 _pluginConfiguration.UseCustomService = value; |                 await StopAllConnections(token); | ||||||
|                 _pluginConfiguration.Save(); |  | ||||||
|  |                 try | ||||||
|  |                 { | ||||||
|  |                     Logger.Debug("Building connection"); | ||||||
|  |                     _heartbeatHub = BuildHubConnection("heartbeat"); | ||||||
|  |                     _userHub = BuildHubConnection("user"); | ||||||
|  |                     _fileHub = BuildHubConnection("files"); | ||||||
|  |  | ||||||
|  |                     await _heartbeatHub.StartAsync(token); | ||||||
|  |                     await _userHub.StartAsync(token); | ||||||
|  |                     await _fileHub.StartAsync(token); | ||||||
|  |  | ||||||
|  |                     if (_pluginConfiguration.FullPause) | ||||||
|  |                     { | ||||||
|  |                         UID = string.Empty; | ||||||
|  |                         return; | ||||||
|  |                     } | ||||||
|  |                     UID = await _heartbeatHub.InvokeAsync<string>("Heartbeat", token); | ||||||
|  |                     if (!string.IsNullOrEmpty(UID) && !token.IsCancellationRequested) // user is authorized | ||||||
|  |                     { | ||||||
|  |                         Logger.Debug("Initializing data"); | ||||||
|  |                         _userHub.On<ClientPairDto, string>("UpdateClientPairs", UpdateLocalClientPairs); | ||||||
|  |                         _userHub.On<CharacterCacheDto, string>("ReceiveCharacterData", ReceiveCharacterData); | ||||||
|  |                         _userHub.On<string>("RemoveOnlinePairedPlayer", | ||||||
|  |                             (s) => PairedClientOffline?.Invoke(s, EventArgs.Empty)); | ||||||
|  |                         _userHub.On<string>("AddOnlinePairedPlayer", | ||||||
|  |                             (s) => PairedClientOnline?.Invoke(s, EventArgs.Empty)); | ||||||
|  |  | ||||||
|  |                         PairedClients = await _userHub!.InvokeAsync<List<ClientPairDto>>("GetPairedClients", token); | ||||||
|  |  | ||||||
|  |                         _heartbeatHub.Closed += HeartbeatHubOnClosed; | ||||||
|  |                         _heartbeatHub.Reconnected += HeartbeatHubOnReconnected; | ||||||
|  |                         _heartbeatHub.Reconnecting += HeartbeatHubOnReconnecting; | ||||||
|  |                         Connected?.Invoke(this, EventArgs.Empty); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 catch (Exception ex) | ||||||
|  |                 { | ||||||
|  |                     Logger.Warn(ex.Message); | ||||||
|  |                     Logger.Warn(ex.StackTrace); | ||||||
|  |                     Logger.Debug("Failed to establish connection, retrying"); | ||||||
|  |                     await Task.Delay(TimeSpan.FromSeconds(5), token); | ||||||
|  |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private string ApiUri => UseCustomService ? _pluginConfiguration.ApiUri : MainServiceUri; |         public void Dispose() | ||||||
|  |         { | ||||||
|  |             Logger.Debug("Disposing " + nameof(ApiController)); | ||||||
|  |  | ||||||
|  |             Task.Run(async () => await StopAllConnections(_cts.Token)); | ||||||
|  |             _cts?.Cancel(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private HubConnection BuildHubConnection(string hubName) | ||||||
|  |         { | ||||||
|  |             return new HubConnectionBuilder() | ||||||
|  |                 .WithUrl(ApiUri + "/" + hubName, options => | ||||||
|  |                 { | ||||||
|  |                     if (!string.IsNullOrEmpty(SecretKey) && !_pluginConfiguration.FullPause) | ||||||
|  |                     { | ||||||
|  |                         options.Headers.Add("Authorization", SecretKey); | ||||||
|  |                     } | ||||||
|  | #if DEBUG | ||||||
|  |                     options.HttpMessageHandlerFactory = (message) => | ||||||
|  |                     { | ||||||
|  |                         if (message is HttpClientHandler clientHandler) | ||||||
|  |                             clientHandler.ServerCertificateCustomValidationCallback += | ||||||
|  |                                 (sender, certificate, chain, sslPolicyErrors) => true; | ||||||
|  |                         return message; | ||||||
|  |                     }; | ||||||
|  | #endif | ||||||
|  |                 }) | ||||||
|  |                 .WithAutomaticReconnect(new ForeverRetryPolicy()) | ||||||
|  |                 .Build(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private Task HeartbeatHubOnClosed(Exception? arg) | ||||||
|  |         { | ||||||
|  |             Logger.Debug("Connection closed"); | ||||||
|  |             Disconnected?.Invoke(null, EventArgs.Empty); | ||||||
|  |             return Task.CompletedTask; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private Task HeartbeatHubOnReconnected(string? arg) | ||||||
|  |         { | ||||||
|  |             Logger.Debug("Connection restored"); | ||||||
|  |             Connected?.Invoke(this, EventArgs.Empty); | ||||||
|  |             return Task.CompletedTask; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private Task HeartbeatHubOnReconnecting(Exception? arg) | ||||||
|  |         { | ||||||
|  |             Logger.Debug("Connection closed... Reconnecting…"); | ||||||
|  |             Disconnected?.Invoke(null, EventArgs.Empty); | ||||||
|  |             return Task.CompletedTask; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private async Task StopAllConnections(CancellationToken token) | ||||||
|  |         { | ||||||
|  |             if (_heartbeatHub is { State: HubConnectionState.Connected }) | ||||||
|  |             { | ||||||
|  |                 await _heartbeatHub.StopAsync(token); | ||||||
|  |                 _heartbeatHub.Closed -= HeartbeatHubOnClosed; | ||||||
|  |                 _heartbeatHub.Reconnected -= HeartbeatHubOnReconnected; | ||||||
|  |                 _heartbeatHub.Reconnecting += HeartbeatHubOnReconnecting; | ||||||
|  |                 await _heartbeatHub.DisposeAsync(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (_fileHub is { State: HubConnectionState.Connected }) | ||||||
|  |             { | ||||||
|  |                 await _fileHub.StopAsync(token); | ||||||
|  |                 await _fileHub.DisposeAsync(); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             if (_userHub is { State: HubConnectionState.Connected }) | ||||||
|  |             { | ||||||
|  |                 await _userHub.StopAsync(token); | ||||||
|  |                 await _userHub.DisposeAsync(); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public partial class ApiController | ||||||
|  |     { | ||||||
|         public void CancelUpload() |         public void CancelUpload() | ||||||
|         { |         { | ||||||
|             if (_uploadCancellationTokenSource != null) |             if (_uploadCancellationTokenSource != null) | ||||||
| @@ -84,12 +232,17 @@ namespace MareSynchronos.WebAPI | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void Dispose() |         public async Task DeleteAccount() | ||||||
|         { |         { | ||||||
|             Logger.Debug("Disposing " + nameof(ApiController)); |             _pluginConfiguration.ClientSecret.Remove(ApiUri); | ||||||
|  |             await _fileHub!.SendAsync("DeleteAllFiles"); | ||||||
|  |             await _userHub!.SendAsync("DeleteAccount"); | ||||||
|  |             await CreateConnections(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|             _cts?.Cancel(); |         public async Task DeleteAllMyFiles() | ||||||
|             _ = DisposeHubConnections(); |         { | ||||||
|  |             await _fileHub!.SendAsync("DeleteAllFiles"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task<string> DownloadFile(string hash, CancellationToken ct) |         public async Task<string> DownloadFile(string hash, CancellationToken ct) | ||||||
| @@ -167,41 +320,6 @@ namespace MareSynchronos.WebAPI | |||||||
|                 hashedCharacterNames); |                 hashedCharacterNames); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task Heartbeat() |  | ||||||
|         { |  | ||||||
|             while (!ServerAlive && !_cts.Token.IsCancellationRequested) |  | ||||||
|             { |  | ||||||
|                 try |  | ||||||
|                 { |  | ||||||
|                     if (_pluginConfiguration.FullPause) return; |  | ||||||
|                     Logger.Debug("Attempting to establish heartbeat connection to " + ApiUri); |  | ||||||
|                     _heartbeatHub = BuildHubConnection("heartbeat"); |  | ||||||
|  |  | ||||||
|                     await _heartbeatHub.StartAsync(_cts.Token); |  | ||||||
|                     UID = await _heartbeatHub!.InvokeAsync<string>("Heartbeat"); |  | ||||||
|                     Logger.Debug("Heartbeat started: " + ApiUri); |  | ||||||
|                     try |  | ||||||
|                     { |  | ||||||
|                         await InitializeHubConnections(); |  | ||||||
|                         await LoadInitialData(); |  | ||||||
|                         Connected?.Invoke(this, EventArgs.Empty); |  | ||||||
|                     } |  | ||||||
|                     catch |  | ||||||
|                     { |  | ||||||
|                         //PluginLog.Error(ex, "Error during Heartbeat initialization"); |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     _heartbeatHub.Closed += OnHeartbeatHubOnClosed; |  | ||||||
|                     _heartbeatHub.Reconnected += OnHeartbeatHubOnReconnected; |  | ||||||
|                     Logger.Debug("Heartbeat established to: " + ApiUri); |  | ||||||
|                 } |  | ||||||
|                 catch (Exception ex) |  | ||||||
|                 { |  | ||||||
|                     PluginLog.Error(ex, "Creating heartbeat failure"); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public Task ReceiveCharacterData(CharacterCacheDto character, string characterHash) |         public Task ReceiveCharacterData(CharacterCacheDto character, string characterHash) | ||||||
|         { |         { | ||||||
|             Logger.Debug("Received DTO for " + characterHash); |             Logger.Debug("Received DTO for " + characterHash); | ||||||
| @@ -216,29 +334,9 @@ namespace MareSynchronos.WebAPI | |||||||
|             var response = await _userHub!.InvokeAsync<string>("Register"); |             var response = await _userHub!.InvokeAsync<string>("Register"); | ||||||
|             _pluginConfiguration.ClientSecret[ApiUri] = response; |             _pluginConfiguration.ClientSecret[ApiUri] = response; | ||||||
|             _pluginConfiguration.Save(); |             _pluginConfiguration.Save(); | ||||||
|             RestartHeartbeat(); |             ChangingServers?.Invoke(null, EventArgs.Empty); | ||||||
|  |             await CreateConnections(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void RestartHeartbeat() |  | ||||||
|         { |  | ||||||
|             Logger.Debug("Restarting heartbeat"); |  | ||||||
|  |  | ||||||
|             Task.Run(async () => |  | ||||||
|             { |  | ||||||
|                 if (_heartbeatHub != null) |  | ||||||
|                 { |  | ||||||
|                     _heartbeatHub.Closed -= OnHeartbeatHubOnClosed; |  | ||||||
|                     _heartbeatHub.Reconnected -= OnHeartbeatHubOnReconnected; |  | ||||||
|                     await _heartbeatHub.StopAsync(_cts.Token); |  | ||||||
|                     await _heartbeatHub.DisposeAsync(); |  | ||||||
|                     await OnHeartbeatHubOnClosed(null); |  | ||||||
|                     _heartbeatHub = null!; |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 _ = Heartbeat(); |  | ||||||
|             }); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async Task SendCharacterData(CharacterCacheDto character, List<string> visibleCharacterIds) |         public async Task SendCharacterData(CharacterCacheDto character, List<string> visibleCharacterIds) | ||||||
|         { |         { | ||||||
|             if (!IsConnected || SecretKey == "-") return; |             if (!IsConnected || SecretKey == "-") return; | ||||||
| @@ -323,40 +421,6 @@ namespace MareSynchronos.WebAPI | |||||||
|             await _userHub!.SendAsync("SendPairedClientRemoval", uid); |             await _userHub!.SendAsync("SendPairedClientRemoval", uid); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task DeleteAllMyFiles() |  | ||||||
|         { |  | ||||||
|             await _fileHub!.SendAsync("DeleteAllFiles"); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public async Task DeleteAccount() |  | ||||||
|         { |  | ||||||
|             _pluginConfiguration.ClientSecret.Remove(ApiUri); |  | ||||||
|             await _fileHub!.SendAsync("DeleteAllFiles"); |  | ||||||
|             await _userHub!.SendAsync("DeleteAccount"); |  | ||||||
|             _ = OnHeartbeatHubOnClosed(null); |  | ||||||
|             AccountDeleted?.Invoke(null, EventArgs.Empty); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private async Task DisposeHubConnections() |  | ||||||
|         { |  | ||||||
|             if (_fileHub != null) |  | ||||||
|             { |  | ||||||
|                 Logger.Debug("Disposing File Hub"); |  | ||||||
|                 CancelUpload(); |  | ||||||
|                 await _fileHub!.StopAsync(); |  | ||||||
|                 await _fileHub!.DisposeAsync(); |  | ||||||
|                 _fileHub = null; |  | ||||||
|             } |  | ||||||
|  |  | ||||||
|             if (_userHub != null) |  | ||||||
|             { |  | ||||||
|                 Logger.Debug("Disposing User Hub"); |  | ||||||
|                 await _userHub.StopAsync(); |  | ||||||
|                 await _userHub.DisposeAsync(); |  | ||||||
|                 _userHub = null; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private async Task<(string, byte[])> GetCompressedFileData(string fileHash, CancellationToken uploadToken) |         private async Task<(string, byte[])> GetCompressedFileData(string fileHash, CancellationToken uploadToken) | ||||||
|         { |         { | ||||||
|             await using var db = new FileCacheContext(); |             await using var db = new FileCacheContext(); | ||||||
| @@ -364,67 +428,6 @@ namespace MareSynchronos.WebAPI | |||||||
|             return (fileHash, LZ4Codec.WrapHC(await File.ReadAllBytesAsync(fileCache.Filepath, uploadToken), 0, |             return (fileHash, LZ4Codec.WrapHC(await File.ReadAllBytesAsync(fileCache.Filepath, uploadToken), 0, | ||||||
|                 (int)new FileInfo(fileCache.Filepath).Length)); |                 (int)new FileInfo(fileCache.Filepath).Length)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private async Task InitializeHubConnections() |  | ||||||
|         { |  | ||||||
|             await DisposeHubConnections(); |  | ||||||
|  |  | ||||||
|             Logger.Debug("Creating User Hub"); |  | ||||||
|             _userHub = BuildHubConnection("user"); |  | ||||||
|             await _userHub.StartAsync(); |  | ||||||
|             _userHub.On<ClientPairDto, string>("UpdateClientPairs", UpdateLocalClientPairs); |  | ||||||
|             _userHub.On<CharacterCacheDto, string>("ReceiveCharacterData", ReceiveCharacterData); |  | ||||||
|             _userHub.On<string>("RemoveOnlinePairedPlayer", (s) => PairedClientOffline?.Invoke(s, EventArgs.Empty)); |  | ||||||
|             _userHub.On<string>("AddOnlinePairedPlayer", (s) => PairedClientOnline?.Invoke(s, EventArgs.Empty)); |  | ||||||
|  |  | ||||||
|             Logger.Debug("Creating File Hub"); |  | ||||||
|             _fileHub = BuildHubConnection("files"); |  | ||||||
|             await _fileHub.StartAsync(_cts.Token); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private HubConnection BuildHubConnection(string hubName) |  | ||||||
|         { |  | ||||||
|             return new HubConnectionBuilder() |  | ||||||
|                 .WithUrl(ApiUri + "/" + hubName, options => |  | ||||||
|                 { |  | ||||||
|                     if (!string.IsNullOrEmpty(SecretKey) && !_pluginConfiguration.FullPause) |  | ||||||
|                     { |  | ||||||
|                         options.Headers.Add("Authorization", SecretKey); |  | ||||||
|                     } |  | ||||||
| #if DEBUG |  | ||||||
|                     options.HttpMessageHandlerFactory = (message) => |  | ||||||
|                     { |  | ||||||
|                         if (message is HttpClientHandler clientHandler) |  | ||||||
|                             clientHandler.ServerCertificateCustomValidationCallback += |  | ||||||
|                                 (sender, certificate, chain, sslPolicyErrors) => true; |  | ||||||
|                         return message; |  | ||||||
|                     }; |  | ||||||
| #endif |  | ||||||
|                 }) |  | ||||||
|                 .Build(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private async Task LoadInitialData() |  | ||||||
|         { |  | ||||||
|             var pairedClients = await _userHub!.InvokeAsync<List<ClientPairDto>>("GetPairedClients"); |  | ||||||
|             PairedClients = pairedClients.ToList(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private Task OnHeartbeatHubOnClosed(Exception? exception) |  | ||||||
|         { |  | ||||||
|             Logger.Debug("Connection closed: " + ApiUri); |  | ||||||
|             Disconnected?.Invoke(null, EventArgs.Empty); |  | ||||||
|             Task.Run(DisposeHubConnections); |  | ||||||
|             RestartHeartbeat(); |  | ||||||
|             return Task.CompletedTask; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private async Task OnHeartbeatHubOnReconnected(string? s) |  | ||||||
|         { |  | ||||||
|             Logger.Debug("Reconnected: " + ApiUri); |  | ||||||
|             UID = await _heartbeatHub!.InvokeAsync<string>("Heartbeat"); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private void UpdateLocalClientPairs(ClientPairDto dto, string characterIdentifier) |         private void UpdateLocalClientPairs(ClientPairDto dto, string characterIdentifier) | ||||||
|         { |         { | ||||||
|             var entry = PairedClients.SingleOrDefault(e => e.OtherUID == dto.OtherUID); |             var entry = PairedClients.SingleOrDefault(e => e.OtherUID == dto.OtherUID); | ||||||
| @@ -492,4 +495,12 @@ namespace MareSynchronos.WebAPI | |||||||
|         public CharacterCacheDto CharacterData { get; set; } |         public CharacterCacheDto CharacterData { get; set; } | ||||||
|         public string CharacterNameHash { get; set; } |         public string CharacterNameHash { get; set; } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public class ForeverRetryPolicy : IRetryPolicy | ||||||
|  |     { | ||||||
|  |         public TimeSpan? NextRetryDelay(RetryContext retryContext) | ||||||
|  |         { | ||||||
|  |             return TimeSpan.FromSeconds(5); | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Stanley Dimant
					Stanley Dimant