diff --git a/docs/release-notes.md b/docs/release-notes.md
index 9047ae88..63343d0a 100644
--- a/docs/release-notes.md
+++ b/docs/release-notes.md
@@ -1,4 +1,8 @@
# Release notes
+## Upcoming release
+* For players:
+ * Fixed error when a mod makes invalid changes to an NPC schedule.
+
## 2.9.1
* For players:
* Fixed crash in SMAPI 2.9 when constructing certain buildings.
diff --git a/src/SMAPI/Framework/ContentCoordinator.cs b/src/SMAPI/Framework/ContentCoordinator.cs
index 08a32a9b..7e256939 100644
--- a/src/SMAPI/Framework/ContentCoordinator.cs
+++ b/src/SMAPI/Framework/ContentCoordinator.cs
@@ -81,7 +81,7 @@ namespace StardewModdingAPI.Framework
this.ContentManagers.Add(
this.MainContentManager = new GameContentManager("Game1.content", serviceProvider, rootDirectory, currentCulture, this, monitor, reflection, this.OnDisposing)
);
- this.CoreAssets = new CoreAssetPropagator(this.MainContentManager.AssertAndNormaliseAssetName, reflection);
+ this.CoreAssets = new CoreAssetPropagator(this.MainContentManager.AssertAndNormaliseAssetName, reflection, monitor);
}
/// Get a new content manager which handles reading files from the game content folder with support for interception.
diff --git a/src/SMAPI/Metadata/CoreAssetPropagator.cs b/src/SMAPI/Metadata/CoreAssetPropagator.cs
index 90629d7f..4667be7e 100644
--- a/src/SMAPI/Metadata/CoreAssetPropagator.cs
+++ b/src/SMAPI/Metadata/CoreAssetPropagator.cs
@@ -31,6 +31,9 @@ namespace StardewModdingAPI.Metadata
/// Simplifies access to private game code.
private readonly Reflector Reflection;
+ /// Encapsulates monitoring and logging.
+ private readonly IMonitor Monitor;
+
/*********
** Public methods
@@ -38,10 +41,12 @@ namespace StardewModdingAPI.Metadata
/// Initialise the core asset data.
/// Normalises an asset key to match the cache key.
/// Simplifies access to private code.
- public CoreAssetPropagator(Func getNormalisedPath, Reflector reflection)
+ /// Encapsulates monitoring and logging.
+ public CoreAssetPropagator(Func getNormalisedPath, Reflector reflection, IMonitor monitor)
{
this.GetNormalisedPath = getNormalisedPath;
this.Reflection = reflection;
+ this.Monitor = monitor;
}
/// Reload one of the game's core assets (if applicable).
@@ -619,6 +624,11 @@ namespace StardewModdingAPI.Metadata
{
// reload schedule
villager.Schedule = villager.getSchedule(Game1.dayOfMonth);
+ if (villager.Schedule == null)
+ {
+ this.Monitor.Log($"A mod set an invalid schedule for {villager.Name ?? key}, so the NPC may not behave correctly.", LogLevel.Warn);
+ return true;
+ }
// switch to new schedule if needed
int lastScheduleTime = villager.Schedule.Keys.Where(p => p <= Game1.timeOfDay).OrderByDescending(p => p).FirstOrDefault();