Revamp SMAPI startup process
Pathoschild opened this issue ยท 6 comments
Revamp the SMAPI startup process to simplify mod development, ensure that core components are ready when mods are called, and eliminate or reduce SEHException
errors some players get.
Background
Mods are currently initialised before the game is started, at which point many of the core components (like content managers) aren't ready. This leads to some significant issues:
- New modders are often confused when they access core components in
Entry
and get errors likeNullReferenceException
. - Mods often register for an event like
GameEvents.UpdateTick
to continuously check whether the things they need are ready. This is very inefficient and unnecessary work for the developer. - SMAPI can't provide APIs for many core components through the
IModHelper
, since that's initialised before the mod (which is initialised before many core components). This notably impacts the content API planned for SMAPI 2.0.
Initialising everything before the game is ready can also lead to SEHException
errors for some players.
Current init order
Here's the current init order. Everything happens before the game is started.
- Handle command-line arguments.
- Read settings from
StardewModdingAPI.config.json
. - Init before game starts:
- log file + monitor;
- mod registry;
- deprecation manager;
- API shims;
- console redirection;
- game version check;
- file paths;
- exception handlers.
- Override
Game1
and hook events. - Load mods.
- Start console listener.
- Start game.
Proposed init order
Here's the init order I propose. Only core SMAPI init happens before the game starts; everything else (including mods) happens after the game's Initialize
/LoadContent
phase.
- Handle command-line arguments.
- Init before game starts:
- log file + monitor;
- file paths;
- game version check;
- exception handlers.
- Override
Game1
and hook events. - Start game.
- Init after game starts (blocking):
- settings from
StardewModdingAPI.config.json
; - deprecation manager;
- mod registry;
- API shims;
- console redirection;
- mods;
- console listener.
- settings from
Main effect
For most mods, this will have two visible effects:
GameEvents.Initialize
andGameEvents.LoadContent
no longer exist.- Most mod initialisation can now happen in their
Entry
method, instead of needing a separate event likeUpdateTick
.
For most players, this should have no visible effect. For players who get SEHException
errors, this should eliminate or significantly reduce their frequency.
@Entoarox and @TehPers: you both have mods that hook into the game initialisation, so your feedback would be appreciated. All mods would now be loaded after the Initialize
/LoadContent
phase, but you could still ensure your mods are loaded before others (just like you do now). Will that cause any problems for you?
I dont see any obvious problems... If I am correct, the new order essentially has all mods Entry happen directly after LoadContent?
The game's Initialize
/LoadContent
phases are intertwined (e.g. LoadContent
happens partway through Initialize
), but mods would be loaded immediately after the combined Initialize
/LoadContent
phase.
I see no issues with this, assuming it's still possible to handle content that is loaded without needing to access every variable in the game that contains an asset in it. It'd definitely clean up the update tick code since you'd no longer need to check if the game has been fully initialized.