diff options
author | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2019-05-10 23:49:08 -0400 |
---|---|---|
committer | Jesse Plamondon-Willard <Pathoschild@users.noreply.github.com> | 2019-09-14 17:57:42 -0400 |
commit | f2dd11fe3fbe8b31665ad25e6e58b0026c00098e (patch) | |
tree | ba7f2c8466a6b57d3393294e50bd48db5c7184b4 /src/SMAPI/Patches | |
parent | 2be3b7fb01045d274cdd77633ffbb690c5fb2f6d (diff) | |
download | SMAPI-f2dd11fe3fbe8b31665ad25e6e58b0026c00098e.tar.gz SMAPI-f2dd11fe3fbe8b31665ad25e6e58b0026c00098e.tar.bz2 SMAPI-f2dd11fe3fbe8b31665ad25e6e58b0026c00098e.zip |
fix inconsistent LoadStage behavior when creating a new save
Diffstat (limited to 'src/SMAPI/Patches')
-rw-r--r-- | src/SMAPI/Patches/LoadContextPatch.cs | 55 |
1 files changed, 17 insertions, 38 deletions
diff --git a/src/SMAPI/Patches/LoadContextPatch.cs b/src/SMAPI/Patches/LoadContextPatch.cs index 3f86c9a9..93a059aa 100644 --- a/src/SMAPI/Patches/LoadContextPatch.cs +++ b/src/SMAPI/Patches/LoadContextPatch.cs @@ -1,16 +1,15 @@ using System; -using System.Collections.ObjectModel; -using System.Collections.Specialized; using Harmony; using StardewModdingAPI.Enums; using StardewModdingAPI.Framework.Patching; using StardewModdingAPI.Framework.Reflection; using StardewValley; using StardewValley.Menus; +using StardewValley.Minigames; namespace StardewModdingAPI.Patches { - /// <summary>A Harmony patch for <see cref="Game1.loadForNewGame"/> which notifies SMAPI for save creation load stages.</summary> + /// <summary>Harmony patches which notify SMAPI for save creation load stages.</summary> /// <remarks>This patch hooks into <see cref="Game1.loadForNewGame"/>, checks if <c>TitleMenu.transitioningCharacterCreationMenu</c> is true (which means the player is creating a new save file), then raises <see cref="LoadStage.CreatedBasicInfo"/> after the location list is cleared twice (the second clear happens right before locations are created), and <see cref="LoadStage.CreatedLocations"/> when the method ends.</remarks> internal class LoadContextPatch : IHarmonyPatch { @@ -23,12 +22,6 @@ namespace StardewModdingAPI.Patches /// <summary>A callback to invoke when the load stage changes.</summary> private static Action<LoadStage> OnStageChanged; - /// <summary>Whether <see cref="Game1.loadForNewGame"/> was called as part of save creation.</summary> - private static bool IsCreating; - - /// <summary>The number of times that <see cref="Game1.locations"/> has been cleared since <see cref="Game1.loadForNewGame"/> started.</summary> - private static int TimesLocationsCleared; - /********* ** Accessors @@ -53,9 +46,15 @@ namespace StardewModdingAPI.Patches /// <param name="harmony">The Harmony instance.</param> public void Apply(HarmonyInstance harmony) { + // detect CreatedBasicInfo + harmony.Patch( + original: AccessTools.Method(typeof(TitleMenu), nameof(TitleMenu.createdNewCharacter)), + prefix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.Before_TitleMenu_CreatedNewCharacter)) + ); + + // detect CreatedLocations harmony.Patch( original: AccessTools.Method(typeof(Game1), nameof(Game1.loadForNewGame)), - prefix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.Before_Game1_LoadForNewGame)), postfix: new HarmonyMethod(this.GetType(), nameof(LoadContextPatch.After_Game1_LoadForNewGame)) ); } @@ -64,45 +63,25 @@ namespace StardewModdingAPI.Patches /********* ** Private methods *********/ - /// <summary>The method to call instead of <see cref="Game1.loadForNewGame"/>.</summary> + /// <summary>Called 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_Game1_LoadForNewGame() + private static bool Before_TitleMenu_CreatedNewCharacter() { - LoadContextPatch.IsCreating = Game1.activeClickableMenu is TitleMenu menu && LoadContextPatch.Reflection.GetField<bool>(menu, "transitioningCharacterCreationMenu").GetValue(); - LoadContextPatch.TimesLocationsCleared = 0; - if (LoadContextPatch.IsCreating) - { - // raise CreatedBasicInfo after locations are cleared twice - ObservableCollection<GameLocation> locations = (ObservableCollection<GameLocation>)Game1.locations; - locations.CollectionChanged += LoadContextPatch.OnLocationListChanged; - } - + LoadContextPatch.OnStageChanged(LoadStage.CreatedBasicInfo); return true; } - /// <summary>The method to call instead after <see cref="Game1.loadForNewGame"/>.</summary> + /// <summary>Called after <see cref="Game1.loadForNewGame"/>.</summary> /// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks> private static void After_Game1_LoadForNewGame() { - if (LoadContextPatch.IsCreating) - { - // clean up - ObservableCollection<GameLocation> locations = (ObservableCollection<GameLocation>)Game1.locations; - locations.CollectionChanged -= LoadContextPatch.OnLocationListChanged; + bool creating = + (Game1.currentMinigame is Intro) // creating save with intro + || (Game1.activeClickableMenu is TitleMenu menu && LoadContextPatch.Reflection.GetField<bool>(menu, "transitioningCharacterCreationMenu").GetValue()); // creating save, skipped intro - // raise stage changed + if (creating) LoadContextPatch.OnStageChanged(LoadStage.CreatedLocations); - } - } - - /// <summary>Raised when <see cref="Game1.locations"/> changes.</summary> - /// <param name="sender">The event sender.</param> - /// <param name="e">The event arguments.</param> - private static void OnLocationListChanged(object sender, NotifyCollectionChangedEventArgs e) - { - if (++LoadContextPatch.TimesLocationsCleared == 2) - LoadContextPatch.OnStageChanged(LoadStage.CreatedBasicInfo); } } } |