User:Pepoluan/Harmony

From Stardew Modding Wiki
Jump to navigation Jump to search

THIS IS A SANDBOXY WORK-IN-PROGRESS

Harmony is a framework to perform patching on program code.

Harmony should be a last resort. It's a powerful tool that lets you do things that may be harder otherwise, but it comes with significant disadvantages:

  • It's very easy to cause crashes, errors, or subtle bugs, including difficult-to-diagnose memory corruption errors.
  • SMAPI often can't detect incompatible Harmony code.
  • Crossplatform compatibility isn't guaranteed.
  • Patches may conflict with other Harmony mods, sometimes in ways that are difficult to troubleshoot.
  • Patches may have unpredictable effects on other mods that aren't using Harmony. That may also irritate other modders, if players often report bugs to other mods due to your patches.
  • Patches may prevent you from attaching a debugger when testing (even when you're testing unrelated code).
  • If someone else's mod calls code you patched and that code crashes, the error will be logged under their mod's name (unless you handle errors). This can cause players to report bugs to other authors, which can be irritating if they know it's due to your mod.
  • SMAPI will show a warning when your mod is loaded saying it may affect game stability.

You should only use Harmony if you're sure what you want isn't feasible without it. For example: instead of patching logic that handles player interaction, you can detect and suppress the interaction using SMAPI's input API, and run your own code to handle it.

Harmony's patching concepts

If you really, really have to resort to Harmony, you can patch using three methods. In order of decreasing preference:

  1. postfix -- modify game state after method has executed. This provides maximum compatibility and smallest possibility of breakage.
  2. prefix -- intercept execution before method is invoked; optionally replaces the method completely.
  3. transpiler -- patches game code directly.

See the image on the right for illustration.

So what will happen:

  • Harmony will first attempt patch OriginalMethod() with a Transpiler method into a ModifiedMethod()
  • Invoking OriginalMethod() will transfer execution to Harmony
  • Harmony will execute one (or more) "Prefix method(s)" in order of priority
  • If none of the prefix method(s) instruct Harmony to "skip", execution will be transferred to ModifiedMethod() (or OriginalMethod() if no Transpiler had been executed)
  • Upon completion of OriginalMethod()/ModifiedMethod(), Harmony will execute the "Postfix method(s)"