migrate to Harmony 2.1 (#711)
This commit is contained in:
parent
bd20c2e137
commit
8df578edb6
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
@ -38,6 +38,7 @@
|
||||||
<Copy SourceFiles="$(TargetDir)\SMAPI.config.json" DestinationFiles="$(GamePath)\smapi-internal\config.json" />
|
<Copy SourceFiles="$(TargetDir)\SMAPI.config.json" DestinationFiles="$(GamePath)\smapi-internal\config.json" />
|
||||||
<Copy SourceFiles="$(TargetDir)\SMAPI.metadata.json" DestinationFiles="$(GamePath)\smapi-internal\metadata.json" />
|
<Copy SourceFiles="$(TargetDir)\SMAPI.metadata.json" DestinationFiles="$(GamePath)\smapi-internal\metadata.json" />
|
||||||
<Copy SourceFiles="$(TargetDir)\0Harmony.dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
<Copy SourceFiles="$(TargetDir)\0Harmony.dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||||
|
<Copy SourceFiles="$(TargetDir)\0Harmony.xml" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||||
<Copy SourceFiles="$(TargetDir)\Mono.Cecil.dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
<Copy SourceFiles="$(TargetDir)\Mono.Cecil.dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||||
<Copy SourceFiles="$(TargetDir)\Newtonsoft.Json.dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
<Copy SourceFiles="$(TargetDir)\Newtonsoft.Json.dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||||
<Copy SourceFiles="$(TargetDir)\TMXTile.dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
<Copy SourceFiles="$(TargetDir)\TMXTile.dll" DestinationFolder="$(GamePath)\smapi-internal" />
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
<Copy SourceFiles="$(SmapiBin)\StardewModdingAPI.xml" DestinationFolder="$(PackagePath)\bundle" />
|
<Copy SourceFiles="$(SmapiBin)\StardewModdingAPI.xml" DestinationFolder="$(PackagePath)\bundle" />
|
||||||
<Copy SourceFiles="$(SmapiBin)\steam_appid.txt" DestinationFolder="$(PackagePath)\bundle" />
|
<Copy SourceFiles="$(SmapiBin)\steam_appid.txt" DestinationFolder="$(PackagePath)\bundle" />
|
||||||
<Copy SourceFiles="$(SmapiBin)\0Harmony.dll" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
<Copy SourceFiles="$(SmapiBin)\0Harmony.dll" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
||||||
|
<Copy SourceFiles="$(SmapiBin)\0Harmony.xml" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
||||||
<Copy SourceFiles="$(SmapiBin)\Mono.Cecil.dll" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
<Copy SourceFiles="$(SmapiBin)\Mono.Cecil.dll" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
||||||
<Copy SourceFiles="$(SmapiBin)\Newtonsoft.Json.dll" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
<Copy SourceFiles="$(SmapiBin)\Newtonsoft.Json.dll" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
||||||
<Copy SourceFiles="$(SmapiBin)\TMXTile.dll" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
<Copy SourceFiles="$(SmapiBin)\TMXTile.dll" DestinationFolder="$(PackagePath)\bundle\smapi-internal" />
|
||||||
|
|
|
@ -1,11 +1,9 @@
|
||||||
← [README](README.md)
|
← [README](README.md)
|
||||||
|
|
||||||
# Release notes
|
# Release notes
|
||||||
<!--
|
## Upcoming release
|
||||||
## Future release
|
|
||||||
* For mod authors:
|
* For mod authors:
|
||||||
* Migrated to Harmony 2.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info).
|
* Updated Harmony 1.2.0.1 to 2.1.0 (see [_migrate to Harmony 2.0_](https://stardewvalleywiki.com/Modding:Migrate_to_Harmony_2.0) for more info).
|
||||||
-->
|
|
||||||
|
|
||||||
## 3.11.0
|
## 3.11.0
|
||||||
Released 09 July 2021 for Stardew Valley 1.5.4 or later. See [release highlights](https://www.patreon.com/posts/53514295).
|
Released 09 July 2021 for Stardew Valley 1.5.4 or later. See [release highlights](https://www.patreon.com/posts/53514295).
|
||||||
|
|
|
@ -59,7 +59,6 @@ flag | purpose
|
||||||
`SMAPI_FOR_WINDOWS` | Whether SMAPI is being compiled for Windows; if not set, the code assumes Linux/macOS. Set automatically in `common.targets`.
|
`SMAPI_FOR_WINDOWS` | Whether SMAPI is being compiled for Windows; if not set, the code assumes Linux/macOS. Set automatically in `common.targets`.
|
||||||
`SMAPI_FOR_WINDOWS_64BIT_HACK` | Whether SMAPI is being [compiled for Windows with a 64-bit Linux version of the game](https://github.com/Pathoschild/SMAPI/issues/767). This is highly specialized and shouldn't be used in most cases. False by default.
|
`SMAPI_FOR_WINDOWS_64BIT_HACK` | Whether SMAPI is being [compiled for Windows with a 64-bit Linux version of the game](https://github.com/Pathoschild/SMAPI/issues/767). This is highly specialized and shouldn't be used in most cases. False by default.
|
||||||
`SMAPI_FOR_XNA` | Whether SMAPI is being compiled for XNA Framework; if not set, the code assumes MonoGame. Set automatically in `common.targets` with the same value as `SMAPI_FOR_WINDOWS` (unless `SMAPI_FOR_WINDOWS_64BIT_HACK` is set).
|
`SMAPI_FOR_XNA` | Whether SMAPI is being compiled for XNA Framework; if not set, the code assumes MonoGame. Set automatically in `common.targets` with the same value as `SMAPI_FOR_WINDOWS` (unless `SMAPI_FOR_WINDOWS_64BIT_HACK` is set).
|
||||||
`HARMONY_2` | Whether to enable experimental Harmony 2.0 support and rewrite existing Harmony 1._x_ mods for compatibility. Note that you need to replace `build/0Harmony.dll` with a Harmony 2.0 build (or switch to a package reference) to use this flag.
|
|
||||||
|
|
||||||
## For SMAPI developers
|
## For SMAPI developers
|
||||||
### Compiling from source
|
### Compiling from source
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using StardewModdingAPI.Framework.Patching;
|
|
||||||
using StardewValley;
|
|
||||||
#if HARMONY_2
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using StardewModdingAPI.Framework;
|
using StardewModdingAPI.Framework;
|
||||||
#else
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using System.Reflection;
|
using StardewValley;
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
{
|
{
|
||||||
|
@ -41,9 +36,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
DialogueErrorPatch.Reflection = reflector;
|
DialogueErrorPatch.Reflection = reflector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
{
|
{
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
|
@ -55,25 +48,11 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
finalizer: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Finalize_NPC_CurrentDialogue))
|
finalizer: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Finalize_NPC_CurrentDialogue))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
{
|
|
||||||
harmony.Patch(
|
|
||||||
original: AccessTools.Constructor(typeof(Dialogue), new[] { typeof(string), typeof(NPC) }),
|
|
||||||
prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Before_Dialogue_Constructor))
|
|
||||||
);
|
|
||||||
harmony.Patch(
|
|
||||||
original: AccessTools.Property(typeof(NPC), nameof(NPC.CurrentDialogue)).GetMethod,
|
|
||||||
prefix: new HarmonyMethod(this.GetType(), nameof(DialogueErrorPatch.Before_NPC_CurrentDialogue))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Private methods
|
** Private methods
|
||||||
*********/
|
*********/
|
||||||
#if HARMONY_2
|
|
||||||
/// <summary>The method to call after the Dialogue constructor.</summary>
|
/// <summary>The method to call after the Dialogue constructor.</summary>
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
/// <param name="__instance">The instance being patched.</param>
|
||||||
/// <param name="masterDialogue">The dialogue being parsed.</param>
|
/// <param name="masterDialogue">The dialogue being parsed.</param>
|
||||||
|
@ -113,72 +92,5 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
|
|
||||||
/// <summary>The method to call instead of the Dialogue constructor.</summary>
|
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
|
||||||
/// <param name="masterDialogue">The dialogue being parsed.</param>
|
|
||||||
/// <param name="speaker">The NPC for which the dialogue is being parsed.</param>
|
|
||||||
/// <returns>Returns whether to execute the original method.</returns>
|
|
||||||
private static bool Before_Dialogue_Constructor(Dialogue __instance, string masterDialogue, NPC speaker)
|
|
||||||
{
|
|
||||||
// get private members
|
|
||||||
bool nameArraysTranslated = DialogueErrorPatch.Reflection.GetField<bool>(typeof(Dialogue), "nameArraysTranslated").GetValue();
|
|
||||||
IReflectedMethod translateArraysOfStrings = DialogueErrorPatch.Reflection.GetMethod(typeof(Dialogue), "TranslateArraysOfStrings");
|
|
||||||
IReflectedMethod parseDialogueString = DialogueErrorPatch.Reflection.GetMethod(__instance, "parseDialogueString");
|
|
||||||
IReflectedMethod checkForSpecialDialogueAttributes = DialogueErrorPatch.Reflection.GetMethod(__instance, "checkForSpecialDialogueAttributes");
|
|
||||||
|
|
||||||
// replicate base constructor
|
|
||||||
__instance.dialogues ??= new List<string>();
|
|
||||||
|
|
||||||
// duplicate code with try..catch
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (!nameArraysTranslated)
|
|
||||||
translateArraysOfStrings.Invoke();
|
|
||||||
__instance.speaker = speaker;
|
|
||||||
parseDialogueString.Invoke(masterDialogue);
|
|
||||||
checkForSpecialDialogueAttributes.Invoke();
|
|
||||||
}
|
|
||||||
catch (Exception baseEx) when (baseEx.InnerException is TargetInvocationException invocationEx && invocationEx.InnerException is Exception ex)
|
|
||||||
{
|
|
||||||
string name = !string.IsNullOrWhiteSpace(speaker?.Name) ? speaker.Name : null;
|
|
||||||
DialogueErrorPatch.MonitorForGame.Log($"Failed parsing dialogue string{(name != null ? $" for {name}" : "")}:\n{masterDialogue}\n{ex}", LogLevel.Error);
|
|
||||||
|
|
||||||
parseDialogueString.Invoke("...");
|
|
||||||
checkForSpecialDialogueAttributes.Invoke();
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>The method to call instead of <see cref="NPC.CurrentDialogue"/>.</summary>
|
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
|
||||||
/// <param name="__result">The return value of the original method.</param>
|
|
||||||
/// <param name="__originalMethod">The method being wrapped.</param>
|
|
||||||
/// <returns>Returns whether to execute the original method.</returns>
|
|
||||||
private static bool Before_NPC_CurrentDialogue(NPC __instance, ref Stack<Dialogue> __result, MethodInfo __originalMethod)
|
|
||||||
{
|
|
||||||
const string key = nameof(DialogueErrorPatch.Before_NPC_CurrentDialogue);
|
|
||||||
if (!PatchHelper.StartIntercept(key))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
__result = (Stack<Dialogue>)__originalMethod.Invoke(__instance, new object[0]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (TargetInvocationException ex)
|
|
||||||
{
|
|
||||||
DialogueErrorPatch.MonitorForGame.Log($"Failed loading current dialogue for NPC {__instance.Name}:\n{ex.InnerException ?? ex}", LogLevel.Error);
|
|
||||||
__result = new Stack<Dialogue>();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
PatchHelper.StopIntercept(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
#if HARMONY_2
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#else
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
using StardewModdingAPI.Framework.Patching;
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
|
|
||||||
|
@ -34,11 +30,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(Event), nameof(Event.LogErrorAndHalt)),
|
original: AccessTools.Method(typeof(Event), nameof(Event.LogErrorAndHalt)),
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
#if HARMONY_2
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#else
|
|
||||||
using System.Reflection;
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
using StardewModdingAPI.Framework.Patching;
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using xTile;
|
using xTile;
|
||||||
|
@ -36,37 +31,22 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
{
|
{
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.checkEventPrecondition)),
|
original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.checkEventPrecondition)),
|
||||||
finalizer: new HarmonyMethod(this.GetType(), nameof(EventErrorPatch.Finalize_GameLocation_CheckEventPrecondition))
|
finalizer: new HarmonyMethod(this.GetType(), nameof(GameLocationPatches.Finalize_GameLocation_CheckEventPrecondition))
|
||||||
);
|
|
||||||
harmony.Patch(
|
|
||||||
original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.updateSeasonalTileSheets)),
|
|
||||||
finalizer: new HarmonyMethod(this.GetType(), nameof(EventErrorPatch.Before_GameLocation_UpdateSeasonalTileSheets))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
{
|
|
||||||
harmony.Patch(
|
|
||||||
original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.checkEventPrecondition)),
|
|
||||||
prefix: new HarmonyMethod(this.GetType(), nameof(GameLocationPatches.Before_GameLocation_CheckEventPrecondition))
|
|
||||||
);
|
);
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.updateSeasonalTileSheets)),
|
original: AccessTools.Method(typeof(GameLocation), nameof(GameLocation.updateSeasonalTileSheets)),
|
||||||
prefix: new HarmonyMethod(this.GetType(), nameof(GameLocationPatches.Before_GameLocation_UpdateSeasonalTileSheets))
|
finalizer: new HarmonyMethod(this.GetType(), nameof(GameLocationPatches.Before_GameLocation_UpdateSeasonalTileSheets))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Private methods
|
** Private methods
|
||||||
*********/
|
*********/
|
||||||
#if HARMONY_2
|
|
||||||
/// <summary>The method to call instead of GameLocation.checkEventPrecondition.</summary>
|
/// <summary>The method to call instead of GameLocation.checkEventPrecondition.</summary>
|
||||||
/// <param name="__result">The return value of the original method.</param>
|
/// <param name="__result">The return value of the original method.</param>
|
||||||
/// <param name="precondition">The precondition to be parsed.</param>
|
/// <param name="precondition">The precondition to be parsed.</param>
|
||||||
|
@ -77,43 +57,12 @@ harmony.Patch(
|
||||||
if (__exception != null)
|
if (__exception != null)
|
||||||
{
|
{
|
||||||
__result = -1;
|
__result = -1;
|
||||||
EventErrorPatch.MonitorForGame.Log($"Failed parsing event precondition ({precondition}):\n{__exception.InnerException}", LogLevel.Error);
|
GameLocationPatches.MonitorForGame.Log($"Failed parsing event precondition ({precondition}):\n{__exception.InnerException}", LogLevel.Error);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/// <summary>The method to call instead of <see cref="GameLocation.checkEventPrecondition"/>.</summary>
|
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
|
||||||
/// <param name="__result">The return value of the original method.</param>
|
|
||||||
/// <param name="precondition">The precondition to be parsed.</param>
|
|
||||||
/// <param name="__originalMethod">The method being wrapped.</param>
|
|
||||||
/// <returns>Returns whether to execute the original method.</returns>
|
|
||||||
private static bool Before_GameLocation_CheckEventPrecondition(GameLocation __instance, ref int __result, string precondition, MethodInfo __originalMethod)
|
|
||||||
{
|
|
||||||
const string key = nameof(GameLocationPatches.Before_GameLocation_CheckEventPrecondition);
|
|
||||||
if (!PatchHelper.StartIntercept(key))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
__result = (int)__originalMethod.Invoke(__instance, new object[] { precondition });
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (TargetInvocationException ex)
|
|
||||||
{
|
|
||||||
__result = -1;
|
|
||||||
GameLocationPatches.MonitorForGame.Log($"Failed parsing event precondition ({precondition}):\n{ex.InnerException}", LogLevel.Error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
PatchHelper.StopIntercept(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if HARMONY_2
|
|
||||||
/// <summary>The method to call instead of <see cref="GameLocation.updateSeasonalTileSheets"/>.</summary>
|
/// <summary>The method to call instead of <see cref="GameLocation.updateSeasonalTileSheets"/>.</summary>
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
/// <param name="__instance">The instance being patched.</param>
|
||||||
/// <param name="map">The map whose tilesheets to update.</param>
|
/// <param name="map">The map whose tilesheets to update.</param>
|
||||||
|
@ -126,33 +75,5 @@ harmony.Patch(
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/// <summary>The method to call instead of <see cref="GameLocation.updateSeasonalTileSheets"/>.</summary>
|
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
|
||||||
/// <param name="map">The map whose tilesheets to update.</param>
|
|
||||||
/// <param name="__originalMethod">The method being wrapped.</param>
|
|
||||||
/// <returns>Returns whether to execute the original method.</returns>
|
|
||||||
private static bool Before_GameLocation_UpdateSeasonalTileSheets(GameLocation __instance, Map map, MethodInfo __originalMethod)
|
|
||||||
{
|
|
||||||
const string key = nameof(GameLocationPatches.Before_GameLocation_UpdateSeasonalTileSheets);
|
|
||||||
if (!PatchHelper.StartIntercept(key))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
__originalMethod.Invoke(__instance, new object[] { map });
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (TargetInvocationException ex)
|
|
||||||
{
|
|
||||||
GameLocationPatches.MonitorForGame.Log($"Failed updating seasonal tilesheets for location '{__instance.NameOrUniqueName}'. Technical details:\n{ex.InnerException}", LogLevel.Error);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
PatchHelper.StopIntercept(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
#if HARMONY_2
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#else
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
using StardewModdingAPI.Framework.Exceptions;
|
using StardewModdingAPI.Framework.Exceptions;
|
||||||
using StardewModdingAPI.Framework.Patching;
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
|
@ -45,11 +41,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(SaveGame), nameof(SaveGame.loadDataToLocations)),
|
original: AccessTools.Method(typeof(SaveGame), nameof(SaveGame.loadDataToLocations)),
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using HarmonyLib;
|
||||||
using StardewModdingAPI.Framework.Patching;
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Menus;
|
using StardewValley.Menus;
|
||||||
using SObject = StardewValley.Object;
|
using SObject = StardewValley.Object;
|
||||||
#if HARMONY_2
|
|
||||||
using System;
|
|
||||||
using HarmonyLib;
|
|
||||||
#else
|
|
||||||
using System.Reflection;
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
{
|
{
|
||||||
|
@ -24,11 +19,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
** Public methods
|
** Public methods
|
||||||
*********/
|
*********/
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
// object.getDescription
|
// object.getDescription
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
|
@ -39,11 +30,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
// object.getDisplayName
|
// object.getDisplayName
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(SObject), "loadDisplayName"),
|
original: AccessTools.Method(typeof(SObject), "loadDisplayName"),
|
||||||
#if HARMONY_2
|
|
||||||
finalizer: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Finalize_Object_loadDisplayName))
|
finalizer: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Finalize_Object_loadDisplayName))
|
||||||
#else
|
|
||||||
prefix: new HarmonyMethod(this.GetType(), nameof(ObjectErrorPatch.Before_Object_loadDisplayName))
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// IClickableMenu.drawToolTip
|
// IClickableMenu.drawToolTip
|
||||||
|
@ -73,7 +60,6 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if HARMONY_2
|
|
||||||
/// <summary>The method to call after <see cref="StardewValley.Object.loadDisplayName"/>.</summary>
|
/// <summary>The method to call after <see cref="StardewValley.Object.loadDisplayName"/>.</summary>
|
||||||
/// <param name="__result">The patched method's return value.</param>
|
/// <param name="__result">The patched method's return value.</param>
|
||||||
/// <param name="__exception">The exception thrown by the wrapped method, if any.</param>
|
/// <param name="__exception">The exception thrown by the wrapped method, if any.</param>
|
||||||
|
@ -88,38 +74,6 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
|
|
||||||
return __exception;
|
return __exception;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/// <summary>The method to call instead of <see cref="StardewValley.Object.loadDisplayName"/>.</summary>
|
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
|
||||||
/// <param name="__result">The patched method's return value.</param>
|
|
||||||
/// <param name="__originalMethod">The method being wrapped.</param>
|
|
||||||
/// <returns>Returns whether to execute the original method.</returns>
|
|
||||||
private static bool Before_Object_loadDisplayName(SObject __instance, ref string __result, MethodInfo __originalMethod)
|
|
||||||
{
|
|
||||||
const string key = nameof(ObjectErrorPatch.Before_Object_loadDisplayName);
|
|
||||||
if (!PatchHelper.StartIntercept(key))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
__result = (string)__originalMethod.Invoke(__instance, new object[0]);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (TargetInvocationException ex) when (ex.InnerException is KeyNotFoundException)
|
|
||||||
{
|
|
||||||
__result = "???";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
PatchHelper.StopIntercept(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>The method to call instead of <see cref="IClickableMenu.drawToolTip"/>.</summary>
|
/// <summary>The method to call instead of <see cref="IClickableMenu.drawToolTip"/>.</summary>
|
||||||
/// <param name="hoveredItem">The item for which to draw a tooltip.</param>
|
/// <param name="hoveredItem">The item for which to draw a tooltip.</param>
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using StardewModdingAPI.Framework.Patching;
|
|
||||||
using StardewValley;
|
|
||||||
#if HARMONY_2
|
|
||||||
using System;
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
using StardewModdingAPI.Framework;
|
using StardewModdingAPI.Framework;
|
||||||
#else
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using System.Reflection;
|
using StardewValley;
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
{
|
{
|
||||||
|
@ -37,19 +32,11 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: AccessTools.Method(typeof(NPC), nameof(NPC.parseMasterSchedule)),
|
original: AccessTools.Method(typeof(NPC), nameof(NPC.parseMasterSchedule)),
|
||||||
#if HARMONY_2
|
|
||||||
finalizer: new HarmonyMethod(this.GetType(), nameof(ScheduleErrorPatch.Finalize_NPC_parseMasterSchedule))
|
finalizer: new HarmonyMethod(this.GetType(), nameof(ScheduleErrorPatch.Finalize_NPC_parseMasterSchedule))
|
||||||
#else
|
|
||||||
prefix: new HarmonyMethod(this.GetType(), nameof(ScheduleErrorPatch.Before_NPC_parseMasterSchedule))
|
|
||||||
#endif
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +44,6 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
/*********
|
/*********
|
||||||
** Private methods
|
** Private methods
|
||||||
*********/
|
*********/
|
||||||
#if HARMONY_2
|
|
||||||
/// <summary>The method to call instead of <see cref="NPC.parseMasterSchedule"/>.</summary>
|
/// <summary>The method to call instead of <see cref="NPC.parseMasterSchedule"/>.</summary>
|
||||||
/// <param name="rawData">The raw schedule data to parse.</param>
|
/// <param name="rawData">The raw schedule data to parse.</param>
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
/// <param name="__instance">The instance being patched.</param>
|
||||||
|
@ -74,35 +60,5 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/// <summary>The method to call instead of <see cref="NPC.parseMasterSchedule"/>.</summary>
|
|
||||||
/// <param name="rawData">The raw schedule data to parse.</param>
|
|
||||||
/// <param name="__instance">The instance being patched.</param>
|
|
||||||
/// <param name="__result">The patched method's return value.</param>
|
|
||||||
/// <param name="__originalMethod">The method being wrapped.</param>
|
|
||||||
/// <returns>Returns whether to execute the original method.</returns>
|
|
||||||
private static bool Before_NPC_parseMasterSchedule(string rawData, NPC __instance, ref Dictionary<int, SchedulePathDescription> __result, MethodInfo __originalMethod)
|
|
||||||
{
|
|
||||||
const string key = nameof(ScheduleErrorPatch.Before_NPC_parseMasterSchedule);
|
|
||||||
if (!PatchHelper.StartIntercept(key))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
__result = (Dictionary<int, SchedulePathDescription>)__originalMethod.Invoke(__instance, new object[] { rawData });
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (TargetInvocationException ex)
|
|
||||||
{
|
|
||||||
ScheduleErrorPatch.MonitorForGame.Log($"Failed parsing schedule for NPC {__instance.Name}:\n{rawData}\n{ex.InnerException ?? ex}", LogLevel.Error);
|
|
||||||
__result = new Dictionary<int, SchedulePathDescription>();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
PatchHelper.StopIntercept(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
#if HARMONY_2
|
|
||||||
using HarmonyLib;
|
|
||||||
#else
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using HarmonyLib;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using StardewModdingAPI.Framework.Patching;
|
using StardewModdingAPI.Framework.Patching;
|
||||||
|
|
||||||
|
@ -20,11 +16,7 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
** Public methods
|
** Public methods
|
||||||
*********/
|
*********/
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
original: Constants.GameFramework == GameFramework.Xna
|
original: Constants.GameFramework == GameFramework.Xna
|
||||||
|
|
|
@ -1,12 +1,6 @@
|
||||||
#if HARMONY_2
|
|
||||||
using System;
|
|
||||||
using HarmonyLib;
|
|
||||||
#else
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Reflection;
|
using HarmonyLib;
|
||||||
using StardewModdingAPI.Framework.Patching;
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
|
|
||||||
|
@ -22,7 +16,6 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
** Public methods
|
** Public methods
|
||||||
*********/
|
*********/
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
{
|
{
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
|
@ -30,21 +23,11 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
finalizer: new HarmonyMethod(this.GetType(), nameof(UtilityErrorPatches.Finalize_Utility_GetItemFromStandardTextDescription))
|
finalizer: new HarmonyMethod(this.GetType(), nameof(UtilityErrorPatches.Finalize_Utility_GetItemFromStandardTextDescription))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
{
|
|
||||||
harmony.Patch(
|
|
||||||
original: AccessTools.Method(typeof(Utility), nameof(Utility.getItemFromStandardTextDescription)),
|
|
||||||
prefix: new HarmonyMethod(this.GetType(), nameof(UtilityErrorPatches.Before_Utility_GetItemFromStandardTextDescription))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Private methods
|
** Private methods
|
||||||
*********/
|
*********/
|
||||||
#if HARMONY_2
|
|
||||||
/// <summary>The method to call instead of <see cref="Utility.getItemFromStandardTextDescription"/>.</summary>
|
/// <summary>The method to call instead of <see cref="Utility.getItemFromStandardTextDescription"/>.</summary>
|
||||||
/// <param name="description">The item text description to parse.</param>
|
/// <param name="description">The item text description to parse.</param>
|
||||||
/// <param name="delimiter">The delimiter by which to split the text description.</param>
|
/// <param name="delimiter">The delimiter by which to split the text description.</param>
|
||||||
|
@ -56,34 +39,5 @@ namespace StardewModdingAPI.Mods.ErrorHandler.Patches
|
||||||
? new FormatException($"Failed to parse item text description \"{description}\" with delimiter \"{delimiter}\".", __exception)
|
? new FormatException($"Failed to parse item text description \"{description}\" with delimiter \"{delimiter}\".", __exception)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
/// <summary>The method to call instead of <see cref="Utility.getItemFromStandardTextDescription"/>.</summary>
|
|
||||||
/// <param name="__result">The return value of the original method.</param>
|
|
||||||
/// <param name="description">The item text description to parse.</param>
|
|
||||||
/// <param name="who">The player for which the item is being parsed.</param>
|
|
||||||
/// <param name="delimiter">The delimiter by which to split the text description.</param>
|
|
||||||
/// <param name="__originalMethod">The method being wrapped.</param>
|
|
||||||
/// <returns>Returns whether to execute the original method.</returns>
|
|
||||||
private static bool Before_Utility_GetItemFromStandardTextDescription(ref Item __result, string description, Farmer who, char delimiter, MethodInfo __originalMethod)
|
|
||||||
{
|
|
||||||
const string key = nameof(UtilityErrorPatches.Before_Utility_GetItemFromStandardTextDescription);
|
|
||||||
if (!PatchHelper.StartIntercept(key))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
__result = (Item)__originalMethod.Invoke(null, new object[] { description, who, delimiter });
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
catch (TargetInvocationException ex)
|
|
||||||
{
|
|
||||||
throw new FormatException($"Failed to parse item text description \"{description}\" with delimiter \"{delimiter}\".", ex.InnerException);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
PatchHelper.StopIntercept(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,25 +3,13 @@ using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
#if HARMONY_2
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#else
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Commands
|
namespace StardewModdingAPI.Framework.Commands
|
||||||
{
|
{
|
||||||
/// <summary>The 'harmony_summary' SMAPI console command.</summary>
|
/// <summary>The 'harmony_summary' SMAPI console command.</summary>
|
||||||
internal class HarmonySummaryCommand : IInternalCommand
|
internal class HarmonySummaryCommand : IInternalCommand
|
||||||
{
|
{
|
||||||
#if !HARMONY_2
|
|
||||||
/*********
|
|
||||||
** Fields
|
|
||||||
*********/
|
|
||||||
/// <summary>The Harmony instance through which to fetch patch info.</summary>
|
|
||||||
private readonly HarmonyInstance HarmonyInstance = HarmonyInstance.Create($"SMAPI.{nameof(HarmonySummaryCommand)}");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*********
|
/*********
|
||||||
** Accessors
|
** Accessors
|
||||||
*********/
|
*********/
|
||||||
|
@ -60,9 +48,7 @@ namespace StardewModdingAPI.Framework.Commands
|
||||||
{
|
{
|
||||||
PatchType.Prefix => 0,
|
PatchType.Prefix => 0,
|
||||||
PatchType.Postfix => 1,
|
PatchType.Postfix => 1,
|
||||||
#if HARMONY_2
|
|
||||||
PatchType.Finalizer => 2,
|
PatchType.Finalizer => 2,
|
||||||
#endif
|
|
||||||
PatchType.Transpiler => 3,
|
PatchType.Transpiler => 3,
|
||||||
_ => 4
|
_ => 4
|
||||||
});
|
});
|
||||||
|
@ -111,26 +97,16 @@ namespace StardewModdingAPI.Framework.Commands
|
||||||
/// <summary>Get all current Harmony patches.</summary>
|
/// <summary>Get all current Harmony patches.</summary>
|
||||||
private IEnumerable<SearchResult> GetAllPatches()
|
private IEnumerable<SearchResult> GetAllPatches()
|
||||||
{
|
{
|
||||||
#if HARMONY_2
|
|
||||||
foreach (MethodBase method in Harmony.GetAllPatchedMethods().ToArray())
|
foreach (MethodBase method in Harmony.GetAllPatchedMethods().ToArray())
|
||||||
#else
|
|
||||||
foreach (MethodBase method in this.HarmonyInstance.GetPatchedMethods().ToArray())
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
// get metadata for method
|
// get metadata for method
|
||||||
#if HARMONY_2
|
|
||||||
HarmonyLib.Patches patchInfo = Harmony.GetPatchInfo(method);
|
HarmonyLib.Patches patchInfo = Harmony.GetPatchInfo(method);
|
||||||
#else
|
|
||||||
Harmony.Patches patchInfo = this.HarmonyInstance.GetPatchInfo(method);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IDictionary<PatchType, IReadOnlyCollection<Patch>> patchGroups = new Dictionary<PatchType, IReadOnlyCollection<Patch>>
|
IDictionary<PatchType, IReadOnlyCollection<Patch>> patchGroups = new Dictionary<PatchType, IReadOnlyCollection<Patch>>
|
||||||
{
|
{
|
||||||
[PatchType.Prefix] = patchInfo.Prefixes,
|
[PatchType.Prefix] = patchInfo.Prefixes,
|
||||||
[PatchType.Postfix] = patchInfo.Postfixes,
|
[PatchType.Postfix] = patchInfo.Postfixes,
|
||||||
#if HARMONY_2
|
|
||||||
[PatchType.Finalizer] = patchInfo.Finalizers,
|
[PatchType.Finalizer] = patchInfo.Finalizers,
|
||||||
#endif
|
|
||||||
[PatchType.Transpiler] = patchInfo.Transpilers
|
[PatchType.Transpiler] = patchInfo.Transpilers
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -160,10 +136,8 @@ namespace StardewModdingAPI.Framework.Commands
|
||||||
/// <summary>A postfix patch.</summary>
|
/// <summary>A postfix patch.</summary>
|
||||||
Postfix,
|
Postfix,
|
||||||
|
|
||||||
#if HARMONY_2
|
|
||||||
/// <summary>A finalizer patch.</summary>
|
/// <summary>A finalizer patch.</summary>
|
||||||
Finalizer,
|
Finalizer,
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>A transpiler patch.</summary>
|
/// <summary>A transpiler patch.</summary>
|
||||||
Transpiler
|
Transpiler
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#if HARMONY_2
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
@ -41,4 +40,3 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#if HARMONY_2
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
@ -81,4 +80,3 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#if HARMONY_2
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -44,4 +43,3 @@ namespace StardewModdingAPI.Framework.ModLoading.RewriteFacades
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#if HARMONY_2
|
|
||||||
extern alias MonoCecilPackage;
|
extern alias MonoCecilPackage;
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
@ -44,7 +43,7 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public override bool Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction, Action<Instruction> replaceWith)
|
public override bool Handle(ModuleDefinition module, ILProcessor cil, Instruction instruction)
|
||||||
{
|
{
|
||||||
// rewrite Harmony 1.x methods to Harmony 2.0
|
// rewrite Harmony 1.x methods to Harmony 2.0
|
||||||
MethodReference methodRef = RewriteHelper.AsMethodReference(instruction);
|
MethodReference methodRef = RewriteHelper.AsMethodReference(instruction);
|
||||||
|
@ -119,4 +118,3 @@ namespace StardewModdingAPI.Framework.ModLoading.Rewriters
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,9 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
#if HARMONY_2
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#else
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Patching
|
namespace StardewModdingAPI.Framework.Patching
|
||||||
{
|
{
|
||||||
|
@ -31,11 +27,7 @@ namespace StardewModdingAPI.Framework.Patching
|
||||||
/// <param name="patches">The patches to apply.</param>
|
/// <param name="patches">The patches to apply.</param>
|
||||||
public void Apply(params IHarmonyPatch[] patches)
|
public void Apply(params IHarmonyPatch[] patches)
|
||||||
{
|
{
|
||||||
#if HARMONY_2
|
|
||||||
Harmony harmony = new Harmony("SMAPI");
|
Harmony harmony = new Harmony("SMAPI");
|
||||||
#else
|
|
||||||
HarmonyInstance harmony = HarmonyInstance.Create("SMAPI");
|
|
||||||
#endif
|
|
||||||
foreach (IHarmonyPatch patch in patches)
|
foreach (IHarmonyPatch patch in patches)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
|
@ -1,8 +1,4 @@
|
||||||
#if HARMONY_2
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#else
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Patching
|
namespace StardewModdingAPI.Framework.Patching
|
||||||
{
|
{
|
||||||
|
@ -14,10 +10,6 @@ namespace StardewModdingAPI.Framework.Patching
|
||||||
*********/
|
*********/
|
||||||
/// <summary>Apply the Harmony patch.</summary>
|
/// <summary>Apply the Harmony patch.</summary>
|
||||||
/// <param name="harmony">The Harmony instance.</param>
|
/// <param name="harmony">The Harmony instance.</param>
|
||||||
#if HARMONY_2
|
|
||||||
void Apply(Harmony harmony);
|
void Apply(Harmony harmony);
|
||||||
#else
|
|
||||||
void Apply(HarmonyInstance harmony);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
#if !HARMONY_2
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace StardewModdingAPI.Framework.Patching
|
|
||||||
{
|
|
||||||
/// <summary>Provides generic methods for implementing Harmony patches.</summary>
|
|
||||||
internal class PatchHelper
|
|
||||||
{
|
|
||||||
/*********
|
|
||||||
** Fields
|
|
||||||
*********/
|
|
||||||
/// <summary>The interception keys currently being intercepted.</summary>
|
|
||||||
private static readonly HashSet<string> InterceptingKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
|
|
||||||
/*********
|
|
||||||
** Public methods
|
|
||||||
*********/
|
|
||||||
/// <summary>Track a method that will be intercepted.</summary>
|
|
||||||
/// <param name="key">The intercept key.</param>
|
|
||||||
/// <returns>Returns false if the method was already marked for interception, else true.</returns>
|
|
||||||
public static bool StartIntercept(string key)
|
|
||||||
{
|
|
||||||
return PatchHelper.InterceptingKeys.Add(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Track a method as no longer being intercepted.</summary>
|
|
||||||
/// <param name="key">The intercept key.</param>
|
|
||||||
public static void StopIntercept(string key)
|
|
||||||
{
|
|
||||||
PatchHelper.InterceptingKeys.Remove(key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
|
@ -48,10 +48,8 @@ namespace StardewModdingAPI.Metadata
|
||||||
yield return new HeuristicFieldRewriter(this.ValidateReferencesToAssemblies);
|
yield return new HeuristicFieldRewriter(this.ValidateReferencesToAssemblies);
|
||||||
yield return new HeuristicMethodRewriter(this.ValidateReferencesToAssemblies);
|
yield return new HeuristicMethodRewriter(this.ValidateReferencesToAssemblies);
|
||||||
|
|
||||||
#if HARMONY_2
|
// rewrite for SMAPI 3.12 (Harmony 1.x => 2.0 update)
|
||||||
// rewrite for SMAPI 3.x (Harmony 1.x => 2.0 update)
|
|
||||||
yield return new Harmony1AssemblyRewriter();
|
yield return new Harmony1AssemblyRewriter();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****
|
/****
|
||||||
|
@ -64,11 +62,7 @@ namespace StardewModdingAPI.Metadata
|
||||||
/****
|
/****
|
||||||
** detect code which may impact game stability
|
** detect code which may impact game stability
|
||||||
****/
|
****/
|
||||||
#if HARMONY_2
|
|
||||||
yield return new TypeFinder(typeof(HarmonyLib.Harmony).FullName, InstructionHandleResult.DetectedGamePatch);
|
yield return new TypeFinder(typeof(HarmonyLib.Harmony).FullName, InstructionHandleResult.DetectedGamePatch);
|
||||||
#else
|
|
||||||
yield return new TypeFinder(typeof(Harmony.HarmonyInstance).FullName, InstructionHandleResult.DetectedGamePatch);
|
|
||||||
#endif
|
|
||||||
yield return new TypeFinder("System.Runtime.CompilerServices.CallSite", InstructionHandleResult.DetectedDynamic);
|
yield return new TypeFinder("System.Runtime.CompilerServices.CallSite", InstructionHandleResult.DetectedDynamic);
|
||||||
yield return new FieldFinder(typeof(SaveGame).FullName, nameof(SaveGame.serializer), InstructionHandleResult.DetectedSaveSerializer);
|
yield return new FieldFinder(typeof(SaveGame).FullName, nameof(SaveGame.serializer), InstructionHandleResult.DetectedSaveSerializer);
|
||||||
yield return new FieldFinder(typeof(SaveGame).FullName, nameof(SaveGame.farmerSerializer), InstructionHandleResult.DetectedSaveSerializer);
|
yield return new FieldFinder(typeof(SaveGame).FullName, nameof(SaveGame.farmerSerializer), InstructionHandleResult.DetectedSaveSerializer);
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
#if HARMONY_2
|
|
||||||
using HarmonyLib;
|
using HarmonyLib;
|
||||||
#else
|
|
||||||
using Harmony;
|
|
||||||
#endif
|
|
||||||
using StardewModdingAPI.Enums;
|
using StardewModdingAPI.Enums;
|
||||||
using StardewModdingAPI.Framework.Patching;
|
using StardewModdingAPI.Framework.Patching;
|
||||||
using StardewModdingAPI.Framework.Reflection;
|
using StardewModdingAPI.Framework.Reflection;
|
||||||
|
@ -46,11 +42,7 @@ namespace StardewModdingAPI.Patches
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
#if HARMONY_2
|
|
||||||
public void Apply(Harmony harmony)
|
public void Apply(Harmony harmony)
|
||||||
#else
|
|
||||||
public void Apply(HarmonyInstance harmony)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
// detect CreatedBasicInfo
|
// detect CreatedBasicInfo
|
||||||
harmony.Patch(
|
harmony.Patch(
|
||||||
|
|
Loading…
Reference in New Issue