summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Plamondon-Willard <github@jplamondonw.com>2017-10-13 00:33:05 -0400
committerJesse Plamondon-Willard <github@jplamondonw.com>2017-10-13 00:33:05 -0400
commitaa5c5b27839b72343f751ffabd6c4625d1fc3f80 (patch)
treedfe7678b69ef48279ea07426cbdb4047f2bfee88
parentb3ac93a0dcc3ff40d3fed0e1ad293619f9522524 (diff)
downloadSMAPI-aa5c5b27839b72343f751ffabd6c4625d1fc3f80.tar.gz
SMAPI-aa5c5b27839b72343f751ffabd6c4625d1fc3f80.tar.bz2
SMAPI-aa5c5b27839b72343f751ffabd6c4625d1fc3f80.zip
fix SDate.Now() crashing during new-game intro (#369)
-rw-r--r--docs/release-notes.md1
-rw-r--r--src/SMAPI.Tests/Utilities/SDateTests.cs2
-rw-r--r--src/SMAPI/Utilities/SDate.cs56
3 files changed, 41 insertions, 18 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md
index fd59bd07..64588744 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -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.
diff --git a/src/SMAPI.Tests/Utilities/SDateTests.cs b/src/SMAPI.Tests/Utilities/SDateTests.cs
index 25acbaf3..86a0d3d0 100644
--- a/src/SMAPI.Tests/Utilities/SDateTests.cs
+++ b/src/SMAPI.Tests/Utilities/SDateTests.cs
@@ -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
diff --git a/src/SMAPI/Utilities/SDate.cs b/src/SMAPI/Utilities/SDate.cs
index 326d7fc7..2630731a 100644
--- a/src/SMAPI/Utilities/SDate.cs
+++ b/src/SMAPI/Utilities/SDate.cs
@@ -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()
{