diff --git a/Intersect.Client.Core/Interface/Game/SimplifiedEscapeMenu.cs b/Intersect.Client.Core/Interface/Game/SimplifiedEscapeMenu.cs index a381d5d171..0007d7c403 100644 --- a/Intersect.Client.Core/Interface/Game/SimplifiedEscapeMenu.cs +++ b/Intersect.Client.Core/Interface/Game/SimplifiedEscapeMenu.cs @@ -35,7 +35,7 @@ public SimplifiedEscapeMenu(Canvas gameCanvas, Func settingsWind _settings.Clicked += OpenSettingsWindow; _character.Clicked += LogoutToCharacterSelectSelectClicked; _logout.Clicked += LogoutToMainToMainMenuClicked; - _exit.Clicked += ExitToDesktopToDesktopClicked; + _exit.Clicked += ExitToDesktopClicked; LoadJsonUi(GameContentManager.UI.InGame, Graphics.Renderer?.GetResolutionString()); } @@ -80,7 +80,13 @@ private void LogoutToCharacterSelectSelectClicked(Base sender, MouseButtonState { if (Globals.Me?.CombatTimer > Timing.Global.Milliseconds) { - ShowCombatWarning(); + AlertWindow.Open( + Strings.Combat.WarningCharacterSelect, + Strings.Combat.WarningTitle, + AlertType.Warning, + handleSubmit: LogoutToCharacterSelect, + inputType: InputType.YesNo + ); } else { @@ -92,7 +98,13 @@ private void LogoutToMainToMainMenuClicked(Base sender, MouseButtonState argumen { if (Globals.Me?.CombatTimer > Timing.Global.Milliseconds) { - ShowCombatWarning(); + AlertWindow.Open( + Strings.Combat.WarningLogout, + Strings.Combat.WarningTitle, + AlertType.Warning, + handleSubmit: LogoutToMainMenu, + inputType: InputType.YesNo + ); } else { @@ -100,29 +112,37 @@ private void LogoutToMainToMainMenuClicked(Base sender, MouseButtonState argumen } } - private void ExitToDesktopToDesktopClicked(Base sender, MouseButtonState arguments) + private void ExitToDesktopClicked(Base sender, MouseButtonState arguments) { - if (Globals.Me?.CombatTimer > Timing.Global.Milliseconds) + if (Globals.Me?.CombatTimer > Timing.Global?.Milliseconds) { - ShowCombatWarning(); + AlertWindow.Open( + Strings.Combat.WarningExitDesktop, + Strings.Combat.WarningTitle, + AlertType.Warning, + inputType: InputType.YesNo, + handleSubmit: (_, _) => + { + Globals.Me.CombatTimer = 0; + Globals.IsRunning = false; + } + ); } else { - ExitToDesktop(null, null); + AlertWindow.Open( + Strings.General.QuitPrompt, + Strings.General.QuitTitle, + AlertType.Warning, + inputType: InputType.YesNo, + handleSubmit: (_, _) => + { + Globals.IsRunning = false; + } + ); } } - private static void ShowCombatWarning() - { - AlertWindow.Open( - Strings.Combat.WarningCharacterSelect, - Strings.Combat.WarningTitle, - AlertType.Warning, - handleSubmit: LogoutToCharacterSelect, - inputType: InputType.YesNo - ); - } - private void OpenSettingsWindow(object? sender, EventArgs? e) { var settingsWindow = _settingsWindowProvider(); @@ -153,23 +173,4 @@ private static void LogoutToMainMenu(object? sender, EventArgs? e) Main.Logout(false); } - - private static void ExitToDesktop(object? sender, EventArgs? e) - { - AlertWindow.Open( - Strings.General.QuitPrompt, - Strings.General.QuitTitle, - AlertType.Warning, - inputType: InputType.YesNo, - handleSubmit: (_, _) => - { - if (Globals.Me != null) - { - Globals.Me.CombatTimer = 0; - } - - Globals.IsRunning = false; - } - ); - } } \ No newline at end of file diff --git a/Intersect.Client.Core/MonoGame/IntersectGame.cs b/Intersect.Client.Core/MonoGame/IntersectGame.cs index b79e245dc9..dbb9e0fb4d 100644 --- a/Intersect.Client.Core/MonoGame/IntersectGame.cs +++ b/Intersect.Client.Core/MonoGame/IntersectGame.cs @@ -43,8 +43,6 @@ internal partial class IntersectGame : Game private GraphicsDeviceManager mGraphics; - private bool _isShowingExitConfirmation = false; - #region "Autoupdate Variables" private Updater? _updater; @@ -341,64 +339,57 @@ protected override void Draw(GameTime gameTime) protected override void OnExiting(object sender, ExitingEventArgs args) { - // If already showing dialog, just cancel and return - if (_isShowingExitConfirmation) + // If game is already shutting down, allow it to exit normally + if (!Globals.IsRunning) { - args.Cancel = true; + ApplicationContext.Context.Value?.Logger.LogInformation("System window closing (due to user interaction most likely)."); + TryExit(sender, args); return; } - ApplicationContext.Context.Value?.Logger.LogInformation("System window closing (due to user interaction most likely)."); - - // Check if player is logged in and in game - if (Globals.Me != null && Globals.LoggedIn && Globals.GameState == GameStates.InGame) - { - // Set flag to prevent multiple dialogs - _isShowingExitConfirmation = true; - - // Check if player is in combat - bool inCombat = Globals.Me.CombatTimer > Timing.Global?.Milliseconds; + // Cancel the exit event + args.Cancel = true; - // Cancel the exit event - args.Cancel = true; + // Check if there's a player in combat + bool inCombat = Globals.Me != null && + Globals.Me.CombatTimer > Timing.Global?.Milliseconds && + Globals.GameState == GameStates.InGame; - if (inCombat) - { - // Show combat warning - var inputBox = new InputBox( - title: Strings.Combat.WarningTitle, - prompt: Strings.Combat.WarningExitDesktop, - inputType: InputType.YesNo, - onSubmit: (s, e) => + if (inCombat) + { + AlertWindow.Open( + Strings.Combat.WarningExitDesktop, + Strings.Combat.WarningTitle, + AlertType.Warning, + inputType: InputType.YesNo, + handleSubmit: (_, _) => + { + if (Globals.Me != null) { Globals.Me.CombatTimer = 0; - _isShowingExitConfirmation = false; - Globals.IsRunning = false; - }, - onCancel: (s, e) => { _isShowingExitConfirmation = false; } - ); - inputBox.Closed += (s, e) => { _isShowingExitConfirmation = false; }; - } - else - { - // Show quit confirmation - var inputBox = new InputBox( - title: Strings.General.QuitTitle, - prompt: Strings.General.QuitPrompt, - inputType: InputType.YesNo, - onSubmit: (s, e) => - { - _isShowingExitConfirmation = false; - Globals.IsRunning = false; - }, - onCancel: (s, e) => { _isShowingExitConfirmation = false; } - ); - inputBox.Closed += (s, e) => { _isShowingExitConfirmation = false; }; - } + } - return; + Globals.IsRunning = false; + } + ); } + else + { + AlertWindow.Open( + Strings.General.QuitPrompt, + Strings.General.QuitTitle, + AlertType.Warning, + inputType: InputType.YesNo, + handleSubmit: (_, _) => + { + Globals.IsRunning = false; + } + ); + } + } + private void TryExit(object sender, ExitingEventArgs args) + { try { _updater?.Stop(); diff --git a/Intersect.Client.Framework/Gwen/Control/Base.cs b/Intersect.Client.Framework/Gwen/Control/Base.cs index b49cb19e8a..eda1d4a7e0 100644 --- a/Intersect.Client.Framework/Gwen/Control/Base.cs +++ b/Intersect.Client.Framework/Gwen/Control/Base.cs @@ -861,6 +861,12 @@ public bool IsHidden private static void SetVisible(Base @this, bool value) { + // Check if already disposed + if (@this._disposed) + { + return; + } + var wasVisibleInParent = @this._visible; if (@this.GetType().Name == "VersionPanel") diff --git a/Intersect.Client.Framework/Gwen/Control/WindowControl.cs b/Intersect.Client.Framework/Gwen/Control/WindowControl.cs index 4f5e8ed22d..cd0765761c 100644 --- a/Intersect.Client.Framework/Gwen/Control/WindowControl.cs +++ b/Intersect.Client.Framework/Gwen/Control/WindowControl.cs @@ -273,7 +273,14 @@ private void Close(Base sender, EventArgs args) return; } - IsHidden = true; + try + { + IsHidden = true; + } + catch (ObjectDisposedException) + { + // Canvas already disposed during shutdown, this is fine + } if (_modal != null) {