summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI/Program.cs
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2016-11-16 17:36:28 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2016-11-16 17:36:28 -0500
commit19bb255c988f161ce00586cb516de830732efe31 (patch)
tree3c631751827ddebf97c020f5c1d4b976aa83582e /src/StardewModdingAPI/Program.cs
parent92cf3ab65e550e6f4170efbc52d37dc6d355c89f (diff)
downloadSMAPI-19bb255c988f161ce00586cb516de830732efe31.tar.gz
SMAPI-19bb255c988f161ce00586cb516de830732efe31.tar.bz2
SMAPI-19bb255c988f161ce00586cb516de830732efe31.zip
add emergency interrupt feature (#168)
Diffstat (limited to 'src/StardewModdingAPI/Program.cs')
-rw-r--r--src/StardewModdingAPI/Program.cs44
1 files changed, 37 insertions, 7 deletions
diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs
index ab3d8f5c..962a30f8 100644
--- a/src/StardewModdingAPI/Program.cs
+++ b/src/StardewModdingAPI/Program.cs
@@ -42,6 +42,9 @@ namespace StardewModdingAPI
/// <summary>Whether SMAPI is running in developer mode.</summary>
private static bool DeveloperMode;
+ /// <summary>Tracks whether the game should exit immediately and any pending initialisation should be cancelled.</summary>
+ private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
+
/*********
** Accessors
@@ -127,7 +130,7 @@ namespace StardewModdingAPI
if (!File.Exists(Program.GameExecutablePath))
{
Program.Monitor.Log($"Couldn't find executable: {Program.GameExecutablePath}", LogLevel.Error);
- Console.ReadKey();
+ Program.PressAnyKeyToExit();
return;
}
@@ -139,10 +142,23 @@ namespace StardewModdingAPI
}
catch (Exception ex)
{
- Console.WriteLine(ex);
- Console.ReadKey();
Program.Monitor.Log($"Critical error: {ex}", LogLevel.Error);
}
+ Program.PressAnyKeyToExit();
+ }
+
+ /// <summary>Immediately exit the game without saving. This should only be invoked when an irrecoverable fatal error happens that risks save corruption or game-breaking bugs.</summary>
+ /// <param name="module">The module which requested an immediate exit.</param>
+ /// <param name="reason">The reason provided for the shutdown.</param>
+ internal static void ExitGameImmediately(string module, string reason)
+ {
+ Program.Monitor.LogFatal($"{module} requested an immediate game shutdown: {reason}");
+ Program.CancellationTokenSource.Cancel();
+ if (Program.ready)
+ {
+ Program.gamePtr.Exiting += (sender, e) => Program.PressAnyKeyToExit();
+ Program.gamePtr.Exit();
+ }
}
@@ -199,6 +215,11 @@ namespace StardewModdingAPI
// load mods
Program.LoadMods();
+ if (Program.CancellationTokenSource.IsCancellationRequested)
+ {
+ Program.Monitor.Log("Shutdown requested; interrupting initialisation.", LogLevel.Error);
+ return;
+ }
// initialise console after game launches
new Thread(() =>
@@ -223,11 +244,15 @@ namespace StardewModdingAPI
// abort the console thread, we're closing
if (consoleInputThread.ThreadState == ThreadState.Running)
consoleInputThread.Abort();
- Program.PressAnyKeyToExit();
}).Start();
// start game loop
Program.Monitor.Log("Starting game...");
+ if (Program.CancellationTokenSource.IsCancellationRequested)
+ {
+ Program.Monitor.Log("Shutdown requested; interrupting initialisation.", LogLevel.Error);
+ return;
+ }
try
{
Program.ready = true;
@@ -241,8 +266,6 @@ namespace StardewModdingAPI
catch (Exception ex)
{
Program.Monitor.Log($"SMAPI encountered a fatal error:\n{ex}", LogLevel.Error);
- Program.PressAnyKeyToExit();
- return;
}
}
@@ -269,6 +292,13 @@ namespace StardewModdingAPI
{
foreach (string manifestPath in Directory.GetFiles(directory, "manifest.json"))
{
+ // check for cancellation
+ if (Program.CancellationTokenSource.IsCancellationRequested)
+ {
+ Program.Monitor.Log("Shutdown requested; interrupting mod loading.", LogLevel.Error);
+ return;
+ }
+
ModHelper helper = new ModHelper(directory);
string errorPrefix = $"Couldn't load mod for manifest '{manifestPath}'";
@@ -426,8 +456,8 @@ namespace StardewModdingAPI
private static void PressAnyKeyToExit()
{
Program.Monitor.Log("Game has ended. Press any key to exit.", LogLevel.Info);
- Console.ReadKey();
Thread.Sleep(100);
+ Console.ReadKey();
Environment.Exit(0);
}
}