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