SMAPI - Stardew Modding API

SMAPI - Stardew Modding API

971k Downloads

Add save-related events

Pathoschild opened this issue ยท 2 comments

commented

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 by SaveEvents.AfterLoad).
  • Deprecate TimeEvents.OnNewDay (unreliable for any purpose).
commented

Here's how the game typically triggers a save:

  1. The game sets Game1.newDay = true.

  2. On a later update tick, it eventually detects Game1.newDay and calls Game1.newDayAfterFade.
    That method can also be called directly regardless of Game1.newDay, such as when Game1.eventOver == true and Game1.dayOfMonth == 0. The newDay field doesn't even necessarily trigger a new save (e.g. it won't trigger if Game1.exitToTitle is also set), and the save doesn't necessarily happen on the next tick due to preceding flags. That means newDay is not sufficient to detect an upcoming save.

  3. Game1.newDayAfterFade does a bunch of cleanup and end-of-day stuff (e.g. sending mail), then calls showEndOfNightStuff (if Game1.farmEvent is clear).
    The latter method may also be called directly by the update tick logic when an ongoing Game1.farmEvent ends.

  4. Game1.showEndOfNightStuff method does more end-of-night stuff (e.g. selling items in the shipping box), and eventually sets the active menu to SaveGameMenu.

  5. The SaveGameMenu will sit there doing UI stuff until it decides it's done, at which point its update method will call SaveGame.Save().
    This is the only place where SaveGame.Save() is ever called.

  6. 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 detects Game1.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 the SaveGameMenu is closed.
commented

Done in develop for the upcoming 1.6 release.