From f945349ed40b770c1f7788f659d4ef3980abe3ff Mon Sep 17 00:00:00 2001 From: David Camp Date: Fri, 15 Jan 2021 18:48:29 -0500 Subject: [PATCH] (feat) Disable Mod rewrites if requested --- src/SMAPI/Framework/Logging/LogManager.cs | 5 +++- .../Framework/ModLoading/AssemblyLoader.cs | 9 +++++-- src/SMAPI/Framework/Models/SConfig.cs | 6 ++++- src/SMAPI/Framework/SCore.cs | 4 +-- src/SMAPI/Metadata/InstructionMetadata.cs | 25 +++++++++++-------- src/SMAPI/SMAPI.config.json | 6 +++++ 6 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/SMAPI/Framework/Logging/LogManager.cs b/src/SMAPI/Framework/Logging/LogManager.cs index e504218b..cc573427 100644 --- a/src/SMAPI/Framework/Logging/LogManager.cs +++ b/src/SMAPI/Framework/Logging/LogManager.cs @@ -286,12 +286,15 @@ namespace StardewModdingAPI.Framework.Logging /// Log details for settings that don't match the default. /// Whether to enable full console output for developers. /// Whether to check for newer versions of SMAPI and mods on startup. - public void LogSettingsHeader(bool isDeveloperMode, bool checkForUpdates) + /// ///Whether to rewrite mods, might need to be false to hook up to the Visual Studio Debugger. + public void LogSettingsHeader(bool isDeveloperMode, bool checkForUpdates, bool rewriteMods) { if (isDeveloperMode) this.Monitor.Log($"You have SMAPI for developers, so the console will 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 (!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 (!rewriteMods) + this.Monitor.Log($"You configured SMAPI to not rewrite potentially broken mods. This is not reccomended except in certain circumstances such as attaching to the Visual Studio debugger. You can enable mod rewrites 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.Monitor.VerboseLog("Verbose logging enabled."); diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 9fb5384e..d6a32621 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -37,6 +37,9 @@ namespace StardewModdingAPI.Framework.ModLoading /// The objects to dispose as part of this instance. private readonly HashSet Disposables = new HashSet(); + /// Whether mods should be re-writen for compatibility. + private readonly bool RewriteMods; + /********* ** Public methods @@ -45,10 +48,12 @@ namespace StardewModdingAPI.Framework.ModLoading /// The current game platform. /// Encapsulates monitoring and logging. /// Whether to detect paranoid mode issues. - public AssemblyLoader(Platform targetPlatform, IMonitor monitor, bool paranoidMode) + /// Whether to rewrite potentially broken mods or not. + public AssemblyLoader(Platform targetPlatform, IMonitor monitor, bool paranoidMode, bool rewriteMods) { this.Monitor = monitor; this.ParanoidMode = paranoidMode; + this.RewriteMods = rewriteMods; this.AssemblyMap = this.TrackForDisposal(Constants.GetAssemblyMap(targetPlatform)); // init resolver @@ -308,7 +313,7 @@ namespace StardewModdingAPI.Framework.ModLoading } // find or rewrite code - IInstructionHandler[] handlers = new InstructionMetadata().GetHandlers(this.ParanoidMode, platformChanged).ToArray(); + IInstructionHandler[] handlers = new InstructionMetadata().GetHandlers(this.ParanoidMode, platformChanged, this.RewriteMods).ToArray(); RecursiveRewriter rewriter = new RecursiveRewriter( module: module, rewriteType: (type, replaceWith) => diff --git a/src/SMAPI/Framework/Models/SConfig.cs b/src/SMAPI/Framework/Models/SConfig.cs index 3a3f6960..a5b27c17 100644 --- a/src/SMAPI/Framework/Models/SConfig.cs +++ b/src/SMAPI/Framework/Models/SConfig.cs @@ -20,7 +20,8 @@ namespace StardewModdingAPI.Framework.Models [nameof(GitHubProjectName)] = "Pathoschild/SMAPI", [nameof(WebApiBaseUrl)] = "https://smapi.io/api/", [nameof(VerboseLogging)] = false, - [nameof(LogNetworkTraffic)] = false + [nameof(LogNetworkTraffic)] = false, + [nameof(RewriteMods)] = true }; /// The default values for , to log changes if different. @@ -64,6 +65,9 @@ namespace StardewModdingAPI.Framework.Models /// The mod IDs SMAPI should ignore when performing update checks or validating update keys. public string[] SuppressUpdateChecks { get; set; } + /// Whether to rewrite mods for compatibility. Should only be set to false to facilitate joining to the Visual Studio Debugger. + public bool RewriteMods { get; set; } = (bool)SConfig.DefaultValues[nameof(SConfig.RewriteMods)]; + /******** ** Public methods diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index 00c2de75..06c88851 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -276,7 +276,7 @@ namespace StardewModdingAPI.Framework // log basic info this.LogManager.HandleMarkerFiles(); - this.LogManager.LogSettingsHeader(this.Settings.DeveloperMode, this.Settings.CheckForUpdates); + this.LogManager.LogSettingsHeader(this.Settings.DeveloperMode, this.Settings.CheckForUpdates, this.Settings.RewriteMods); // set window titles this.SetWindowTitles( @@ -1389,7 +1389,7 @@ namespace StardewModdingAPI.Framework // load mods IList skippedMods = new List(); - using (AssemblyLoader modAssemblyLoader = new AssemblyLoader(Constants.Platform, this.Monitor, this.Settings.ParanoidWarnings)) + using (AssemblyLoader modAssemblyLoader = new AssemblyLoader(Constants.Platform, this.Monitor, this.Settings.ParanoidWarnings, this.Settings.RewriteMods)) { // init HashSet suppressUpdateChecks = new HashSet(this.Settings.SuppressUpdateChecks, StringComparer.OrdinalIgnoreCase); diff --git a/src/SMAPI/Metadata/InstructionMetadata.cs b/src/SMAPI/Metadata/InstructionMetadata.cs index 2c1e14ce..1816e7f9 100644 --- a/src/SMAPI/Metadata/InstructionMetadata.cs +++ b/src/SMAPI/Metadata/InstructionMetadata.cs @@ -27,29 +27,32 @@ namespace StardewModdingAPI.Metadata /// Get rewriters which detect or fix incompatible CIL instructions in mod assemblies. /// Whether to detect paranoid mode issues. /// Whether the assembly was rewritten for crossplatform compatibility. - public IEnumerable GetHandlers(bool paranoidMode, bool platformChanged) + /// Whether to return Rewriters + public IEnumerable GetHandlers(bool paranoidMode, bool platformChanged, bool rewriteMods) { /**** ** rewrite CIL to fix incompatible code ****/ // rewrite for crossplatform compatibility - if (platformChanged) - yield return new MethodParentRewriter(typeof(SpriteBatch), typeof(SpriteBatchFacade)); + if (rewriteMods) + { + if (platformChanged) + yield return new MethodParentRewriter(typeof(SpriteBatch), typeof(SpriteBatchFacade)); - // rewrite for Stardew Valley 1.5 - yield return new FieldReplaceRewriter(typeof(DecoratableLocation), "furniture", typeof(GameLocation), nameof(GameLocation.furniture)); - yield return new FieldReplaceRewriter(typeof(Farm), "resourceClumps", typeof(GameLocation), nameof(GameLocation.resourceClumps)); - yield return new FieldReplaceRewriter(typeof(MineShaft), "resourceClumps", typeof(GameLocation), nameof(GameLocation.resourceClumps)); + // rewrite for Stardew Valley 1.5 + yield return new FieldReplaceRewriter(typeof(DecoratableLocation), "furniture", typeof(GameLocation), nameof(GameLocation.furniture)); + yield return new FieldReplaceRewriter(typeof(Farm), "resourceClumps", typeof(GameLocation), nameof(GameLocation.resourceClumps)); + yield return new FieldReplaceRewriter(typeof(MineShaft), "resourceClumps", typeof(GameLocation), nameof(GameLocation.resourceClumps)); - // heuristic rewrites - yield return new HeuristicFieldRewriter(this.ValidateReferencesToAssemblies); - yield return new HeuristicMethodRewriter(this.ValidateReferencesToAssemblies); + // heuristic rewrites + yield return new HeuristicFieldRewriter(this.ValidateReferencesToAssemblies); + yield return new HeuristicMethodRewriter(this.ValidateReferencesToAssemblies); #if HARMONY_2 // rewrite for SMAPI 3.6 (Harmony 1.x => 2.0 update) yield return new Harmony1AssemblyRewriter(); #endif - + } /**** ** detect mod issues ****/ diff --git a/src/SMAPI/SMAPI.config.json b/src/SMAPI/SMAPI.config.json index f44c422f..7b9f76d4 100644 --- a/src/SMAPI/SMAPI.config.json +++ b/src/SMAPI/SMAPI.config.json @@ -68,6 +68,12 @@ copy all the settings, or you may cause bugs due to overridden changes in future */ "LogNetworkTraffic": false, + /** + * Whether SMAPI should rewrite mods for compatibility. + * Note: This is best left to true unless you are attempting to hook into the Visual Studio Debugger + */ + "RewriteMods": true, + /** * The colors to use for text written to the SMAPI console. *