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 Dictionary<string, string> ClientSecret { get; set; } = new();
|
||||
public Dictionary<string, string> CustomServerList { get; set; } = new();
|
||||
[JsonIgnore]
|
||||
public bool HasValidSetup => AcceptedAgreement && InitialScanComplete && !string.IsNullOrEmpty(CacheFolder) &&
|
||||
Directory.Exists(CacheFolder) && ClientSecret.ContainsKey(ApiUri);
|
||||
@@ -46,7 +47,6 @@ namespace MareSynchronos
|
||||
|
||||
public bool FullPause { get; set; } = false;
|
||||
public Dictionary<string, string> UidComments { get; set; } = new();
|
||||
public bool UseCustomService { get; set; } = false;
|
||||
public int Version { get; set; } = 0;
|
||||
|
||||
public bool ShowTransferWindow { get; set; } = true;
|
||||
|
||||
@@ -4,12 +4,9 @@ using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Game;
|
||||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Game.ClientState.Objects;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
using MareSynchronos.Models;
|
||||
using MareSynchronos.Utils;
|
||||
using MareSynchronos.WebAPI;
|
||||
using Penumbra.PlayerWatch;
|
||||
|
||||
namespace MareSynchronos.Managers;
|
||||
|
||||
@@ -20,23 +17,20 @@ public class CachedPlayersManager : IDisposable
|
||||
private readonly DalamudUtil _dalamudUtil;
|
||||
private readonly Framework _framework;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly IPlayerWatcher _watcher;
|
||||
private readonly ObjectTable _objectTable;
|
||||
private readonly List<CachedPlayer> _onlineCachedPlayers = new();
|
||||
private readonly List<string> _localVisiblePlayers = new();
|
||||
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));
|
||||
|
||||
_clientState = clientState;
|
||||
_framework = framework;
|
||||
_objectTable = objectTable;
|
||||
_apiController = apiController;
|
||||
_dalamudUtil = dalamudUtil;
|
||||
_ipcManager = ipcManager;
|
||||
_watcher = watcher;
|
||||
|
||||
_clientState.Login += ClientStateOnLogin;
|
||||
_clientState.Logout += ClientStateOnLogout;
|
||||
@@ -53,7 +47,7 @@ public class CachedPlayersManager : IDisposable
|
||||
ClientStateOnLogin(null, EventArgs.Empty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void IpcManagerOnPenumbraDisposed(object? sender, EventArgs e)
|
||||
{
|
||||
_onlineCachedPlayers.ForEach(p => p.DisposePlayer());
|
||||
@@ -159,14 +153,10 @@ public class CachedPlayersManager : IDisposable
|
||||
if (DateTime.Now < _lastPlayerObjectCheck.AddSeconds(0.25)) return;
|
||||
|
||||
_localVisiblePlayers.Clear();
|
||||
string ownName = _dalamudUtil.PlayerName;
|
||||
var playerCharacters = _objectTable.Where(obj =>
|
||||
obj.ObjectKind == Dalamud.Game.ClientState.Objects.Enums.ObjectKind.Player &&
|
||||
obj.Name.ToString() != ownName).ToList();
|
||||
foreach (var obj in playerCharacters)
|
||||
var playerCharacters = _dalamudUtil.GetPlayerCharacters();
|
||||
foreach (var pChar in playerCharacters)
|
||||
{
|
||||
var pObj = (PlayerCharacter)obj;
|
||||
var pObjName = pObj.Name.ToString();
|
||||
var pObjName = pChar.Name.ToString();
|
||||
_localVisiblePlayers.Add(pObjName);
|
||||
var existingCachedPlayer = _onlineCachedPlayers.SingleOrDefault(p => p.PlayerName == pObjName);
|
||||
if (existingCachedPlayer != null)
|
||||
@@ -175,8 +165,8 @@ public class CachedPlayersManager : IDisposable
|
||||
continue;
|
||||
}
|
||||
|
||||
var hashedName = Crypto.GetHash256(pObj.Name.ToString() + pObj.HomeWorld.Id.ToString());
|
||||
_onlineCachedPlayers.SingleOrDefault(p => p.PlayerNameHash == hashedName)?.InitializePlayer(pObj);
|
||||
var hashedName = Crypto.GetHash256(pChar);
|
||||
_onlineCachedPlayers.SingleOrDefault(p => p.PlayerNameHash == hashedName)?.InitializePlayer(pChar);
|
||||
}
|
||||
|
||||
_onlineCachedPlayers.Where(p => !string.IsNullOrEmpty(p.PlayerName) && !_localVisiblePlayers.Contains(p.PlayerName))
|
||||
@@ -191,6 +181,6 @@ public class CachedPlayersManager : IDisposable
|
||||
|
||||
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()
|
||||
{
|
||||
if (_ipcManager.Initialized && _pluginConfiguration.HasValidSetup)
|
||||
{
|
||||
Logger.Debug("Penumbra is active, configuration is valid, starting watchers and scan");
|
||||
StartWatchers();
|
||||
StartInitialScan();
|
||||
}
|
||||
if (!_ipcManager.Initialized || !_pluginConfiguration.HasValidSetup) return;
|
||||
Logger.Debug("Penumbra is active, configuration is valid, starting watchers and scan");
|
||||
StartWatchers();
|
||||
StartInitialScan();
|
||||
}
|
||||
|
||||
private void IpcManagerOnPenumbraInitialized(object? sender, EventArgs e)
|
||||
|
||||
@@ -146,7 +146,9 @@ namespace MareSynchronos.Managers
|
||||
{
|
||||
if (!CheckPenumbraApi()) return string.Empty;
|
||||
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)
|
||||
|
||||
@@ -4,7 +4,6 @@ using MareSynchronos.Models;
|
||||
using MareSynchronos.Utils;
|
||||
using MareSynchronos.WebAPI;
|
||||
using Newtonsoft.Json;
|
||||
using Penumbra.PlayerWatch;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
@@ -20,12 +19,11 @@ namespace MareSynchronos.Managers
|
||||
private readonly CharacterDataFactory _characterDataFactory;
|
||||
private readonly DalamudUtil _dalamudUtil;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly IPlayerWatcher _watcher;
|
||||
private string _lastSentHash = string.Empty;
|
||||
private Task? _playerChangedTask;
|
||||
|
||||
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));
|
||||
|
||||
@@ -34,9 +32,8 @@ namespace MareSynchronos.Managers
|
||||
_characterDataFactory = characterDataFactory;
|
||||
_cachedPlayersManager = cachedPlayersManager;
|
||||
_dalamudUtil = dalamudUtil;
|
||||
_watcher = watcher;
|
||||
|
||||
_watcher.AddPlayerToWatch(_dalamudUtil.PlayerName);
|
||||
_dalamudUtil.AddPlayerToWatch(_dalamudUtil.PlayerName);
|
||||
_apiController.Connected += ApiController_Connected;
|
||||
_apiController.Disconnected += ApiController_Disconnected;
|
||||
|
||||
@@ -54,7 +51,7 @@ namespace MareSynchronos.Managers
|
||||
_ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent;
|
||||
_apiController.Connected -= ApiController_Connected;
|
||||
_apiController.Disconnected -= ApiController_Disconnected;
|
||||
_watcher.PlayerChanged -= Watcher_PlayerChanged;
|
||||
_dalamudUtil.PlayerChanged -= Watcher_PlayerChanged;
|
||||
}
|
||||
|
||||
private void ApiController_Connected(object? sender, EventArgs args)
|
||||
@@ -69,7 +66,7 @@ namespace MareSynchronos.Managers
|
||||
|
||||
_ipcManager.PenumbraRedrawEvent += IpcManager_PenumbraRedrawEvent;
|
||||
_ipcManager.PenumbraRedraw(_dalamudUtil.PlayerName);
|
||||
_watcher.PlayerChanged += Watcher_PlayerChanged;
|
||||
_dalamudUtil.PlayerChanged += Watcher_PlayerChanged;
|
||||
}
|
||||
|
||||
private void ApiController_Disconnected(object? sender, EventArgs args)
|
||||
@@ -77,7 +74,7 @@ namespace MareSynchronos.Managers
|
||||
Logger.Debug(nameof(ApiController_Disconnected));
|
||||
|
||||
_ipcManager.PenumbraRedrawEvent -= IpcManager_PenumbraRedrawEvent;
|
||||
_watcher.PlayerChanged -= Watcher_PlayerChanged;
|
||||
_dalamudUtil.PlayerChanged -= Watcher_PlayerChanged;
|
||||
}
|
||||
|
||||
private async Task<CharacterData> CreateFullCharacterCache()
|
||||
|
||||
@@ -11,7 +11,6 @@ using MareSynchronos.FileCacheDB;
|
||||
using MareSynchronos.Managers;
|
||||
using MareSynchronos.Utils;
|
||||
using MareSynchronos.WebAPI;
|
||||
using Penumbra.PlayerWatch;
|
||||
|
||||
namespace MareSynchronos.Models;
|
||||
|
||||
@@ -20,16 +19,14 @@ public class CachedPlayer
|
||||
private readonly DalamudUtil _dalamudUtil;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly ApiController _apiController;
|
||||
private readonly IPlayerWatcher _watcher;
|
||||
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;
|
||||
_ipcManager = ipcManager;
|
||||
_apiController = apiController;
|
||||
_dalamudUtil = dalamudUtil;
|
||||
_watcher = watcher;
|
||||
}
|
||||
|
||||
public bool IsVisible
|
||||
@@ -165,7 +162,7 @@ public class CachedPlayer
|
||||
_downloadCancellationTokenSource?.Cancel();
|
||||
_downloadCancellationTokenSource?.Dispose();
|
||||
_downloadCancellationTokenSource = null;
|
||||
_watcher.RemovePlayerFromWatch(PlayerName);
|
||||
_dalamudUtil.RemovePlayerFromWatch(PlayerName);
|
||||
_ipcManager.PenumbraRemoveTemporaryCollection(PlayerName);
|
||||
_ipcManager.GlamourerRevertCharacterCustomization(PlayerName);
|
||||
_ipcManager.GlamourerApplyOnlyCustomization(_originalGlamourerData, PlayerName);
|
||||
@@ -177,7 +174,7 @@ public class CachedPlayer
|
||||
}
|
||||
finally
|
||||
{
|
||||
_watcher.PlayerChanged -= WatcherOnPlayerChanged;
|
||||
_dalamudUtil.PlayerChanged -= WatcherOnPlayerChanged;
|
||||
_ipcManager.PenumbraRedrawEvent -= IpcManagerOnPenumbraRedrawEvent;
|
||||
_apiController.CharacterReceived -= ApiControllerOnCharacterReceived;
|
||||
PlayerName = string.Empty;
|
||||
@@ -191,8 +188,8 @@ public class CachedPlayer
|
||||
PlayerName = character.Name.ToString();
|
||||
PlayerCharacter = character;
|
||||
Logger.Debug("Initializing Player " + this);
|
||||
_watcher.AddPlayerToWatch(PlayerName!);
|
||||
_watcher.PlayerChanged += WatcherOnPlayerChanged;
|
||||
_dalamudUtil.AddPlayerToWatch(PlayerName!);
|
||||
_dalamudUtil.PlayerChanged += WatcherOnPlayerChanged;
|
||||
_ipcManager.PenumbraRedrawEvent += IpcManagerOnPenumbraRedrawEvent;
|
||||
_apiController.CharacterReceived += ApiControllerOnCharacterReceived;
|
||||
_originalGlamourerData = _ipcManager.GlamourerGetCharacterCustomization(PlayerName);
|
||||
@@ -203,15 +200,15 @@ public class CachedPlayer
|
||||
return PlayerNameHash + ":" + PlayerName + ":HasChar " + (PlayerCharacter != null);
|
||||
}
|
||||
|
||||
private Task? penumbraRedrawEventTask;
|
||||
private Task? _penumbraRedrawEventTask;
|
||||
|
||||
private void IpcManagerOnPenumbraRedrawEvent(object? sender, EventArgs e)
|
||||
{
|
||||
var player = _dalamudUtil.GetPlayerCharacterFromObjectTableIndex((int)sender!);
|
||||
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;
|
||||
_dalamudUtil.WaitWhileCharacterIsDrawing(PlayerCharacter.Address);
|
||||
|
||||
@@ -28,14 +28,12 @@ namespace MareSynchronos
|
||||
private readonly FileCacheManager _fileCacheManager;
|
||||
private readonly IntroUi _introUi;
|
||||
private readonly IpcManager _ipcManager;
|
||||
private readonly ObjectTable _objectTable;
|
||||
public static DalamudPluginInterface PluginInterface { get; set; }
|
||||
private readonly PluginUi _pluginUi;
|
||||
private readonly WindowSystem _windowSystem;
|
||||
private PlayerManager? _playerManager;
|
||||
private readonly DalamudUtil _dalamudUtil;
|
||||
private CachedPlayersManager? _characterCacheManager;
|
||||
private readonly IPlayerWatcher _playerWatcher;
|
||||
private readonly DownloadUi _downloadUi;
|
||||
private readonly FileDialogManager _fileDialogManager;
|
||||
|
||||
@@ -46,7 +44,6 @@ namespace MareSynchronos
|
||||
PluginInterface = pluginInterface;
|
||||
_commandManager = commandManager;
|
||||
_framework = framework;
|
||||
_objectTable = objectTable;
|
||||
_clientState = clientState;
|
||||
_configuration = PluginInterface.GetPluginConfig() as Configuration ?? new Configuration();
|
||||
_configuration.Initialize(PluginInterface);
|
||||
@@ -74,13 +71,11 @@ namespace MareSynchronos
|
||||
};
|
||||
_downloadUi = new DownloadUi(_windowSystem, _configuration, _apiController);
|
||||
|
||||
_dalamudUtil = new DalamudUtil(_clientState, _objectTable);
|
||||
_playerWatcher = PlayerWatchFactory.Create(framework, _clientState, _objectTable);
|
||||
_playerWatcher.Enable();
|
||||
_dalamudUtil = new DalamudUtil(_clientState, objectTable, PlayerWatchFactory.Create(framework, _clientState, objectTable));
|
||||
|
||||
clientState.Login += ClientState_Login;
|
||||
clientState.Logout += ClientState_Logout;
|
||||
_apiController.AccountDeleted += ApiControllerOnAccountDeleted;
|
||||
_apiController.ChangingServers += ApiControllerOnChangingServers;
|
||||
|
||||
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;
|
||||
_introUi.IsOpen = true;
|
||||
_characterCacheManager?.Dispose();
|
||||
_playerManager?.Dispose();
|
||||
}
|
||||
|
||||
public string Name => "Mare Synchronos";
|
||||
public void Dispose()
|
||||
{
|
||||
Logger.Debug("Disposing " + Name);
|
||||
_apiController.AccountDeleted -= ApiControllerOnAccountDeleted;
|
||||
_apiController.ChangingServers -= ApiControllerOnChangingServers;
|
||||
_apiController?.Dispose();
|
||||
|
||||
_commandManager.RemoveHandler(CommandName);
|
||||
@@ -115,8 +108,7 @@ namespace MareSynchronos
|
||||
_ipcManager?.Dispose();
|
||||
_playerManager?.Dispose();
|
||||
_characterCacheManager?.Dispose();
|
||||
_playerWatcher.Disable();
|
||||
_playerWatcher.Dispose();
|
||||
_dalamudUtil.Dispose();
|
||||
}
|
||||
|
||||
|
||||
@@ -152,30 +144,32 @@ namespace MareSynchronos
|
||||
|
||||
public void ReLaunchCharacterManager()
|
||||
{
|
||||
_playerManager?.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
|
||||
{
|
||||
var characterCacheFactory =
|
||||
new CharacterDataFactory(_dalamudUtil, _ipcManager);
|
||||
_characterCacheManager = new CachedPlayersManager(_clientState, _framework, _objectTable,
|
||||
_apiController, _dalamudUtil, _ipcManager, _playerWatcher);
|
||||
_playerManager = new PlayerManager(_apiController, _ipcManager,
|
||||
characterCacheFactory, _characterCacheManager, _dalamudUtil, _playerWatcher);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Debug(ex.Message);
|
||||
}
|
||||
});
|
||||
try
|
||||
{
|
||||
var characterCacheFactory =
|
||||
new CharacterDataFactory(_dalamudUtil, _ipcManager);
|
||||
_characterCacheManager = new CachedPlayersManager(_clientState, _framework,
|
||||
_apiController, _dalamudUtil, _ipcManager);
|
||||
_playerManager = new PlayerManager(_apiController, _ipcManager,
|
||||
characterCacheFactory, _characterCacheManager, _dalamudUtil);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Debug(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void Draw()
|
||||
|
||||
@@ -51,31 +51,20 @@ namespace MareSynchronos.UI
|
||||
return;
|
||||
}
|
||||
|
||||
if (_apiController.SecretKey != "-" && !_apiController.IsConnected && _apiController.ServerAlive)
|
||||
{
|
||||
if (ImGui.Button("Reset Secret Key"))
|
||||
{
|
||||
_configuration.ClientSecret.Clear();
|
||||
_configuration.Save();
|
||||
_apiController.RestartHeartbeat();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var pluginState = _uiShared.DrawOtherPluginState();
|
||||
var pluginState = _uiShared.DrawOtherPluginState();
|
||||
|
||||
DrawSettingsContent(pluginState);
|
||||
}
|
||||
if (pluginState)
|
||||
DrawSettingsContent();
|
||||
}
|
||||
|
||||
private void DrawSettingsContent(bool pluginState)
|
||||
private void DrawSettingsContent()
|
||||
{
|
||||
_uiShared.PrintServerState();
|
||||
ImGui.Separator();
|
||||
ImGui.SetWindowFontScale(1.2f);
|
||||
ImGui.Text("Your UID");
|
||||
ImGui.SameLine();
|
||||
if (_apiController.ServerAlive)
|
||||
if (_apiController.IsConnected)
|
||||
{
|
||||
ImGui.TextColored(ImGuiColors.ParsedGreen, _apiController.UID);
|
||||
ImGui.SameLine();
|
||||
@@ -89,18 +78,18 @@ namespace MareSynchronos.UI
|
||||
}
|
||||
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.Separator();
|
||||
if (_apiController.ServerAlive)
|
||||
if (_apiController.IsConnected)
|
||||
DrawPairedClientsContent();
|
||||
DrawFileCacheSettings();
|
||||
if (_apiController.ServerAlive)
|
||||
if (_apiController.IsConnected)
|
||||
DrawCurrentTransfers();
|
||||
DrawAdministration(_apiController.ServerAlive);
|
||||
|
||||
DrawAdministration(_apiController.IsConnected);
|
||||
}
|
||||
|
||||
private bool _deleteFilesPopupModalShown = false;
|
||||
@@ -181,15 +170,39 @@ namespace MareSynchronos.UI
|
||||
}
|
||||
}
|
||||
|
||||
var marePaused = _configuration.FullPause;
|
||||
if (ImGui.Checkbox("Pause Mare Synchronos", ref marePaused))
|
||||
if (!_configuration.FullPause)
|
||||
{
|
||||
_configuration.FullPause = marePaused;
|
||||
_configuration.Save();
|
||||
_apiController.RestartHeartbeat();
|
||||
ImGui.PushStyleColor(ImGuiCol.Text, ImGuiColors.DalamudYellow);
|
||||
UiShared.TextWrapped("Note: to change servers you need to pause Mare Synchronos.");
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using Dalamud.Interface;
|
||||
@@ -74,7 +75,10 @@ namespace MareSynchronos.UI
|
||||
|
||||
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();
|
||||
var color = _apiController.ServerAlive ? ImGuiColors.ParsedGreen : ImGuiColors.DalamudRed;
|
||||
ImGui.TextColored(color, _apiController.ServerAlive ? "Available" : "Unavailable");
|
||||
@@ -132,59 +136,91 @@ namespace MareSynchronos.UI
|
||||
}
|
||||
|
||||
private int _serverSelectionIndex = 0;
|
||||
private string _customServerName = "";
|
||||
private string _customServerUri = "";
|
||||
|
||||
public void DrawServiceSelection()
|
||||
{
|
||||
string[] comboEntries = new[] { ApiController.MainServer, "Custom Service" };
|
||||
if (ImGui.BeginCombo("Service", comboEntries[_serverSelectionIndex]))
|
||||
string[] comboEntries = _apiController.ServerDictionary.Values.ToArray();
|
||||
_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;
|
||||
if (ImGui.Selectable(comboEntries[n], isSelected))
|
||||
bool isSelected = _serverSelectionIndex == i;
|
||||
if (ImGui.Selectable(comboEntries[i], isSelected))
|
||||
{
|
||||
_serverSelectionIndex = n;
|
||||
_pluginConfiguration.ApiUri = _apiController.ServerDictionary.Single(k => k.Value == comboEntries[i]).Key;
|
||||
_pluginConfiguration.Save();
|
||||
}
|
||||
|
||||
if (isSelected)
|
||||
{
|
||||
ImGui.SetItemDefaultFocus();
|
||||
}
|
||||
|
||||
bool useCustomService = _serverSelectionIndex != 0;
|
||||
|
||||
if (_apiController.UseCustomService != useCustomService)
|
||||
{
|
||||
_apiController.UseCustomService = useCustomService;
|
||||
_pluginConfiguration.Save();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
if (_apiController.UseCustomService)
|
||||
if (_serverSelectionIndex != 0)
|
||||
{
|
||||
string serviceAddress = _pluginConfiguration.ApiUri;
|
||||
if (ImGui.InputText("Service address", ref serviceAddress, 255))
|
||||
ImGui.SameLine();
|
||||
ImGui.PushFont(UiBuilder.IconFont);
|
||||
if (ImGui.Button(FontAwesomeIcon.Trash.ToIconString() + "##deleteService"))
|
||||
{
|
||||
if (_pluginConfiguration.ApiUri != serviceAddress)
|
||||
{
|
||||
_pluginConfiguration.ApiUri = serviceAddress;
|
||||
_apiController.RestartHeartbeat();
|
||||
_pluginConfiguration.Save();
|
||||
}
|
||||
_pluginConfiguration.CustomServerList.Remove(_pluginConfiguration.ApiUri);
|
||||
_pluginConfiguration.ApiUri = ApiController.MainServiceUri;
|
||||
_pluginConfiguration.Save();
|
||||
}
|
||||
ImGui.PopFont();
|
||||
}
|
||||
|
||||
PrintServerState();
|
||||
if (_apiController.ServerAlive)
|
||||
|
||||
if (_apiController.ServerAlive && !_pluginConfiguration.ClientSecret.ContainsKey(_pluginConfiguration.ApiUri))
|
||||
{
|
||||
if (ImGui.Button("Register"))
|
||||
{
|
||||
_pluginConfiguration.FullPause = false;
|
||||
_pluginConfiguration.Save();
|
||||
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)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Dalamud.Game.ClientState.Objects.SubKinds;
|
||||
|
||||
namespace MareSynchronos.Utils
|
||||
{
|
||||
@@ -24,5 +25,11 @@ namespace MareSynchronos.Utils
|
||||
using SHA256CryptoServiceProvider cryptoProvider = new();
|
||||
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.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Dalamud.Game.ClientState;
|
||||
using Dalamud.Game.ClientState.Objects;
|
||||
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
|
||||
{
|
||||
public class DalamudUtil
|
||||
public delegate void PlayerChange(Character actor);
|
||||
|
||||
public class DalamudUtil : IDisposable
|
||||
{
|
||||
private readonly ClientState _clientState;
|
||||
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;
|
||||
_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;
|
||||
@@ -49,6 +75,13 @@ namespace MareSynchronos.Utils
|
||||
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)
|
||||
{
|
||||
var objTableObj = _objectTable[index];
|
||||
@@ -85,5 +118,11 @@ namespace MareSynchronos.Utils
|
||||
}
|
||||
|
||||
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
|
||||
{
|
||||
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";
|
||||
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 CancellationTokenSource _cts;
|
||||
|
||||
private HubConnection? _fileHub;
|
||||
|
||||
private HubConnection? _heartbeatHub;
|
||||
|
||||
private CancellationTokenSource? _uploadCancellationTokenSource;
|
||||
|
||||
private HubConnection? _userHub;
|
||||
|
||||
public ApiController(Configuration pluginConfiguration)
|
||||
{
|
||||
Logger.Debug("Creating " + nameof(ApiController));
|
||||
@@ -34,9 +45,11 @@ namespace MareSynchronos.WebAPI
|
||||
_pluginConfiguration = pluginConfiguration;
|
||||
_cts = new CancellationTokenSource();
|
||||
|
||||
_ = Heartbeat();
|
||||
Task.Run(CreateConnections);
|
||||
}
|
||||
|
||||
public event EventHandler? ChangingServers;
|
||||
|
||||
public event EventHandler<CharacterReceivedEventArgs>? CharacterReceived;
|
||||
|
||||
public event EventHandler? Connected;
|
||||
@@ -50,30 +63,165 @@ namespace MareSynchronos.WebAPI
|
||||
public event EventHandler? PairedWithOther;
|
||||
|
||||
public event EventHandler? UnpairedFromOther;
|
||||
public event EventHandler? AccountDeleted;
|
||||
|
||||
public ConcurrentDictionary<string, (long, long)> CurrentDownloads { get; } = new();
|
||||
|
||||
public ConcurrentDictionary<string, (long, long)> CurrentUploads { get; } = new();
|
||||
|
||||
public bool IsConnected => !string.IsNullOrEmpty(UID);
|
||||
|
||||
public bool IsDownloading { get; private set; }
|
||||
|
||||
public bool IsUploading { get; private set; }
|
||||
|
||||
public List<ClientPairDto> PairedClients { get; set; } = new();
|
||||
|
||||
public string SecretKey => _pluginConfiguration.ClientSecret.ContainsKey(ApiUri) ? _pluginConfiguration.ClientSecret[ApiUri] : "-";
|
||||
|
||||
public bool ServerAlive =>
|
||||
(_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 bool UseCustomService
|
||||
|
||||
private string ApiUri => _pluginConfiguration.ApiUri;
|
||||
|
||||
public async Task CreateConnections()
|
||||
{
|
||||
get => _pluginConfiguration.UseCustomService;
|
||||
set
|
||||
_cts = new CancellationTokenSource();
|
||||
var token = _cts.Token;
|
||||
await StopAllConnections(token);
|
||||
|
||||
while (!ServerAlive && !token.IsCancellationRequested)
|
||||
{
|
||||
_pluginConfiguration.UseCustomService = value;
|
||||
_pluginConfiguration.Save();
|
||||
await StopAllConnections(token);
|
||||
|
||||
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()
|
||||
{
|
||||
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();
|
||||
_ = DisposeHubConnections();
|
||||
public async Task DeleteAllMyFiles()
|
||||
{
|
||||
await _fileHub!.SendAsync("DeleteAllFiles");
|
||||
}
|
||||
|
||||
public async Task<string> DownloadFile(string hash, CancellationToken ct)
|
||||
@@ -167,41 +320,6 @@ namespace MareSynchronos.WebAPI
|
||||
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)
|
||||
{
|
||||
Logger.Debug("Received DTO for " + characterHash);
|
||||
@@ -216,29 +334,9 @@ namespace MareSynchronos.WebAPI
|
||||
var response = await _userHub!.InvokeAsync<string>("Register");
|
||||
_pluginConfiguration.ClientSecret[ApiUri] = response;
|
||||
_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)
|
||||
{
|
||||
if (!IsConnected || SecretKey == "-") return;
|
||||
@@ -323,40 +421,6 @@ namespace MareSynchronos.WebAPI
|
||||
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)
|
||||
{
|
||||
await using var db = new FileCacheContext();
|
||||
@@ -364,67 +428,6 @@ namespace MareSynchronos.WebAPI
|
||||
return (fileHash, LZ4Codec.WrapHC(await File.ReadAllBytesAsync(fileCache.Filepath, uploadToken), 0,
|
||||
(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)
|
||||
{
|
||||
var entry = PairedClients.SingleOrDefault(e => e.OtherUID == dto.OtherUID);
|
||||
@@ -492,4 +495,12 @@ namespace MareSynchronos.WebAPI
|
||||
public CharacterCacheDto CharacterData { 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