Add save-related events
Pathoschild opened this issue ยท 2 comments
Create SaveEvents
with three events:
event | description |
---|---|
BeforeSave |
raised just before the game serialises data to the save file. |
AfterSave |
raised just after the game serialises data to the save file. |
AfterLoad |
raised after player loads a saved game. (This deprecates PlayerEvents.LoadedGame , which is often confused with GameEvents.GameLoaded .) |
This is an oft-requested feature, e.g. for mods that create custom content that can't be serialised to the save file.
To do
- Figure out how to reliably detect pre-save and post-save.
- Implement
SaveEvents
events. - Deprecate
PlayerEvents.LoadedGame
(replaced bySaveEvents.AfterLoad
). - Deprecate
TimeEvents.OnNewDay
(unreliable for any purpose).
Here's how the game typically triggers a save:
-
The game sets
Game1.newDay = true
. -
On a later update tick, it eventually detects
Game1.newDay
and callsGame1.newDayAfterFade
.
That method can also be called directly regardless ofGame1.newDay
, such as whenGame1.eventOver == true
andGame1.dayOfMonth == 0
. ThenewDay
field doesn't even necessarily trigger a new save (e.g. it won't trigger ifGame1.exitToTitle
is also set), and the save doesn't necessarily happen on the next tick due to preceding flags. That meansnewDay
is not sufficient to detect an upcoming save. -
Game1.newDayAfterFade
does a bunch of cleanup and end-of-day stuff (e.g. sending mail), then callsshowEndOfNightStuff
(ifGame1.farmEvent
is clear).
The latter method may also be called directly by the update tick logic when an ongoingGame1.farmEvent
ends. -
Game1.showEndOfNightStuff
method does more end-of-night stuff (e.g. selling items in the shipping box), and eventually sets the active menu toSaveGameMenu
. -
The
SaveGameMenu
will sit there doing UI stuff until it decides it's done, at which point itsupdate
method will callSaveGame.Save()
.
This is the only place whereSaveGame.Save()
is ever called. -
SaveGameMenu
will then wait asynchronously while the save serialiser does its work. Eventually it'll detect completion, and close itself.
Based on that:
BeforeSave
can be triggered when SMAPI detectsGame1.activeMenu is SaveGameMenu
. A save is guaranteed in the next few ticks after that, and the menu doesn't change any save-related data.AfterSave
can be triggered when theSaveGameMenu
is closed.