Difference between revisions of "Modding:Migrate to Harmony 2.0"

From Stardew Valley Wiki
Jump to navigation Jump to search
(expand)
(→‎What's changing?: + AccessTools.Is* methods)
Line 13: Line 13:
 
* Added [https://harmony.pardeike.net/articles/patching-finalizer.html finalizers] and [https://harmony.pardeike.net/articles/reverse-patching.html reverse patches].
 
* Added [https://harmony.pardeike.net/articles/patching-finalizer.html finalizers] and [https://harmony.pardeike.net/articles/reverse-patching.html reverse patches].
 
* Added <tt>CodeInstruction</tt> extensions, <tt>Manipulator</tt> utility, and other improvements for transpilers.
 
* Added <tt>CodeInstruction</tt> extensions, <tt>Manipulator</tt> utility, and other improvements for transpilers.
 +
* Added more <tt>AccessTools.Is*</tt> methods.
 
* Transpilers can now default to the original input by returning <tt>null</tt>.
 
* Transpilers can now default to the original input by returning <tt>null</tt>.
 
* Better compatibility with Android modding.
 
* Better compatibility with Android modding.

Revision as of 15:38, 10 May 2020

Index

The following describes the upcoming SMAPI 3.6, and may change before release.

This page is for modders. Players: see Modding:Mod compatibility instead.

This page explains how to update your mod code for Harmony 2.0. This only applies to mods which use Harmony directly; that's discouraged in most cases, isn't officially part of SMAPI's public API, and isn't subject to SMAPI's normal versioning policy.

Overview

What's changing?

Harmony 2.0 has many changes that benefit SMAPI and mods. Some notable changes:

  • Added finalizers and reverse patches.
  • Added CodeInstruction extensions, Manipulator utility, and other improvements for transpilers.
  • Added more AccessTools.Is* methods.
  • Transpilers can now default to the original input by returning null.
  • Better compatibility with Android modding.
  • Better exception messages.
  • Better validation for invalid patches.
  • Fixed cases where methods were inlined and unpatchable on Linux/Mac.
  • Fixed methods with struct return types being unpatchable.
  • Various other improvements and fixes; see the Harmony 2.0 release notes and Harmony 2.0 documentation for more info.

After waiting ≈four months to make sure the release is stable, SMAPI 3.6 will transition to Harmony 2.0.

Is this the modapocalypse?

Nope. Although this is a major change, significant efforts were undertaken to minimise the impact:

  • Mods which don't use Harmony directly are not affected.
  • SMAPI automatically rewrites most Harmony 1.x code for compatibility so many mods can work without an update;
  • pull requests will be submitted to update affected open-source mods;
  • unofficial updates will be created for mods which haven't updated officially by the time SMAPI 3.6 is released;
  • the changes will be actively communicated and documented to modders.

In addition, the current target is at least 90% compatibility for open-source mods before SMAPI 3.6 is released. All of this means that the 3.6 release should have minimal impact on mod compatibility, despite the scope of the changes.

How to update your mod

  1. Make sure you follow best practices outlined in the Harmony guide. In particular, use the EnableHarmony option (don't reference the Harmony DLL directly).
  2. Change using Harmony; to using HarmonyLib;.
  3. Change HarmonyInstance harmony = HarmonyInstance.Create("your mod id"); to Harmony harmony = new Harmony("your mod id");.
  4. Check if any breaking changes listed below apply to your mod.
  5. Recompile the mod.

Breaking changes

API changes

See how to update your mod.

Stricter validation

Harmony 2.0 has stricter validation in general, so invalid patches that would previously work (e.g. setting __result to the wrong type) will now cause errors. See the exception messages for help fixing these.

Patching static constructors

The AccessTools methods for constructors (DeclaredConstructor, Constructor, and GetDeclaredConstructors) no longer match static constructors by default. Pass searchForStatic: true to the methods if needed.

Patching virtual methods

You can no longer patch a non-implemented virtual method; doing so results in the error "You can only patch implemented methods/constructors".

For example, consider this code:

public class GameLocation
{
   public virtual void cleanupBeforePlayerExit() {}
}

public class Farm : GameLocation {}

Farm.cleanupBeforePlayerExit doesn't exist, so it's inherited from GameLocation. Harmony 1.x would let you patch Farm.cleanupBeforePlayerExit, but in Harmony 2.x you must target the actual method (GameLocation.cleanupBeforePlayerExit in this example).