feat(cli): Add -loadsave option - #3001
Conversation
|
| Filename | Overview |
|---|---|
| Generals/Code/GameEngine/Source/Common/GameEngine.cpp | Adds the base-game startup path that prepares and loads a command-line-selected save before entering the main loop. |
| GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp | Adds the equivalent Zero Hour startup save-loading path. |
| Generals/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp | Excludes renderer-owned snapshot blocks when saving or loading in base-game headless mode. |
| GeneralsMD/Code/GameEngine/Source/Common/System/SaveGame/GameState.cpp | Updates Zero Hour save result handling and headless snapshot-block serialization. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/SaveLoadFeedback.cpp | Introduces shared UI feedback handling for Zero Hour save and load result codes. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/PopupSaveLoad.cpp | Routes save/load menu result handling through the shared feedback implementation. |
| GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp | Prevents shell and shell-map startup while a command-line save load is pending. |
Sequence Diagram
sequenceDiagram
participant CLI as Command line
participant Engine as GameEngine
participant State as GameState
participant Logic as GameLogic
participant Shell as Shell
CLI->>Engine: Set -loadsave filename
Engine->>State: Read save metadata
Engine->>Logic: Prepare single-player game
Engine->>State: Load save
alt Load succeeds
Engine->>Shell: Hide shell
Engine->>Engine: Enter main loop
else Load fails
Engine->>Engine: Exit
end
Reviews (2): Last reviewed commit: "feat(commandline): Add -loadsave option ..." | Re-trigger Greptile
ab119a6 to
e2a2c83
Compare
e2a2c83 to
65b9e16
Compare
|
This needs a rebase |
65b9e16 to
bc65271
Compare
|
rebased |
bc65271 to
a689346
Compare
|
Did some polishing and updated the description - give it a try :) |
xezon
left a comment
There was a problem hiding this comment.
Looks better, but can be improved more.
Too many "TheSuperHackers" labeled comments are added in the code. Prefer using authored comments only for crucial comments that describe a bigger change, not small tweaks, refactors and accomodating changes.
a689346 to
dfc6ebd
Compare
xezon
left a comment
There was a problem hiding this comment.
It's getting better, but it is still hacking its way.
|
|
||
| m_intro = NEW Intro; | ||
| // The intro leads into the shell, which is not shown when a save game is loaded on startup | ||
| if (TheGlobalData->m_loadSaveGame.isEmpty()) |
There was a problem hiding this comment.
This also looks like a hack.
I expect there is a more elegant way to do this. Before TheShell is shown, TheGameLogic->prepareNewGame(GAME_SINGLE_PLAYER, DIFFICULTY_NORMAL, 0); should have executed, so there likely is some game state info available that allows skipping shell if a game is already running.
However, not starting the shell also sounds like hack. I suggest properly study this and implement a graceful shell launch without loading shell map.
There was a problem hiding this comment.
I cleaned this up - now we don't create the intro when a save game is queued, so doPostIntro never suspends rendering and the shell is never pushed. That let me revert the Shell::showShell/showShellMap guards too
There was a problem hiding this comment.
Also, reworked things so startup initializes the shell normally instead of suppressing it.
-loadsave disables intro playback and the shell-map game, but the normal post-intro shell transition still runs. showShell() pushes the Main Menu directly, then the queued save is loaded. prepareNewGame() hides the shell while preserving the Main Menu on its stack, and loadGame() restores the save.
This removes the load-specific intro branch and the direct m_breakTheMovie change. MainMenuInit clears that flag through the normal path. Keeping Main Menu on the stack also restores the expected mission-end flow: game → score screen → Main Menu.
GameEngine.cpp and Shell.cpp are now unchanged. The only post-intro handoff is:
TheShell->showShellMap(TRUE);
TheShell->showShell();
if (TheGlobalData->m_loadSaveGame.isNotEmpty())
{
TheGameState->loadQueuedSaveGame();
}
I also found two separate issues while testing that are now fixed:
- loadGame() takes AvailableGameInfo by value again. The copy is required because resetting the engine during a mission-save load frees the caller’s save-list entry.
- Missing or malformed -loadsave files are caught and logged instead of escaping from getSaveGameInfoFromFile() as an exception.
Verified with normal and headless save loading in both games, including the complete mission-exit path back through the score screen to a working Main Menu.
dfc6ebd to
46df43d
Compare
Fixes #2999
Now -loadsave loads a save from the user Save directory during startup in normal or headless mode.
Snapshots can now disable xfer to be excluded from save game data. The particle, terrain visual and ghost object snapshots disable xfer in headless mode, so their blocks are omitted when saving and are skipped like unknown blocks when loading rendered saves headlessly.
Todo:
Notes:
If the save file is not found, the game logs the failure and exits after engine initialization. Debug builds show a "File not found" assert first.