diff options
-rw-r--r-- | build/common.targets | 2 | ||||
-rw-r--r-- | docs/release-notes.md | 13 | ||||
-rw-r--r-- | src/SMAPI.Mods.ConsoleCommands/manifest.json | 4 | ||||
-rw-r--r-- | src/SMAPI.Mods.ErrorHandler/manifest.json | 4 | ||||
-rw-r--r-- | src/SMAPI.Mods.SaveBackup/manifest.json | 4 | ||||
-rw-r--r-- | src/SMAPI.Web/wwwroot/SMAPI.metadata.json | 66 | ||||
-rw-r--r-- | src/SMAPI/Constants.cs | 33 | ||||
-rw-r--r-- | src/SMAPI/Framework/ModLoading/AssemblyLoader.cs | 1 | ||||
-rw-r--r-- | src/SMAPI/Framework/SCore.cs | 10 | ||||
-rw-r--r-- | src/SMAPI/Patches/SaveGamePatcher.cs | 55 |
10 files changed, 145 insertions, 47 deletions
diff --git a/build/common.targets b/build/common.targets index d526a2bb..f2614998 100644 --- a/build/common.targets +++ b/build/common.targets @@ -1,7 +1,7 @@ <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <!--set general build properties --> - <Version>3.12.0</Version> + <Version>3.12.1</Version> <Product>SMAPI</Product> <LangVersion>latest</LangVersion> <AssemblySearchPaths>$(AssemblySearchPaths);{GAC}</AssemblySearchPaths> diff --git a/docs/release-notes.md b/docs/release-notes.md index 36f07129..16744b24 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -1,8 +1,19 @@ ← [README](README.md) # Release notes +## 3.12.1 +Released 03 August 2021 for Stardew Valley 1.5.4 or later. + +* For players: + * The software conflict message is now shown as a warning to simplify troubleshooting. + * Fixed error loading older Harmony mods for some Windows players using unofficial 64-bit Stardew Valley. + * Updated compatibility list. + +* For mod authors: + * Fixed `Constants.Save*` fields incorrect if the save's folder name and ID don't match. + ## 3.12.0 -01 August 2021 for Stardew Valley 1.5.4 or later. See [release highlights](https://www.patreon.com/posts/54388616). +Released 01 August 2021 for Stardew Valley 1.5.4 or later. See [release highlights](https://www.patreon.com/posts/54388616). * For players: * Added save recovery when content mods leave null objects in the save (in _Error Handler_). diff --git a/src/SMAPI.Mods.ConsoleCommands/manifest.json b/src/SMAPI.Mods.ConsoleCommands/manifest.json index 09684f32..7023180b 100644 --- a/src/SMAPI.Mods.ConsoleCommands/manifest.json +++ b/src/SMAPI.Mods.ConsoleCommands/manifest.json @@ -1,9 +1,9 @@ { "Name": "Console Commands", "Author": "SMAPI", - "Version": "3.12.0", + "Version": "3.12.1", "Description": "Adds SMAPI console commands that let you manipulate the game.", "UniqueID": "SMAPI.ConsoleCommands", "EntryDll": "ConsoleCommands.dll", - "MinimumApiVersion": "3.12.0" + "MinimumApiVersion": "3.12.1" } diff --git a/src/SMAPI.Mods.ErrorHandler/manifest.json b/src/SMAPI.Mods.ErrorHandler/manifest.json index c83ca3d0..8aa2a6a4 100644 --- a/src/SMAPI.Mods.ErrorHandler/manifest.json +++ b/src/SMAPI.Mods.ErrorHandler/manifest.json @@ -1,9 +1,9 @@ { "Name": "Error Handler", "Author": "SMAPI", - "Version": "3.12.0", + "Version": "3.12.1", "Description": "Handles some common vanilla errors to log more useful info or avoid breaking the game.", "UniqueID": "SMAPI.ErrorHandler", "EntryDll": "ErrorHandler.dll", - "MinimumApiVersion": "3.12.0" + "MinimumApiVersion": "3.12.1" } diff --git a/src/SMAPI.Mods.SaveBackup/manifest.json b/src/SMAPI.Mods.SaveBackup/manifest.json index 42f1af59..dbd65cbe 100644 --- a/src/SMAPI.Mods.SaveBackup/manifest.json +++ b/src/SMAPI.Mods.SaveBackup/manifest.json @@ -1,9 +1,9 @@ { "Name": "Save Backup", "Author": "SMAPI", - "Version": "3.12.0", + "Version": "3.12.1", "Description": "Automatically backs up all your saves once per day into its folder.", "UniqueID": "SMAPI.SaveBackup", "EntryDll": "SaveBackup.dll", - "MinimumApiVersion": "3.12.0" + "MinimumApiVersion": "3.12.1" } diff --git a/src/SMAPI.Web/wwwroot/SMAPI.metadata.json b/src/SMAPI.Web/wwwroot/SMAPI.metadata.json index eeda13eb..7dff16c4 100644 --- a/src/SMAPI.Web/wwwroot/SMAPI.metadata.json +++ b/src/SMAPI.Web/wwwroot/SMAPI.metadata.json @@ -168,6 +168,60 @@ }, /********* + ** Broke in SMAPI 3.12.0 + *********/ + "PlatoTK": { + "ID": "Platonymous.PlatoTK", + "~1.9.3 | Status": "AssumeBroken", + "~1.9.3 | StatusReasonDetails": "fails to load with 'ReflectionTypeLoadException' error" + }, + "Stardew Hack": { + "ID": "bcmpinc.StardewHack", + "~5.0.0 | Status": "AssumeBroken", + "~5.0.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" + }, + "Always Scroll Map": { + "ID": "bcmpinc.AlwaysScrollMap", + "~4.1.0 | Status": "AssumeBroken", + "~4.1.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" // requested by the mod author + }, + "Fix Animal Tools": { + "ID": "bcmpinc.FixAnimalTools", + "~4.1.0 | Status": "AssumeBroken", + "~4.1.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" // requested by the mod author + }, + "Harvest With Scythe (bcmpinc)": { + "ID": "bcmpinc.HarvestWithScythe", + "~4.1.0 | Status": "AssumeBroken", + "~4.1.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" // requested by the mod author + }, + "Grass Growth": { + "ID": "bcmpinc.GrassGrowth", + "~4.1.0 | Status": "AssumeBroken", + "~4.1.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" // requested by the mod author + }, + "Tilled Soil Decay": { + "ID": "bcmpinc.TilledSoilDecay", + "~4.1.0 | Status": "AssumeBroken", + "~4.1.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" // requested by the mod author + }, + "Movement Speed": { + "ID": "bcmpinc.MovementSpeed", + "~4.1.0 | Status": "AssumeBroken", + "~4.1.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" // requested by the mod author + }, + "Tree Spread": { + "ID": "bcmpinc.TreeSpread", + "~4.2.0 | Status": "AssumeBroken", + "~4.2.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" // requested by the mod author + }, + "Wear More Rings": { + "ID": "bcmpinc.WearMoreRings", + "~4.1.0 | Status": "AssumeBroken", + "~4.1.0 | StatusReasonDetails": "causes Harmony patching errors for other mods" // requested by the mod author + }, + + /********* ** Broke in SDV 1.5 (Content Patcher packs) *********/ "mi.Mermaids": { @@ -222,18 +276,6 @@ "~1.0.8 | StatusReasonDetails": "crashes on save load" }, - "Movement Speed": { - "ID": "bcmpinc.MovementSpeed", - "~3.0.0 | Status": "AssumeBroken", - "~3.0.0 | StatusReasonDetails": "broken due to transpiler errors" - }, - - "Tree Spread": { - "ID": "bcmpinc.TreeSpread", - "~3.0.0 | Status": "AssumeBroken", - "~3.0.0 | StatusReasonDetails": "broken due to transpiler errors" - }, - "TreeTransplant": { "ID": "TreeTransplant", "~1.0.9 | Status": "AssumeBroken", diff --git a/src/SMAPI/Constants.cs b/src/SMAPI/Constants.cs index 3877e17a..05800970 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; @@ -61,7 +60,7 @@ namespace StardewModdingAPI internal static int? LogScreenId { get; set; } /// <summary>SMAPI's current raw semantic version.</summary> - internal static string RawApiVersion = "3.12.0"; + internal static string RawApiVersion = "3.12.1"; } /// <summary>Contains SMAPI's constants and assumptions.</summary> @@ -165,6 +164,9 @@ namespace StardewModdingAPI /// <summary>The language code for non-translated mod assets.</summary> internal static LocalizedContentManager.LanguageCode DefaultLanguage { get; } = LocalizedContentManager.LanguageCode.en; + /// <summary>The name of the last save file loaded by the game.</summary> + 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/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<string, Assembly>(); diff --git a/src/SMAPI/Framework/SCore.cs b/src/SMAPI/Framework/SCore.cs index a34b3eff..3f97bd4e 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(); } + /// <summary>Raised before the game begins reading a save file.</summary> + /// <param name="fileName">The save folder name.</param> + internal void OnSaveFileReading(string fileName) + { + Constants.LastRawSaveFileName = fileName; + } + /// <summary>Apply fixes to the save after it's loaded.</summary> private void ApplySaveFixes() { @@ -1315,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!"); } 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 +{ + /// <summary>Harmony patches for <see cref="SaveGame"/> which track the last loaded save ID.</summary> + /// <remarks>Patch methods must be static for Harmony to work correctly. See the Harmony documentation before renaming patch arguments.</remarks> + [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 + *********/ + /// <summary>A callback to invoke when a save file is being loaded.</summary> + private static Action<string> OnSaveFileReading; + + + /********* + ** Public methods + *********/ + /// <summary>Construct an instance.</summary> + /// <param name="onSaveFileReading">A callback to invoke when a save file is being loaded.</param> + public SaveGamePatcher(Action<string> onSaveFileReading) + { + SaveGamePatcher.OnSaveFileReading = onSaveFileReading; + } + + /// <inheritdoc /> + public override void Apply(Harmony harmony, IMonitor monitor) + { + harmony.Patch( + original: this.RequireMethod<SaveGame>(nameof(SaveGame.getLoadEnumerator)), + prefix: this.GetHarmonyMethod(nameof(SaveGamePatcher.Before_GetLoadEnumerator)) + ); + } + + + /********* + ** Private methods + *********/ + /// <summary>The method to call before <see cref="TitleMenu.createdNewCharacter"/>.</summary> + /// <returns>Returns whether to execute the original method.</returns> + /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> + private static bool Before_GetLoadEnumerator(string file) + { + SaveGamePatcher.OnSaveFileReading(file); + return true; + } + } +} |