/// <summary>Initialise SMAPI and mods after the game starts.</summary> private void InitialiseAfterGameStart() { // load settings this.Settings = JsonConvert.DeserializeObject <SConfig>(File.ReadAllText(Constants.ApiConfigPath)); this.GameInstance.VerboseLogging = this.Settings.VerboseLogging; // load core components this.ModRegistry = new ModRegistry(); this.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry); this.CommandManager = new CommandManager(); // redirect direct console output { Monitor monitor = this.GetSecondaryMonitor("Console.Out"); if (monitor.WriteToConsole) { this.ConsoleManager.OnMessageIntercepted += message => this.HandleConsoleMessage(monitor, message); } } // add headers if (this.Settings.DeveloperMode) { this.Monitor.ShowTraceInConsole = true; this.Monitor.ShowFullStampInConsole = 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 {Constants.ApiConfigPath}.", LogLevel.Info); } 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 reinstalling SMAPI or editing {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); } this.VerboseLog("Verbose logging enabled."); // validate XNB integrity if (!this.ValidateContentIntegrity()) { this.Monitor.Log("SMAPI found problems in your game's content files which are likely to cause errors or crashes. Consider uninstalling XNB mods or reinstalling the game.", LogLevel.Error); } // load mods { this.Monitor.Log("Loading mod metadata...", LogLevel.Trace); ModResolver resolver = new ModResolver(); // load manifests IModMetadata[] mods = resolver.ReadManifests(Constants.ModPath, new JsonHelper(), this.Settings.ModData).ToArray(); resolver.ValidateManifests(mods, Constants.ApiVersion, Constants.VendorModUrls); // process dependencies mods = resolver.ProcessDependencies(mods).ToArray(); // load mods this.LoadMods(mods, new JsonHelper(), this.ContentManager); // check for updates this.CheckForUpdatesAsync(mods); } if (this.Monitor.IsExiting) { this.Monitor.Log("SMAPI shutting down: aborting initialisation.", LogLevel.Warn); return; } // update window titles int modsLoaded = this.ModRegistry.GetMods().Count(); this.GameInstance.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion} with {modsLoaded} mods"; Console.Title = $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion} with {modsLoaded} mods"; // start SMAPI console new Thread(this.RunConsoleLoop).Start(); }
/// <summary>Initialise SMAPI and mods after the game starts.</summary> private void InitialiseAfterGameStart() { // load settings this.Settings = JsonConvert.DeserializeObject <SConfig>(File.ReadAllText(Constants.ApiConfigPath)); this.GameInstance.VerboseLogging = this.Settings.VerboseLogging; // load core components this.ModRegistry = new ModRegistry(); this.DeprecationManager = new DeprecationManager(this.Monitor, this.ModRegistry); this.CommandManager = new CommandManager(); #if SMAPI_1_x // inject compatibility shims #pragma warning disable 618 Command.Shim(this.CommandManager, this.DeprecationManager, this.ModRegistry); Config.Shim(this.DeprecationManager); Log.Shim(this.DeprecationManager, this.GetSecondaryMonitor("legacy mod"), this.ModRegistry); Mod.Shim(this.DeprecationManager); GameEvents.Shim(this.DeprecationManager); PlayerEvents.Shim(this.DeprecationManager); TimeEvents.Shim(this.DeprecationManager); #pragma warning restore 618 #endif // redirect direct console output { Monitor monitor = this.GetSecondaryMonitor("Console.Out"); if (monitor.WriteToConsole) { this.ConsoleManager.OnMessageIntercepted += message => this.HandleConsoleMessage(monitor, message); } } // add headers if (this.Settings.DeveloperMode) { this.Monitor.ShowTraceInConsole = true; #if !SMAPI_1_x this.Monitor.ShowFullStampInConsole = true; #endif 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 {Constants.ApiConfigPath}.", LogLevel.Info); } 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 reinstalling SMAPI or editing {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); } if (this.Settings.VerboseLogging) { this.Monitor.Log("Verbose logging enabled.", LogLevel.Trace); } // validate XNB integrity if (!this.ValidateContentIntegrity()) { this.Monitor.Log("SMAPI found problems in your game's content files which are likely to cause errors or crashes. Consider uninstalling XNB mods or reinstalling the game.", LogLevel.Error); } // load mods { #if SMAPI_1_x this.Monitor.Log("Loading mod metadata..."); #else this.Monitor.Log("Loading mod metadata...", LogLevel.Trace); #endif ModResolver resolver = new ModResolver(); // load manifests IModMetadata[] mods = resolver.ReadManifests(Constants.ModPath, new JsonHelper(), this.Settings.ModCompatibility, this.Settings.DisabledMods).ToArray(); resolver.ValidateManifests(mods, Constants.ApiVersion); // check for deprecated metadata #if SMAPI_1_x IList <Action> deprecationWarnings = new List <Action>(); foreach (IModMetadata mod in mods.Where(m => m.Status != ModMetadataStatus.Failed)) { // missing fields that will be required in SMAPI 2.0 { List <string> missingFields = new List <string>(3); if (string.IsNullOrWhiteSpace(mod.Manifest.Name)) { missingFields.Add(nameof(IManifest.Name)); } if (mod.Manifest.Version == null || mod.Manifest.Version.ToString() == "0.0") { missingFields.Add(nameof(IManifest.Version)); } if (string.IsNullOrWhiteSpace(mod.Manifest.UniqueID)) { missingFields.Add(nameof(IManifest.UniqueID)); } if (missingFields.Any()) { deprecationWarnings.Add(() => this.Monitor.Log($"{mod.DisplayName} is missing some manifest fields ({string.Join(", ", missingFields)}) which will be required in an upcoming SMAPI version.", LogLevel.Warn)); } } // per-save directories if ((mod.Manifest as Manifest)?.PerSaveConfigs == true) { deprecationWarnings.Add(() => this.DeprecationManager.Warn(mod.DisplayName, $"{nameof(Manifest)}.{nameof(Manifest.PerSaveConfigs)}", "1.0", DeprecationLevel.PendingRemoval)); try { string psDir = Path.Combine(mod.DirectoryPath, "psconfigs"); Directory.CreateDirectory(psDir); if (!Directory.Exists(psDir)) { mod.SetStatus(ModMetadataStatus.Failed, "it requires per-save configuration files ('psconfigs') which couldn't be created for some reason."); } } catch (Exception ex) { mod.SetStatus(ModMetadataStatus.Failed, $"it requires per-save configuration files ('psconfigs') which couldn't be created: {ex.GetLogSummary()}"); } } } #endif // process dependencies mods = resolver.ProcessDependencies(mods).ToArray(); // load mods #if SMAPI_1_x this.LoadMods(mods, new JsonHelper(), this.ContentManager, deprecationWarnings); foreach (Action warning in deprecationWarnings) { warning(); } #else this.LoadMods(mods, new JsonHelper(), this.ContentManager); #endif } if (this.Monitor.IsExiting) { this.Monitor.Log("SMAPI shutting down: aborting initialisation.", LogLevel.Warn); return; } // update window titles int modsLoaded = this.ModRegistry.GetMods().Count(); this.GameInstance.Window.Title = $"Stardew Valley {Constants.GameVersion} - running SMAPI {Constants.ApiVersion} with {modsLoaded} mods"; Console.Title = $"SMAPI {Constants.ApiVersion} - running Stardew Valley {Constants.GameVersion} with {modsLoaded} mods"; // start SMAPI console new Thread(this.RunConsoleLoop).Start(); }