using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Harmony;
using StardewModdingAPI.Framework.Patching;
using StardewModdingAPI.Framework.Reflection;
using StardewValley;
namespace StardewModdingAPI.Patches {
/// A Harmony patch for the constructor which intercepts invalid dialogue lines and logs an error instead of crashing.
internal class CheckEventPreconditionErrorPatch : IHarmonyPatch {
/*********
** Private methods
*********/
/// Writes messages to the console and log file on behalf of the game.
private static IMonitor MonitorForGame;
/// Local variable to store the original method.
private static MethodInfo originalMethod;
/// Local variable to check if the method was already arbitrated.
private static bool isArbitrated;
/*********
** Accessors
*********/
/// A unique name for this patch.
public string Name => $"{nameof(CheckEventPreconditionErrorPatch)}";
/*********
** Public methods
*********/
/// Construct an instance.
/// Writes messages to the console and log file on behalf of the game.
/// Simplifies access to private code.
public CheckEventPreconditionErrorPatch(IMonitor monitorForGame, Reflector reflector) {
CheckEventPreconditionErrorPatch.MonitorForGame = monitorForGame;
}
/// Apply the Harmony patch.
/// The Harmony instance.
public void Apply(HarmonyInstance harmony) {
originalMethod = AccessTools.Method(typeof(GameLocation), "checkEventPrecondition");
harmony.Patch(originalMethod, new HarmonyMethod(AccessTools.Method(this.GetType(), "Prefix")));
}
/*********
** Private methods
*********/
/// The method to call instead of the GameLocation.CheckEventPrecondition.
/// The instance being patched.
/// The return value of the original method.
/// The precondition to be parsed.
/// Returns whether to execute the original method.
/// This method must be static for Harmony to work correctly. See the Harmony documentation before renaming arguments.
[SuppressMessage("ReSharper", "InconsistentNaming", Justification = "Argument names are defined by Harmony.")]
private static bool Prefix(GameLocation __instance, ref int __result, string precondition) {
if (isArbitrated) {
isArbitrated = false;
return true;
} else {
isArbitrated = true;
try {
object _ = originalMethod.Invoke(__instance, new object[] { precondition });
__result = _ is null ? -1 : (int)_;
} catch (System.Exception ex) {
__result = -1;
CheckEventPreconditionErrorPatch.MonitorForGame.Log($"Failed parsing event info. Event precondition: {precondition}\n{ex}", LogLevel.Error);
}
return false;
}
}
}
}