Skip to content

Commit c4a912b

Browse files
authored
enhancement: confirmation dialogues when closing the client (#2788)
This commit restores original engine behavior that prevents accidental game exits and ensures players don't lose progress by accidentally pressing Alt+F4 or clicking the window close button, especially during combat situations. - Intercept OnExiting event to prevent immediate closure when player is in-game - Show combat warning dialog if player is in combat, requiring confirmation to exit - Show standard quit confirmation dialog if player is not in combat - Add _isShowingExitConfirmation flag to prevent infinite OnExiting event loop - Makes InputBox.Closed event to handle X button clicks on dialogs - Add QuitTitle and QuitPrompt strings to General localization - Normal cleanup continues if player is not logged in or not in-game - replicated this logic for both, simplified and regular game menus when pressing the desktop option
1 parent 533a806 commit c4a912b

File tree

4 files changed

+79
-42
lines changed

4 files changed

+79
-42
lines changed

Intersect.Client.Core/Interface/Game/SimplifiedEscapeMenu.cs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -156,11 +156,20 @@ private static void LogoutToMainMenu(object? sender, EventArgs? e)
156156

157157
private static void ExitToDesktop(object? sender, EventArgs? e)
158158
{
159-
if (Globals.Me != null)
160-
{
161-
Globals.Me.CombatTimer = 0;
162-
}
159+
AlertWindow.Open(
160+
Strings.General.QuitPrompt,
161+
Strings.General.QuitTitle,
162+
AlertType.Warning,
163+
inputType: InputType.YesNo,
164+
handleSubmit: (_, _) =>
165+
{
166+
if (Globals.Me != null)
167+
{
168+
Globals.Me.CombatTimer = 0;
169+
}
163170

164-
Globals.IsRunning = false;
171+
Globals.IsRunning = false;
172+
}
173+
);
165174
}
166175
}

Intersect.Client.Core/Interface/Menu/EscapeMenuWindow.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,11 +217,20 @@ private void ShowCombatWarning()
217217

218218
private void ExitToDesktop(object? sender, EventArgs? e)
219219
{
220-
if (Globals.Me != null)
221-
{
222-
Globals.Me.CombatTimer = 0;
223-
}
224-
225-
Globals.IsRunning = false;
220+
AlertWindow.Open(
221+
Strings.General.QuitPrompt,
222+
Strings.General.QuitTitle,
223+
AlertType.Warning,
224+
inputType: InputType.YesNo,
225+
handleSubmit: (_, _) =>
226+
{
227+
if (Globals.Me != null)
228+
{
229+
Globals.Me.CombatTimer = 0;
230+
}
231+
232+
Globals.IsRunning = false;
233+
}
234+
);
226235
}
227236
}

Intersect.Client.Core/Localization/Strings.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1273,6 +1273,12 @@ public partial struct General
12731273

12741274
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
12751275
public static LocalizedString PingLabelFormat = @"{0}ms";
1276+
1277+
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
1278+
public static LocalizedString QuitTitle { get; set; } = @"Quit Game";
1279+
1280+
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
1281+
public static LocalizedString QuitPrompt { get; set; } = @"Are you sure you want to quit the game?";
12761282
}
12771283

12781284
public partial struct Guilds

Intersect.Client.Core/MonoGame/IntersectGame.cs

Lines changed: 44 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ internal partial class IntersectGame : Game
4343

4444
private GraphicsDeviceManager mGraphics;
4545

46+
private bool _isShowingExitConfirmation = false;
47+
4648
#region "Autoupdate Variables"
4749

4850
private Updater? _updater;
@@ -339,51 +341,62 @@ protected override void Draw(GameTime gameTime)
339341

340342
protected override void OnExiting(object sender, ExitingEventArgs args)
341343
{
344+
// If already showing dialog, just cancel and return
345+
if (_isShowingExitConfirmation)
346+
{
347+
args.Cancel = true;
348+
return;
349+
}
350+
342351
ApplicationContext.Context.Value?.Logger.LogInformation("System window closing (due to user interaction most likely).");
343352

344-
if (Globals.Me != null && Globals.Me.CombatTimer > Timing.Global?.Milliseconds)
353+
// Check if player is logged in and in game
354+
if (Globals.Me != null && Globals.LoggedIn && Globals.GameState == GameStates.InGame)
345355
{
346-
//Try to prevent SDL Window Close
347-
var exception = false;
348-
try
349-
{
350-
var platform = GetType()
351-
.GetField("Platform", BindingFlags.NonPublic | BindingFlags.Instance)
352-
.GetValue(this);
356+
// Set flag to prevent multiple dialogs
357+
_isShowingExitConfirmation = true;
353358

354-
var field = platform.GetType()
355-
.GetField("_isExiting", BindingFlags.NonPublic | BindingFlags.Instance);
359+
// Check if player is in combat
360+
bool inCombat = Globals.Me.CombatTimer > Timing.Global?.Milliseconds;
356361

357-
field.SetValue(platform, 0);
358-
}
359-
catch
360-
{
361-
//TODO: Should we log here? I really don't know if it's necessary.
362-
exception = true;
363-
}
362+
// Cancel the exit event
363+
args.Cancel = true;
364364

365-
if (!exception)
365+
if (inCombat)
366366
{
367-
//Show Message Getting Exit Confirmation From Player to Leave in Combat
368-
_ = new InputBox(
367+
// Show combat warning
368+
var inputBox = new InputBox(
369369
title: Strings.Combat.WarningTitle,
370-
prompt: Strings.Combat.WarningCharacterSelect,
370+
prompt: Strings.Combat.WarningExitDesktop,
371371
inputType: InputType.YesNo,
372372
onSubmit: (s, e) =>
373373
{
374-
if (Globals.Me != null)
375-
{
376-
Globals.Me.CombatTimer = 0;
377-
}
378-
374+
Globals.Me.CombatTimer = 0;
375+
_isShowingExitConfirmation = false;
379376
Globals.IsRunning = false;
380-
}
377+
},
378+
onCancel: (s, e) => { _isShowingExitConfirmation = false; }
381379
);
382-
383-
//Restart the MonoGame RunLoop
384-
Run();
385-
return;
380+
inputBox.Closed += (s, e) => { _isShowingExitConfirmation = false; };
386381
}
382+
else
383+
{
384+
// Show quit confirmation
385+
var inputBox = new InputBox(
386+
title: Strings.General.QuitTitle,
387+
prompt: Strings.General.QuitPrompt,
388+
inputType: InputType.YesNo,
389+
onSubmit: (s, e) =>
390+
{
391+
_isShowingExitConfirmation = false;
392+
Globals.IsRunning = false;
393+
},
394+
onCancel: (s, e) => { _isShowingExitConfirmation = false; }
395+
);
396+
inputBox.Closed += (s, e) => { _isShowingExitConfirmation = false; };
397+
}
398+
399+
return;
387400
}
388401

389402
try

0 commit comments

Comments
 (0)