fix save folder constants not available during early load stages

This commit is contained in:
Jesse Plamondon-Willard 2019-02-07 22:28:55 -05:00
parent 79c6166005
commit 9240bdbf9b
No known key found for this signature in database
GPG Key ID: 7D7C8097B62033CE
4 changed files with 79 additions and 29 deletions

View File

@ -1,4 +1,9 @@
# Release notes # Release notes
## Upcoming
* For modders:
* Fixed `Constants.SaveFolderName` and `CurrentSavePath` not available during early load stages when using `Specialised.LoadStageChanged` event.
## 2.10.1 ## 2.10.1
Released 30 December 2018 for Stardew Valley 1.3.32. Released 30 December 2018 for Stardew Valley 1.3.32.

View File

@ -2,6 +2,7 @@ using System;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using StardewModdingAPI.Enums;
using StardewModdingAPI.Framework; using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.ModLoading; using StardewModdingAPI.Framework.ModLoading;
using StardewModdingAPI.Internal; using StardewModdingAPI.Internal;
@ -12,16 +13,6 @@ namespace StardewModdingAPI
/// <summary>Contains SMAPI's constants and assumptions.</summary> /// <summary>Contains SMAPI's constants and assumptions.</summary>
public static class Constants public static class Constants
{ {
/*********
** Fields
*********/
/// <summary>The directory path containing the current save's data (if a save is loaded).</summary>
private static string RawSavePath => Context.IsSaveLoaded ? Path.Combine(Constants.SavesPath, Constants.GetSaveFolderName()) : null;
/// <summary>Whether the directory containing the current save's data exists on disk.</summary>
private static bool SavePathReady => Context.IsSaveLoaded && Directory.Exists(Constants.RawSavePath);
/********* /*********
** Accessors ** Accessors
*********/ *********/
@ -52,11 +43,33 @@ namespace StardewModdingAPI
/// <summary>The directory path where all saves are stored.</summary> /// <summary>The directory path where all saves are stored.</summary>
public static string SavesPath { get; } = Path.Combine(Constants.DataPath, "Saves"); public static string SavesPath { get; } = Path.Combine(Constants.DataPath, "Saves");
/// <summary>The directory name containing the current save's data (if a save is loaded and the directory exists).</summary> /// <summary>The name of the current save folder (if save info is available, regardless of whether the save file exists yet).</summary>
public static string SaveFolderName => Context.IsSaveLoaded ? Constants.GetSaveFolderName() : ""; public static string SaveFolderName
{
get
{
return Constants.GetSaveFolderName()
#if SMAPI_3_0_STRICT
;
#else
?? "";
#endif
}
}
/// <summary>The directory path containing the current save's data (if a save is loaded and the directory exists).</summary> /// <summary>The absolute path to the current save folder (if save info is available and the save file exists).</summary>
public static string CurrentSavePath => Constants.SavePathReady ? Path.Combine(Constants.SavesPath, Constants.GetSaveFolderName()) : ""; public static string CurrentSavePath
{
get
{
return Constants.GetSaveFolderPathIfExists()
#if SMAPI_3_0_STRICT
;
#else
?? "";
#endif
}
}
/**** /****
** Internal ** Internal
@ -184,13 +197,6 @@ namespace StardewModdingAPI
/********* /*********
** Private methods ** Private methods
*********/ *********/
/// <summary>Get the name of a save directory for the current player.</summary>
private static string GetSaveFolderName()
{
string prefix = new string(Game1.player.Name.Where(char.IsLetterOrDigit).ToArray());
return $"{prefix}_{Game1.uniqueIDForThisGame}";
}
/// <summary>Get the game's current version string.</summary> /// <summary>Get the game's current version string.</summary>
private static string GetGameVersion() private static string GetGameVersion()
{ {
@ -200,5 +206,43 @@ namespace StardewModdingAPI
throw new InvalidOperationException($"The {nameof(Game1)}.{nameof(Game1.version)} field could not be found."); throw new InvalidOperationException($"The {nameof(Game1)}.{nameof(Game1.version)} field could not be found.");
return (string)field.GetValue(null); return (string)field.GetValue(null);
} }
/// <summary>Get the name of the save folder, if any.</summary>
internal static string GetSaveFolderName()
{
// save not available
if (Context.LoadStage == LoadStage.None)
return null;
// get basic info
string playerName;
ulong saveID;
if (Context.LoadStage == LoadStage.SaveParsed)
{
playerName = SaveGame.loaded.player.Name;
saveID = SaveGame.loaded.uniqueIDForThisGame;
}
else
{
playerName = Game1.player.Name;
saveID = Game1.uniqueIDForThisGame;
}
// build folder name
return $"{new string(playerName.Where(char.IsLetterOrDigit).ToArray())}_{saveID}";
}
/// <summary>Get the path to the current save folder, if any.</summary>
internal static string GetSaveFolderPathIfExists()
{
string folderName = Constants.GetSaveFolderName();
if (folderName == null)
return null;
string path = Path.Combine(Constants.SavesPath, folderName);
return Directory.Exists(path)
? path
: null;
}
} }
} }

View File

@ -1,3 +1,4 @@
using StardewModdingAPI.Enums;
using StardewModdingAPI.Events; using StardewModdingAPI.Events;
using StardewValley; using StardewValley;
using StardewValley.Menus; using StardewValley.Menus;
@ -39,5 +40,8 @@ namespace StardewModdingAPI
/// <summary>Whether the game is currently writing to the save file.</summary> /// <summary>Whether the game is currently writing to the save file.</summary>
internal static bool IsSaving => Game1.activeClickableMenu is SaveGameMenu || Game1.activeClickableMenu is ShippingMenu; // saving is performed by SaveGameMenu, but it's wrapped by ShippingMenu on days when the player shipping something internal static bool IsSaving => Game1.activeClickableMenu is SaveGameMenu || Game1.activeClickableMenu is ShippingMenu; // saving is performed by SaveGameMenu, but it's wrapped by ShippingMenu on days when the player shipping something
/// <summary>The current stage in the game's loading process.</summary>
internal static LoadStage LoadStage { get; set; }
} }
} }

View File

@ -69,9 +69,6 @@ namespace StardewModdingAPI.Framework
/// <remarks>Skipping a few frames ensures the game finishes initialising the world before mods try to change it.</remarks> /// <remarks>Skipping a few frames ensures the game finishes initialising the world before mods try to change it.</remarks>
private readonly Countdown AfterLoadTimer = new Countdown(5); private readonly Countdown AfterLoadTimer = new Countdown(5);
/// <summary>The current stage in the game's loading process.</summary>
private LoadStage LoadStage = LoadStage.None;
/// <summary>Whether the game is saving and SMAPI has already raised <see cref="IGameLoopEvents.Saving"/>.</summary> /// <summary>Whether the game is saving and SMAPI has already raised <see cref="IGameLoopEvents.Saving"/>.</summary>
private bool IsBetweenSaveEvents; private bool IsBetweenSaveEvents;
@ -215,12 +212,12 @@ namespace StardewModdingAPI.Framework
internal void OnLoadStageChanged(LoadStage newStage) internal void OnLoadStageChanged(LoadStage newStage)
{ {
// nothing to do // nothing to do
if (newStage == this.LoadStage) if (newStage == Context.LoadStage)
return; return;
// update data // update data
LoadStage oldStage = this.LoadStage; LoadStage oldStage = Context.LoadStage;
this.LoadStage = newStage; Context.LoadStage = newStage;
if (newStage == LoadStage.None) if (newStage == LoadStage.None)
{ {
this.Monitor.Log("Context: returned to title", LogLevel.Trace); this.Monitor.Log("Context: returned to title", LogLevel.Trace);
@ -511,7 +508,7 @@ namespace StardewModdingAPI.Framework
*********/ *********/
if (wasWorldReady && !Context.IsWorldReady) if (wasWorldReady && !Context.IsWorldReady)
this.OnLoadStageChanged(LoadStage.None); this.OnLoadStageChanged(LoadStage.None);
else if (Context.IsWorldReady && this.LoadStage != LoadStage.Ready) else if (Context.IsWorldReady && Context.LoadStage != LoadStage.Ready)
{ {
// print context // print context
string context = $"Context: loaded saved game '{Constants.SaveFolderName}', starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}."; string context = $"Context: loaded saved game '{Constants.SaveFolderName}', starting {Game1.currentSeason} {Game1.dayOfMonth} Y{Game1.year}.";
@ -884,7 +881,7 @@ namespace StardewModdingAPI.Framework
events.GameLaunched.Raise(new GameLaunchedEventArgs()); events.GameLaunched.Raise(new GameLaunchedEventArgs());
// preloaded // preloaded
if (Context.IsSaveLoaded && this.LoadStage != LoadStage.Loaded && this.LoadStage != LoadStage.Ready) if (Context.IsSaveLoaded && Context.LoadStage != LoadStage.Loaded && Context.LoadStage != LoadStage.Ready)
this.OnLoadStageChanged(LoadStage.Loaded); this.OnLoadStageChanged(LoadStage.Loaded);
// update tick // update tick