summaryrefslogtreecommitdiff
path: root/src/SMAPI
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-08-02 21:14:22 -0400
committerJesse Plamondon-Willard <Pathoschild@users.noreply.github.com>2021-08-02 21:14:22 -0400
commit5256b738b486aa1591c6b25b41410973f1feaf46 (patch)
tree4b43fc95e2bcd72eb2f67673239e28b3ef86579b /src/SMAPI
parent5b31be76dd90711ff475341de8dfdb6e1f50b98a (diff)
downloadSMAPI-5256b738b486aa1591c6b25b41410973f1feaf46.tar.gz
SMAPI-5256b738b486aa1591c6b25b41410973f1feaf46.tar.bz2
SMAPI-5256b738b486aa1591c6b25b41410973f1feaf46.zip
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.
Diffstat (limited to 'src/SMAPI')
-rw-r--r--src/SMAPI/Constants.cs31
-rw-r--r--src/SMAPI/Framework/SCore.cs8
-rw-r--r--src/SMAPI/Patches/SaveGamePatcher.cs55
3 files changed, 69 insertions, 25 deletions
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
/// <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/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();
}
+ /// <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()
{
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;
+ }
+ }
+}