fix SDate.Now() crashing during new-game intro (#369)

This commit is contained in:
Jesse Plamondon-Willard 2017-10-13 00:33:05 -04:00
parent b3ac93a0dc
commit aa5c5b2783
3 changed files with 41 additions and 18 deletions

View File

@ -29,6 +29,7 @@ For mod developers:
* Removed support for mods with no `Name`, `Version`, or `UniqueID` in their manifest.
* Removed support for mods with a non-unique `UniqueID` value in their manifest.
* Removed access to SMAPI internals through the reflection helper, to discourage fragile mods.
* Fixed `SDate.Now()` crashing when called during the new-game intro.
* Fixed `TimeEvents.AfterDayStarted` being raised during the new-game intro.
* Fixed SMAPI allowing map tilesheets with absolute or directory-climbing paths. These are now rejected even if the path exists, to avoid problems when players install the mod.

View File

@ -69,6 +69,8 @@ namespace StardewModdingAPI.Tests.Utilities
[TestCase(01, "Spring", 1)] // seasons are case-sensitive
[TestCase(01, "springs", 1)] // invalid season name
[TestCase(-1, "spring", 1)] // day < 0
[TestCase(0, "spring", 1)] // day zero
[TestCase(0, "spring", 2)] // day zero
[TestCase(29, "spring", 1)] // day > 28
[TestCase(01, "spring", -1)] // year < 1
[TestCase(01, "spring", 0)] // year < 1

View File

@ -52,28 +52,12 @@ namespace StardewModdingAPI.Utilities
/// <param name="year">The year.</param>
/// <exception cref="ArgumentException">One of the arguments has an invalid value (like day 35).</exception>
public SDate(int day, string season, int year)
{
// validate
if (season == null)
throw new ArgumentNullException(nameof(season));
if (!this.Seasons.Contains(season))
throw new ArgumentException($"Unknown season '{season}', must be one of [{string.Join(", ", this.Seasons)}].");
if (day < 1 || day > this.DaysInSeason)
throw new ArgumentException($"Invalid day '{day}', must be a value from 1 to {this.DaysInSeason}.");
if (year < 1)
throw new ArgumentException($"Invalid year '{year}', must be at least 1.");
// initialise
this.Day = day;
this.Season = season;
this.Year = year;
this.DayOfWeek = this.GetDayOfWeek();
}
: this(day, season, year, allowDayZero: false) { }
/// <summary>Get the current in-game date.</summary>
public static SDate Now()
{
return new SDate(Game1.dayOfMonth, Game1.currentSeason, Game1.year);
return new SDate(Game1.dayOfMonth, Game1.currentSeason, Game1.year, allowDayZero: true);
}
/// <summary>Get a new date with the given number of days added.</summary>
@ -195,6 +179,42 @@ namespace StardewModdingAPI.Utilities
/*********
** Private methods
*********/
/// <summary>Construct an instance.</summary>
/// <param name="day">The day of month.</param>
/// <param name="season">The season name.</param>
/// <param name="year">The year.</param>
/// <param name="allowDayZero">Whether to allow 0 spring Y1 as a valid date.</param>
/// <exception cref="ArgumentException">One of the arguments has an invalid value (like day 35).</exception>
private SDate(int day, string season, int year, bool allowDayZero)
{
// validate
if (season == null)
throw new ArgumentNullException(nameof(season));
if (!this.Seasons.Contains(season))
throw new ArgumentException($"Unknown season '{season}', must be one of [{string.Join(", ", this.Seasons)}].");
if (day < 0 || day > this.DaysInSeason)
throw new ArgumentException($"Invalid day '{day}', must be a value from 1 to {this.DaysInSeason}.");
if(day == 0 && !(allowDayZero && this.IsDayZero(day, season, year)))
throw new ArgumentException($"Invalid day '{day}', must be a value from 1 to {this.DaysInSeason}.");
if (year < 1)
throw new ArgumentException($"Invalid year '{year}', must be at least 1.");
// initialise
this.Day = day;
this.Season = season;
this.Year = year;
this.DayOfWeek = this.GetDayOfWeek();
}
/// <summary>Get whether a date represents 0 spring Y1, which is the date during the in-game intro.</summary>
/// <param name="day">The day of month.</param>
/// <param name="season">The season name.</param>
/// <param name="year">The year.</param>
private bool IsDayZero(int day, string season, int year)
{
return day == 0 && season == "spring" && year == 1;
}
/// <summary>Get the day of week for the current date.</summary>
private DayOfWeek GetDayOfWeek()
{