summaryrefslogtreecommitdiff
path: root/src/StardewModdingAPI/Program.cs
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2017-02-16 00:54:41 -0500
committerJesse Plamondon-Willard <github@jplamondonw.com>2017-02-16 00:54:41 -0500
commit176eddbf7b70934c2665aa3a0ac8b46bef04012a (patch)
treea09c26179f2445b21bae3a79076c58839924cdb5 /src/StardewModdingAPI/Program.cs
parent2c6ab6805de0e0a21d5191838237db04aa0176ec (diff)
downloadSMAPI-176eddbf7b70934c2665aa3a0ac8b46bef04012a.tar.gz
SMAPI-176eddbf7b70934c2665aa3a0ac8b46bef04012a.tar.bz2
SMAPI-176eddbf7b70934c2665aa3a0ac8b46bef04012a.zip
make SMAPI core non-static, eliminate direct access between core components
Diffstat (limited to 'src/StardewModdingAPI/Program.cs')
-rw-r--r--src/StardewModdingAPI/Program.cs287
1 files changed, 156 insertions, 131 deletions
diff --git a/src/StardewModdingAPI/Program.cs b/src/StardewModdingAPI/Program.cs
index c3f8f8d8..0857d41b 100644
--- a/src/StardewModdingAPI/Program.cs
+++ b/src/StardewModdingAPI/Program.cs
@@ -28,7 +28,7 @@ namespace StardewModdingAPI
** Properties
*********/
/// <summary>The target game platform.</summary>
- private static readonly Platform TargetPlatform =
+ private readonly Platform TargetPlatform =
#if SMAPI_FOR_WINDOWS
Platform.Windows;
#else
@@ -36,47 +36,47 @@ namespace StardewModdingAPI
#endif
/// <summary>The full path to the Stardew Valley executable.</summary>
- private static readonly string GameExecutablePath = Path.Combine(Constants.ExecutionPath, Program.TargetPlatform == Platform.Windows ? "Stardew Valley.exe" : "StardewValley.exe");
+ private readonly string GameExecutablePath;
/// <summary>The full path to the folder containing mods.</summary>
- private static readonly string ModPath = Path.Combine(Constants.ExecutionPath, "Mods");
+ private readonly string ModPath = Path.Combine(Constants.ExecutionPath, "Mods");
/// <summary>The log file to which to write messages.</summary>
- private static readonly LogFileManager LogFile = new LogFileManager(Constants.LogPath);
+ private readonly LogFileManager LogFile = new LogFileManager(Constants.LogPath);
/// <summary>Manages console output interception.</summary>
- private static readonly ConsoleInterceptionManager ConsoleManager = new ConsoleInterceptionManager();
+ private readonly ConsoleInterceptionManager ConsoleManager = new ConsoleInterceptionManager();
/// <summary>The core logger for SMAPI.</summary>
- private static readonly Monitor Monitor = new Monitor("SMAPI", Program.ConsoleManager, Program.LogFile);
+ private readonly Monitor Monitor;
/// <summary>The user settings for SMAPI.</summary>
- private static UserSettings Settings;
+ private UserSettings Settings;
/// <summary>Tracks whether the game should exit immediately and any pending initialisation should be cancelled.</summary>
- private static readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
+ private readonly CancellationTokenSource CancellationTokenSource = new CancellationTokenSource();
/// <summary>Whether the game is currently running.</summary>
- private static bool ready;
+ private bool IsGameRunning;
/*********
** Accessors
*********/
/// <summary>The underlying game instance.</summary>
- internal static SGame GameInstance;
+ internal SGame GameInstance;
/// <summary>The number of mods currently loaded by SMAPI.</summary>
- internal static int ModsLoaded;
+ internal int ModsLoaded;
/// <summary>Tracks the installed mods.</summary>
- internal static readonly ModRegistry ModRegistry = new ModRegistry();
+ internal readonly ModRegistry ModRegistry = new ModRegistry();
/// <summary>Manages deprecation warnings.</summary>
- internal static readonly DeprecationManager DeprecationManager = new DeprecationManager(Program.Monitor, Program.ModRegistry);
+ internal readonly DeprecationManager DeprecationManager;
/// <summary>Manages console commands.</summary>
- internal static readonly CommandManager CommandManager = new CommandManager();
+ internal readonly CommandManager CommandManager = new CommandManager();
/*********
@@ -86,10 +86,35 @@ namespace StardewModdingAPI
/// <param name="args">The command-line arguments.</param>
private static void Main(string[] args)
{
+ new Program(writeToConsole: !args.Contains("--no-terminal"))
+ .LaunchInteractively();
+ }
+
+ /// <summary>Construct an instance.</summary>
+ internal Program(bool writeToConsole)
+ {
+ this.GameExecutablePath = Path.Combine(Constants.ExecutionPath, this.TargetPlatform == Platform.Windows ? "Stardew Valley.exe" : "StardewValley.exe");
+ this.Monitor = new Monitor("SMAPI", this.ConsoleManager, this.LogFile, this.ExitGameImmediately) { WriteToConsole = writeToConsole };
+ this.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry);
+ }
+
+ /// <summary>Launch SMAPI.</summary>
+ internal void LaunchInteractively()
+ {
// initialise logging
- Program.Monitor.WriteToConsole = !args.Contains("--no-terminal");
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB"); // for consistent log formatting
- Program.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Game1.version} on {Environment.OSVersion}", LogLevel.Info);
+ this.Monitor.Log($"SMAPI {Constants.ApiVersion} with Stardew Valley {Game1.version} on {Environment.OSVersion}", LogLevel.Info);
+
+ // inject compatibility shims
+#pragma warning disable 618
+ Command.Shim(this.CommandManager, this.DeprecationManager, this.ModRegistry);
+ Config.Shim(this.DeprecationManager);
+ InternalExtensions.Shim(this.ModRegistry);
+ Log.Shim(this.DeprecationManager);
+ Mod.Shim(this.DeprecationManager);
+ PlayerEvents.Shim(this.DeprecationManager);
+ TimeEvents.Shim(this.DeprecationManager);
+#pragma warning restore 618
// read config
{
@@ -97,39 +122,39 @@ namespace StardewModdingAPI
if (File.Exists(settingsPath))
{
string json = File.ReadAllText(settingsPath);
- Program.Settings = JsonConvert.DeserializeObject<UserSettings>(json);
+ this.Settings = JsonConvert.DeserializeObject<UserSettings>(json);
}
else
- Program.Settings = new UserSettings();
+ this.Settings = new UserSettings();
- File.WriteAllText(settingsPath, JsonConvert.SerializeObject(Program.Settings, Formatting.Indented));
+ File.WriteAllText(settingsPath, JsonConvert.SerializeObject(this.Settings, Formatting.Indented));
}
// redirect direct console output
{
- Monitor monitor = Program.GetSecondaryMonitor("Console.Out");
+ Monitor monitor = this.GetSecondaryMonitor("Console.Out");
monitor.WriteToFile = false; // not useful for troubleshooting mods per discussion
if (monitor.WriteToConsole)
- Program.ConsoleManager.OnLineIntercepted += line => monitor.Log(line, LogLevel.Trace);
+ this.ConsoleManager.OnLineIntercepted += line => monitor.Log(line, LogLevel.Trace);
}
// add warning headers
- if (Program.Settings.DeveloperMode)
+ if (this.Settings.DeveloperMode)
{
- Program.Monitor.ShowTraceInConsole = true;
- Program.Monitor.Log($"You configured SMAPI to run in developer mode. The console may be much more verbose. You can disable developer mode by installing the non-developer version of SMAPI, or by editing or deleting {Constants.ApiConfigPath}.", LogLevel.Warn);
+ this.Monitor.ShowTraceInConsole = true;
+ this.Monitor.Log($"You configured SMAPI to run in developer mode. The console may be much more verbose. You can disable developer mode by installing the non-developer version of SMAPI, or by editing or deleting {Constants.ApiConfigPath}.", LogLevel.Warn);
}
- if (!Program.Settings.CheckForUpdates)
- Program.Monitor.Log($"You configured SMAPI to not check for updates. Running an old version of SMAPI is not recommended. You can enable update checks by editing or deleting {Constants.ApiConfigPath}.", LogLevel.Warn);
- if (!Program.Monitor.WriteToConsole)
- Program.Monitor.Log("Writing to the terminal is disabled because the --no-terminal argument was received. This usually means launching the terminal failed.", LogLevel.Warn);
+ if (!this.Settings.CheckForUpdates)
+ this.Monitor.Log($"You configured SMAPI to not check for updates. Running an old version of SMAPI is not recommended. You can enable update checks by editing or deleting {Constants.ApiConfigPath}.", LogLevel.Warn);
+ if (!this.Monitor.WriteToConsole)
+ this.Monitor.Log("Writing to the terminal is disabled because the --no-terminal argument was received. This usually means launching the terminal failed.", LogLevel.Warn);
// print file paths
- Program.Monitor.Log($"Mods go here: {Program.ModPath}");
+ this.Monitor.Log($"Mods go here: {this.ModPath}");
// initialise legacy log
- Log.Monitor = Program.GetSecondaryMonitor("legacy mod");
- Log.ModRegistry = Program.ModRegistry;
+ Log.Monitor = this.GetSecondaryMonitor("legacy mod");
+ Log.ModRegistry = this.ModRegistry;
// hook into & launch the game
try
@@ -137,56 +162,56 @@ namespace StardewModdingAPI
// verify version
if (String.Compare(Game1.version, Constants.MinimumGameVersion, StringComparison.InvariantCultureIgnoreCase) < 0)
{
- Program.Monitor.Log($"Oops! You're running Stardew Valley {Game1.version}, but the oldest supported version is {Constants.MinimumGameVersion}. Please update your game before using SMAPI. If you're on the Steam beta channel, note that the beta channel may not receive the latest updates.", LogLevel.Error);
+ this.Monitor.Log($"Oops! You're running Stardew Valley {Game1.version}, but the oldest supported version is {Constants.MinimumGameVersion}. Please update your game before using SMAPI. If you're on the Steam beta channel, note that the beta channel may not receive the latest updates.", LogLevel.Error);
return;
}
// initialise
- Program.Monitor.Log("Loading SMAPI...");
- Console.Title = Constants.ConsoleTitle;
- Program.VerifyPath(Program.ModPath);
- Program.VerifyPath(Constants.LogDir);
- if (!File.Exists(Program.GameExecutablePath))
+ this.Monitor.Log("Loading SMAPI...");
+ Console.Title = $"Stardew Modding API Console - Version {Constants.ApiVersion}";
+ this.VerifyPath(this.ModPath);
+ this.VerifyPath(Constants.LogDir);
+ if (!File.Exists(this.GameExecutablePath))
{
- Program.Monitor.Log($"Couldn't find executable: {Program.GameExecutablePath}", LogLevel.Error);
- Program.PressAnyKeyToExit();
+ this.Monitor.Log($"Couldn't find executable: {this.GameExecutablePath}", LogLevel.Error);
+ this.PressAnyKeyToExit();
return;
}
// check for update when game loads
- if (Program.Settings.CheckForUpdates)
- GameEvents.GameLoaded += (sender, e) => Program.CheckForUpdateAsync();
+ if (this.Settings.CheckForUpdates)
+ GameEvents.GameLoaded += (sender, e) => this.CheckForUpdateAsync();
// launch game
- Program.StartGame();
+ this.StartGame();
}
catch (Exception ex)
{
- Program.Monitor.Log($"Critical error: {ex.GetLogSummary()}", LogLevel.Error);
+ this.Monitor.Log($"Critical error: {ex.GetLogSummary()}", LogLevel.Error);
}
- Program.PressAnyKeyToExit();
+ this.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)
+ internal void ExitGameImmediately(string module, string reason)
{
- Program.Monitor.LogFatal($"{module} requested an immediate game shutdown: {reason}");
- Program.CancellationTokenSource.Cancel();
- if (Program.ready)
+ this.Monitor.LogFatal($"{module} requested an immediate game shutdown: {reason}");
+ this.CancellationTokenSource.Cancel();
+ if (this.IsGameRunning)
{
- Program.GameInstance.Exiting += (sender, e) => Program.PressAnyKeyToExit();
- Program.GameInstance.Exit();
+ this.GameInstance.Exiting += (sender, e) => this.PressAnyKeyToExit();
+ this.GameInstance.Exit();
}
}
/// <summary>Get a monitor for legacy code which doesn't have one passed in.</summary>
[Obsolete("This method should only be used when needed for backwards compatibility.")]
- internal static IMonitor GetLegacyMonitorForMod()
+ internal IMonitor GetLegacyMonitorForMod()
{
- string modName = Program.ModRegistry.GetModFromStack() ?? "unknown";
- return Program.GetSecondaryMonitor(modName);
+ string modName = this.ModRegistry.GetModFromStack() ?? "unknown";
+ return this.GetSecondaryMonitor(modName);
}
@@ -194,7 +219,7 @@ namespace StardewModdingAPI
** Private methods
*********/
/// <summary>Asynchronously check for a new version of SMAPI, and print a message to the console if an update is available.</summary>
- private static void CheckForUpdateAsync()
+ private void CheckForUpdateAsync()
{
new Thread(() =>
{
@@ -203,40 +228,40 @@ namespace StardewModdingAPI
GitRelease release = UpdateHelper.GetLatestVersionAsync(Constants.GitHubRepository).Result;
ISemanticVersion latestVersion = new SemanticVersion(release.Tag);
if (latestVersion.IsNewerThan(Constants.ApiVersion))
- Program.Monitor.Log($"You can update SMAPI from version {Constants.ApiVersion} to {latestVersion}", LogLevel.Alert);
+ this.Monitor.Log($"You can update SMAPI from version {Constants.ApiVersion} to {latestVersion}", LogLevel.Alert);
}
catch (Exception ex)
{
- Program.Monitor.Log($"Couldn't check for a new version of SMAPI. This won't affect your game, but you may not be notified of new versions if this keeps happening.\n{ex.GetLogSummary()}");
+ this.Monitor.Log($"Couldn't check for a new version of SMAPI. This won't affect your game, but you may not be notified of new versions if this keeps happening.\n{ex.GetLogSummary()}");
}
}).Start();
}
/// <summary>Hook into Stardew Valley and launch the game.</summary>
- private static void StartGame()
+ private void StartGame()
{
try
{
// add error handlers
#if SMAPI_FOR_WINDOWS
- Application.ThreadException += (sender, e) => Program.Monitor.Log($"Critical thread exception: {e.Exception.GetLogSummary()}", LogLevel.Error);
+ Application.ThreadException += (sender, e) => this.Monitor.Log($"Critical thread exception: {e.Exception.GetLogSummary()}", LogLevel.Error);
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
#endif
- AppDomain.CurrentDomain.UnhandledException += (sender, e) => Program.Monitor.Log($"Critical app domain exception: {e.ExceptionObject}", LogLevel.Error);
+ AppDomain.CurrentDomain.UnhandledException += (sender, e) => this.Monitor.Log($"Critical app domain exception: {e.ExceptionObject}", LogLevel.Error);
// initialise game
{
// load assembly
- Program.Monitor.Log("Loading game...");
- Assembly gameAssembly = Assembly.UnsafeLoadFrom(Program.GameExecutablePath);
+ this.Monitor.Log("Loading game...");
+ Assembly gameAssembly = Assembly.UnsafeLoadFrom(this.GameExecutablePath);
Type gameProgramType = gameAssembly.GetType("StardewValley.Program", true);
// set Game1 instance
- Program.GameInstance = new SGame(Program.Monitor);
- Program.GameInstance.Exiting += (sender, e) => Program.ready = false;
- Program.GameInstance.Window.ClientSizeChanged += (sender, e) => GraphicsEvents.InvokeResize(Program.Monitor, sender, e);
- Program.GameInstance.Window.Title = $"Stardew Valley - Version {Game1.version}";
- gameProgramType.GetField("gamePtr").SetValue(gameProgramType, Program.GameInstance);
+ this.GameInstance = new SGame(this.Monitor);
+ this.GameInstance.Exiting += (sender, e) => this.IsGameRunning = false;
+ this.GameInstance.Window.ClientSizeChanged += (sender, e) => GraphicsEvents.InvokeResize(this.Monitor, sender, e);
+ this.GameInstance.Window.Title = $"Stardew Valley - Version {Game1.version}";
+ gameProgramType.GetField("gamePtr").SetValue(gameProgramType, this.GameInstance);
// configure
Game1.version += $" | SMAPI {Constants.ApiVersion}";
@@ -244,10 +269,10 @@ namespace StardewModdingAPI
}
// load mods
- Program.LoadMods();
- if (Program.CancellationTokenSource.IsCancellationRequested)
+ this.LoadMods();
+ if (this.CancellationTokenSource.IsCancellationRequested)
{
- Program.Monitor.Log("Shutdown requested; interrupting initialisation.", LogLevel.Error);
+ this.Monitor.Log("Shutdown requested; interrupting initialisation.", LogLevel.Error);
return;
}
@@ -255,18 +280,18 @@ namespace StardewModdingAPI
new Thread(() =>
{
// wait for the game to load up
- while (!Program.ready)
+ while (!this.IsGameRunning)
Thread.Sleep(1000);
// register help command
- Program.CommandManager.Add("SMAPI", "help", "Lists all commands | 'help <cmd>' returns command description", Program.HandleHelpCommand);
+ this.CommandManager.Add("SMAPI", "help", "Lists all commands | 'help <cmd>' returns command description", this.HandleHelpCommand);
// listen for command line input
- Program.Monitor.Log("Starting console...");
- Program.Monitor.Log("Type 'help' for help, or 'help <cmd>' for a command's usage", LogLevel.Info);
- Thread consoleInputThread = new Thread(Program.ConsoleInputLoop);
+ this.Monitor.Log("Starting console...");
+ this.Monitor.Log("Type 'help' for help, or 'help <cmd>' for a command's usage", LogLevel.Info);
+ Thread consoleInputThread = new Thread(this.ConsoleInputLoop);
consoleInputThread.Start();
- while (Program.ready)
+ while (this.IsGameRunning)
Thread.Sleep(1000 / 10); // Check if the game is still running 10 times a second
// abort the console thread, we're closing
@@ -275,31 +300,31 @@ namespace StardewModdingAPI
}).Start();
// start game loop
- Program.Monitor.Log("Starting game...");
- if (Program.CancellationTokenSource.IsCancellationRequested)
+ this.Monitor.Log("Starting game...");
+ if (this.CancellationTokenSource.IsCancellationRequested)
{
- Program.Monitor.Log("Shutdown requested; interrupting initialisation.", LogLevel.Error);
+ this.Monitor.Log("Shutdown requested; interrupting initialisation.", LogLevel.Error);
return;
}
try
{
- Program.ready = true;
- Program.GameInstance.Run();
+ this.IsGameRunning = true;
+ this.GameInstance.Run();
}
finally
{
- Program.ready = false;
+ this.IsGameRunning = false;
}
}
catch (Exception ex)
{
- Program.Monitor.Log($"The game encountered a fatal error:\n{ex.GetLogSummary()}", LogLevel.Error);
+ this.Monitor.Log($"The game encountered a fatal error:\n{ex.GetLogSummary()}", LogLevel.Error);
}
}
/// <summary>Create a directory path if it doesn't exist.</summary>
/// <param name="path">The directory path.</param>
- private static void VerifyPath(string path)
+ private void VerifyPath(string path)
{
try
{
@@ -308,20 +333,20 @@ namespace StardewModdingAPI
}
catch (Exception ex)
{
- Program.Monitor.Log($"Couldn't create a path: {path}\n\n{ex.GetLogSummary()}", LogLevel.Error);
+ this.Monitor.Log($"Couldn't create a path: {path}\n\n{ex.GetLogSummary()}", LogLevel.Error);
}
}
/// <summary>Load and hook up all mods in the mod directory.</summary>
- private static void LoadMods()
+ private void LoadMods()
{
- Program.Monitor.Log("Loading mods...");
+ this.Monitor.Log("Loading mods...");
// get JSON helper
JsonHelper jsonHelper = new JsonHelper();
// get assembly loader
- AssemblyLoader modAssemblyLoader = new AssemblyLoader(Program.TargetPlatform, Program.Monitor);
+ AssemblyLoader modAssemblyLoader = new AssemblyLoader(this.TargetPlatform, this.Monitor);
AppDomain.CurrentDomain.AssemblyResolve += (sender, e) => modAssemblyLoader.ResolveAssembly(e.Name);
// get known incompatible mods
@@ -335,12 +360,12 @@ namespace StardewModdingAPI
catch (Exception ex)
{
incompatibleMods = new Dictionary<string, IncompatibleMod>();
- Program.Monitor.Log($"Couldn't read metadata file at {Constants.ApiModMetadataPath}. SMAPI will still run, but some features may be disabled.\n{ex}", LogLevel.Warn);
+ this.Monitor.Log($"Couldn't read metadata file at {Constants.ApiModMetadataPath}. SMAPI will still run, but some features may be disabled.\n{ex}", LogLevel.Warn);
}
// load mod assemblies
List<Action> deprecationWarnings = new List<Action>(); // queue up deprecation warnings to show after mod list
- foreach (string directoryPath in Directory.GetDirectories(Program.ModPath))
+ foreach (string directoryPath in Directory.GetDirectories(this.ModPath))
{
// passthrough empty directories
DirectoryInfo directory = new DirectoryInfo(directoryPath);
@@ -348,9 +373,9 @@ namespace StardewModdingAPI
directory = directory.GetDirectories().First();
// check for cancellation
- if (Program.CancellationTokenSource.IsCancellationRequested)
+ if (this.CancellationTokenSource.IsCancellationRequested)
{
- Program.Monitor.Log("Shutdown requested; interrupting mod loading.", LogLevel.Error);
+ this.Monitor.Log("Shutdown requested; interrupting mod loading.", LogLevel.Error);
return;
}
@@ -358,7 +383,7 @@ namespace StardewModdingAPI
string manifestPath = Path.Combine(directory.FullName, "manifest.json");
if (!File.Exists(manifestPath))
{
- Program.Monitor.Log($"Ignored folder \"{directory.Name}\" which doesn't have a manifest.json.", LogLevel.Warn);
+ this.Monitor.Log($"Ignored folder \"{directory.Name}\" which doesn't have a manifest.json.", LogLevel.Warn);
continue;
}
string errorPrefix = $"Couldn't load mod for manifest '{manifestPath}'";
@@ -371,7 +396,7 @@ namespace StardewModdingAPI
string json = File.ReadAllText(manifestPath);
if (string.IsNullOrEmpty(json))
{
- Program.Monitor.Log($"{errorPrefix}: manifest is empty.", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: manifest is empty.", LogLevel.Error);
continue;
}
@@ -379,18 +404,18 @@ namespace StardewModdingAPI
manifest = jsonHelper.ReadJsonFile<Manifest>(Path.Combine(directory.FullName, "manifest.json"), null);
if (manifest == null)
{
- Program.Monitor.Log($"{errorPrefix}: the manifest file does not exist.", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: the manifest file does not exist.", LogLevel.Error);
continue;
}
if (string.IsNullOrEmpty(manifest.EntryDll))
{
- Program.Monitor.Log($"{errorPrefix}: manifest doesn't specify an entry DLL.", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: manifest doesn't specify an entry DLL.", LogLevel.Error);
continue;
}
}
catch (Exception ex)
{
- Program.Monitor.Log($"{errorPrefix}: manifest parsing failed.\n{ex.GetLogSummary()}", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: manifest parsing failed.\n{ex.GetLogSummary()}", LogLevel.Error);
continue;
}
@@ -407,7 +432,7 @@ namespace StardewModdingAPI
if (!string.IsNullOrWhiteSpace(compatibility.UnofficialUpdateUrl))
warning += $"{Environment.NewLine}- unofficial update: {compatibility.UnofficialUpdateUrl}";
- Program.Monitor.Log(warning, LogLevel.Error);
+ this.Monitor.Log(warning, LogLevel.Error);
continue;
}
}
@@ -420,13 +445,13 @@ namespace StardewModdingAPI
ISemanticVersion minVersion = new SemanticVersion(manifest.MinimumApiVersion);
if (minVersion.IsNewerThan(Constants.ApiVersion))
{
- Program.Monitor.Log($"{errorPrefix}: this mod requires SMAPI {minVersion} or later. Please update SMAPI to the latest version to use this mod.", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: this mod requires SMAPI {minVersion} or later. Please update SMAPI to the latest version to use this mod.", LogLevel.Error);
continue;
}
}
catch (FormatException ex) when (ex.Message.Contains("not a valid semantic version"))
{
- Program.Monitor.Log($"{errorPrefix}: the mod specified an invalid minimum SMAPI version '{manifest.MinimumApiVersion}'. This should be a semantic version number like {Constants.ApiVersion}.", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: the mod specified an invalid minimum SMAPI version '{manifest.MinimumApiVersion}'. This should be a semantic version number like {Constants.ApiVersion}.", LogLevel.Error);
continue;
}
}
@@ -434,20 +459,20 @@ namespace StardewModdingAPI
// create per-save directory
if (manifest.PerSaveConfigs)
{
- deprecationWarnings.Add(() => Program.DeprecationManager.Warn(manifest.Name, $"{nameof(Manifest)}.{nameof(Manifest.PerSaveConfigs)}", "1.0", DeprecationLevel.Info));
+ deprecationWarnings.Add(() => this.DeprecationManager.Warn(manifest.Name, $"{nameof(Manifest)}.{nameof(Manifest.PerSaveConfigs)}", "1.0", DeprecationLevel.Info));
try
{
string psDir = Path.Combine(directory.FullName, "psconfigs");
Directory.CreateDirectory(psDir);
if (!Directory.Exists(psDir))
{
- Program.Monitor.Log($"{errorPrefix}: couldn't create the per-save configuration directory ('psconfigs') requested by this mod. The failure reason is unknown.", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: couldn't create the per-save configuration directory ('psconfigs') requested by this mod. The failure reason is unknown.", LogLevel.Error);
continue;
}
}
catch (Exception ex)
{
- Program.Monitor.Log($"{errorPrefix}: couldn't create the per-save configuration directory ('psconfigs') requested by this mod.\n{ex.GetLogSummary()}", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: couldn't create the per-save configuration directory ('psconfigs') requested by this mod.\n{ex.GetLogSummary()}", LogLevel.Error);
continue;
}
}
@@ -456,7 +481,7 @@ namespace StardewModdingAPI
string assemblyPath = Path.Combine(directory.FullName, manifest.EntryDll);
if (!File.Exists(assemblyPath))
{
- Program.Monitor.Log($"{errorPrefix}: the entry DLL '{manifest.EntryDll}' does not exist.", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: the entry DLL '{manifest.EntryDll}' does not exist.", LogLevel.Error);
continue;
}
@@ -468,7 +493,7 @@ namespace StardewModdingAPI
}
catch (Exception ex)
{
- Program.Monitor.Log($"{errorPrefix}: an error occurred while preprocessing '{manifest.EntryDll}'.\n{ex.GetLogSummary()}", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: an error occurred while preprocessing '{manifest.EntryDll}'.\n{ex.GetLogSummary()}", LogLevel.Error);
continue;
}
@@ -477,13 +502,13 @@ namespace StardewModdingAPI
{
if (modAssembly.DefinedTypes.Count(x => x.BaseType == typeof(Mod)) == 0)
{
- Program.Monitor.Log($"{errorPrefix}: the mod DLL does not contain an implementation of the 'Mod' class.", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: the mod DLL does not contain an implementation of the 'Mod' class.", LogLevel.Error);
continue;
}
}
catch (Exception ex)
{
- Program.Monitor.Log($"{errorPrefix}: an error occurred while reading the mod DLL.\n{ex.GetLogSummary()}", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: an error occurred while reading the mod DLL.\n{ex.GetLogSummary()}", LogLevel.Error);
continue;
}
@@ -496,25 +521,25 @@ namespace StardewModdingAPI
mod = (Mod)modAssembly.CreateInstance(modEntryType.ToString());
if (mod == null)
{
- Program.Monitor.Log($"{errorPrefix}: the mod's entry class could not be instantiated.");
+ this.Monitor.Log($"{errorPrefix}: the mod's entry class could not be instantiated.");
continue;
}
// inject data
// get helper
mod.ModManifest = manifest;
- mod.Helper = new ModHelper(manifest.Name, directory.FullName, jsonHelper, Program.ModRegistry, Program.CommandManager);
- mod.Monitor = Program.GetSecondaryMonitor(manifest.Name);
+ mod.Helper = new ModHelper(manifest.Name, directory.FullName, jsonHelper, this.ModRegistry, this.CommandManager);
+ mod.Monitor = this.GetSecondaryMonitor(manifest.Name);
mod.PathOnDisk = directory.FullName;
// track mod
- Program.ModRegistry.Add(mod);
- Program.ModsLoaded += 1;
- Program.Monitor.Log($"Loaded mod: {manifest.Name} by {manifest.Author}, v{manifest.Version} | {manifest.Description}", LogLevel.Info);
+ this.ModRegistry.Add(mod);
+ this.ModsLoaded += 1;
+ this.Monitor.Log($"Loaded mod: {manifest.Name} by {manifest.Author}, v{manifest.Version} | {manifest.Description}", LogLevel.Info);
}
catch (Exception ex)
{
- Program.Monitor.Log($"{errorPrefix}: an error occurred while loading the target DLL.\n{ex.GetLogSummary()}", LogLevel.Error);
+ this.Monitor.Log($"{errorPrefix}: an error occurred while loading the target DLL.\n{ex.GetLogSummary()}", LogLevel.Error);
continue;
}
}
@@ -525,7 +550,7 @@ namespace StardewModdingAPI
deprecationWarnings = null;
// initialise mods
- foreach (Mod mod in Program.ModRegistry.GetMods())
+ foreach (Mod mod in this.ModRegistry.GetMods())
{
try
{
@@ -534,54 +559,54 @@ namespace StardewModdingAPI
mod.Entry(mod.Helper);
// raise deprecation warning for old Entry() methods
- if (Program.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(object[]) }))
- Program.DeprecationManager.Warn(mod.ModManifest.Name, $"{nameof(Mod)}.{nameof(Mod.Entry)}(object[]) instead of {nameof(Mod)}.{nameof(Mod.Entry)}({nameof(IModHelper)})", "1.0", DeprecationLevel.Notice);
+ if (this.DeprecationManager.IsVirtualMethodImplemented(mod.GetType(), typeof(Mod), nameof(Mod.Entry), new[] { typeof(object[]) }))
+ this.DeprecationManager.Warn(mod.ModManifest.Name, $"{nameof(Mod)}.{nameof(Mod.Entry)}(object[]) instead of {nameof(Mod)}.{nameof(Mod.Entry)}({nameof(IModHelper)})", "1.0", DeprecationLevel.Notice);
}
catch (Exception ex)
{
- Program.Monitor.Log($"The {mod.ModManifest.Name} mod failed on entry initialisation. It will still be loaded, but may not function correctly.\n{ex.GetLogSummary()}", LogLevel.Warn);
+ this.Monitor.Log($"The {mod.ModManifest.Name} mod failed on entry initialisation. It will still be loaded, but may not function correctly.\n{ex.GetLogSummary()}", LogLevel.Warn);
}
}
// print result
- Program.Monitor.Log($"Loaded {Program.ModsLoaded} mods.");
- Console.Title = Constants.ConsoleTitle;
+ this.Monitor.Log($"Loaded {this.ModsLoaded} mods.");
+ Console.Title = $"Stardew Modding API Console - Version {Constants.ApiVersion} - Mods Loaded: {this.ModsLoaded}";
}
// ReSharper disable once FunctionNeverReturns
/// <summary>Run a loop handling console input.</summary>
- private static void ConsoleInputLoop()
+ private void ConsoleInputLoop()
{
while (true)
{
string input = Console.ReadLine();
- if (!Program.CommandManager.Trigger(input))
- Program.Monitor.Log("Unknown command; type 'help' for a list of available commands.", LogLevel.Error);
+ if (!this.CommandManager.Trigger(input))
+ this.Monitor.Log("Unknown command; type 'help' for a list of available commands.", LogLevel.Error);
}
}
/// <summary>The method called when the user submits the help command in the console.</summary>
/// <param name="name">The command name.</param>
/// <param name="arguments">The command arguments.</param>
- private static void HandleHelpCommand(string name, string[] arguments)
+ private void HandleHelpCommand(string name, string[] arguments)
{
if (arguments.Any())
{
- Framework.Command result = Program.CommandManager.Get(arguments[0]);
+ Framework.Command result = this.CommandManager.Get(arguments[0]);
if (result == null)
- Program.Monitor.Log("There's no command with that name.", LogLevel.Error);
+ this.Monitor.Log("There's no command with that name.", LogLevel.Error);
else
- Program.Monitor.Log($"{result.Name}: {result.Documentation}\n(Added by {result.ModName}.)", LogLevel.Info);
+ this.Monitor.Log($"{result.Name}: {result.Documentation}\n(Added by {result.ModName}.)", LogLevel.Info);
}
else
- Program.Monitor.Log("Commands: " + string.Join(", ", Program.CommandManager.GetAll().Select(p => p.Name)), LogLevel.Info);
+ this.Monitor.Log("Commands: " + string.Join(", ", this.CommandManager.GetAll().Select(p => p.Name)), LogLevel.Info);
}
/// <summary>Show a 'press any key to exit' message, and exit when they press a key.</summary>
- private static void PressAnyKeyToExit()
+ private void PressAnyKeyToExit()
{
- Program.Monitor.Log("Game has ended. Press any key to exit.", LogLevel.Info);
+ this.Monitor.Log("Game has ended. Press any key to exit.", LogLevel.Info);
Thread.Sleep(100);
Console.ReadKey();
Environment.Exit(0);
@@ -589,9 +614,9 @@ namespace StardewModdingAPI
/// <summary>Get a monitor instance derived from SMAPI's current settings.</summary>
/// <param name="name">The name of the module which will log messages with this instance.</param>
- private static Monitor GetSecondaryMonitor(string name)
+ private Monitor GetSecondaryMonitor(string name)
{
- return new Monitor(name, Program.ConsoleManager, Program.LogFile) { WriteToConsole = Program.Monitor.WriteToConsole, ShowTraceInConsole = Program.Settings.DeveloperMode };
+ return new Monitor(name, this.ConsoleManager, this.LogFile, this.ExitGameImmediately) { WriteToConsole = this.Monitor.WriteToConsole, ShowTraceInConsole = this.Settings.DeveloperMode };
}
}
}