From 5256b738b486aa1591c6b25b41410973f1feaf46 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Mon, 2 Aug 2021 21:14:22 -0400 Subject: use more reliable method to get save folder name SMAPI now tracks the actual folder name being loaded to avoid edge cases where the folder name doesn't match the save ID. --- src/SMAPI/Constants.cs | 31 ++++---------------- src/SMAPI/Framework/SCore.cs | 8 ++++++ src/SMAPI/Patches/SaveGamePatcher.cs | 55 ++++++++++++++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 25 deletions(-) create mode 100644 src/SMAPI/Patches/SaveGamePatcher.cs (limited to 'src/SMAPI') diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index 3877e17a..bfaee70e 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; using System.Reflection; using StardewModdingAPI.Enums; using StardewModdingAPI.Framework; @@ -165,6 +164,9 @@ namespace StardewModdingAPI /// The language code for non-translated mod assets. internal static LocalizedContentManager.LanguageCode DefaultLanguage { get; } = LocalizedContentManager.LanguageCode.en; + /// The name of the last save file loaded by the game. + internal static string LastRawSaveFileName { get; set; } + /********* ** Internal methods @@ -341,30 +343,9 @@ namespace StardewModdingAPI if (Context.LoadStage == LoadStage.None) return null; - // get basic info - string rawSaveName = Game1.GetSaveGameName(set_value: false); - ulong saveID = Context.LoadStage == LoadStage.SaveParsed - ? SaveGame.loaded.uniqueIDForThisGame - : Game1.uniqueIDForThisGame; - - // get best match (accounting for rare case where folder name isn't sanitized) - DirectoryInfo folder = null; - foreach (string saveName in new[] { rawSaveName, new string(rawSaveName.Where(char.IsLetterOrDigit).ToArray()) }) - { - try - { - folder = new DirectoryInfo(Path.Combine(Constants.SavesPath, $"{saveName}_{saveID}")); - if (folder.Exists) - return folder; - } - catch (ArgumentException) - { - // ignore invalid path - } - } - - // if save doesn't exist yet, return the default one we expect to be created - return folder; + // get save + string rawSaveName = Constants.LastRawSaveFileName; + return new DirectoryInfo(Path.Combine(Constants.SavesPath, rawSaveName)); } } } diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index a34b3eff..b826789d 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -257,6 +257,7 @@ namespace StardewModdingAPI.Framework MiniMonoModHotfix.Apply(); HarmonyPatcher.Apply("SMAPI", this.Monitor, new Game1Patcher(this.Reflection, this.OnLoadStageChanged), + new SaveGamePatcher(this.OnSaveFileReading), new TitleMenuPatcher(this.OnLoadStageChanged) ); @@ -1101,6 +1102,13 @@ namespace StardewModdingAPI.Framework this.EventManager.ReturnedToTitle.RaiseEmpty(); } + /// Raised before the game begins reading a save file. + /// The save folder name. + internal void OnSaveFileReading(string fileName) + { + Constants.LastRawSaveFileName = fileName; + } + /// Apply fixes to the save after it's loaded. private void ApplySaveFixes() { diff --git a/src/SMAPI/Patches/SaveGamePatcher.cs b/src/SMAPI/Patches/SaveGamePatcher.cs new file mode 100644 index 00000000..969c514e --- /dev/null +++ b/src/SMAPI/Patches/SaveGamePatcher.cs @@ -0,0 +1,55 @@ +using System; +using System.Diagnostics.CodeAnalysis; +using HarmonyLib; +using StardewModdingAPI.Internal.Patching; +using StardewValley; +using StardewValley.Menus; + +namespace StardewModdingAPI.Patches +{ + /// Harmony patches for which track the last loaded save ID. + /// Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments. + [SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + [SuppressMessage("ReSharper", "IdentifierTypo", Justification = "Argument names are defined by Harmony and methods are named for clarity.")] + internal class SaveGamePatcher : BasePatcher + { + /********* + ** Fields + *********/ + /// A callback to invoke when a save file is being loaded. + private static Action OnSaveFileReading; + + + /********* + ** Public methods + *********/ + /// Construct an instance. + /// A callback to invoke when a save file is being loaded. + public SaveGamePatcher(Action onSaveFileReading) + { + SaveGamePatcher.OnSaveFileReading = onSaveFileReading; + } + + /// + public override void Apply(Harmony harmony, IMonitor monitor) + { + harmony.Patch( + original: this.RequireMethod(nameof(SaveGame.getLoadEnumerator)), + prefix: this.GetHarmonyMethod(nameof(SaveGamePatcher.Before_GetLoadEnumerator)) + ); + } + + + /********* + ** Private methods + *********/ + /// The method to call before . + /// Returns whether to execute the original method. + /// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments. + private static bool Before_GetLoadEnumerator(string file) + { + SaveGamePatcher.OnSaveFileReading(file); + return true; + } + } +} -- cgit From cf261ff36ee0c96acd0a8b0b233517991740b8cf Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 3 Aug 2021 12:00:15 -0400 Subject: increase software conflict message to warning level to simplify troubleshooting --- src/SMAPI/Framework/SCore.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI') diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index b826789d..3f97bd4e 100644 --- a/src/SMAPI/Framework/SCore.cs +++ b/src/SMAPI/Framework/SCore.cs @@ -1323,7 +1323,7 @@ namespace StardewModdingAPI.Framework .ToArray(); if (installedNames.Any()) - this.Monitor.Log($" Found {string.Join(" and ", installedNames)} installed, which can conflict with SMAPI. If you experience errors or crashes, try disabling that software or adding an exception for SMAPI / Stardew Valley."); + this.Monitor.Log($"Found {string.Join(" and ", installedNames)} installed, which may conflict with SMAPI. If you experience errors or crashes, try disabling that software or adding an exception for SMAPI and Stardew Valley.", LogLevel.Warn); else this.Monitor.Log(" None found!"); } -- cgit From 6b0d13be7c8383785cc3152d502959b15468b234 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 3 Aug 2021 19:03:51 -0400 Subject: fix Mono.Cecil failing to resolve references to SMAPI in some edge cases --- src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 1 + 1 file changed, 1 insertion(+) (limited to 'src/SMAPI') diff --git a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs index 3606eb66..2b71038a 100644 --- a/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs +++ b/src/SMAPI/Framework/ModLoading/AssemblyLoader.cs @@ -61,6 +61,7 @@ namespace StardewModdingAPI.Framework.ModLoading this.AssemblyDefinitionResolver = this.TrackForDisposal(new AssemblyDefinitionResolver()); this.AssemblyDefinitionResolver.AddSearchDirectory(Constants.ExecutionPath); this.AssemblyDefinitionResolver.AddSearchDirectory(Constants.InternalFilesPath); + this.AssemblyDefinitionResolver.Add(AssemblyDefinition.ReadAssembly(typeof(SGame).Assembly.Location)); // for some reason Mono.Cecil can't resolve SMAPI in very specific cases involving unofficial 64-bit Stardew Valley when launched through Steam (for some players only) // generate type => assembly lookup for types which should be rewritten this.TypeAssemblies = new Dictionary(); -- cgit From 1bb51b2c41bf5acdffb8e25c37187e9bdf9d3dd4 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Tue, 3 Aug 2021 19:11:26 -0400 Subject: prepare for release --- src/SMAPI/Constants.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/SMAPI') diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index bfaee70e..05800970 100644 --- a/src/SMAPI/Constants.cs +++ b/src/SMAPI/Constants.cs @@ -60,7 +60,7 @@ namespace StardewModdingAPI internal static int? LogScreenId { get; set; } /// SMAPI's current raw semantic version. - internal static string RawApiVersion = "3.12.0"; + internal static string RawApiVersion = "3.12.1"; } /// Contains SMAPI's constants and assumptions. -- cgit