From 5d32b9802942e70c2d51d0edc376d92ac35b1032 Mon Sep 17 00:00:00 2001 From: Jesse Plamondon-Willard Date: Fri, 3 Mar 2017 17:13:33 -0500 Subject: [PATCH] fix mods running code concurrently with a SDV 1.2+ background task --- src/StardewModdingAPI/Framework/SGame.cs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/StardewModdingAPI/Framework/SGame.cs b/src/StardewModdingAPI/Framework/SGame.cs index 2e54544b..aa22d572 100644 --- a/src/StardewModdingAPI/Framework/SGame.cs +++ b/src/StardewModdingAPI/Framework/SGame.cs @@ -305,6 +305,22 @@ namespace StardewModdingAPI.Framework /// A snapshot of the game timing state. protected override void Update(GameTime gameTime) { + // While a background new-day task is in progress, the game skips its own update logic + // and defers to the XNA Update method. Running mod code in parallel to the background + // update is risky, because data changes can conflict (e.g. collection changed during + // enumeration errors) and data may change unexpectedly from one mod instruction to the + // next. + // + // Therefore we can just run Game1.Update here without raising any SMAPI events. There's + // a small chance that the task will finish after we defer but before the game checks, + // which means technically events should be raised, but the effects of missing one + // update tick are neglible and not worth the complications of bypassing Game1.Update. + if (SGame._newDayTask != null) + { + base.Update(gameTime); + return; + } + // raise game loaded if (this.FirstUpdate) GameEvents.InvokeGameLoaded(this.Monitor); @@ -361,7 +377,7 @@ namespace StardewModdingAPI.Framework /// The method called to draw everything to the screen. /// A snapshot of the game timing state. - /// This implementation is identical to , except for try..catch around menu draw code, minor formatting, and added events. + /// This implementation is identical to , except for try..catch around menu draw code, private field references replaced by wrappers, and added events. [SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator", Justification = "copied from game code as-is")] [SuppressMessage("ReSharper", "LocalVariableHidesMember", Justification = "copied from game code as-is")] [SuppressMessage("ReSharper", "PossibleLossOfFraction", Justification = "copied from game code as-is")]