feature(gamelogic): Implement ALT + F4 and Window X button to close game#2336
feature(gamelogic): Implement ALT + F4 and Window X button to close game#2336githubawn wants to merge 7 commits intoTheSuperHackers:mainfrom
Conversation
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp | Implemented centralized quit(Bool toDesktop) method with proper handling for multiplayer self-destruct, recording cleanup, and game state management. Added exception-based abort for loading screen. |
| GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp | Identical implementation to Generals version - centralized quit logic with proper cleanup and exception-based loading abort. |
| Generals/Code/GameEngine/Source/GameClient/GameClient.cpp | Added isMovieAbortRequested() helper consolidating ESC, window close, and Alt+F4 detection. Used in movie playback loops to enable graceful exit. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GameClient.cpp | Identical implementation to Generals version - movie abort helper with ESC and window close detection. |
| Core/GameEngine/Source/GameClient/GUI/LoadScreen.cpp | Refactored movie loops to use isMovieAbortRequested() and added quit checks during loading progress updates. Enables graceful exit during loading screens. |
| Generals/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp | Moved MSG_META_DEMO_INSTANT_QUIT out of debug-only section, registered it as system message, and replaced duplicated quit code with quit(TRUE) call. |
| GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/CommandXlat.cpp | Removed ALLOW_ALT_F4 ifdef guard, registered MSG_META_DEMO_INSTANT_QUIT as system message, replaced duplicated quit code with centralized call. |
Flowchart
%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[User Action: Alt+F4 / Window X / Quit Menu] --> B{Check Current State}
B -->|In Movie| C[isMovieAbortRequested checks]
B -->|In Loading| D[LoadScreen.update checks]
B -->|In Menu| E[QuitMenu callback]
C --> F[GameClient::isMovieAbortRequested]
D --> G[GameLogic::updateLoadProgress]
E --> H[GameLogic::quit]
F -->|ESC / Window Close / Alt+F4| H
G -->|Quitting detected| I[Throw QuitGameException]
I --> J[Caught in startNewGame]
H --> K{toDesktop parameter}
K -->|TRUE| L{isInGame?}
K -->|FALSE| M[exitGame]
L -->|Yes| N{isMultiplayer?}
L -->|No| O[Set quitting flag]
N -->|Yes| P[Send self-destruct message]
N -->|No| Q[clearGameData immediately]
P --> R[Set m_quitToDesktopAfterMatch]
R --> S[exitGame - defer quit]
S --> T[clearGameData detects flag]
T --> O
Q --> O
M --> U[setClientQuiet]
O --> U
U --> V[Game exits gracefully]
Last reviewed commit: 6b28aed
GeneralsMD/Code/GameEngine/Source/GameClient/GUI/LoadScreen.cpp
Outdated
Show resolved
Hide resolved
|
Needs rebase. My initial thought on this, without looking at code, is that it will make it easier for players to disconnect from a Multiplayer match - by accident or intentional - so this feature must not work during a Multiplayer Match. |
|
Will rebase soon. The multiplayer behavior was designed based on your comment from #1356 (comment). It also adds safe abort logic so Alt+F4 works consistently everywhere addressing helmutbuhler's #1356 (comment) concern about the button only working in some situations. |
|
Thank you for implementing this. I did a few quick tests and the current implementation appears to work well. |
843b370 to
4fda496
Compare
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp
Outdated
Show resolved
Hide resolved
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp
Outdated
Show resolved
Hide resolved
2d896d5 to
036ed84
Compare
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
xezon
left a comment
There was a problem hiding this comment.
It would have been easier to review if this change just contained Core+GeneralsMD edits for starters.
| void GameLogic::startNewGame( Bool saveGame ) | ||
| { | ||
| try | ||
| { |
There was a problem hiding this comment.
Perhaps do
void GameLogic::startNewGame( Bool saveGame )
{
try
{
tryStartNewGame(saveGame);
}
catch ..
{
}
}
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp
Outdated
Show resolved
Hide resolved
| { | ||
| if (isInMultiplayerGame() && !isInSkirmishGame() && TheGameInfo && !TheGameInfo->isSandbox()) | ||
| { | ||
| GameMessage *msg = TheMessageStream->appendMessage(GameMessage::MSG_SELF_DESTRUCT); |
There was a problem hiding this comment.
Any chance that this can cause player frustration when they accidentally press the X button during a match, for example when they do not use the Mouse Cursor Capture feature?
There was a problem hiding this comment.
Good point, I didn't know about players with disabled mouse capture. I'm considering something like adding a double click + notification.
There was a problem hiding this comment.
if (!TheInGameUI->isQuitMenuVisible())
{
ToggleQuitMenu();
}
else
{
// append self destruct msg
}Would that be enough?
There was a problem hiding this comment.
So the user would need to click the X twice then?
There was a problem hiding this comment.
Yes, unless they already had the menu open, not sure if that's still somewhat undesirable. I think it's easier to implement that than to check for a repeated WM_CLOSE message if that was the idea so far.
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp
Outdated
Show resolved
Hide resolved
3a3c926 to
6f2b0b8
Compare
Fixes #1356
Split up in 2 commits.
Previously, the quit logic was duplicated and inconsistent across several places (the quit menu, the "quit to desktop" button, and the Alt+F4 handler). This commit centralizes all of that into a single GameLogic::quit(Bool toDesktop) method. It properly handles edge cases like stopping an active recording, sending a self-destruct message in multiplayer (using a new m_quitToDesktopAfterMatch flag), unpausing/unfreezing the game before exiting. All the old scattered quit code is replaced with a simple call to TheGameLogic->quit(true/false).
This follow-up extends the graceful exit to two more situations where the game previously couldn't be closed cleanly:
During the loading screen: The load progress update now checks if a quit has been requested and throws a QuitGameException, which is caught in startNewGame() to cleanly abort the loading process mid-way.
During movies: The inline ESC-key checking that was copy-pasted in multiple video playback loops is refactored into a new GameClient::isMovieAbortRequested() method. This method now also checks for window close / Alt+F4 events (not just ESC), so closing the window during a movie no longer gets stuck. The MSG_META_DEMO_INSTANT_QUIT message is also registered as a system message so it propagates correctly even during loading.