Editing Modding Tutorials/Harmony

Jump to navigation Jump to search

Warning: You are not logged in. Your IP address will be publicly visible if you make any edits. If you log in or create an account, your edits will be attributed to your username, along with other benefits.

The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then save the changes below to finish undoing the edit.

Latest revision Your text
Line 1: Line 1:
 
{{BackToTutorials}}
 
{{BackToTutorials}}
  
'''Harmony - A library for patching, replacing and decorating .NET and Mono methods during runtime'''
+
'''[http://rimworldwiki.com/index.php?title=Modding_Tutorials/Injection&action=edit&redlink=1 Harmony] - A library for patching, replacing and decorating .NET and Mono methods during runtime'''
  
 
Harmony is the current best practice for changing the runtime execution of code in RimWorld.
 
Harmony is the current best practice for changing the runtime execution of code in RimWorld.
  
To integrate Harmony into your mod for use, download the latest stable release and add it as a reference to your C# project. You can also get [https://steamcommunity.com/sharedfiles/filedetails/?id=2009463077 Harmony on Steam]. Please '''''do not''''' include the dll (0Harmony.dll) in your mod's assemblies folder! Outdated versions of Harmony can cause issues. Simply add Harmony as a dependency on Steam instead.
+
To integrate Harmony into your mod for use, download the latest stable release and add it as a reference to your C# project. Make sure that you also include the dll, (0Harmony.dll) in your mod's assemblies folder. Please DO NOT use HugsLib for an "easy" Harmony implementation due to the fact that HugsLib becomes an unnecessary and unutilized dependency for mods and beginners grow accustomed to using HugsLib in all their mods even if they never touch HugsLib's API in their code. This is a bad practice, especially for beginners new to RimWorld Modding. Please only use HugsLib when you want to utilize some of its features!
 
 
Additionally, please DO NOT use HugsLib for an "easy" Harmony implementation due to the fact that HugsLib becomes an unnecessary and unutilized dependency for mods and beginners grow accustomed to using HugsLib in all their mods even if they never touch HugsLib's API in their code. This is a bad practice, especially for beginners new to RimWorld Modding. Please only use HugsLib when you want to utilize some of its features!
 
  
 
Harmony is great for running code patches before (Prefix) or after (Postfix) an existing method. Usually this is all you need for your Mod. Because this does not change existing functionality of RimWorld, it MOST LIKELY does not impact other mods and runs in parallel with other Harmony patches.
 
Harmony is great for running code patches before (Prefix) or after (Postfix) an existing method. Usually this is all you need for your Mod. Because this does not change existing functionality of RimWorld, it MOST LIKELY does not impact other mods and runs in parallel with other Harmony patches.
  
''The snippets on this page are not meant as an exhaustive document on all things Harmony. Refer to the original documentation ([https://harmony.pardeike.net/ here]).'' This article is mostly a "this is what you can do" summary in 5 minutes.
+
''The snippets on this page are not meant as an exhaustive document on all things Harmony. Refer to the original documentation.'' This article is mostly a "this is what you can do" summary in 5 minutes.
  
 
==Requirements==
 
==Requirements==
Line 28: Line 26:
  
 
===Transpilers===
 
===Transpilers===
A transpiler is a set of CodeInstructions. These alter the inner working of the method. They use low-level IL-code, from System.Reflection and System.Reflection.Emit. Refer to MSDN and Harmony documentation for more info. Transpilers are difficult to debug and therefor hard to create/maintain/update.
+
A transpiler is a set of CodeInstructions. These alter the inner working of the method. They use low-level IL-code, from System.Reflection and System.Reflection.Emit. Refer to MSDN and Harmony documentation for more info. Transpilers are difficult to debug and therefor hard to create/maintain/update.  
 
 
If you must use a transpiler, you might find useful notes [[Modding_Tutorials/Transpiler Hints|here]].
 
  
 
==Altering the result==
 
==Altering the result==
Line 36: Line 32:
  
 
==Pitfalls==
 
==Pitfalls==
 
 
===Overuse===
 
===Overuse===
 
Harmony is a fantastic tool, that you'll soon want to use for everything. Before you do that, consider the alternatives. Can you subclass? Can you use a ThingComp? A MapComponent? There may be viable alternatives without the added dependency.
 
Harmony is a fantastic tool, that you'll soon want to use for everything. Before you do that, consider the alternatives. Can you subclass? Can you use a ThingComp? A MapComponent? There may be viable alternatives without the added dependency.
Line 45: Line 40:
 
<source lang="csharp">
 
<source lang="csharp">
 
[HarmonyPatch(typeof(Building_Trap))]
 
[HarmonyPatch(typeof(Building_Trap))]
[HarmonyPatch(nameof(Building_Trap.KnowsOfTrap))] //annotation boiler plate to tell Harmony what to patch. Refer to docs.
+
[HarmonyPatch(nameof(Building_Trap.KnowsOfTrap)] //annotation boiler plate to tell Harmony what to patch. Refer to docs.
 
static class Building_Trap_KnowsOfTrap_Patch
 
static class Building_Trap_KnowsOfTrap_Patch
 
{
 
{
Line 55: Line 50:
 
}
 
}
 
</source>
 
</source>
 
 
===Getting the right method to patch===
 
===Getting the right method to patch===
 
'''AccessTools''' is a nice wrapper for reflection. The most reliable way of specifying the method to patch is by providing the Patch() method with MethodInfo. Standard System.Reflection also works. You will need to specify arguments for overloaded methods.
 
'''AccessTools''' is a nice wrapper for reflection. The most reliable way of specifying the method to patch is by providing the Patch() method with MethodInfo. Standard System.Reflection also works. You will need to specify arguments for overloaded methods.
 
===Doesn't seem to get patched?===
 
===Doesn't seem to get patched?===
Does your Log.Message() not show up? Set HarmonyInstance.DEBUG = true and check the new .txt file Harmony placed on your desktop. If you are trying to patch something that runs during game loading, you [[Modding_Tutorials/Hello_World#StaticConstructorOnStartup_vs_inheriting_from_Mod| may need to bootstrap differently]]. Are you doing everything right? If the method you're patching is small, it may have been [https://en.wikipedia.org/wiki/Inline_expansion inlined.]
+
Does your Log.Message() not show up? Set HarmonyInstance.DEBUG = true and check the new .txt file Harmony placed on your desktop. If you are trying to patch something that runs during game loading, you [[Modding_Tutorials/Hello_World#StaticConstructorOnStartup_vs_inheriting_from_Mod| may need bootstrap differently]]. Are you doing everything right? If the method you're patching is small, it may have been [https://en.wikipedia.org/wiki/Inline_expansion inlined.]
  
 
==Bootstrapping==
 
==Bootstrapping==
Remember the [[Modding Tutorials/Hello World|Hello World]] tutorial? The [StaticConstructorOnStartup] is a perfect starting point. Create your harmony instance in there, and use it to call PatchAll() or do your manual patching.
+
Remember the [[Modding Tutorials/Hello World|Hello World]] tutorial? The [StaticConstructorOnStartUp] is a perfect starting point. Create your harmony instance in there, and use it to call PatchAll() or do your manual patching.
 
 
==Links==
 
[https://steamcommunity.com/workshop/filedetails/?id=2009463077 Harmony Mod] (Steam Workshop)
 
 
 
[https://github.com/pardeike/Harmony/releases Harmony 2 Releases] (GitHub)
 
  
[https://www.nuget.org/packages/Lib.Harmony/ Harmony 2 NuGet package]
+
== Links ==
  
[https://harmony.pardeike.net/ Harmony 2 Documentation] - Official documentation for Harmony 2.
+
[https://github.com/pardeike/Harmony/releases Harmony's Releases] - Link to Harmony's latest release(s) for download.
  
[https://github.com/RimWorld-CCL-Reborn/AlienRaces/blob/master/Source/AlienRace/AlienRace/HarmonyPatches.cs Alien races] - The Alien Races framework HarmonyPatches class. With approximately 180 patches, it's considered a good reference as it contains examples of all Harmony patch types.
+
[https://github.com/pardeike/Harmony/wiki Harmony's Wiki] - General outline of how to use Harmony
  
<s>[https://github.com/roxxploxx/RimWorldModGuide/wiki/SHORTTUTORIAL%3A-Harmony RimWorldModGuide on Harmony]</s> - '''OUTDATED''' (Harmony 1) <s>gives some concrete examples and helpful explanations</s>
+
[https://github.com/roxxploxx/RimWorldModGuide/wiki/SHORTTUTORIAL%3A-Harmony RimWorldModGuide on Harmony] - gives some concrete examples and helpful explanations
  
<s>[https://gist.github.com/pardeike/c02e29f9e030e6a016422ca8a89eefc9 Harmony's Author's Transpiler tutorial]</s> - '''OUTDATED''' (Harmony 1) <s>Tutorial and example of using Harmony Transpiler, with helpful links (inject your code inside a RimWorld class's code - #DeepMagic)</s>
+
[https://gist.github.com/pardeike/c02e29f9e030e6a016422ca8a89eefc9 Harmony's Author's Transpiler tutorial] - Tutorial and example of using Harmony Transpiler, with helpful links (inject your code inside a RimWorld class's code - #DeepMagic)
  
<s>[https://ludeon.com/forums/index.php?topic=29517 Harmony Thread]</s> - '''OUTDATED''' (Harmony 1) <s>Harmony thread on Ludeon Studio's Forum.  Announcements of new versions, and the forum in general is a reasonable place to ask questions.</s>
+
[https://ludeon.com/forums/index.php?topic=29517 Harmony Thread] - Harmony thread on Ludeon Studio's Forum.  Announcements of new versions, and the forum in general is a reasonable place to ask questions.
  
[[Category:Modding tutorials]]
+
[https://github.com/RimWorld-CCL-Reborn/AlienRaces/blob/master/Source/AlienRace/AlienRace/HarmonyPatches.cs Alien races] - The unofficial Harmony encyclopedia. Dozens, if not hundreds of patches for all your cargo cult programming needs.

Please note that all contributions to RimWorld Wiki are considered to be released under the CC BY-SA 3.0 (see RimWorld Wiki:Copyrights for details). If you do not want your writing to be edited mercilessly and redistributed at will, then do not submit it here.
You are also promising us that you wrote this yourself, or copied it from a public domain or similar free resource. Do not submit copyrighted work without permission!

Cancel Editing help (opens in new window)

Template used on this page:

This page is a member of 1 hidden category: