fix error on Linux/Mac when a mod tries to load content immediately after save is loaded
This commit is contained in:
parent
e84028f22b
commit
588b42742d
|
@ -18,6 +18,7 @@ For players:
|
||||||
* SMAPI now remembers if your game crashed and offers help next time you relaunch.
|
* SMAPI now remembers if your game crashed and offers help next time you relaunch.
|
||||||
* Fixed installer finding redundant game paths on Linux.
|
* Fixed installer finding redundant game paths on Linux.
|
||||||
* Fixed save events not being raised after the first day on Linux/Mac.
|
* Fixed save events not being raised after the first day on Linux/Mac.
|
||||||
|
* Fixed error on Linux/Mac when a mod tries to load content immediately after the save is loaded.
|
||||||
|
|
||||||
For mod developers:
|
For mod developers:
|
||||||
* Added log entries for basic context changes (e.g. loaded save) to simplify troubleshooting. More detailed logging can be enabled by setting `VerboseLogging: true` in `StardewModdingAPI.config.json`.
|
* Added log entries for basic context changes (e.g. loaded save) to simplify troubleshooting. More detailed logging can be enabled by setting `VerboseLogging: true` in `StardewModdingAPI.config.json`.
|
||||||
|
|
|
@ -264,7 +264,7 @@ namespace StardewModdingAPI.Framework
|
||||||
base.Update(gameTime);
|
base.Update(gameTime);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(this.IsBetweenSaveEvents)
|
if (this.IsBetweenSaveEvents)
|
||||||
{
|
{
|
||||||
// raise after-save
|
// raise after-save
|
||||||
this.IsBetweenSaveEvents = false;
|
this.IsBetweenSaveEvents = false;
|
||||||
|
@ -579,6 +579,53 @@ namespace StardewModdingAPI.Framework
|
||||||
|
|
||||||
/// <summary>The method called to draw everything to the screen.</summary>
|
/// <summary>The method called to draw everything to the screen.</summary>
|
||||||
/// <param name="gameTime">A snapshot of the game timing state.</param>
|
/// <param name="gameTime">A snapshot of the game timing state.</param>
|
||||||
|
protected override void Draw(GameTime gameTime)
|
||||||
|
{
|
||||||
|
Context.IsInDrawLoop = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.DrawImpl(gameTime);
|
||||||
|
this.FailedDraws = 0;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// log error
|
||||||
|
this.Monitor.Log($"An error occured in the overridden draw loop: {ex.GetLogSummary()}", LogLevel.Error);
|
||||||
|
|
||||||
|
// exit if irrecoverable
|
||||||
|
if (this.FailedDraws >= this.MaxFailedDraws)
|
||||||
|
{
|
||||||
|
this.Monitor.ExitGameImmediately("the game crashed when drawing, and SMAPI was unable to recover the game.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.FailedDraws++;
|
||||||
|
|
||||||
|
// abort in known unrecoverable cases
|
||||||
|
if (Game1.toolSpriteSheet?.IsDisposed == true)
|
||||||
|
{
|
||||||
|
this.Monitor.ExitGameImmediately("the game unexpectedly disposed the tool spritesheet, so it crashed trying to draw a tool. This is a known bug in Stardew Valley 1.2.29, and there's no way to recover from it.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// recover sprite batch
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Game1.spriteBatch.IsOpen(SGame.Reflection))
|
||||||
|
{
|
||||||
|
this.Monitor.Log("Recovering sprite batch from error...", LogLevel.Trace);
|
||||||
|
Game1.spriteBatch.End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception innerEx)
|
||||||
|
{
|
||||||
|
this.Monitor.Log($"Could not recover sprite batch state: {innerEx.GetLogSummary()}", LogLevel.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Context.IsInDrawLoop = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>Replicate the game's draw logic with some changes for SMAPI.</summary>
|
||||||
|
/// <param name="gameTime">A snapshot of the game timing state.</param>
|
||||||
/// <remarks>This implementation is identical to <see cref="Game1.Draw"/>, except for try..catch around menu draw code, private field references replaced by wrappers, and added events.</remarks>
|
/// <remarks>This implementation is identical to <see cref="Game1.Draw"/>, except for try..catch around menu draw code, private field references replaced by wrappers, and added events.</remarks>
|
||||||
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator", Justification = "copied from game code as-is")]
|
[SuppressMessage("ReSharper", "CompareOfFloatsByEqualityOperator", Justification = "copied from game code as-is")]
|
||||||
[SuppressMessage("ReSharper", "LocalVariableHidesMember", Justification = "copied from game code as-is")]
|
[SuppressMessage("ReSharper", "LocalVariableHidesMember", Justification = "copied from game code as-is")]
|
||||||
|
@ -587,10 +634,7 @@ namespace StardewModdingAPI.Framework
|
||||||
[SuppressMessage("ReSharper", "RedundantCast", Justification = "copied from game code as-is")]
|
[SuppressMessage("ReSharper", "RedundantCast", Justification = "copied from game code as-is")]
|
||||||
[SuppressMessage("ReSharper", "RedundantExplicitNullableCreation", Justification = "copied from game code as-is")]
|
[SuppressMessage("ReSharper", "RedundantExplicitNullableCreation", Justification = "copied from game code as-is")]
|
||||||
[SuppressMessage("ReSharper", "RedundantTypeArgumentsOfMethod", Justification = "copied from game code as-is")]
|
[SuppressMessage("ReSharper", "RedundantTypeArgumentsOfMethod", Justification = "copied from game code as-is")]
|
||||||
protected override void Draw(GameTime gameTime)
|
private void DrawImpl(GameTime gameTime)
|
||||||
{
|
|
||||||
Context.IsInDrawLoop = true;
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (Game1.debugMode)
|
if (Game1.debugMode)
|
||||||
{
|
{
|
||||||
|
@ -1236,45 +1280,6 @@ namespace StardewModdingAPI.Framework
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset failed draw count
|
|
||||||
this.FailedDraws = 0;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// log error
|
|
||||||
this.Monitor.Log($"An error occured in the overridden draw loop: {ex.GetLogSummary()}", LogLevel.Error);
|
|
||||||
|
|
||||||
// exit if irrecoverable
|
|
||||||
if (this.FailedDraws >= this.MaxFailedDraws)
|
|
||||||
{
|
|
||||||
this.Monitor.ExitGameImmediately("the game crashed when drawing, and SMAPI was unable to recover the game.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.FailedDraws++;
|
|
||||||
|
|
||||||
// abort in known unrecoverable cases
|
|
||||||
if (Game1.toolSpriteSheet?.IsDisposed == true)
|
|
||||||
{
|
|
||||||
this.Monitor.ExitGameImmediately("the game unexpectedly disposed the tool spritesheet, so it crashed trying to draw a tool. This is a known bug in Stardew Valley 1.2.29, and there's no way to recover from it.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// recover sprite batch
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Game1.spriteBatch.IsOpen(SGame.Reflection))
|
|
||||||
{
|
|
||||||
this.Monitor.Log("Recovering sprite batch from error...", LogLevel.Trace);
|
|
||||||
Game1.spriteBatch.End();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception innerEx)
|
|
||||||
{
|
|
||||||
this.Monitor.Log($"Could not recover sprite batch state: {innerEx.GetLogSummary()}", LogLevel.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Context.IsInDrawLoop = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****
|
/****
|
||||||
|
|
Loading…
Reference in New Issue