diff options
-rw-r--r-- | src/SMAPI/Framework/SGame.cs | 39 | ||||
-rw-r--r-- | src/SMAPI/Program.cs | 2 |
2 files changed, 24 insertions, 17 deletions
diff --git a/src/SMAPI/Framework/SGame.cs b/src/SMAPI/Framework/SGame.cs index aeaab9ea..47bc40e6 100644 --- a/src/SMAPI/Framework/SGame.cs +++ b/src/SMAPI/Framework/SGame.cs @@ -25,7 +25,7 @@ using StardewValley.Tools; using xTile.Dimensions; #if !STARDEW_VALLEY_1_3 using xTile.Layers; - #endif +#endif namespace StardewModdingAPI.Framework { @@ -36,6 +36,16 @@ namespace StardewModdingAPI.Framework ** Properties *********/ /**** + ** Constructor hack + ****/ + /// <summary>A static instance of <see cref="Monitor"/> to use while <see cref="Game1"/> is initialising, which happens before the <see cref="SGame"/> constructor runs.</summary> + internal static IMonitor MonitorDuringInitialisation; + + /// <summary>A static instance of <see cref="Reflection"/> to use while <see cref="Game1"/> is initialising, which happens before the <see cref="SGame"/> constructor runs.</summary> + internal static Reflector ReflectorDuringInitialisation; + + + /**** ** SMAPI state ****/ /// <summary>Encapsulates monitoring and logging.</summary> @@ -161,7 +171,7 @@ namespace StardewModdingAPI.Framework ** Accessors *********/ /// <summary>SMAPI's content manager.</summary> - public ContentCore ContentCore { get; } + public ContentCore ContentCore { get; private set; } /// <summary>Whether SMAPI should log more information about the game context.</summary> public bool VerboseLogging { get; set; } @@ -184,18 +194,18 @@ namespace StardewModdingAPI.Framework SGame.Instance = this; SGame.Reflection = reflection; this.OnGameInitialised = onGameInitialised; + if (this.ContentCore == null) // shouldn't happen since CreateContentManager is called first, but let's init here just in case + this.ContentCore = new ContentCore(this.Content.ServiceProvider, this.Content.RootDirectory, Thread.CurrentThread.CurrentUICulture, null, this.Monitor, reflection); // set XNA option required by Stardew Valley Game1.graphics.GraphicsProfile = GraphicsProfile.HiDef; - // override content manager +#if !STARDEW_VALLEY_1_3 + // replace already-created content managers this.Monitor?.Log("Overriding content manager...", LogLevel.Trace); - this.ContentCore = new ContentCore(this.Content.ServiceProvider, this.Content.RootDirectory, Thread.CurrentThread.CurrentUICulture, null, this.Monitor, reflection); this.Content = this.ContentCore.CreateContentManager("SGame.Content"); - Game1.content = this.ContentCore.CreateContentManager("Game1.content"); - - // replace already-created temporary content managers reflection.GetField<LocalizedContentManager>(typeof(Game1), "_temporaryContent").SetValue(this.ContentCore.CreateContentManager("Game1._temporaryContent")); // regenerate value with new content manager +#endif } /**** @@ -206,19 +216,14 @@ namespace StardewModdingAPI.Framework /// <param name="rootDirectory">The root directory to search for content.</param> protected override LocalizedContentManager CreateContentManager(IServiceProvider serviceProvider, string rootDirectory) { - // return default if SMAPI's content manager isn't initialised yet + // NOTE: this method is called from the Game1 constructor, before the SGame constructor runs. + // Don't depend on anything being initialised at this point. if (this.ContentCore == null) { - this.Monitor?.Log("SMAPI's content manager isn't initialised; skipping content manager interception.", LogLevel.Trace); - return base.CreateContentManager(serviceProvider, rootDirectory); + this.ContentCore = new ContentCore(serviceProvider, rootDirectory, Thread.CurrentThread.CurrentUICulture, null, SGame.MonitorDuringInitialisation, SGame.ReflectorDuringInitialisation); + SGame.MonitorDuringInitialisation = null; } - - // return single instance if valid - if (serviceProvider != this.Content.ServiceProvider) - throw new InvalidOperationException("SMAPI uses a single content manager internally. You can't get a new content manager with a different service provider."); - if (rootDirectory != this.Content.RootDirectory) - throw new InvalidOperationException($"SMAPI uses a single content manager internally. You can't get a new content manager with a different root directory (current is {this.Content.RootDirectory}, requested {rootDirectory})."); - return this.ContentCore.CreateContentManager("(generated instance)"); + return this.ContentCore.CreateContentManager("(generated)", rootDirectory); } /// <summary>The method called when the game is updating its state. This happens roughly 60 times per second.</summary> diff --git a/src/SMAPI/Program.cs b/src/SMAPI/Program.cs index 39a5754b..e713add5 100644 --- a/src/SMAPI/Program.cs +++ b/src/SMAPI/Program.cs @@ -190,6 +190,8 @@ namespace StardewModdingAPI AppDomain.CurrentDomain.UnhandledException += (sender, e) => this.Monitor.Log($"Critical app domain exception: {e.ExceptionObject}", LogLevel.Error); // override game + SGame.MonitorDuringInitialisation = this.Monitor; + SGame.ReflectorDuringInitialisation = this.Reflection; this.GameInstance = new SGame(this.Monitor, this.Reflection, this.EventManager, this.InitialiseAfterGameStart); StardewValley.Program.gamePtr = this.GameInstance; |