diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2022-08-20 17:01:59 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2022-08-20 17:01:59 -0400 |
commit | a1bc96d365dc40275f198668d3f4c09bd7a92613 (patch) | |
tree | 5a130399bf8031aa70defb71a121b740d7c6cd7a /src/SMAPI/Framework/SCore.cs | |
parent | d51ffe58f7b7450cd4c4a7ee3d8b4da1cf55e7e4 (diff) | |
parent | f3a79219e85c9af18f2f6d8b2aaa794afa08578d (diff) | |
download | SMAPI-a1bc96d365dc40275f198668d3f4c09bd7a92613.tar.gz SMAPI-a1bc96d365dc40275f198668d3f4c09bd7a92613.tar.bz2 SMAPI-a1bc96d365dc40275f198668d3f4c09bd7a92613.zip |
Merge branch 'develop' into stable
Diffstat (limited to 'src/SMAPI/Framework/SCore.cs')
-rw-r--r-- | src/SMAPI/Framework/SCore.cs | 67 |
1 files changed, 46 insertions, 21 deletions
diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 46d65f6a..0f86ed6b 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1,6 +1,5 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; @@ -50,6 +49,7 @@ using StardewModdingAPI.Utilities; using StardewValley; using StardewValley.Menus; using StardewValley.Objects; +using StardewValley.SDKs; using xTile.Display; using LanguageCode = StardewValley.LocalizedContentManager.LanguageCode; using MiniMonoModHotfix = MonoMod.Utils.MiniMonoModHotfix; @@ -67,8 +67,11 @@ namespace StardewModdingAPI.Framework /**** ** Low-level components ****/ + /// <summary>A state which indicates whether SMAPI should exit immediately and any pending initialization should be cancelled.</summary> + private ExitState ExitState; + /// <summary>Whether the game should exit immediately and any pending initialization should be cancelled.</summary> - private bool IsExiting; + private bool IsExiting => this.ExitState != ExitState.None; /// <summary>Manages the SMAPI console window and log file.</summary> private readonly LogManager LogManager; @@ -297,22 +300,13 @@ namespace StardewModdingAPI.Framework this.IsGameRunning = true; StardewValley.Program.releaseBuild = true; // game's debug logic interferes with SMAPI opening the game window this.Game.Run(); + this.Dispose(isError: false); } catch (Exception ex) { this.LogManager.LogFatalLaunchError(ex); this.LogManager.PressAnyKeyToExit(); - } - finally - { - try - { - this.Dispose(); - } - catch (Exception ex) - { - this.Monitor.Log($"The game ended, but SMAPI wasn't able to dispose correctly. Technical details: {ex}", LogLevel.Error); - } + this.Dispose(isError: true); } } @@ -328,6 +322,14 @@ namespace StardewModdingAPI.Framework [SuppressMessage("ReSharper", "ConditionalAccessQualifierIsNonNullableAccordingToAPIContract", Justification = "May be disposed before SMAPI is fully initialized.")] public void Dispose() { + this.Dispose(isError: true); // if we got here, SMAPI didn't detect the exit before it happened + } + + /// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary> + /// <param name="isError">Whether the process is exiting due to an error or crash.</param> + [SuppressMessage("ReSharper", "ConditionalAccessQualifierIsNonNullableAccordingToAPIContract", Justification = "May be disposed before SMAPI is fully initialized.")] + public void Dispose(bool isError) + { // skip if already disposed if (this.IsDisposed) return; @@ -349,13 +351,29 @@ namespace StardewModdingAPI.Framework // dispose core components this.IsGameRunning = false; - this.IsExiting = true; + if (this.ExitState == ExitState.None || isError) + this.ExitState = isError ? ExitState.Crash : ExitState.GameExit; this.ContentCore?.Dispose(); this.Game?.Dispose(); this.LogManager.Dispose(); // dispose last to allow for any last-second log messages - // end game (moved from Game1.OnExiting to let us clean up first) - Process.GetCurrentProcess().Kill(); + // clean up SDK + // This avoids Steam connection errors when it exits unexpectedly. The game avoids this + // by killing the entire process, but we can't set the error code if we do that. + try + { + FieldInfo? field = typeof(StardewValley.Program).GetField("_sdk", BindingFlags.NonPublic | BindingFlags.Static); + SDKHelper? sdk = field?.GetValue(null) as SDKHelper; + sdk?.Shutdown(); + } + catch + { + // well, at least we tried + } + + // end game with error code + // This helps the OS decide whether to keep the window open (e.g. Windows may keep it open on error). + Environment.Exit(this.ExitState == ExitState.Crash ? 1 : 0); } @@ -387,7 +405,14 @@ namespace StardewModdingAPI.Framework { string[] looseFiles = new DirectoryInfo(this.ModsPath).GetFiles().Select(p => p.Name).ToArray(); if (looseFiles.Any()) + { + if (looseFiles.Any(name => name.Equals("manifest.json", StringComparison.OrdinalIgnoreCase) || name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))) + { + this.Monitor.Log($"Detected mod files directly inside the '{Path.GetFileName(this.ModsPath)}' folder. These will be ignored. Each mod must have its own subfolder instead.", LogLevel.Error); + } + this.Monitor.Log($" Ignored loose files: {string.Join(", ", looseFiles.OrderBy(p => p, StringComparer.OrdinalIgnoreCase))}"); + } } // load manifests @@ -1250,7 +1275,7 @@ namespace StardewModdingAPI.Framework private void OnGameExiting() { this.Multiplayer.Disconnect(StardewValley.Multiplayer.DisconnectType.ClosedGame); - this.Dispose(); + this.Dispose(isError: false); } /// <summary>Raised when a mod network message is received.</summary> @@ -1670,7 +1695,7 @@ namespace StardewModdingAPI.Framework source: metadata, nounPhrase: $"{nameof(IAssetEditor)}", version: "3.14.0", - severity: DeprecationLevel.Notice, + severity: DeprecationLevel.Info, logStackTrace: false ); @@ -1683,7 +1708,7 @@ namespace StardewModdingAPI.Framework source: metadata, nounPhrase: $"{nameof(IAssetLoader)}", version: "3.14.0", - severity: DeprecationLevel.Notice, + severity: DeprecationLevel.Info, logStackTrace: false ); @@ -1715,7 +1740,7 @@ namespace StardewModdingAPI.Framework metadata, $"using {name} without bundling it", "3.14.7", - DeprecationLevel.Notice, + DeprecationLevel.Info, logStackTrace: false ); } @@ -2239,7 +2264,7 @@ namespace StardewModdingAPI.Framework this.Monitor.LogFatal(message); this.LogManager.WriteCrashLog(); - this.IsExiting = true; + this.ExitState = ExitState.Crash; this.Game.Exit(); } |