diff options
Diffstat (limited to 'src/SMAPI')
-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 |
4 files changed, 72 insertions, 27 deletions
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; + } + } +} |