diff options
-rw-r--r-- | docs/release-notes.md | 1 | ||||
-rw-r--r-- | src/SMAPI.Tests/Utilities/SDateTests.cs | 2 | ||||
-rw-r--r-- | src/SMAPI/Utilities/SDate.cs | 56 |
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() { |