diff --git a/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs b/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs index 7e5a5e4..4a75e73 100644 --- a/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs +++ b/MareSynchronos/Services/ServerConfiguration/ServerConfigurationManager.cs @@ -54,7 +54,7 @@ public class ServerConfigurationManager } } - public string? GetSecretKey(int serverIdx = -1) + public string? GetSecretKey(out bool hasMulti, int serverIdx = -1) { ServerStorage? currentServer; currentServer = serverIdx == -1 ? CurrentServer : GetServerByIndex(serverIdx); @@ -63,6 +63,7 @@ public class ServerConfigurationManager currentServer = new(); Save(); } + hasMulti = false; var charaName = _dalamudUtil.GetPlayerNameAsync().GetAwaiter().GetResult(); var worldId = _dalamudUtil.GetHomeWorldIdAsync().GetAwaiter().GetResult(); @@ -81,11 +82,11 @@ public class ServerConfigurationManager var auth = currentServer.Authentications.FindAll(f => string.Equals(f.CharacterName, charaName, StringComparison.Ordinal) && f.WorldId == worldId); if (auth.Count >= 2) { - _mareMediator.Publish(new NotificationMessage("Multiple Identical Characters detected", "Your Service configuration has multiple characters with the same name and world set up. Please delete the duplicates in the character configuration.", - NotificationType.Error)); _logger.LogTrace("GetSecretKey accessed, returning null because multiple ({count}) identical characters.", auth.Count); + hasMulti = true; return null; } + if (auth.Count == 0) { _logger.LogTrace("GetSecretKey accessed, returning null because no set up characters for {chara} on {world}", charaName, worldId); diff --git a/MareSynchronos/UI/CompactUI.cs b/MareSynchronos/UI/CompactUI.cs index 939ef4b..a7a80c5 100644 --- a/MareSynchronos/UI/CompactUI.cs +++ b/MareSynchronos/UI/CompactUI.cs @@ -598,6 +598,7 @@ public class CompactUi : WindowMediatorSubscriberBase ServerState.RateLimited => "You are rate limited for (re)connecting too often. Disconnect, wait 10 minutes and try again.", ServerState.Connected => string.Empty, ServerState.NoSecretKey => "You have no secret key set for this current character. Use the button below or open the settings and set a secret key for the current character. You can reuse the same secret key for multiple characters.", + ServerState.MultiChara => "Your Character Configuration has multiple characters configured with same name and world. You will not be able to connect until you fix this issue. Remove the duplicates from the configuration in Settings -> Service Settings -> Character Management and reconnect manually after.", _ => string.Empty }; } @@ -616,6 +617,7 @@ public class CompactUi : WindowMediatorSubscriberBase ServerState.Offline => ImGuiColors.DalamudRed, ServerState.RateLimited => ImGuiColors.DalamudYellow, ServerState.NoSecretKey => ImGuiColors.DalamudYellow, + ServerState.MultiChara => ImGuiColors.DalamudYellow, _ => ImGuiColors.DalamudRed }; } @@ -633,6 +635,7 @@ public class CompactUi : WindowMediatorSubscriberBase ServerState.Offline => "Unavailable", ServerState.RateLimited => "Rate Limited", ServerState.NoSecretKey => "No Secret Key", + ServerState.MultiChara => "Duplicate Characters", ServerState.Connected => _apiController.DisplayName, _ => string.Empty }; diff --git a/MareSynchronos/UI/SettingsUi.cs b/MareSynchronos/UI/SettingsUi.cs index 1822f50..df94cc1 100644 --- a/MareSynchronos/UI/SettingsUi.cs +++ b/MareSynchronos/UI/SettingsUi.cs @@ -1273,7 +1273,13 @@ public class SettingsUi : WindowMediatorSubscriberBase } var friendlyName = secretKey.FriendlyName; - if (ImGui.TreeNode($"chara", $"Character: {item.CharacterName}, World: {worldPreview}, Secret Key: {friendlyName}")) + bool thisIsYou = false; + if (string.Equals(_dalamudUtilService.GetPlayerName(), item.CharacterName, StringComparison.OrdinalIgnoreCase) + && _dalamudUtilService.GetWorldId() == worldIdx) + { + thisIsYou = true; + } + if (ImGui.TreeNode($"chara", (thisIsYou ? "[CURRENT] " : "") + $"Character: {item.CharacterName}, World: {worldPreview}, Secret Key: {friendlyName}")) { var charaName = item.CharacterName; if (ImGui.InputText("Character Name", ref charaName, 64)) diff --git a/MareSynchronos/UI/UISharedService.cs b/MareSynchronos/UI/UISharedService.cs index 0307f04..2c06837 100644 --- a/MareSynchronos/UI/UISharedService.cs +++ b/MareSynchronos/UI/UISharedService.cs @@ -911,16 +911,13 @@ public partial class UiSharedService : DisposableMediatorSubscriberBase ImGui.EndCombo(); } - if (_serverConfigurationManager.GetSecretKey(_serverSelectionIndex) != null) + ImGui.SameLine(); + var text = "Connect"; + if (_serverSelectionIndex == _serverConfigurationManager.CurrentServerIndex) text = "Reconnect"; + if (NormalizedIconTextButton(FontAwesomeIcon.Link, text)) { - ImGui.SameLine(); - var text = "Connect"; - if (_serverSelectionIndex == _serverConfigurationManager.CurrentServerIndex) text = "Reconnect"; - if (NormalizedIconTextButton(FontAwesomeIcon.Link, text)) - { - _serverConfigurationManager.SelectServer(_serverSelectionIndex); - _ = _apiController.CreateConnections(); - } + _serverConfigurationManager.SelectServer(_serverSelectionIndex); + _ = _apiController.CreateConnections(); } if (ImGui.TreeNode("Add Custom Service")) diff --git a/MareSynchronos/WebAPI/SignalR/ApiController.cs b/MareSynchronos/WebAPI/SignalR/ApiController.cs index 9770214..09cb742 100644 --- a/MareSynchronos/WebAPI/SignalR/ApiController.cs +++ b/MareSynchronos/WebAPI/SignalR/ApiController.cs @@ -115,7 +115,18 @@ public sealed partial class ApiController : DisposableMediatorSubscriberBase, IM return; } - var secretKey = _serverManager.GetSecretKey(); + var secretKey = _serverManager.GetSecretKey(out bool multi); + if (multi) + { + Logger.LogWarning("Multiple secret keys for current character"); + _connectionDto = null; + Mediator.Publish(new NotificationMessage("Multiple Identical Characters detected", "Your Service configuration has multiple characters with the same name and world set up. Delete the duplicates in the character management to be able to connect to Mare.", + NotificationType.Error)); + await StopConnection(ServerState.MultiChara).ConfigureAwait(false); + _connectionCancellationTokenSource?.Cancel(); + return; + } + if (secretKey.IsNullOrEmpty()) { Logger.LogWarning("No secret key set for current character"); diff --git a/MareSynchronos/WebAPI/SignalR/TokenProvider.cs b/MareSynchronos/WebAPI/SignalR/TokenProvider.cs index 087d7e5..41d55f3 100644 --- a/MareSynchronos/WebAPI/SignalR/TokenProvider.cs +++ b/MareSynchronos/WebAPI/SignalR/TokenProvider.cs @@ -64,7 +64,7 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber tokenUri = MareAuth.AuthFullPath(new Uri(_serverManager.CurrentApiUrl .Replace("wss://", "https://", StringComparison.OrdinalIgnoreCase) .Replace("ws://", "http://", StringComparison.OrdinalIgnoreCase))); - var secretKey = _serverManager.GetSecretKey()!; + var secretKey = _serverManager.GetSecretKey(out _)!; var auth = secretKey.GetHash256(); result = await _httpClient.PostAsync(tokenUri, new FormUrlEncodedContent(new[] { @@ -103,7 +103,7 @@ public sealed class TokenProvider : IDisposable, IMediatorSubscriber { jwtIdentifier = new(_serverManager.CurrentApiUrl, _dalamudUtil.GetPlayerNameHashedAsync().GetAwaiter().GetResult(), - _serverManager.GetSecretKey()!); + _serverManager.GetSecretKey(out _)!); _lastJwtIdentifier = jwtIdentifier; } catch (Exception ex) diff --git a/MareSynchronos/WebAPI/SignalR/Utils/ServerState.cs b/MareSynchronos/WebAPI/SignalR/Utils/ServerState.cs index 2988d44..ca34fe3 100644 --- a/MareSynchronos/WebAPI/SignalR/Utils/ServerState.cs +++ b/MareSynchronos/WebAPI/SignalR/Utils/ServerState.cs @@ -12,4 +12,5 @@ public enum ServerState VersionMisMatch, RateLimited, NoSecretKey, + MultiChara, } \ No newline at end of file