diff options
-rw-r--r-- | docs/release-notes.md | 1 | ||||
-rw-r--r-- | src/SMAPI.Toolkit/Serialization/JsonHelper.cs | 5 | ||||
-rw-r--r-- | src/SMAPI/Framework/SMultiplayer.cs | 29 |
3 files changed, 27 insertions, 8 deletions
diff --git a/docs/release-notes.md b/docs/release-notes.md index 99269bc6..a0d8826b 100644 --- a/docs/release-notes.md +++ b/docs/release-notes.md @@ -8,6 +8,7 @@ * Removed experimental 'aggressive memory optimizations' option. _This was disabled by default and is no longer needed in most cases. Memory usage will be better reduced by reworked asset propagation in the upcoming SMAPI 4.0.0._ * Fixed 'content file was not found' error when the game tries to load unlocalized text from a localizable mod data asset. + * Fixed error reading empty JSON files. These are now treated as if they didn't exist like before 3.14.0. * Updated compatibility list. ## 3.14.0 diff --git a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs index 3c9308f2..1a003c51 100644 --- a/src/SMAPI.Toolkit/Serialization/JsonHelper.cs +++ b/src/SMAPI.Toolkit/Serialization/JsonHelper.cs @@ -108,12 +108,11 @@ namespace StardewModdingAPI.Toolkit.Serialization /// <summary>Deserialize JSON text if possible.</summary> /// <typeparam name="TModel">The model type.</typeparam> /// <param name="json">The raw JSON text.</param> - public TModel Deserialize<TModel>(string json) + public TModel? Deserialize<TModel>(string json) { try { - return JsonConvert.DeserializeObject<TModel>(json, this.JsonSettings) - ?? throw new InvalidOperationException($"Couldn't deserialize model type '{typeof(TModel)}' from empty or null JSON."); + return JsonConvert.DeserializeObject<TModel>(json, this.JsonSettings); } catch (JsonReaderException) { diff --git a/src/SMAPI/Framework/SMultiplayer.cs b/src/SMAPI/Framework/SMultiplayer.cs index e41e7edc..2badcbbf 100644 --- a/src/SMAPI/Framework/SMultiplayer.cs +++ b/src/SMAPI/Framework/SMultiplayer.cs @@ -9,6 +9,7 @@ using StardewModdingAPI.Events; using StardewModdingAPI.Framework.Events; using StardewModdingAPI.Framework.Networking; using StardewModdingAPI.Framework.Reflection; +using StardewModdingAPI.Internal; using StardewModdingAPI.Toolkit.Serialization; using StardewModdingAPI.Utilities; using StardewValley; @@ -489,8 +490,8 @@ namespace StardewModdingAPI.Framework private RemoteContextModel? ReadContext(BinaryReader reader) { string data = reader.ReadString(); - RemoteContextModel model = this.JsonHelper.Deserialize<RemoteContextModel>(data); - return model.ApiVersion != null + RemoteContextModel? model = this.JsonHelper.Deserialize<RemoteContextModel>(data); + return model?.ApiVersion != null ? model : null; // no data available for vanilla players } @@ -499,13 +500,31 @@ namespace StardewModdingAPI.Framework /// <param name="message">The raw message to parse.</param> private void ReceiveModMessage(IncomingMessage message) { - // parse message + // read message JSON string json = message.Reader.ReadString(); - ModMessageModel model = this.JsonHelper.Deserialize<ModMessageModel>(json); - HashSet<long> playerIDs = new HashSet<long>(model.ToPlayerIDs ?? this.GetKnownPlayerIDs()); if (this.LogNetworkTraffic) this.Monitor.Log($"Received message: {json}."); + // deserialize model + ModMessageModel? model; + try + { + model = this.JsonHelper.Deserialize<ModMessageModel>(json); + if (model is null) + { + this.Monitor.Log($"Received invalid mod message from {message.FarmerID}.\nRaw message data: {json}"); + return; + } + } + catch (Exception ex) + { + this.Monitor.Log($"Received invalid mod message from {message.FarmerID}.\nRaw message data: {json}\nError details: {ex.GetLogSummary()}"); + return; + } + + // get player IDs + HashSet<long> playerIDs = new HashSet<long>(model.ToPlayerIDs ?? this.GetKnownPlayerIDs()); + // notify local mods if (playerIDs.Contains(Game1.player.UniqueMultiplayerID)) this.OnModMessageReceived(model); |