Prevent crash down from save error.

This commit is contained in:
ZaneYork 2020-04-28 23:05:33 +08:00
parent 6276eff2ca
commit d608774afe
6 changed files with 139 additions and 15 deletions

View File

@ -274,12 +274,13 @@ namespace StardewModdingAPI.Framework
new LoadContextPatch(this.Reflection, this.GameInstance.OnLoadStageChanged),
new LoadErrorPatch(this.Monitor, this.GameInstance.OnSaveContentRemoved),
new ScheduleErrorPatch(this.MonitorForGame),
new SaveBackupPatch(this.EventManager),
new SaveBackupPatch(this.EventManager, this.Monitor),
new JunimoHarvesterPatch(this.Monitor),
new LocationSwitchPatch(this.Monitor),
new SpriteFontPatch(this.Monitor),
new ThreadSilenceExitPatch(this.Monitor),
new SaveGamePatch(this.Translator)
new SaveGamePatch(this.Translator, this.Monitor),
new OnAppPausePatch(this.Monitor)
);
// add exit handler

View File

@ -0,0 +1,69 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Harmony;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Patching;
using StardewValley;
namespace StardewModdingAPI.Patches
{
internal class OnAppPausePatch : IHarmonyPatch
{
/*********
** Accessors
*********/
/// <summary>A unique name for this patch.</summary>
public string Name => $"{nameof(OnAppPausePatch)}";
/// <summary>Writes messages to the console and log file.</summary>
private static IMonitor Monitor;
/*********
** Public methods
*********/
/// <summary>Construct an instance.</summary>
public OnAppPausePatch(Monitor monitor)
{
OnAppPausePatch.Monitor = monitor;
}
/// <summary>Apply the Harmony patch.</summary>
/// <param name="harmony">The Harmony instance.</param>
public void Apply(HarmonyInstance harmony)
{
harmony.Patch(AccessTools.Method(typeof(Game1), nameof(Game1.OnAppPause)),
new HarmonyMethod(AccessTools.Method(this.GetType(), nameof(OnAppPausePatch.Game_OnAppPausePrefix))));
}
/*********
** Private methods
*********/
/// <summary>The method to call instead of <see cref="StardewValley.Game1.OnAppPause"/>.</summary>
/// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks>
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
private static bool Game_OnAppPausePrefix(Game1 __instance, MethodInfo __originalMethod)
{
const string key = nameof(OnAppPausePatch.Game_OnAppPausePrefix);
if (!PatchHelper.StartIntercept(key))
return true;
try
{
__originalMethod.Invoke(__instance, new object[] { });
}
catch (Exception ex)
{
OnAppPausePatch.Monitor.Log($"Failed during OnAppPause method :\n{ex.InnerException ?? ex}", LogLevel.Error);
}
finally
{
PatchHelper.StopIntercept(key);
}
return false;
}
}
}

View File

@ -1,3 +1,4 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Harmony;
@ -19,6 +20,8 @@ namespace StardewModdingAPI.Patches
/// <summary>An Instance of <see cref="EventManager"/>.</summary>
private static EventManager Events;
/// <summary>Writes messages to the console and log file.</summary>
private static IMonitor Monitor;
/*********
** Public methods
@ -26,9 +29,10 @@ namespace StardewModdingAPI.Patches
/// <summary>Construct an instance.</summary>
/// <param name="eventManager">SMAPI's EventManager Instance</param>
public SaveBackupPatch(EventManager eventManager)
public SaveBackupPatch(EventManager eventManager, Monitor monitor)
{
SaveBackupPatch.Events = eventManager;
SaveBackupPatch.Monitor = monitor;
}
@ -40,11 +44,10 @@ namespace StardewModdingAPI.Patches
MethodInfo makeFullBackup = AccessTools.Method(typeof(Game1), nameof(Game1.MakeFullBackup));
MethodInfo saveWholeBackup = AccessTools.Method(typeof(Game1), nameof(Game1.saveWholeBackup));
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(SaveBackupPatch.Prefix));
MethodInfo postfix = AccessTools.Method(this.GetType(), nameof(SaveBackupPatch.PostFix));
MethodInfo prefix = AccessTools.Method(this.GetType(), nameof(SaveBackupPatch.GameSave_Prefix));
harmony.Patch(makeFullBackup, new HarmonyMethod(prefix), new HarmonyMethod(postfix));
harmony.Patch(saveWholeBackup, new HarmonyMethod(prefix), new HarmonyMethod(postfix));
harmony.Patch(makeFullBackup, new HarmonyMethod(prefix));
harmony.Patch(saveWholeBackup, new HarmonyMethod(prefix));
}
@ -54,14 +57,28 @@ namespace StardewModdingAPI.Patches
/// <summary>The method to call instead of <see cref="StardewValley.Object.getDescription"/>.</summary>
/// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks>
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
private static void Prefix()
private static bool GameSave_Prefix(MethodInfo __originalMethod)
{
const string key = nameof(SaveBackupPatch.GameSave_Prefix);
if (!PatchHelper.StartIntercept(key))
return true;
SaveBackupPatch.Events.Saving.RaiseEmpty();
try
{
__originalMethod.Invoke(null, new object[] { });
}
catch (Exception ex)
{
SaveBackupPatch.Monitor.Log($"Failed to save the game :\n{ex.InnerException ?? ex}", LogLevel.Error);
Game1.addHUDMessage(new HUDMessage("An error occurs during save the game.Check the error log for details.", HUDMessage.error_type));
}
finally
{
PatchHelper.StopIntercept(key);
}
SaveBackupPatch.Events.Saved.RaiseEmpty();
return false;
}
private static void PostFix()
{
SaveBackupPatch.Events.Saved.RaiseEmpty();
}
}
}

View File

@ -2,11 +2,14 @@ using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Reflection;
using Harmony;
using Microsoft.AppCenter.Crashes;
using Microsoft.Xna.Framework;
using StardewModdingAPI.Framework;
using StardewModdingAPI.Framework.Patching;
using StardewValley;
using StardewValley.Menus;
namespace StardewModdingAPI.Patches
{
@ -18,6 +21,9 @@ namespace StardewModdingAPI.Patches
/// <summary>A unique name for this patch.</summary>
public string Name => $"{nameof(SaveGamePatch)}";
/// <summary>Writes messages to the console and log file.</summary>
private static IMonitor Monitor;
/// <summary>An Instance of <see cref="Translator"/>.</summary>
private static Translator Translator;
@ -27,8 +33,9 @@ namespace StardewModdingAPI.Patches
*********/
/// <summary>Construct an instance.</summary>
/// <param name="monitor">Monitor</param>
public SaveGamePatch(Translator translator)
public SaveGamePatch(Translator translator, Monitor monitor)
{
SaveGamePatch.Monitor = monitor;
SaveGamePatch.Translator = translator;
}
@ -41,6 +48,10 @@ namespace StardewModdingAPI.Patches
original: AccessTools.Method(typeof(SaveGame), "HandleLoadError"),
prefix: new HarmonyMethod(this.GetType(), nameof(SaveGamePatch.Prefix))
);
harmony.Patch(
original: AccessTools.Method(typeof(SaveGameMenu), "update"),
prefix: new HarmonyMethod(this.GetType(), nameof(SaveGamePatch.SaveGameMenu_UpdatePrefix))
);
}
@ -142,5 +153,29 @@ namespace StardewModdingAPI.Patches
return false;
}
/// <summary>The method to call instead of <see cref="StardewValley.Menus.SaveGameMenu.update"/>.</summary>
/// <remarks>This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.</remarks>
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
private static bool SaveGameMenu_UpdatePrefix(SaveGameMenu __instance, GameTime time, MethodInfo __originalMethod)
{
const string key = nameof(SaveGamePatch.SaveGameMenu_UpdatePrefix);
if (!PatchHelper.StartIntercept(key))
return true;
try
{
__originalMethod.Invoke(__instance, new object[] {time});
}
catch (Exception ex)
{
SaveGamePatch.Monitor.Log($"Failed during SaveGameMenu.update method :\n{ex.InnerException ?? ex}", LogLevel.Error);
__instance.complete();
Game1.addHUDMessage(new HUDMessage("An error occurs during save the game.Check the error log for details.", HUDMessage.error_type));
}
finally
{
PatchHelper.StopIntercept(key);
}
return false;
}
}
}

View File

@ -2,6 +2,7 @@ using System;
using Android.App;
using Android.OS;
using Java.Lang;
using Exception = System.Exception;
namespace StardewModdingAPI
{
@ -56,14 +57,14 @@ namespace StardewModdingAPI
{
Looper.Prepare();
}
catch
catch (Exception)
{
}
Looper.Loop();
}
}
catch
catch(Exception)
{
// ignored
}

View File

@ -401,6 +401,7 @@
<Compile Include="Mod.cs" />
<Compile Include="Patches\DialogueErrorPatch.cs" />
<Compile Include="Patches\EventErrorPatch.cs" />
<Compile Include="Patches\OnAppPausePatch.cs" />
<Compile Include="Patches\SaveGamePatch.cs" />
<Compile Include="Patches\ThreadSilenceExitPatch.cs" />
<Compile Include="Patches\LocationSwitchPatch.cs" />